source: trunk/third/gnome-vfs/devel-docs/gnome-vfs-tutorial/gnome-vfs-tutorial.sgml @ 15497

Revision 15497, 146.7 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15496, which included commits to RCS files with non-trunk default branches.
Line 
1<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
2<book id="index">
3<bookinfo>
4<title>Application Programming Using the GNOME Libraries</title>
5<authorgroup>
6  <author>
7    <firstname>George</firstname>
8    <surname>Lebl</surname>
9    <affiliation>
10      <orgname>The GNOME Project</orgname>
11      <address>
12        <email>jirka@5z.com</email>
13      </address>
14    </affiliation>
15  </author>
16</authorgroup>
17<copyright>
18  <year>1999</year>
19  <holder>George Lebl</holder>
20</copyright>
21
22<abstract>
23<para>
24In this tutorial, you will receive an overview of the GNOME libraries.
25You will learn how to speed up development of applications by using the
26many utility routines and objects available through the GNOME libraries,
27and how to make the GUI more consistent by using standard GNOME UI
28components. Focus will also be given to C applications using the GTK+
29toolkit.</para>
30</abstract>
31</bookinfo>
32
33<preface>
34<title>Credits, Copyrights and Other Such Informations</title>
35
36<para>
37All of the code given in this tutorial is under the GNU General
38Public License or the GNU Library General Public License. It
39was written by me or the rest of the Gnome core team.</para>
40
41<para>
42Also I would like to apologize if some of my English is not
43correct, as English is not my first language. I hope that
44my C is better then my English.</para></preface>
45
46<chapter id="gnome-libraries-overview">
47<title>GNOME Libraries Overview</title>
48
49<sect1 id="where-gnome-libraries-fit">
50<title>Where do GNOME Libraries Fit</title>
51
52<para>
53Before going into the specifics of the GNOME libraries, it is important
54to see where do they fit in the picture of all the different libraries
55that are used in a GNOME application. The GNOME libraries are the most
56high level. GTK+ with it's two parts, GTK and GDK, comes next.
57GTK level provides an object model for C and a UI toolkit with the basic
58widgets to provide the generic basis for a GUI. GTK depends on GDK, which
59is a low-level wrapper around Xlib, the library directly talking to the
60X server. Everything (except for Xlib) depends on GLib which is a very
61useful C library with many utility and portability functions as well as
62a range of easy to use containers for C.
63
64<figure>
65<title>GNOME application library hierarchy</title>
66<graphic fileref="gnome-arch" format="GIF"></graphic>
67</figure>
68
69</para>
70
71</sect1>
72
73<sect1 id="structure-of-gnome-libraries">
74<title>Structure of GNOME Libraries</title>
75
76<para>
77We now look at the structure of the GNOME libraries to
78see what they can offer. Here is a listing of the different libraries
79that are present in the gnome-libs package:
80
81<variablelist>
82<varlistentry>
83<term>libgnome</term>
84<listitem>
85<para>Toolkit independent utility library</para>
86</listitem></varlistentry>
87<varlistentry>
88<term>libgnomeui</term>
89<listitem>
90<para>Toolkit dependent library</para>
91</listitem></varlistentry>
92<varlistentry>
93<term>libgnorba</term>
94<listitem>
95<para>Library for using ORBit corba implementation with gnome</para>
96</listitem></varlistentry>
97<varlistentry>
98<term>gtk-xmhtml</term>
99<listitem>
100<para>xmHTML widget ported to gtk, used in the help browser</para>
101</listitem></varlistentry>
102<varlistentry>
103<term>zvt</term>
104<listitem>
105<para>A very lean and mean terminal emulator widget</para>
106</listitem></varlistentry>
107<varlistentry>
108<term>libvfs</term>
109<listitem>
110<para>A virtual file-system library used in Midnight Commander</para>
111</listitem></varlistentry>
112<varlistentry>
113<term>libart_lgpl</term>
114<listitem>
115<para>A library used for nice anti-aliased graphics</para>
116</listitem></varlistentry>
117</variablelist></para>
118
119<para>
120We will not cover gtk-xmhtml,
121zvt, libvfs, libart_lgpl and libgnorba as they are mostly specialty
122libraries and some, notably the libvfs and gtk-xmhtml will most likely
123be phased out and replaced by better components.</para>
124
125<para>
126We can see a clear division between the <emphasis>libgnome</emphasis>
127and <emphasis>libgnomeui</emphasis>
128libraries. The former is used in a toolkit independent fashion and could
129even be used for command line programs that never use X. The latter is
130the library which supplies the standard widgets and an application framework
131for applications written using <emphasis>GTK+</emphasis>. It is
132conceivable to write applications with other toolkits, but nobody as of
133yet has written a <emphasis>libgnomeui</emphasis> with a different
134toolkit, and I doubt it will happen
135soon, as GTK+ is a really great toolkit.</para>
136</sect1>
137</chapter>
138
139<chapter id="gtk-programming">
140<title>GTK+ Programming</title>
141<sect1 id="gtk-overview">
142<title>Overview</title>
143
144<para>
145GTK+ is a C based toolkit for programming graphical applications in X
146windows. It is highly object oriented and has bindings to many popular
147languages, such as C++, Objective C, Perl, TOM, Guile, Python, etc ...
148GTK+ also uses GLib, which is a very useful C library, and includes
149things to help porting to different architectures, and containers
150such as a linked list or a hash.  If you are already familiar with GTK+,
151you are now free to get bored.</para></sect1>
152
153<sect1 id="glib">
154<title>GLib</title>
155<sect2>
156<title>Naming Conventions</title>
157
158<para>
159GLib is a utility library which is heavily used in GTK+ and most of GNOME.
160GLib's functions are named starting with <emphasis>g_</emphasis> (such as
161<emphasis>g_strdup</emphasis>), GLib's typedefs for common types are just
162prefixed with a <emphasis>g</emphasis> (such as <emphasis>gint32</emphasis>),
163and GLib's structures are capitalized and start with <emphasis>G</emphasis>
164(such as <emphasis>GHashTable</emphasis>).</para></sect2>
165
166<sect2>
167<title>Typedefs</title>
168
169<para>
170GLib provides some typedefs for portability, simplification of code,
171clarity of code and yet others just to keep consistent. The
172following table lists these typedefs. If the
173<emphasis>Equivalent</emphasis>, field is blank, there is no platform
174independent equivalent.
175
176<table>
177<title>
178GLib typedefs
179</title>
180
181<tgroup cols=3>
182<thead>
183<row>
184<entry>Name</entry>
185<entry>Equivalent</entry>
186<entry>Description</entry>
187</row>
188</thead>
189<tbody>
190
191<row><entry>gint8</entry><entry></entry>
192<entry>8bit wide signed integer</entry></row>
193<row><entry>guint8</entry><entry></entry>
194<entry>8bit wide unsigned integer</entry></row>
195
196<row><entry>gint16</entry><entry></entry>
197<entry>16bit wide signed integer</entry></row>
198<row><entry>guint16</entry><entry></entry>
199<entry>16bit wide unsigned integer</entry></row>
200
201<row><entry>gint32</entry><entry></entry>
202<entry>32bit wide signed integer</entry></row>
203<row><entry>guint32</entry><entry></entry>
204<entry>32bit wide unsigned integer</entry></row>
205
206<row><entry>gint64</entry><entry></entry>
207<entry>64bit wide signed integer (see note below)</entry></row>
208<row><entry>guint64</entry><entry></entry>
209<entry>64bit wide unsigned integer (see note below)</entry></row>
210
211<row><entry>gchar</entry><entry>char</entry>
212<entry>Standard character value</entry></row>
213<row><entry>guchar</entry><entry>unsigned char</entry>
214<entry>Standard unsigned character value</entry></row>
215<row><entry>gshort</entry><entry>short</entry>
216<entry>Standard short integer</entry></row>
217<row><entry>gushort</entry><entry>unsigned short</entry>
218<entry>Standard unsigned short integer</entry></row>
219<row><entry>glong</entry><entry>long</entry>
220<entry>Standard long integer</entry></row>
221<row><entry>gulong</entry><entry>unsigned long</entry>
222<entry>Standard unsigned long integer</entry></row>
223<row><entry>gint</entry><entry>int</entry>
224<entry>Standard integer</entry></row>
225<row><entry>guint</entry><entry>unsigned int</entry>
226<entry>Standard unsigned integer</entry></row>
227
228<row><entry>gfloat</entry><entry>float</entry>
229<entry>Standard float number type</entry></row>
230
231<row><entry>gdouble</entry><entry>double</entry>
232<entry>Standard float number type</entry></row>
233
234<row><entry>gboolean</entry><entry>int</entry>
235<entry>Type for storing TRUE/FALSE values</entry></row>
236
237<row><entry>gpointer</entry><entry>void *</entry>
238<entry>Type for storing pointers to arbitrary objects</entry></row>
239
240<row><entry>gconstpointer</entry><entry>const void *</entry>
241<entry>Type for storing pointers to arbitrary immutable objects</entry></row>
242</tbody>
243</tgroup>
244</table>
245</para>
246
247<para>It should be noted that <emphasis>gint64</emphasis> and
248<emphasis>guint64</emphasis> might not be available on all platforms. You can
249check for this in your code by checking to see if the macro
250<emphasis>G_HAVE_GINT64</emphasis> is defined.
251</para>
252
253<para>As you can see, some of the typedefs such as <emphasis>gint</emphasis>
254seem to have no other meaning in life then that of having a 'g' prefix and
255looking the same as the other typedefs. The logic behind this is to make the
256code look more consistent and clear. While it is no crime not to use these
257typedefs, you should really be consistent in your code. Some of the typedefs
258such as <emphasis>gboolean</emphasis> are only for improving code clarity
259and you could just as well use <emphasis>int</emphasis> to do exactly the
260same thing, but the former method clearly indicates that you are talking
261about a value that can only take TRUE or FALSE.
262</para>
263</sect2>
264
265<sect2>
266<title>Portability and Utility Functions</title>
267
268<para>
269There are some functions that have different implementations across
270different systems or are not extremely safe, or don't exist at all on some
271systems, so GLib provides it's own implementations or wrappers that have a
272constant behavior and usually check their arguments.</para>
273
274<para>Here are some of the more useful functions that fit this category.
275Note that the prototype is more of an informative one, as some of these
276might be macros in reality.
277
278<table>
279<title>
280Few GLib Portability Functions
281</title>
282
283<tgroup cols=2>
284<thead>
285<row>
286<entry>Prototype</entry>
287<entry>Description</entry>
288</row>
289</thead>
290<tbody>
291
292<row><entry>gchar * g_strdup (const gchar *)</entry>
293<entry>Returns a newly allocated string which is a copy of the argument,
294if the argument is NULL, NULL is returned</entry></row>
295<row><entry>gpointer g_malloc (int size)</entry>
296<entry>Returns a newly region of memory with 'size' bytes</entry></row>
297<row><entry>void g_free (gpointer p)</entry>
298<entry>Frees memory pointed to by 'p', and only returns if 'p' is
299NULL</entry></row>
300<row><entry>gint g_snprintf (gchar *string, gulong n, gchar const *format, ...)
301</entry>
302<entry>Works just like sprintf by printing the arguments according to the
303'format' into string, however it will only use 'n' bytes of the string and
304will thus truncate the result if it needed more. It returns the number
305of bytes actually printed into 'string'</entry></row>
306
307<row><entry>void g_usleep (gulong count)</entry>
308<entry>Suspend execution for at least 'count' microseconds</entry></row>
309
310</tbody>
311</tgroup>
312</table>
313
314</para>
315
316<para>And there are also some utility functions and macros that are not
317really found in the normal c library. Here is a very short list of some
318of the more important and useful ones.
319
320<table>
321<title>
322Few GLib Utility Functions
323</title>
324
325<tgroup cols=2>
326<thead>
327<row>
328<entry>Prototype</entry>
329<entry>Description</entry>
330</row>
331</thead>
332<tbody>
333
334<row><entry>g_new (type,count)</entry>
335<entry>A macro which will allocate new memory for 'count' items
336of type 'type' and cast the result to 'type'. It is equivalent to
337'(type) g_malloc(count * sizeof(type))'</entry></row>
338
339<row><entry>g_new0 (type,count)</entry>
340<entry>Same semantics as g_new, except that the returned memory will
341be set to all zeros. Note that you should not assume that setting the
342memory to zeros will zero out floating point types</entry></row>
343
344<row><entry>gchar * g_strconcat (const gchar *str, ...)</entry>
345<entry>When passed any number of arguments of the type (const char *) and
346a NULL after the last argument, it will return a newly allocated string
347that results by concatenation of all the arguments.</entry></row>
348
349<row><entry>gchar * g_strdup_printf (const gchar *format, ...)</entry>
350<entry>A printf like function that will return a newly allocated string
351with the result of the printf operation</entry></row>
352
353<row><entry>gchar * g_strstrip (gchar *string)</entry>
354<entry>Will strip leading and trailing whitespace from the string. It will
355not allocate new memory, but will modify the original string and return
356a pointer to it. If you wish to allocate new memory use a construction such as:
357'string2 = g_strstrip(g_strdup(string1));'</entry></row>
358
359
360</tbody>
361</tgroup>
362</table>
363
364</para>
365
366<para>
367There are many other useful methods in GLib, and I urge you to study GLib
368documentation and the GLib header file (<emphasis>glib.h</emphasis>), and
369you may be able to save a lot of time by not re-implementing some basic
370functionality.</para>
371</sect2>
372
373<sect2>
374<title>Containers</title>
375
376<para>
377Probably the best part of GLib are its containers. Here's a list of
378GLib's containers.
379
380<table>
381<title>
382Common GLib containers
383</title>
384
385<tgroup cols=2>
386<thead>
387<row>
388<entry>Name</entry>
389<entry>Description</entry>
390</row>
391</thead>
392<tbody>
393
394<row><entry>GList</entry>
395<entry>Doubly linked list</entry></row>
396<row><entry>GSList</entry>
397<entry>Singly linked list</entry></row>
398<row><entry>GHashTable</entry>
399<entry>Hash table</entry></row>
400<row><entry>GCache</entry>
401<entry>Cache</entry></row>
402<row><entry>GTree</entry>
403<entry>Balanced binary tree</entry></row>
404<row><entry>GNode</entry>
405<entry>n-ary tree</entry></row>
406<row><entry>GString</entry>
407<entry>Dynamically sized string</entry></row>
408<row><entry>GArray</entry>
409<entry>Dynamically sized array</entry></row>
410<row><entry>GPtrArray</entry>
411<entry>Dynamically sized array of pointers</entry></row>
412<row><entry>GByteArray</entry>
413<entry>Dynamically sized array of bytes (guint8)</entry></row>
414
415</tbody>
416</tgroup>
417</table>
418
419</para>
420
421<sect3>
422<title>GList</title>
423
424<para>
425The easiest to use are <emphasis>GList</emphasis>'s.
426The basic <emphasis>GList</emphasis> structure is just a single node
427of the linked list and you can put your data into the data pointer
428in the <emphasis>GList</emphasis>
429structure. To store a linked list you just store a pointer to the
430first node of the list. Here is the list of functions that operate on
431a GList. The functions usually take in a pointer and return the new
432pointer of the list, since the first node could now be a different one.
433
434<table>
435<title>
436Most important GList functions
437</title>
438
439<tgroup cols=2>
440<thead>
441<row>
442<entry>Prototype</entry>
443<entry>Description</entry>
444</row>
445</thead>
446<tbody>
447
448<row><entry>GList* g_list_append (GList *list, gpointer data)</entry>
449<entry>Append 'data' to a list. 'list' can be NULL to make a new list.</entry></row>
450
451<row><entry>GList* g_list_prepend (GList *list, gpointer data)</entry>
452<entry>Prepend 'data' to a list. 'list' can be NULL to make a new list.</entry></row>
453
454<row><entry>GList* g_list_remove (GList *list, gpointer data)</entry>
455<entry>Remove the node containing 'data' from the list.</entry></row>
456
457<row><entry>GList* g_list_find (GList *list, gpointer data)</entry>
458<entry>Find the GList node that contains the 'data'</entry></row>
459
460<row><entry>GList* g_list_next (GList *list)</entry>
461<entry>A macro that returns a pointer to the next node</entry></row>
462
463<row><entry>GList* g_list_previous (GList *list)</entry>
464<entry>A macro that returns a pointer to the next node</entry></row>
465
466<row><entry>void g_list_free(GList *list)</entry>
467<entry>Free the entire list.</entry></row>
468
469</tbody>
470</tgroup>
471</table>
472
473</para>
474
475<para>
476To access the data from a particular <emphasis>GList</emphasis> node
477You look at the <emphasis>data</emphasis> member in the
478<emphasis>GList</emphasis> structure.
479So code that would create a linked list of
480two elements which are strdup'ed strings, and later free that list
481and the strings would look like:
482
483<informalexample><programlisting>
484GList *list = NULL; /*the actual list pointer*/
485GList *li; /*just a temporary pointer to a node used for iterating
486             over the list*/
487...
488/*here we add two strings to the list*/
489list = g_list_append(list,g_strdup("String 1"));
490list = g_list_append(list,g_strdup("String 2"));
491...
492/*here we loop though the list, freeing all the strings and then
493  we free the list itself*/
494for(li = list; li!= NULL; li = g_list_next(li)) {
495        char *string = li-&gt;data;
496        g_free(string);
497}
498g_list_free(list);
499</programlisting></informalexample></para>
500</sect3>
501
502<sect3>
503<title>GString</title>
504
505<para>Another simple to use and useful container is the
506<emphasis>GString</emphasis> container.
507It's a dynamically sized string container for the times when you don't
508know how large the string you will need will be. Here's a list of the
509most important functions.
510
511<table>
512<title>
513Most important GString functions
514</title>
515
516<tgroup cols=2>
517<thead>
518<row>
519<entry>Prototype</entry>
520<entry>Description</entry>
521</row>
522</thead>
523<tbody>
524
525<row><entry>GString* g_string_new (const gchar *init)</entry>
526<entry>Create a new GString with initial value of 'init'</entry></row>
527
528<row><entry>void g_string_free (GString *string, int free_segment)</entry>
529<entry>Free the GString structure and optionally also the string data segment</entry></row>
530
531<row><entry>GString* g_string_append (GString *string, const gchar *val)</entry>
532<entry>Append 'val' to 'string'</entry></row>
533
534<row><entry>GString* g_string_prepend (GString *string, const gchar *val)</entry>
535<entry>Prepend 'val' to 'string'</entry></row>
536
537<row><entry>void g_string_sprintf (GString *string, const gchar *format, ...)</entry>
538<entry>A sprintf like function for GString</entry></row>
539
540<row><entry>void g_string_sprintfa (GString *string, const gchar *format, ...)</entry>
541<entry>A sprintf like function for GString, but appends the string instead of overwriting it</entry></row>
542
543</tbody>
544</tgroup>
545</table>
546
547</para>
548
549<para>
550To access the string data for use as a <emphasis>char *</emphasis>, just
551access the <emphasis>str</emphasis> element of the
552<emphasis>GString</emphasis> structure. You can actually free the
553<emphasis>GString</emphasis> structure without freeing this data segment.
554This is useful if you want to create a normal C string. The following example
555is a function that takes an array of integers and sprintfs them into a string
556and returns a <emphasis>char *</emphasis>.
557
558<informalexample><programlisting>
559char *
560create_number_list(int array[], int array_len)
561{
562        int i;           /* the array iterator */
563        GString *string; /* the GString */
564        char *ret;       /* the return value */
565
566        /* make a new GString that is empty */
567        string = g_string_new("");
568
569        /* iterate over the integer array */
570        for(i=0; i&lt;array_len; i++) {
571                /* append the number to the string in parenthesis */
572                g_string_sprintfa(string, "(%d)", array[i]);
573        }
574
575        /* setup the return value */
576        ret = string-&gt;str;
577
578        /* free the GString structure, but not the data */
579        g_string_free(string,FALSE);
580
581        /* return the string */
582        return ret;
583}
584</programlisting></informalexample></para>
585
586</sect3>
587
588<sect3>
589<title>GHashTable</title>
590
591<para>
592Though less often used then GList's and GString's. The hash table container
593is a very useful one. Usually by a hash table one would mean an object
594(in GLib's terms a <emphasis>gpointer</emphasis>) would have a string
595key, by which we could recall the object at a later time. GLib takes this
596a step further, making the key a <emphasis>gpointer</emphasis> as well,
597and letting you provide a hashing and a comparison function yourself.
598While this makes <emphasis>GHashTable</emphasis> much more flexible, it
599can lead to some confusion with respect to memory allocation for the
600keys. Let's give some important functions and deal with the details
601later:
602
603<table>
604<title>
605Most important GHashTable functions
606</title>
607
608<tgroup cols=2>
609<thead>
610<row>
611<entry>Prototype</entry>
612<entry>Description</entry>
613</row>
614</thead>
615<tbody>
616
617<row><entry>GHashTable* g_hash_table_new (GHashFunc hash_func,
618GCompareFunc key_compare_func)</entry>
619<entry>Creates a new hash table using the specified hash function and
620comparison function</entry></row>
621
622<row><entry>void g_hash_table_destroy (GHashTable *hash_table)</entry>
623<entry>Destroy the hash table and free memory. This does not however free
624neither the data, nor the keys, you have to do this
625yourself</entry></row>
626
627<row><entry>void g_hash_table_insert (GHashTable *hash_table, gpointer
628key, gpointer value)</entry>
629<entry>Insert a new 'value' with a key of 'key'.</entry></row>
630
631<row><entry>void g_hash_table_remove (GHashTable *hash_table,
632gconstpointer key)</entry>
633<entry>Remove the value with the key of 'key' from the table. Doesn't
634free neither the key nor the value.</entry></row>
635
636<row><entry>gpointer g_hash_table_lookup (GHashTable *hash_table,
637gconstpointer key)</entry>
638<entry>Fetch the pointer of the value, with the key of 'key'. Returns
639NULL if it isn't found</entry></row>
640
641
642<row><entry>gboolean g_hash_table_lookup_extended (GHashTable *hash_table,
643gconstpointer lookup_key, gpointer *orig_key, gpointer *value)</entry>
644<entry>Lookup the data with the key of 'value_key', store the original
645key pointer in 'orig_key' and the value in 'value'. Returns TRUE if the
646lookup was successful else it returns FALSE. You should use this
647function when removing an item to get rid of the original key in memory.
648</entry></row>
649
650<row><entry>void g_hash_table_foreach (GHashTable *hash_table, GHFunc
651func, gpointer user_data)</entry>
652<entry>Run a function for each data stored in the hash table. The
653'user_data' will be passed to the function as the last argument. The
654GHFunc prototype follows.</entry></row>
655
656<row><entry>void (*GHFunc) (gpointer key, gpointer value, gpointer
657user_data)</entry>
658<entry>This is the function prototype that you will use for the function
659that is passed to g_hash_table_foreach. It gets passed the key, the value
660and the user_data specified in the g_hash_table_foreach
661call.</entry></row>
662
663<row><entry>guint g_str_hash (gconstpointer v)</entry>
664<entry>A standard string hash function for string hash
665tables</entry></row>
666
667<row><entry>gint g_str_equal (gconstpointer v, gconstpointer v2)</entry>
668<entry>A standard string compare function for string hash tables</entry></row>
669
670</tbody>
671</tgroup>
672</table>
673
674</para>
675
676<para>
677To create a hash table, you pass the hash and key compare functions
678to <emphasis>g_hash_table_new</emphasis>. There are standard functions
679defined for strings (<emphasis>g_str_hash</emphasis> and
680<emphasis>g_str_equal</emphasis>) and others. However
681if you pass NULL as the hash and compare functions, you will get a direct
682pointer hash, where pointers will be actually themselves used as keys.
683</para>
684
685<para>
686The problem of memory allocation becomes apparent when we start using
687string hashes. <emphasis>GHashTable</emphasis> doesn't store the string,
688all it stores is a pointer. Therefore, when inserting a value into the
689hash, you have to create a new copy of the key for that value.
690This is an important thing to remember as otherwise things are not going
691to behave really nice for you. The other problem is how to then get rid
692of the key. If you do a <emphasis>g_hash_table_remove</emphasis>, you
693give as a key a string with the same contents as the original key, but
694not the same memory location. After then a pointer to the original key
695would be lost and unless you stored a pointer to it somewhere, you just
696created a memory leak. What you need to do instead is to do a
697<emphasis>g_hash_table_lookup_extended</emphasis> first to get both
698the value and the original key pointer and then do the
699<emphasis>g_hash_table_remove</emphasis>.
700</para>
701
702<para>
703The following example will make a new string hash, insert a couple of strings
704into it, retrieve them, and then destroy the hash and the values stored
705in it:
706
707<informalexample><programlisting>
708/* function we use for freeing the keys and data in the hash before
709   we destroy the hash */
710static void
711free_key_value(gpointer key, gpointer value, gpointer user_data)
712{
713        g_free(key);
714        g_free(value);
715}
716
717...
718
719/* somewhere else in the code */
720
721GHashTable *ht;
722
723/* create a new hash table with strings as keys */
724ht = g_hash_table_new(g_str_hash, g_str_equal);
725
726/* insert a couple of strings (say colors keyed by shape) */
727g_hash_table_insert(ht, g_strdup("triangle"), g_strdup("green"));
728g_hash_table_insert(ht, g_strdup("square"), g_strdup("red"));
729g_hash_table_insert(ht, g_strdup("circle"), g_strdup("blue"));
730
731/* again, somewhere else in the code */
732...
733/* now here we wish to print out the color of a square */
734char *color;
735
736/* get the color of a square */
737color = g_hash_table_lookup(ht, "square");
738
739printf("The color of a square is: %s\n",color);
740
741/* yet again somewhere else */
742...
743/* Now here we just want to destroy the hash table and free all the
744 * memory associated with it. We use the free_key_value function and
745 * have it run over all the values in the hash table. */
746g_hash_foreach(ht, free_key_value, NULL);
747
748/* now we can destroy the actual hash table */
749g_hash_table_destroy(ht);
750</programlisting></informalexample></para>
751
752</sect3>
753
754</sect2>
755
756
757<sect2>
758<title>More GLib information</title>
759<para>
760For more information look at the <emphasis>glib.h</emphasis> header file and at
761the documentation on the <ulink url="http://www.gtk.org/">www.gtk.org</ulink>
762web site.</para></sect2></sect1>
763
764<sect1 id="gtk">
765<title>GTK+</title>
766<sect2>
767<title>GUI Basics</title>
768
769<para>
770Writing a GTK+ based GUI application is in essence extremely simple, and
771we'll use the Hello World example from Ian Main's excellent GTK+ tutorial,
772which is a very useful guide to writing gnome applications. But first we'll
773talk about the basic philosophy behind GTK+.</para>
774
775<para>
776GTK+ is a container based toolkit, meaning you don't specify where the
777widget is, but you specify in what container it is. Some widgets,
778such as a window or a frame or a button, are containers that hold only
779one other widget. For example a button with a label is actually a button
780into which we added a label widget. If you need to put more widgets into
781that container, you will need to add another container into them, one
782that holds more then one widget such as a horizontal box.</para>
783
784<para>
785In fact most layout of windows is usually done with containers such as
786horizontal boxes, vertical boxes and tables, those are the most important
787to learn. A horizontal box is a widget that you can add several widgets
788into and they will be added in a horizontal row. The height of the
789horizontal box is the height of the highest widget added, and the
790length is the length of all widgets combined. Vertical box behaves exactly
791the same, except that it's vertical instead of horizontal. A table
792can take in widgets at different rows and columns.
793
794<figure>
795<title>Example window hierarchy</title>
796<graphic fileref="gtkhierarchy" format="GIF"></graphic>
797</figure>
798
799</para></sect2>
800
801<sect2>
802<title>GTK+ Object Model</title>
803
804<para>
805Gtk's object model is an object oriented framework for C. It includes
806singular object inheritance, virtual methods, signals, runtime object
807modification, runtime type checking, and other goodies. While writing
808a GTK+ object is more involved then say writing an object in something
809like Java, it does have many advantages. GTK+ is an object model which
810doesn't require inheritance for most things you do with objects. For one,
811since methods are just functions that take the pointer to the object
812as the first argument, it's easy to write more methods in your own code,
813which are missing in the original object.</para></sect2>
814
815<sect2>
816<title>Data on Objects</title>
817
818<para>
819There is a way to store arbitrary named data in objects to extend the object.
820This is done with the method, <emphasis>gtk_object_set_data</emphasis> (or
821<emphasis>gtk_object_set_user_data</emphasis> for a single unnamed pointer). To
822retrieve data, one uses <emphasis>gtk_object_get_data</emphasis>. Example:
823
824<informalexample><programlisting>
825GtkObject *obj;
826void *some_pointer;
827...
828/*here we set "some_data" data on obj to point to some_pointer*/
829gtk_object_set_data(obj,"some_data",some_pointer);
830...
831/*retrieve pointer to some_data from obj and store it in
832  some_pointer*/
833some_pointer = gtk_object_get_data(obj,"some_data");
834</programlisting></informalexample>
835The pointer can be a pointer to anything since it's manipulated as a (void *).</para></sect2>
836
837<sect2>
838<title>GTK+/GNOME Naming Conventions</title>
839
840<para>
841Both GTK+ and GNOME use the same naming convention when naming objects and
842functions. GTK+ uses a prefix of <emphasis>gtk_</emphasis> for functions, and
843<emphasis>Gtk</emphasis> for objects, and GNOME uses
844<emphasis>gnome_</emphasis> and <emphasis>Gnome</emphasis>. When a function is
845a method for an object, the name (lower case) is appended to the prefix.  For
846example the button object is named <emphasis>GtkButton</emphasis> (that is the
847name of the C struct holding the data for the object), and say the
848"<emphasis>new</emphasis>" method for <emphasis>GtkButton</emphasis> is then
849called <emphasis>gtk_button_new</emphasis>. Macros associated with objects use
850the same naming convention as functions, but are all capitalized. For example a
851macro that casts an object to a <emphasis>GtkButton</emphasis> is called
852<emphasis>GTK_BUTTON</emphasis>. There are exceptions, notably the type
853checking macro, which is called <emphasis>GTK_IS_BUTTON</emphasis> for
854<emphasis>GtkButton</emphasis>.</para></sect2>
855
856<sect2>
857<title>Using GTK+ Methods</title>
858
859<para>
860Since GTK+ is object oriented, it uses inheritance for it's widgets. For
861example <emphasis>GtkHBox</emphasis> and <emphasis>GtkVBox</emphasis> are
862derived from <emphasis>GtkBox</emphasis>.  And thus you can use any
863<emphasis>GtkBox</emphasis> method on a <emphasis>GtkVBox</emphasis> or
864<emphasis>GtkHBox</emphasis>. However you need to cast the
865<emphasis>GtkVBox</emphasis> object to <emphasis>GtkBox</emphasis> before you
866call the function. This could be done with standard C casts such as:
867
868<informalexample><programlisting>
869GtkVBox *vbox;
870...
871gtk_box_pack_start((GtkBox *)vbox, ...);
872...
873</programlisting></informalexample>
874This would work, however it is unsafe. GTK+ provides a mechanism of checking
875the types, so that it can warn you if you are casting an object which
876does not derive from the object you are casting to, or if you try to
877cast a NULL pointer. The macro is all capital name of the widget. For example
878the above code snippet would be
879
880<informalexample><programlisting>
881GtkVBox *vbox;
882...
883gtk_box_pack_start(GTK_BOX(vbox), ...);
884...
885</programlisting></informalexample></para>
886
887<para>
888GNOME uses the exact same form so anything you learn about GTK+ can be used
889for GNOME widgets, you just replace the GTK prefix with GNOME.</para></sect2>
890
891<sect2>
892<title>Example Hello World Program</title>
893
894<para>
895Here is the promised example code for the hello world program.
896It doesn't use any advanced containers, just a window and a button
897onto which a label is added. It illustrates the basic workings
898of a GUI program written in GTK+. Don't be scared by it's size,
899it's mostly comments.
900
901<informalexample><programlisting>
902/* example-start helloworld helloworld.c */
903
904#include &lt;gtk/gtk.h&gt;
905
906/* this is a callback function. the data arguments are ignored in
907 * this example.. More on callbacks below. */
908void
909hello (GtkWidget *widget, gpointer data)
910{
911        g_print ("Hello World\n");
912}
913
914gint
915delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
916{
917        g_print ("delete event occurred\n");
918        /* if you return FALSE in the "delete_event" signal
919         * handler, GTK will emit the "destroy" signal.
920         * Returning TRUE means you don't want the window
921         * to be destroyed. This is useful for popping up
922         * 'are you sure you want to quit ?' type dialogs. */
923
924        /* Change TRUE to FALSE and the main window will
925         * be destroyed with a "delete_event". */
926
927        return (TRUE);
928}
929
930/* another callback */
931void
932destroy (GtkWidget *widget, gpointer data)
933{
934        gtk_main_quit ();
935}
936
937int
938main (int argc, char *argv[])
939{
940        /* GtkWidget is the storage type for widgets */
941        GtkWidget *window;
942        GtkWidget *button;
943
944        /* this is called in all GTK applications.
945         * arguments are parsed from the command line and
946         * are returned to the application. */
947        gtk_init (&amp;argc, &amp;argv);
948
949        /* create a new window */
950        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
951
952        /* when the window is given the "delete_event" signal
953         * (this is given by the window manager, usually by
954         * the 'close' option, or on the titlebar), we ask
955         * it to call the delete_event () function as defined
956         * above.  The data passed to the callback function
957         * is NULL and is ignored in the callback function. */
958        gtk_signal_connect (GTK_OBJECT (window), "delete_event",
959                            GTK_SIGNAL_FUNC (delete_event), NULL);
960
961        /* here we connect the "destroy" event to a signal
962         * handler. This event occurs when we call
963         * gtk_widget_destroy() on the window, or if we
964         * return 'FALSE' in the "delete_event" callback. */
965        gtk_signal_connect (GTK_OBJECT (window), "destroy",
966                            GTK_SIGNAL_FUNC (destroy), NULL);
967
968        /* sets the border width of the window. */
969        gtk_container_border_width (GTK_CONTAINER (window), 10);
970
971        /* creates a new button with the label "Hello World". */
972        button = gtk_button_new_with_label ("Hello World");
973
974        /* When the button receives the "clicked" signal, it
975         * will call the function hello() passing it NULL as
976         * it's argument.  The hello() function is defined
977         * above. */
978        gtk_signal_connect (GTK_OBJECT (button), "clicked",
979                            GTK_SIGNAL_FUNC (hello), NULL);
980
981        /* This will cause the window to be destroyed by
982         * calling gtk_widget_destroy(window) when "clicked".
983         * Again, the destroy signal could come from here,
984         * or the window manager. */
985        gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
986                                   GTK_SIGNAL_FUNC (gtk_widget_destroy),
987                                   GTK_OBJECT (window));
988
989        /* this packs the button into the window
990         * (a gtk container). */
991        gtk_container_add (GTK_CONTAINER (window), button);
992
993        /* the final step is to display this newly created
994         * widget... */
995        gtk_widget_show (button);
996
997        /* and the window */
998        gtk_widget_show (window);
999
1000        /* all GTK applications must have a gtk_main().
1001         * Control ends here and waits for an event to occur
1002         * (like a key press or mouse event). */
1003        gtk_main ();
1004
1005        return 0;
1006}
1007/* example-end */
1008</programlisting></informalexample></para>
1009
1010<para>
1011For more information look at the header files in &lt;prefix&gt;/include/gtk/
1012and &lt;prefix&gt;/include/gdk/ and at the documentation on the
1013<ulink url="http://www.gtk.org/">www.gtk.org</ulink> web site.
1014</para></sect2></sect1></chapter>
1015
1016<chapter id="gnome-programming">
1017<title>GNOME Programming</title>
1018<sect1 id="gnome-introduction">
1019<title>Introduction</title>
1020<sect2>
1021<title>What Is a GNOME Program</title>
1022
1023<para>
1024A GNOME program is a GTK+ GUI application, which makes use of the
1025GNOME libraries. The GNOME libraries make it possible to have similar
1026look and feel among applications, and to make simple things, simple
1027to program. Plus the GNOME libraries add a whole bunch of widgets that
1028simply don't fit into GTK+.
1029</para>
1030</sect2>
1031
1032<sect2>
1033<title>Very Basic GNOME Program</title>
1034
1035<para>
1036The following program creates a basic gnome window and adds a horizontal box
1037into which it packs two buttons, which (when pressed) print a string onto the
1038stdout of the terminal you started the application from. The semantics and
1039structure of a GNOME program is very similar to a pure GTK+ program.
1040
1041<informalexample><programlisting>
1042/*
1043 * A simple Gnome program, outside of GNOME tree, not using i18n
1044 * buttons.c
1045 */
1046/* the very basic gnome include */
1047#include &lt;gnome.h&gt;
1048
1049/* a callback for the buttons */
1050static void
1051button_clicked(GtkWidget *button, gpointer data)
1052{
1053        /* the string to print is passed though the data field
1054           (which is a void *) */
1055        char *string = data;
1056        /* print a string on the standard output */
1057        g_print(string);
1058}
1059
1060/* called when the user closes the window */
1061static gint
1062delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
1063{
1064        /* signal the main loop to quit */
1065        gtk_main_quit();
1066        /* return FALSE to continue closing the window */
1067        return FALSE;
1068}
1069
1070int
1071main(int argc, char *argv[])
1072{
1073        GtkWidget *app;
1074        GtkWidget *button;
1075        GtkWidget *hbox;
1076
1077        /* Initialize GNOME, this is very similar to gtk_init */
1078        gnome_init ("buttons-basic-example", "0.1", argc, argv);
1079       
1080        /* Create a Gnome app widget, which sets up a basic window
1081           for your application */
1082        app = gnome_app_new ("buttons-basic-example",
1083                             "Basic GNOME Application");
1084
1085        /* bind "delete_event", which is the event we get when
1086           the user closes the window with the window manager,
1087           to gtk_main_quit, which is a function that causes
1088           the gtk_main loop to exit, and consequently to quit
1089           the application */
1090        gtk_signal_connect (GTK_OBJECT (app), "delete_event",
1091                            GTK_SIGNAL_FUNC (delete_event),
1092                            NULL);
1093
1094        /* create a horizontal box for the buttons and add it
1095           into the app widget */
1096        hbox = gtk_hbox_new (FALSE,5);
1097        gnome_app_set_contents (GNOME_APP (app), hbox);
1098
1099        /* make a button and add it into the horizontal box,
1100           and bind the clicked event to call button_clicked */
1101        button = gtk_button_new_with_label("Button 1");
1102        gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
1103        gtk_signal_connect (GTK_OBJECT (button), "clicked",
1104                            GTK_SIGNAL_FUNC (button_clicked),
1105                            "Button 1\n");
1106
1107        /* and another button */
1108        button = gtk_button_new_with_label("Button 2");
1109        gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
1110        gtk_signal_connect (GTK_OBJECT (button), "clicked",
1111                            GTK_SIGNAL_FUNC (button_clicked),
1112                            "Button 2\n");
1113       
1114        /* show everything inside this app widget and the app
1115           widget itself */
1116        gtk_widget_show_all(app);
1117       
1118        /* enter the main loop */
1119        gtk_main ();
1120       
1121        return 0;
1122}
1123</programlisting></informalexample></para>
1124
1125<para>
1126Please note the use of <emphasis>gnome_init</emphasis> instead of
1127<emphasis>gtk_init</emphasis>, and <emphasis>GnomeApp</emphasis> widget instead
1128of just a regular <emphasis>GtkWindow</emphasis>. We will go into detail of
1129these later.
1130</para>
1131</sect2>
1132</sect1>
1133
1134<sect1 id="gnome-overview">
1135<title>Overview</title>
1136
1137<para>
1138OK now we look at what the different libraries that we are going to cover do.
1139First we look at the <emphasis>libgnome</emphasis> library and it's
1140functionality, then we'll cover <emphasis>libgnomeui</emphasis> to complete all
1141the basic functionality of a gnome program. We will take a look at the
1142<emphasis>gnome-canvas</emphasis> in detail, as it is extremely powerful and
1143useful widget. We'll also say a few things about drag and drop.
1144</para>
1145</sect1>
1146
1147<sect1 id="using-the-libgnome-library">
1148<title>Using the libgnome Library</title>
1149
1150<para>
1151The <emphasis>libgnome</emphasis> library is the non-toolkit specific utility
1152library for GNOME applications, and includes things like configuration file
1153reading, .desktop file handling, special GLib like utility routines, getting
1154the standard file locations for GNOME, handling mime types, handling meta-data
1155on files, sound, "triggers", and other useful things one could want to use.
1156Also say that you are writing an application in say motif, but you want your
1157app to be more GNOME friendly. Then you could use this library to make your
1158application work well with other GNOME programs.</para>
1159
1160<sect2>
1161<title>Configuration Files</title>
1162
1163<para>
1164The <emphasis>gnome-config</emphasis> routines provide an easy way to store
1165configuration info in files. To see a full list of the routines, look in the
1166<emphasis>libgnome/gnome-config.h</emphasis> header file.</para>
1167
1168<para>
1169The routines all working with a path. The path is a Unix like path, but the
1170root is set to the <emphasis>~/.gnome/</emphasis> directory. So
1171<emphasis>/some/config/path/file/sectionA/keyB</emphasis>, refers to the file
1172<emphasis>~/.gnome/some/config/path/file</emphasis>, and inside the file using
1173section <emphasis>sectionA</emphasis> and key <emphasis>keyB</emphasis>.</para>
1174
1175<sect3>
1176<title>Reading Configuration Info</title>
1177
1178<para>
1179To read configuration information <emphasis>gnome_config_get_*</emphasis>
1180functions are used. the <emphasis>*</emphasis> is replaced by the type of the
1181data, it can be <emphasis>int</emphasis>, <emphasis>float</emphasis>,
1182<emphasis>string</emphasis>, <emphasis>bool</emphasis> and
1183<emphasis>vector</emphasis>. The <emphasis>int</emphasis> functions work with
1184<emphasis>gint</emphasis>, <emphasis>float</emphasis> functions work with
1185<emphasis>gdouble</emphasis>, <emphasis>string</emphasis> functions work with
1186<emphasis>gchar *</emphasis>, <emphasis>bool</emphasis> functions work with
1187<emphasis>gboolean</emphasis> and <emphasis>vector</emphasis> work with an argc
1188like array of strings (<emphasis>gint</emphasis> and <emphasis>gchar
1189**</emphasis>). For the <emphasis>gnome_config_get_*</emphasis> functions, the
1190default to be returned if the file section or key are not found can be appended
1191to the path after an equals sign. If you need to know if the default was used,
1192you can append <emphasis>_with_default</emphasis> to the function name and add
1193a parameter which is a <emphasis>gboolean *</emphasis>, though which the
1194function returns whether it used the default or if it actually found a real
1195value. Example follows:
1196
1197<informalexample><programlisting>
1198int counter;
1199char *text;
1200gboolean def;
1201...
1202counter = gnome_config_get_int_with_default("/example/section/counter=1",
1203                                            &amp;def);
1204if(def) g_print("Default used for counter!\n");
1205text = gnome_config_get_string("/example/section/text=TEXT");
1206...
1207g_free(text);
1208</programlisting></informalexample>
1209Note that the string returned by <emphasis>gnome_config_get_string</emphasis>
1210should be freed with <emphasis>g_free</emphasis>, the vector from
1211<emphasis>gnome_config_get_vector</emphasis> should also be freed with
1212<emphasis>g_free</emphasis>.
1213</para>
1214</sect3>
1215
1216<sect3>
1217<title>Writing Configuration Info</title>
1218
1219<para>
1220To write configuration info to files, the
1221<emphasis>gnome_config_set_*</emphasis> functions are used. The use is very
1222similar to above to the <emphasis>gnome_config_get_*</emphasis> functions. The
1223types used are exactly the same. Except with the "set" functions, you pass the
1224data you want to store after the path, and there is no default inside the path.
1225If the directory in the path doesn't exist it will get created when the
1226functions are written to disk. After you set all your data, you need to call
1227<emphasis>gnome_config_sync</emphasis> to actually write your data to file. The
1228library will not write the data to file immediately for efficiency reasons.
1229Example follows:
1230
1231<informalexample><programlisting>
1232char *text;
1233int counter;
1234...
1235/*after we have set text and counter to some values we can
1236  write them to our config location*/
1237gnome_config_set_int("/example/section/counter",counter);
1238gnome_config_set_string("/example/section/text",text);
1239gnome_config_sync();
1240</programlisting></informalexample></para></sect3>
1241
1242<sect3>
1243<title>Privacy Functions</title>
1244
1245<para>
1246If you want to store sensitive data, that other users should not read, use the
1247<emphasis>gnome_config_private_*</emphasis> functions, which have exactly the
1248same behavior as the above functions, with the exception of
1249<emphasis>gnome_config_sync</emphasis> (and a few others) which doesn't have a
1250private equivalent since it works for both. The difference is that these
1251functions write to a directory called <emphasis>~/.gnome_private</emphasis> on
1252which 0700 permissions are enforced. This is not extremely secure, but because
1253of the highly brain-dead US export restrictions, we can't really use
1254encryption.
1255</para>
1256</sect3>
1257
1258<sect3>
1259<title>Using gnome-config for Arbitrary Files</title>
1260
1261<para>
1262If you wish to use <emphasis>gnome-config</emphasis> for reading and writing of
1263arbitrary files on the file-system (as long as those files are in the
1264<emphasis>gnome-config</emphasis> format), you can just prepend
1265<emphasis>'='</emphasis> to the beginning of the path and another
1266<emphasis>'='</emphasis> to the end of the file name. Example follows:
1267
1268<informalexample><programlisting>
1269char buf[256];
1270...
1271/*write some bogus data to a temporary file*/
1272g_snprintf(buf,256,"=%s=/section/key",tmpnam(tmpnam));
1273gnome_config_set_int(buf,999);
1274gnome_config_sync();
1275</programlisting></informalexample>
1276Note that it doesn't really make sense to use the private versions when
1277using an arbitrary absolute path, as there will be absolutely no difference
1278between the two.</para></sect3>
1279
1280<sect3>
1281<title>Automatic Prefixes</title>
1282
1283<para>
1284Sometime, especially if you have a long path, would be much easier to say have
1285the config automatically prefix the path with a given string.  This is what
1286<emphasis>gnome_config_push_prefix</emphasis> and
1287<emphasis>gnome_config_pop_prefix</emphasis> are for. You pass the string you
1288want to prefix to <emphasis>gnome_config_push_prefix</emphasis> and call
1289<emphasis>gnome_config_pop_prefix</emphasis> when you are done. Note that these
1290functions are common between private and normal config functions. Example:
1291
1292<informalexample><programlisting>
1293gnome_config_push_prefix("/file/section/");
1294gnome_config_set_int("key1",1);
1295gnome_config_set_int("key2",2);
1296gnome_config_set_int("key3",-88);
1297gnome_config_pop_prefix();
1298</programlisting></informalexample></para></sect3>
1299
1300<sect3>
1301<title>Misc gnome-config Stuff</title>
1302
1303<para>
1304If you need to remove a file in your configuration file, you will use
1305<emphasis>gnome_config_clean_file</emphasis>. This function will schedule that
1306file to be deleted on the next <emphasis>gnome_config_sync</emphasis>. You can
1307do a <emphasis>gnome_config_clean_file</emphasis> and then use the file and
1308then do <emphasis>gnome_config_sync</emphasis>, and it will have the expected
1309behavior.
1310</para>
1311
1312<para>
1313If you have written to a file or read from a file and want
1314<emphasis>gnome-config</emphasis> to drop it from memory, use
1315<emphasis>gnome_config_drop_file</emphasis>. This is used if you want to forget
1316changes done to that file, or to simply conserve memory, since
1317<emphasis>gnome-config</emphasis> will otherwise keep a copy of the data in
1318memory for faster access.
1319</para>
1320</sect3>
1321</sect2>
1322
1323<sect2>
1324<title>.desktop Files</title>
1325
1326<para>
1327The <emphasis>.desktop</emphasis> files are the files that contain information about
1328programs. The files are in the <emphasis>gnome-config</emphasis> format and are internally
1329read using <emphasis>gnome-config</emphasis>. Your app definitely needs one of these
1330files installed in the system menu paths if it wants to be added to the menu.</para>
1331
1332<para>
1333You can use <emphasis>gnome_desktop_entry_*</emphasis> functions to manipulate these files.
1334These functions work with a structure called <emphasis>GnomeDesktopEntry</emphasis> and
1335you should look at the <emphasis>libgnome/gnome-dentry.h</emphasis> header file for the format
1336of this structure.</para>
1337
1338<para>
1339The basic functions that you use to manipulate these files are
1340<emphasis>gnome_desktop_entry_load</emphasis> which returns a newly allocated
1341<emphasis>GnomeDesktopEntry</emphasis> structure, <emphasis>gnome_desktop_entry_launch</emphasis>
1342which takes the <emphasis>GnomeDesktopEntry</emphasis> structure as an argument and
1343launches the program it describes and <emphasis>gnome_desktop_entry_free</emphasis>
1344which frees the allocated memory with the structure.</para>
1345
1346<para>
1347An example .desktop file for your app might look like:
1348
1349<informalexample><programlisting>
1350[Desktop Entry]
1351Name=Clock
1352Name[cz]=Hodiny
1353Comment=Digital Clock
1354Comment[cz]=Digitalni Hodiny
1355Exec=digital-clock
1356Icon=clock.png
1357Terminal=0
1358Type=Application
1359</programlisting></informalexample>
1360You will notice that there are translations for Name and Comment
1361fields in Czech. For gnome programs to notice your .desktop file,
1362it is usually located somewhere under <emphasis>&lt;prefix&gt;/share/apps/</emphasis>, which
1363contains the hierarchy of the system menus. For the system to find
1364your icon, your icon should be placed inside the
1365<emphasis>&lt;prefix&gt;/share/pixmaps</emphasis> directory. Note that the prefix refers
1366to the location where GNOME was installed.</para></sect2>
1367
1368<sect2>
1369<title>Utility and Files</title>
1370<sect3>
1371<title>Files</title>
1372
1373<para>
1374There is a standard way to find files that belong to gnome installation,
1375you shouldn't really be using your own logic to find them and you should
1376use these functions to get filenames for icons, sounds or other data.
1377Also these functions are only for finding files that were installed with
1378the GNOME libraries. There is not at this time functions to deal with
1379data installed by your application. The functions are:
1380
1381<table>
1382<title>
1383File finding functions
1384</title>
1385
1386<tgroup cols=2>
1387<thead>
1388<row>
1389<entry>Prototype</entry>
1390<entry>Description</entry>
1391</row>
1392</thead>
1393<tbody>
1394
1395<row><entry>char *gnome_libdir_file (const char *filename)</entry>
1396<entry>Get a full path of a file in the library directory or NULL if the file doesn't exist</entry></row>
1397<row><entry>char *gnome_unconditional_libdir_file (const char *filename)</entry>
1398<entry>Get a full path of a file in the library directory</entry></row>
1399
1400<row><entry>char *gnome_datadir_file (const char *filename)</entry>
1401<entry>Get a full path of a file in the data director or NULL if the file doesn't exist</entry></row>
1402<row><entry>char *gnome_unconditional_datadir_file (const char *filename)</entry>
1403<entry>Get a full path of a file in the data director</entry></row>
1404 
1405<row><entry>char *gnome_sound_file (const char *filename)</entry>
1406<entry>Get a full path of a file in the sound directory or NULL if the file doesn't exist</entry></row>
1407<row><entry>char *gnome_unconditional_sound_file (const char *filename)</entry>
1408<entry>Get a full path of a file in the sound directory</entry></row>
1409
1410<row><entry>char *gnome_pixmap_file (const char *filename)</entry>
1411<entry>Get a full path of a file in the pixmap directory or NULL if the file doesn't exist</entry></row>
1412<row><entry>char *gnome_unconditional_pixmap_file (const char *filename)</entry>
1413<entry>Get a full path of a file in the pixmap directory</entry></row>
1414
1415<row><entry>char *gnome_config_file (const char *filename)</entry>
1416<entry>Get a full path of a file in the config directory or NULL if the file doesn't exist</entry></row>
1417<row><entry>char *gnome_unconditional_config_file (const char *filename)</entry>
1418<entry>Get a full path of a file in the config directory</entry></row>
1419
1420</tbody>
1421</tgroup>
1422</table>
1423</para>
1424
1425<para>
1426These functions return a newly <emphasis>g_malloc</emphasis>ed string and you
1427should use <emphasis>g_free</emphasis> on the string when you are done. The
1428<emphasis>gnome_unconditional_*</emphasis> functions don't check if the file
1429actually exist and will just return a file name. The normal functions will
1430check and return <emphasis>NULL</emphasis> if the file doesn't exist. So you
1431shouldn't use those functions when you will do saving. As an example we want to
1432get a pixmap from the standard pixmap directory, for example we need to get the
1433"gnome-help.png" icon:
1434
1435<informalexample><programlisting>
1436char *name;
1437...
1438name = gnome_pixmap_file("gnome-help.png");
1439if(!name) {
1440        g_warning("gnome-help.png doesn't exist!");
1441} else {
1442        /*here we use the file*/
1443        ...
1444        g_free(name);
1445}
1446</programlisting></informalexample></para>
1447
1448<para>
1449Also of interest are the functions (actually macros)
1450<emphasis>gnome_util_home_file</emphasis> and
1451<emphasis>gnome_util_user_home</emphasis>.
1452<emphasis>gnome_util_home_file</emphasis> takes one argument (string) and
1453returns a newly allocated string with the home directory and .gnome prepended
1454to the file. So for example if you pass it say
1455<emphasis>someconfigfile</emphasis>, it would return
1456<emphasis>/home/jirka/.gnome/someconfigfile</emphasis>.  Similar is the
1457<emphasis>gnome_util_user_home</emphasis>, it takes one argument and returns
1458the file with just the home directory added. So if you pass it
1459<emphasis>.dotfile</emphasis>, it would return
1460<emphasis>/home/jirka/.dotfile</emphasis>.</para></sect3>
1461
1462<sect3>
1463<title>Utility</title>
1464
1465<para>
1466There are also a number of GLib like named functions to make your life easier,
1467of note would be <emphasis>g_file_exists</emphasis> which takes a filename and
1468returns <emphasis>TRUE</emphasis> if it exists or <emphasis>FALSE</emphasis> if
1469it doesn't, or <emphasis>g_concat_dir_and_file</emphasis> which takes a
1470directory name and a file name, and takes care of the <emphasis>'/'</emphasis>
1471issue, this is useful when working with strings where you don't want to check
1472for the '/', you just want to append a directory to some file, or another
1473directory. Note that you should <emphasis>g_free</emphasis> the string you get
1474as usual. For more utility functions, look into
1475<emphasis>libgnome/gnome-util.h</emphasis>, it is well
1476commented.
1477</para>
1478</sect3>
1479</sect2>
1480
1481<sect2>
1482<title>Mime Types</title>
1483
1484<para>
1485Sometimes it's useful to know the mime-type of a file. You can do this by using
1486the <emphasis>gnome_mime_type_or_default</emphasis> function, which takes two
1487arguments, the filename and a default mime-type string which it will return if
1488it can't figure out the mime type from the filename.  This call doesn't
1489actually look into the file, it tries to guess the type by looking at the
1490filename itself. Also the string it returns is a pointer to it's internal
1491database and you should not free it as that would likely result in a segfault
1492later on. You can also use <emphasis>gnome_mime_type</emphasis> which will
1493return NULL if it can't guess the mime-type.</para>
1494
1495<para>
1496It is also possible to work with URI lists, such as the ones used sometimes in
1497Drag and Drop. Usually from an URI list you want to extract a list of filenames
1498that you just received. For that you use the
1499<emphasis>gnome_uri_list_extract_filenames</emphasis> function, which takes the
1500URI list as a string argument, and returns a <emphasis>GList *</emphasis> of
1501newly allocated strings. Once you are done with the files, you should free the
1502strings and the list. You can use the utility routine
1503<emphasis>gnome_uri_list_free_strings</emphasis> to do this for you.
1504</para>
1505
1506<para>
1507In the following example I write a drag and drop handler
1508that takes the files and finds out their mime information, then you
1509could just write code that can do things based on the mime type
1510of the files.
1511
1512<informalexample><programlisting>
1513/*this is the handler for the drag_data_receive signal, assuming our
1514  widget only accepts the "text/uri-list" mime type of data, drag and
1515  drop is a more complicated topic and you should read up on GTK+
1516  documentation for better treatment*/
1517static void
1518dnd_drop_internal (GtkWidget        *widget,
1519                   GdkDragContext   *context,
1520                   gint              x,
1521                   gint              y,
1522                   GtkSelectionData *selection_data,
1523                   guint             info,
1524                   guint             time)
1525{
1526        GList *files, *li;
1527
1528        /*here we extract the filenames from the URI-list we received*/
1529        files = gnome_uri_list_extract_filenames(selection_data-&gt;data);
1530
1531        /*here we loop though the files and get their mime-type*/
1532        for(li = files; li!=NULL ; li = g_list_next(li)) {
1533                  char *mimetype;
1534                  char *filename = li-&gt;data;
1535
1536                  /*guess the mime type of the file*/
1537                  mimetype = gnome_mime_type(filename);
1538
1539                  /*if we can't guess it, just loop to the
1540                    next filename*/
1541                  if(!mimetype) continue;
1542
1543                  /*here comes code that can actually do something
1544                    based on the mime-type of the file we received*/
1545                  ...
1546        }
1547        /*free the list of files we got*/
1548        gnome_uri_list_free_strings (files);
1549}
1550</programlisting></informalexample>
1551Note how easy it is to find out what files you got, and what type
1552they are. You would just need to add some code instead of the three
1553dots that actually compares the mime strings you got to some you have
1554to figure out what you can do with the files.</para></sect2>
1555
1556<sect2>
1557<title>Meta Data</title>
1558
1559<para>
1560Sometimes it is useful to store some information along with a filename, this
1561can be done easily with the <emphasis>gnome-metadata</emphasis>. It is a set of
1562functions to manage this data. Since Unix doesn't natively support meta-data,
1563you have to help it yourself. For example if your app copies, renames or
1564deletes files, use the following functions.
1565
1566<table>
1567<title>
1568Metadata functions
1569</title>
1570
1571<tgroup cols=2>
1572<thead>
1573<row>
1574<entry>Prototype</entry>
1575<entry>Description</entry>
1576</row>
1577</thead>
1578<tbody>
1579
1580<row><entry>int gnome_metadata_rename (const char *from, const char *to)</entry>
1581<entry>Notify the metadata database that a file has been renamed</entry></row>
1582
1583<row><entry>int gnome_metadata_copy (const char *from, const char *to)</entry>
1584<entry>Notify the metadata database that a file has been copied</entry></row>
1585
1586<row><entry>int gnome_metadata_delete (const char *file)</entry>
1587<entry>Notify the metadata database that a file has been deleted</entry></row>
1588
1589<row><entry>int gnome_metadata_set (const char *file, const char *name, int size, const char *data)</entry>
1590<entry>Set data associated with the file 'file', and key 'name'. The data is
1591pointed to by 'data' and is 'size' bytes long. GNOME_METADATA_OK is returned on success.</entry></row>
1592
1593<row><entry>int gnome_metadata_get (const char *file, const char *name, int *size, char **buffer)</entry>
1594<entry>Get data associated with file 'file' and key 'name'. Data will be copied to a buffer and 'buffer' will be set to point to it, and 'size' will be set to the size of the buffer. GNOME_METADATA_OK is returned on success.</entry></row>
1595
1596<row><entry>char **gnome_metadata_list (const char *file)</entry>
1597<entry>Get a list of the keys for which there is some data set on 'file'. The list will be a newly allocated, NULL terminated string vector and should be freed with g_strfreev</entry></row>
1598
1599</tbody>
1600</tgroup>
1601</table>
1602
1603<table>
1604<title>
1605Metadata return values
1606</title>
1607
1608<tgroup cols=2>
1609<thead>
1610<row>
1611<entry>Name</entry>
1612<entry>Description</entry>
1613</row>
1614</thead>
1615<tbody>
1616
1617<row><entry>GNOME_METADATA_OK</entry><entry>No error (this is actually 0)</entry></row>
1618<row><entry>GNOME_METADATA_IO_ERROR</entry><entry>IO or other low-level communications/storage error.</entry></row>
1619<row><entry>GNOME_METADATA_NOT_FOUND</entry><entry>Information not found.</entry></row>
1620
1621</tbody>
1622</tgroup>
1623</table>
1624
1625
1626</para>
1627
1628<para>
1629These functions don't actually do the operations on the files, they just
1630change the meta-data accordingly. So if your app does any of these
1631operations, it is nicer towards other apps, that it notifies the
1632meta-data database of the changes. You shouldn't rely on the data
1633being stored. Only non-critical data should be stored in the
1634meta-data, since apps that do not notify the database with these
1635functions will make you loose your data for the file. These functions will
1636return 0 or <emphasis>GNOME_METADATA_OK</emphasis> if there was no error,
1637or an error-code (described above).</para>
1638
1639<para>
1640Now if you actually want to use the meta-data to store information about files,
1641you will most likely use the functions <emphasis>gnome_metadata_set</emphasis>,
1642<emphasis>gnome_metadata_remove</emphasis> and
1643<emphasis>gnome_metadata_get</emphasis>. Again these functions return an
1644integer, which is <emphasis>GNOME_METADATA_OK</emphasis> in case there was no
1645error, or they use the same error codes as the previous functions.</para>
1646
1647<para>
1648The functions work with a a key string for which they store a piece of data.
1649The data is represented by a size integer and a character pointer.
1650<emphasis>gnome_metadata_set</emphasis> takes the filename as the first
1651argument, the name or key of the data as the second argument, the size as the
1652third and the pointer to the actual data as the forth argument. This function
1653just sets that data for that file and key.
1654<emphasis>gnome_metadata_remove</emphasis> will clear a particular data item on
1655a file, so it takes a file and then the key name as the second argument.
1656<emphasis>gnome_metadata_get</emphasis> takes the filename as the first
1657argument and the key name as the second, then it returns data size though an
1658integer pointer you pass though the third argument and the actual data though a
1659pointer to a pointer you pass as the fourth argument. The data returned is
1660newly allocated and should be freed after use. Small example follows (in real
1661life you should also check the return of the functions for errors):
1662
1663<informalexample><programlisting>
1664int size;
1665char *data;
1666...
1667/*set some bogus data on a file*/
1668gnome_metadata_set("/some/file/name","bogus",5,"BLAH");
1669...
1670/*retrieve the data back*/
1671gnome_metadata_get("/some/file/name","bogus",&amp;size,&amp;data);
1672</programlisting></informalexample>
1673</para>
1674</sect2>
1675</sect1>
1676
1677<sect1 id="using-the-libgnomeui-library">
1678<title>Using the libgnomeui Library</title>
1679
1680<para>
1681The libgnomeui library is the library you'll be using most, it includes
1682the basic UI framework of your application and other X and GTK+ specific
1683things, such as session management, and many utility widgets. It also
1684contains the GnomeCanvas widget, which deserves separate treatment.
1685This is the library that makes the programmers life easy. With
1686plain GTK+ you have to do a lot of things by yourself, reinventing
1687the wheel every time, but this library takes care of the UI setup for
1688you and still allows the user to configure that behavior and have it
1689be consistent over different applications.</para>
1690
1691<sect2>
1692<title>GnomeApp Widget Basics</title>
1693<sect3>
1694<title>Overview</title>
1695
1696<para>
1697<emphasis>GnomeApp</emphasis> is the basic widget behind each app. It is the main window of
1698the application, containing the document being worked on and the applications
1699menus, tool-bars and status bars. It also remembers the docked positions
1700of menu bars and tool-bars and such for you so that the user gets the window
1701the way he left it when he left the application last time.</para></sect3>
1702
1703<sect3>
1704<title>Creating</title>
1705
1706<para>
1707Creating a new <emphasis>GnomeApp</emphasis> widget is as easy as calling
1708<emphasis>gnome_app_new</emphasis> with the application name, which is usually the name
1709of the executable or something else that is unique to your application and
1710the title of the main window. Then you create the content of the main window
1711and add it to the <emphasis>GnomeApp</emphasis> widget by calling <emphasis>gnome_app_set_contents</emphasis>
1712with your contents as the argument.</para>
1713
1714<para>
1715Adding menu-bars, tool-bars and status-bars is equally easy, you call
1716<emphasis>gnome_app_set_toolbar</emphasis>, <emphasis>gnome_app_set_menus</emphasis> or
1717<emphasis>gnome_app_set_statusbar</emphasis>. <emphasis>gnome_app_set_toolbar</emphasis> is for simple
1718applications that have only one tool-bar, for more complicated applications
1719you need to use <emphasis>gnome_app_add_toolbar</emphasis>, which allows you to add as
1720many docked tool-bars as you need.</para></sect3>
1721
1722<sect3>
1723<title>Menu and Tool-bar Creation</title>
1724
1725<sect4>
1726<title>Automatic Menu and Tool-bar Creation</title>
1727
1728<para>
1729Most of the time, you don't really want to create your menu-bars
1730and tool-bars by yourself. You can use functions from
1731<emphasis>libgnomeui/gnome-app-helper.h</emphasis> to construct menus and tool-bars for you.
1732All you need is to fill in a couple of structures with the your
1733information, and call <emphasis>gnome_app_create_menus</emphasis> or
1734<emphasis>gnome_app_create_toolbar</emphasis> with that structure and voila,
1735your application has menus and tool-bars. Sometimes you wish to pass
1736a data pointer to all the callbacks from those structures to work with,
1737then you'd use the <emphasis>gnome_app_create_toolbar_with_data</emphasis> and
1738<emphasis>gnome_app_create_menus_with_data</emphasis>, and pass an extra parameter which
1739will be passed in the data field of the callbacks.</para></sect4>
1740
1741
1742<sect4>
1743<title>GnomeUIInfo Structure Definition</title>
1744
1745<para>
1746Here is the definition of
1747the structure you need to fill (actually you fill in an array of
1748such structures). Also note I included the enums that you will need
1749to fill that structure.
1750
1751<informalexample><programlisting>
1752/* These values identify the type of pixmap used in an item */
1753typedef enum {
1754        GNOME_APP_PIXMAP_NONE,          /* No pixmap specified */
1755        GNOME_APP_PIXMAP_STOCK,         /* Use a stock pixmap
1756                                           (GnomeStock) */
1757        GNOME_APP_PIXMAP_DATA,          /* Use a pixmap from inline
1758                                           xpm data */
1759        GNOME_APP_PIXMAP_FILENAME       /* Use a pixmap from the
1760                                           specified filename */
1761} GnomeUIPixmapType;
1762
1763/* This is the structure that defines an item in a menu bar
1764 * or tool-bar.  The idea is to create an array of such
1765 * structures with the information needed to create menus or
1766 * tool-bars.  The most convenient way to create such a structure
1767 * is to use the GNOMEUIINFO_* macros provided below. */
1768typedef struct {
1769        GnomeUIInfoType type;           /* Type of item */
1770        gchar *label;                   /* String to use in the label */
1771        gchar *hint;                    /* For tool-bar items, the
1772                                           tool-tip. For menu items, the
1773                                           status bar message */
1774        gpointer moreinfo;              /* For an item, toggle-item, or
1775                                           radio-item, this is a pointer
1776                                           to the function to call when
1777                                           the item is activated. For
1778                                           a subtree, a pointer to
1779                                           another array of GnomeUIInfo
1780                                           structures. For a radio-item
1781                                           lead entry, a pointer to an
1782                                           array of GnomeUIInfo
1783                                           structures for the radio
1784                                           item group. For a help item,
1785                                           specifies the help node to
1786                                           load (i.e. the application's
1787                                           identifier) or NULL for the
1788                                           main program's name.  For
1789                                           builder data, points to the
1790                                           GnomeUIBuilderData structure
1791                                           for the following items */
1792        gpointer user_data;             /* Data pointer to pass to
1793                                           callbacks */
1794        gpointer unused_data;           /* Reserved for future expansion,
1795                                           should be NULL */
1796        GnomeUIPixmapType pixmap_type;  /* Type of pixmap for the item */
1797        gpointer pixmap_info;           /* Pointer to the pixmap
1798                                         * information:
1799                                         *
1800                                         * For GNOME_APP_PIXMAP_STOCK, a
1801                                         * pointer to the stock icon name.
1802                                         *
1803                                         * For GNOME_APP_PIXMAP_DATA, a
1804                                         * pointer to the inline xpm data.
1805                                         *
1806                                         * For GNOME_APP_PIXMAP_FILENAME, a
1807                                         * pointer to the filename string.
1808                                         */
1809        guint accelerator_key;          /* Accelerator key, or 0 for none */
1810        GdkModifierType ac_mods;        /* Mask of modifier keys for the
1811                                           accelerator */
1812
1813        GtkWidget *widget;              /* Filled in by gnome_app_create*,
1814                                           you can use this to tweak the
1815                                           widgets once they have been
1816                                           created */
1817} GnomeUIInfo;
1818</programlisting></informalexample>
1819Don't worry if you don't know all the items or what they mean. If you don't
1820know what it is, just leave it NULL or 0. Most of the time, it's easiest
1821to copy the menu's from another app and just modify them for your
1822needs, that way you will also know much better what does what then
1823by just looking at the structure.</para></sect4>
1824
1825<sect4>
1826<title>Helper Macros</title>
1827
1828<para>
1829Most of the time, menu entries are very simple, so one can just use one
1830of the simple macros provided. For example, for the end of a menu,
1831one would use the <emphasis>GNOMEUIINFO_END</emphasis> macro, for a separator one uses the
1832<emphasis>GNOMEUIINFO_SEPARATOR</emphasis> macro. Now for the actual items there
1833are also macros, which require you to fill in less info. For example
1834if you have an item that you provide an xpm format data for, you can
1835use the <emphasis>GNOMEUIINFO_ITEM(label, tooltip, callback, xpm_data)</emphasis>
1836macro, where label is the text of the label, tool-tip is the tool-tip
1837that the user gets when he goes over that item (or it can be <emphasis>NULL</emphasis>),
1838callback is the function that gets called when the user presses that item,
1839and the xpm_data is a pointer to an xpm data you want to use as the
1840icon. If you have no icon you can just use the
1841<emphasis>GNOMEUIINFO_ITEM_NONE(label, tooltip, callback)</emphasis> macro. If what you
1842are adding is a standard item for which there is a stock icon (we'll talk
1843about those next), you can use the
1844<emphasis>GNOMEUIINFO_ITEM_STOCK(label, tooltip, callback, stock_id)</emphasis> macro
1845where the stock_id is the id of the stock icon you want to use.
1846Then for your
1847main menu bar, or to put sub-menus inside your menus, you can use
1848<emphasis>GNOMEUIINFO_SUBTREE(label, tree)</emphasis> and
1849<emphasis>GNOMEUIINFO_SUBTREE_STOCK(label, tree, stock_id)</emphasis>, where the
1850tree is the array of <emphasis>GnomeUIInfo</emphasis> structures that you want to use as
1851that sub-menu. There are a few other macros, but most of the time you will
1852get by with just these macros, so you don't need to learn the entire
1853structure of the <emphasis>GnomeUIInfo</emphasis>.
1854</para></sect4>
1855
1856<sect4>
1857<title>Standard Menu Item Macros</title>
1858
1859<para>
1860Just about all application contain a couple of standard menu items, so to
1861keep things more consistent there are a bunch of macros that fill in
1862everything for you except for the callback function and the data. The
1863advantage of using the macros is consistency across applications, user
1864customization, and translation.</para>
1865
1866<sect5>
1867<title>Menu Items</title>
1868
1869<para>
1870Most of these macros have the form:
1871<emphasis>GNOMEUIINFO_MENU_&lt;name&gt;_ITEM (callback, data)</emphasis>.
1872However, there is an exception, the "New xxx" item. The GNOME style guide
1873Requires that you put what the "New" thing is into the item name. Not to
1874mention that it will have a different hint as well. So the "New xxx" item
1875has the structure of:
1876<emphasis>GNOMEUIINFO_MENU_NEW_ITEM(label, hint, callback, data)</emphasis>.
1877The "label" should start with "New ". Also note that if you have more new
1878items, you need to use the "New" subtree macro, which is explained later.
1879</para>
1880
1881<para>
1882<variablelist>
1883<title>the File menu</title>
1884<varlistentry>
1885<term>GNOMEUIINFO_MENU_NEW_ITEM(label, hint, cb, data)</term>
1886<listitem><para>"New" menu item (you need to provide label and hint
1887yourself here)</para></listitem></varlistentry>
1888<varlistentry>
1889<term>GNOMEUIINFO_MENU_OPEN_ITEM(cb, data)</term>
1890<listitem><para>"Open" menu item</para></listitem></varlistentry>
1891<varlistentry>
1892<term>GNOMEUIINFO_MENU_SAVE_ITEM(cb, data)</term>
1893<listitem><para>"Save" menu item</para></listitem></varlistentry>
1894<varlistentry>
1895<term>GNOMEUIINFO_MENU_SAVE_AS_ITEM(cb, data)</term>
1896<listitem><para>"Save as..." menu item</para></listitem></varlistentry>
1897<varlistentry>
1898<term>GNOMEUIINFO_MENU_REVERT_ITEM(cb, data)</term>
1899<listitem><para>"Revert" menu item</para></listitem></varlistentry>
1900<varlistentry>
1901<term>GNOMEUIINFO_MENU_PRINT_ITEM(cb, data)</term>
1902<listitem><para>"Print" menu item</para></listitem></varlistentry>
1903<varlistentry>
1904<term>GNOMEUIINFO_MENU_PRINT_SETUP_ITEM(cb, data)</term>
1905<listitem><para>"Print Setup" menu item</para></listitem></varlistentry>
1906<varlistentry>
1907<term>GNOMEUIINFO_MENU_CLOSE_ITEM(cb, data)</term>
1908<listitem><para>"Close" menu item</para></listitem></varlistentry>
1909<varlistentry>
1910<term>GNOMEUIINFO_MENU_EXIT_ITEM(cb, data)</term>
1911<listitem><para>"Exit" menu item</para></listitem></varlistentry>
1912</variablelist></para>
1913
1914
1915<para>
1916<variablelist>
1917<title>the Edit menu</title>
1918<varlistentry>
1919<term>GNOMEUIINFO_MENU_CUT_ITEM(cb, data)</term>
1920<listitem><para>"Cut" menu item</para></listitem></varlistentry>
1921<varlistentry>
1922<term>GNOMEUIINFO_MENU_COPY_ITEM(cb, data)</term>
1923<listitem><para>"Copy" menu item</para></listitem></varlistentry>
1924<varlistentry>
1925<term>GNOMEUIINFO_MENU_PASTE_ITEM(cb, data)</term>
1926<listitem><para>"Paste" menu item</para></listitem></varlistentry>
1927<varlistentry>
1928<term>GNOMEUIINFO_MENU_SELECT_ALL_ITEM(cb, data)</term>
1929<listitem><para>"Select" menu item</para></listitem></varlistentry>
1930<varlistentry>
1931<term>GNOMEUIINFO_MENU_CLEAR_ITEM(cb, data)</term>
1932<listitem><para>"Clear" menu item</para></listitem></varlistentry>
1933<varlistentry>
1934<term>GNOMEUIINFO_MENU_UNDO_ITEM(cb, data)</term>
1935<listitem><para>"Undo" menu item</para></listitem></varlistentry>
1936<varlistentry>
1937<term>GNOMEUIINFO_MENU_REDO_ITEM(cb, data)</term>
1938<listitem><para>"Redo" menu item</para></listitem></varlistentry>
1939<varlistentry>
1940<term>GNOMEUIINFO_MENU_FIND_ITEM(cb, data)</term>
1941<listitem><para>"Find" menu item</para></listitem></varlistentry>
1942<varlistentry>
1943<term>GNOMEUIINFO_MENU_FIND_AGAIN_ITEM(cb, data)</term>
1944<listitem><para>"Find Again" menu item</para></listitem></varlistentry>
1945<varlistentry>
1946<term>GNOMEUIINFO_MENU_REPLACE_ITEM(cb, data)</term>
1947<listitem><para>"Replace" menu item</para></listitem></varlistentry>
1948<varlistentry>
1949<term>GNOMEUIINFO_MENU_PROPERTIES_ITEM(cb, data)</term>
1950<listitem><para>"Properties" menu item</para></listitem></varlistentry>
1951</variablelist></para>
1952
1953<para>
1954<variablelist>
1955<title>the Settings menu</title>
1956<varlistentry>
1957<term>GNOMEUIINFO_MENU_PREFERENCES_ITEM(cb, data)</term>
1958<listitem><para>"Preferences" menu item</para></listitem></varlistentry>
1959</variablelist></para>
1960
1961<para>
1962<variablelist>
1963<title>the Windows menu</title>
1964<varlistentry>
1965<term>GNOMEUIINFO_MENU_NEW_WINDOW_ITEM(cb, data)</term>
1966<listitem><para>"New window" menu item</para></listitem></varlistentry>
1967<varlistentry>
1968<term>GNOMEUIINFO_MENU_CLOSE_WINDOW_ITEM(cb, data)</term>
1969<listitem><para>"Close window" menu item</para></listitem></varlistentry>
1970</variablelist></para>
1971
1972<para>
1973<variablelist>
1974<title>the Help menu</title>
1975<varlistentry>
1976<term>GNOMEUIINFO_MENU_ABOUT_ITEM(cb, data)</term>
1977<listitem><para>"About" menu item</para></listitem></varlistentry>
1978</variablelist></para>
1979
1980<para>
1981<variablelist>
1982<title>the Game menu</title>
1983<varlistentry>
1984<term>GNOMEUIINFO_MENU_NEW_GAME_ITEM(cb, data)</term>
1985<listitem><para>"New game" menu item</para></listitem></varlistentry>
1986<varlistentry>
1987<term>GNOMEUIINFO_MENU_PAUSE_GAME_ITEM(cb, data)</term>
1988<listitem><para>"Pause game" menu item</para></listitem></varlistentry>
1989<varlistentry>
1990<term>GNOMEUIINFO_MENU_RESTART_GAME_ITEM(cb, data)</term>
1991<listitem><para>"Restart game" menu item</para></listitem></varlistentry>
1992<varlistentry>
1993<term>GNOMEUIINFO_MENU_UNDO_MOVE_ITEM(cb, data)</term>
1994<listitem><para>"Undo move" menu item</para></listitem></varlistentry>
1995<varlistentry>
1996<term>GNOMEUIINFO_MENU_REDO_MOVE_ITEM(cb, data)</term>
1997<listitem><para>"Redo move" menu item</para></listitem></varlistentry>
1998<varlistentry>
1999<term>GNOMEUIINFO_MENU_HINT_ITEM(cb, data)</term>
2000<listitem><para>"Hint" menu item</para></listitem></varlistentry>
2001<varlistentry>
2002<term>GNOMEUIINFO_MENU_SCORES_ITEM(cb, data)</term>
2003<listitem><para>"Scores" menu item</para></listitem></varlistentry>
2004<varlistentry>
2005<term>GNOMEUIINFO_MENU_END_GAME_ITEM(cb, data)</term>
2006<listitem><para>"End game" menu item</para></listitem></varlistentry>
2007</variablelist></para></sect5>
2008
2009<sect5>
2010<title>Menu trees and subtrees</title>
2011
2012<para>
2013We have already mentioned a "New" subtree. For this you should use the
2014<emphasis>GNOMEUIINFO_MENU_NEW_SUBTREE (tree)</emphasis> macro, where
2015the tree argument is another GnomeUIInfo structure array of the different
2016new items.</para>
2017
2018<para>
2019There are also the standard top level menus. Again you pass the array of
2020GnomeUIInfo structures to the macro.
2021
2022<variablelist>
2023<varlistentry>
2024<term>GNOMEUIINFO_MENU_FILE_TREE (tree)</term>
2025<listitem><para>"File" menu</para></listitem></varlistentry>
2026<varlistentry>
2027<term>GNOMEUIINFO_MENU_EDIT_TREE (tree)</term>
2028<listitem><para>"Edit" menu</para></listitem></varlistentry>
2029<varlistentry>
2030<term>GNOMEUIINFO_MENU_VIEW_TREE (tree)</term>
2031<listitem><para>"View" menu</para></listitem></varlistentry>
2032<varlistentry>
2033<term>GNOMEUIINFO_MENU_SETTINGS_TREE (tree)</term>
2034<listitem><para>"Settings" menu</para></listitem></varlistentry>
2035<varlistentry>
2036<term>GNOMEUIINFO_MENU_FILES_TREE (tree)</term>
2037<listitem><para>"Files" menu</para></listitem></varlistentry>
2038<varlistentry>
2039<term>GNOMEUIINFO_MENU_WINDOWS_TREE (tree)</term>
2040<listitem><para>"Windows" menu</para></listitem></varlistentry>
2041<varlistentry>
2042<term>GNOMEUIINFO_MENU_HELP_TREE (tree)</term>
2043<listitem><para>"Help" menu</para></listitem></varlistentry>
2044<varlistentry>
2045<term>GNOMEUIINFO_MENU_GAME_TREE (tree)</term>
2046<listitem><para>"Game" menu</para></listitem></varlistentry>
2047</variablelist></para>
2048
2049<para>
2050Sometimes you may want to refer to menu path of these menus, such as
2051for adding items to a "Windows" menu. For this you should use the macros
2052of the form <emphasis>GNOME_MENU_&lt;name&gt;_STRING</emphasis> and
2053<emphasis>GNOME_MENU_&lt;name&gt;_PATH</emphasis>. These will expand to the
2054appropriate string. The macro ending with <emphasis>_STRING</emphasis>
2055will expand to just the menu name, and the macro ending with
2056<emphasis>_PATH</emphasis> to the menu name followed by a "/". The
2057&lt;name&gt; can be one of the following: FILE, EDIT, VIEW, SETTINGS,
2058NEW, FILES or WINDOWS.
2059</para></sect5></sect4>
2060
2061<sect4>
2062<title>Help menu</title>
2063
2064<para>
2065Your application should contain a help menu, the help menu can be defined
2066as:
2067
2068<informalexample><programlisting>
2069     GNOMEUIINFO_HELP("app_name"),
2070     GNOMEUIINFO_MENU_ABOUT_ITEM(callback, data),
2071     GNOMEUIINFO_END
2072</programlisting></informalexample>
2073
2074The GNOMEUIINFO_HELP macro takes the name of your application and expects
2075the help files to be installed as per normal gnome procedures.
2076<emphasis>FixMe: we need to add some section on help files and stuff
2077</emphasis>
2078</para>
2079</sect4>
2080
2081<sect4>
2082<title>Example</title>
2083
2084<para>
2085Here is a very simple application that makes use of these:
2086
2087<informalexample><programlisting>
2088/*
2089 * A simple Gnome program, outside of GNOME tree, not using i18n
2090 * uiinfo.c
2091 */
2092/* the very basic gnome include */
2093#include &lt;gnome.h&gt;
2094
2095/* a callback for the buttons */
2096static void
2097a_callback(GtkWidget *button, gpointer data)
2098{
2099        /*just print a string so that we know we got there*/
2100        g_print("Inside Callback\n");
2101}
2102
2103GnomeUIInfo file_menu[] = {
2104        GNOMEUIINFO_MENU_EXIT_ITEM(gtk_main_quit,NULL),
2105        GNOMEUIINFO_END
2106};
2107
2108GnomeUIInfo some_menu[] = {
2109        GNOMEUIINFO_ITEM_NONE("_Menuitem","Just a menuitem",
2110                              a_callback),
2111        GNOMEUIINFO_SEPARATOR,
2112        GNOMEUIINFO_ITEM_NONE("M_enuitem2","Just a menuitem",
2113                              a_callback),
2114        GNOMEUIINFO_END
2115};
2116
2117GnomeUIInfo menubar[] = {
2118        GNOMEUIINFO_MENU_FILE_TREE(file_menu),
2119        GNOMEUIINFO_SUBTREE("_Some menu",some_menu),
2120        GNOMEUIINFO_END
2121};
2122
2123GnomeUIInfo toolbar[] = {
2124        GNOMEUIINFO_ITEM_STOCK("Exit","Exit the application",
2125                               gtk_main_quit,
2126                               GNOME_STOCK_PIXMAP_EXIT),
2127        GNOMEUIINFO_END
2128};
2129
2130int
2131main(int argc, char *argv[])
2132{
2133        GtkWidget *app;
2134        GtkWidget *button;
2135        GtkWidget *hbox;
2136        GtkWidget *label;
2137
2138        /* Initialize GNOME, this is very similar to gtk_init */
2139        gnome_init ("menu-basic-example", "0.1", argc, argv);
2140       
2141        /* Create a Gnome app widget, which sets up a basic
2142           window for your application */
2143        app = gnome_app_new ("menu-basic-example",
2144                             "Basic GNOME Application");
2145
2146        /* bind "delete_event", which is the event we get when
2147           the user closes the window with the window manager,
2148           to gtk_main_quit, which is a function that causes
2149           the gtk_main loop to exit, and consequently to quit
2150           the application */
2151        gtk_signal_connect (GTK_OBJECT (app), "delete_event",
2152                            GTK_SIGNAL_FUNC (gtk_main_quit),
2153                            NULL);
2154
2155        /*make a label as the contents*/
2156        label = gtk_label_new("BLAH BLAH BLAH BLAH BLAH");
2157
2158        /*add the label as contents of the window*/
2159        gnome_app_set_contents (GNOME_APP (app), label);
2160
2161        /*create the menus for the application*/
2162        gnome_app_create_menus (GNOME_APP (app), menubar);
2163
2164        /*create the tool-bar for the application*/
2165        gnome_app_create_toolbar (GNOME_APP (app), toolbar);
2166
2167        /* show everything inside this app widget and the app
2168           widget itself */
2169        gtk_widget_show_all(app);
2170       
2171        /* enter the main loop */
2172        gtk_main ();
2173       
2174        return 0;
2175}
2176</programlisting></informalexample>
2177Voila, an application with a menu and a tool-bar. As you see, adding
2178extra menu items is just adding extra definitions to the GnomeUIInfo
2179structure array.</para></sect4></sect3>
2180
2181<sect3>
2182<title>Accelerator keys</title>
2183
2184<para>
2185You have probably noticed the underlines in the labels for the menu items,
2186these specify the accelerators for that menu. That's really all you need
2187to do to add accelerators for menu items. The way accelerators work
2188is very similar to the other windowing systems out there, <emphasis>alt-&lt;key&gt;</emphasis>
2189if you are not browsing the menus or just the <emphasis>&lt;key&gt;</emphasis> if you have the
2190menu open.</para></sect3></sect2>
2191
2192<sect2>
2193<title>Stock Icons</title>
2194
2195<para>
2196Since most of the time you will want to use standard buttons and menu items
2197(such as <emphasis>Open</emphasis> or <emphasis>Save as...</emphasis>), and you want to provide icons
2198with the menu items or tool-bar buttons or just dialog buttons, to make
2199it easier to navigate, you can use some of the predefined icons from
2200<emphasis>gnome-libs</emphasis>. These are called <emphasis>Stock Icons</emphasis>. You have already
2201seen an example of how to use stock menu icons and regular stock icons
2202in menus and tool-bars (you just use the proper define from
2203<emphasis>libgnomeui/gnome-stock.h</emphasis>). There are also stock buttons, where
2204you can get back a button widget based on a stock description.</para>
2205
2206<para>
2207Here is a list of the <emphasis>normal</emphasis> gnome stock icons, these are regular
2208sized for use in tool-bars and other places where you need a normal sized
2209icon. They are given as defines of string constants and their meaning
2210should be obvious.
2211
2212<informalexample><programlisting>
2213#define GNOME_STOCK_PIXMAP_NEW         "New"
2214#define GNOME_STOCK_PIXMAP_OPEN        "Open"
2215#define GNOME_STOCK_PIXMAP_CLOSE       "Close"
2216#define GNOME_STOCK_PIXMAP_REVERT      "Revert"
2217#define GNOME_STOCK_PIXMAP_SAVE        "Save"
2218#define GNOME_STOCK_PIXMAP_SAVE_AS     "Save As"
2219#define GNOME_STOCK_PIXMAP_CUT         "Cut"
2220#define GNOME_STOCK_PIXMAP_COPY        "Copy"
2221#define GNOME_STOCK_PIXMAP_PASTE       "Paste"
2222#define GNOME_STOCK_PIXMAP_PROPERTIES  "Properties"
2223#define GNOME_STOCK_PIXMAP_PREFERENCES "Preferences"
2224#define GNOME_STOCK_PIXMAP_HELP        "Help"
2225#define GNOME_STOCK_PIXMAP_SCORES      "Scores"
2226#define GNOME_STOCK_PIXMAP_PRINT       "Print"
2227#define GNOME_STOCK_PIXMAP_SEARCH      "Search"
2228#define GNOME_STOCK_PIXMAP_SRCHRPL     "Search/Replace"
2229#define GNOME_STOCK_PIXMAP_BACK        "Back"
2230#define GNOME_STOCK_PIXMAP_FORWARD     "Forward"
2231#define GNOME_STOCK_PIXMAP_FIRST       "First"
2232#define GNOME_STOCK_PIXMAP_LAST        "Last"
2233#define GNOME_STOCK_PIXMAP_HOME        "Home"
2234#define GNOME_STOCK_PIXMAP_STOP        "Stop"
2235#define GNOME_STOCK_PIXMAP_REFRESH     "Refresh"
2236#define GNOME_STOCK_PIXMAP_UNDO        "Undo"
2237#define GNOME_STOCK_PIXMAP_REDO        "Redo"
2238#define GNOME_STOCK_PIXMAP_TIMER       "Timer"
2239#define GNOME_STOCK_PIXMAP_TIMER_STOP  "Timer Stopped"
2240#define GNOME_STOCK_PIXMAP_MAIL        "Mail"
2241#define GNOME_STOCK_PIXMAP_MAIL_RCV    "Receive Mail"
2242#define GNOME_STOCK_PIXMAP_MAIL_SND    "Send Mail"
2243#define GNOME_STOCK_PIXMAP_MAIL_RPL    "Reply to Mail"
2244#define GNOME_STOCK_PIXMAP_MAIL_FWD    "Forward Mail"
2245#define GNOME_STOCK_PIXMAP_MAIL_NEW    "New Mail"
2246#define GNOME_STOCK_PIXMAP_TRASH       "Trash"
2247#define GNOME_STOCK_PIXMAP_TRASH_FULL  "Trash Full"
2248#define GNOME_STOCK_PIXMAP_UNDELETE    "Undelete"
2249#define GNOME_STOCK_PIXMAP_SPELLCHECK  "Spellchecker"
2250#define GNOME_STOCK_PIXMAP_MIC         "Microphone"
2251#define GNOME_STOCK_PIXMAP_LINE_IN     "Line In"
2252#define GNOME_STOCK_PIXMAP_CDROM       "Cdrom"
2253#define GNOME_STOCK_PIXMAP_VOLUME      "Volume"
2254#define GNOME_STOCK_PIXMAP_BOOK_RED    "Book Red"
2255#define GNOME_STOCK_PIXMAP_BOOK_GREEN  "Book Green"
2256#define GNOME_STOCK_PIXMAP_BOOK_BLUE   "Book Blue"
2257#define GNOME_STOCK_PIXMAP_BOOK_YELLOW "Book Yellow"
2258#define GNOME_STOCK_PIXMAP_BOOK_OPEN   "Book Open"
2259#define GNOME_STOCK_PIXMAP_ABOUT       "About"
2260#define GNOME_STOCK_PIXMAP_QUIT        "Quit"
2261#define GNOME_STOCK_PIXMAP_MULTIPLE    "Multiple"
2262#define GNOME_STOCK_PIXMAP_NOT         "Not"
2263#define GNOME_STOCK_PIXMAP_CONVERT     "Convert"
2264#define GNOME_STOCK_PIXMAP_JUMP_TO     "Jump To"
2265#define GNOME_STOCK_PIXMAP_UP          "Up"
2266#define GNOME_STOCK_PIXMAP_DOWN        "Down"
2267#define GNOME_STOCK_PIXMAP_TOP         "Top"
2268#define GNOME_STOCK_PIXMAP_BOTTOM      "Bottom"
2269#define GNOME_STOCK_PIXMAP_ATTACH      "Attach"
2270#define GNOME_STOCK_PIXMAP_INDEX       "Index"
2271#define GNOME_STOCK_PIXMAP_FONT        "Font"
2272#define GNOME_STOCK_PIXMAP_EXEC        "Exec"
2273
2274#define GNOME_STOCK_PIXMAP_ALIGN_LEFT  "Left"
2275#define GNOME_STOCK_PIXMAP_ALIGN_RIGHT "Right"
2276#define GNOME_STOCK_PIXMAP_ALIGN_CENTER "Center"
2277#define GNOME_STOCK_PIXMAP_ALIGN_JUSTIFY "Justify"
2278
2279#define GNOME_STOCK_PIXMAP_TEXT_BOLD    "Bold"
2280#define GNOME_STOCK_PIXMAP_TEXT_ITALIC  "Italic"
2281#define GNOME_STOCK_PIXMAP_TEXT_UNDERLINE "Underline"
2282#define GNOME_STOCK_PIXMAP_TEXT_STRIKEOUT "Strikeout"
2283
2284#define GNOME_STOCK_PIXMAP_EXIT        GNOME_STOCK_PIXMAP_QUIT
2285</programlisting></informalexample>
2286If you need to use these outside of <emphasis>GnomeUIInfo</emphasis>, you need
2287to get the widget with the pixmap. What you do is you call the
2288<emphasis>gnome_stock_pixmap_widget</emphasis> function with your main window
2289as the first argument (so that it can copy it's style) and
2290the icon name (one of the above defines) as the second argument.
2291It returns a new widget which you can just use as a pixmap.</para>
2292
2293<para>
2294For menus you want to use the <emphasis>_MENU_</emphasis> variety of the stock
2295pixmaps. These are smaller and these should be the ones you use
2296for the stock menu items in your <emphasis>GnomeUIInfo</emphasis> definitions.
2297
2298<informalexample><programlisting>
2299#define GNOME_STOCK_MENU_BLANK        "Menu_"
2300#define GNOME_STOCK_MENU_NEW          "Menu_New"
2301#define GNOME_STOCK_MENU_SAVE         "Menu_Save"
2302#define GNOME_STOCK_MENU_SAVE_AS      "Menu_Save As"
2303#define GNOME_STOCK_MENU_REVERT       "Menu_Revert"
2304#define GNOME_STOCK_MENU_OPEN         "Menu_Open"
2305#define GNOME_STOCK_MENU_CLOSE        "Menu_Close"
2306#define GNOME_STOCK_MENU_QUIT         "Menu_Quit"
2307#define GNOME_STOCK_MENU_CUT          "Menu_Cut"
2308#define GNOME_STOCK_MENU_COPY         "Menu_Copy"
2309#define GNOME_STOCK_MENU_PASTE        "Menu_Paste"
2310#define GNOME_STOCK_MENU_PROP         "Menu_Properties"
2311#define GNOME_STOCK_MENU_PREF         "Menu_Preferences"
2312#define GNOME_STOCK_MENU_ABOUT        "Menu_About"
2313#define GNOME_STOCK_MENU_SCORES       "Menu_Scores"
2314#define GNOME_STOCK_MENU_UNDO         "Menu_Undo"
2315#define GNOME_STOCK_MENU_REDO         "Menu_Redo"
2316#define GNOME_STOCK_MENU_PRINT        "Menu_Print"
2317#define GNOME_STOCK_MENU_SEARCH       "Menu_Search"
2318#define GNOME_STOCK_MENU_SRCHRPL      "Menu_Search/Replace"
2319#define GNOME_STOCK_MENU_BACK         "Menu_Back"
2320#define GNOME_STOCK_MENU_FORWARD      "Menu_Forward"
2321#define GNOME_STOCK_MENU_FIRST        "Menu_First"
2322#define GNOME_STOCK_MENU_LAST         "Menu_Last"
2323#define GNOME_STOCK_MENU_HOME         "Menu_Home"
2324#define GNOME_STOCK_MENU_STOP         "Menu_Stop"
2325#define GNOME_STOCK_MENU_REFRESH      "Menu_Refresh"
2326#define GNOME_STOCK_MENU_MAIL         "Menu_Mail"
2327#define GNOME_STOCK_MENU_MAIL_RCV     "Menu_Receive Mail"
2328#define GNOME_STOCK_MENU_MAIL_SND     "Menu_Send Mail"
2329#define GNOME_STOCK_MENU_MAIL_RPL     "Menu_Reply to Mail"
2330#define GNOME_STOCK_MENU_MAIL_FWD     "Menu_Forward Mail"
2331#define GNOME_STOCK_MENU_MAIL_NEW     "Menu_New Mail"
2332#define GNOME_STOCK_MENU_TRASH        "Menu_Trash"
2333#define GNOME_STOCK_MENU_TRASH_FULL   "Menu_Trash Full"
2334#define GNOME_STOCK_MENU_UNDELETE     "Menu_Undelete"
2335#define GNOME_STOCK_MENU_TIMER        "Menu_Timer"
2336#define GNOME_STOCK_MENU_TIMER_STOP   "Menu_Timer Stopped"
2337#define GNOME_STOCK_MENU_SPELLCHECK   "Menu_Spellchecker"
2338#define GNOME_STOCK_MENU_MIC          "Menu_Microphone"
2339#define GNOME_STOCK_MENU_LINE_IN      "Menu_Line In"
2340#define GNOME_STOCK_MENU_CDROM        "Menu_Cdrom"
2341#define GNOME_STOCK_MENU_VOLUME       "Menu_Volume"
2342#define GNOME_STOCK_MENU_BOOK_RED     "Menu_Book Red"
2343#define GNOME_STOCK_MENU_BOOK_GREEN   "Menu_Book Green"
2344#define GNOME_STOCK_MENU_BOOK_BLUE    "Menu_Book Blue"
2345#define GNOME_STOCK_MENU_BOOK_YELLOW  "Menu_Book Yellow"
2346#define GNOME_STOCK_MENU_BOOK_OPEN    "Menu_Book Open"
2347#define GNOME_STOCK_MENU_CONVERT      "Menu_Convert"
2348#define GNOME_STOCK_MENU_JUMP_TO      "Menu_Jump To"
2349#define GNOME_STOCK_MENU_UP           "Menu_Up"
2350#define GNOME_STOCK_MENU_DOWN         "Menu_Down"
2351#define GNOME_STOCK_MENU_TOP          "Menu_Top"
2352#define GNOME_STOCK_MENU_BOTTOM       "Menu_Bottom"
2353#define GNOME_STOCK_MENU_ATTACH       "Menu_Attach"
2354#define GNOME_STOCK_MENU_INDEX        "Menu_Index"
2355#define GNOME_STOCK_MENU_FONT         "Menu_Font"
2356#define GNOME_STOCK_MENU_EXEC         "Menu_Exec"
2357
2358#define GNOME_STOCK_MENU_ALIGN_LEFT     "Menu_Left"
2359#define GNOME_STOCK_MENU_ALIGN_RIGHT    "Menu_Right"
2360#define GNOME_STOCK_MENU_ALIGN_CENTER   "Menu_Center"
2361#define GNOME_STOCK_MENU_ALIGN_JUSTIFY  "Menu_Justify"
2362
2363#define GNOME_STOCK_MENU_TEXT_BOLD      "Menu_Bold"
2364#define GNOME_STOCK_MENU_TEXT_ITALIC    "Menu_Italic"
2365#define GNOME_STOCK_MENU_TEXT_UNDERLINE "Menu_Underline"
2366#define GNOME_STOCK_MENU_TEXT_STRIKEOUT "Menu_Strikeout"
2367
2368#define GNOME_STOCK_MENU_EXIT     GNOME_STOCK_MENU_QUIT
2369</programlisting></informalexample>
2370If you are building the menu yourself and just want to get a menu-item
2371that's built with the stock icon and a label, you can use the
2372<emphasis>gnome_stock_menu_item</emphasis> convenience routine. It takes the stock
2373icon type (one of the defines above) as the first argument, and the menu
2374text as the second argument, and it returns a newly created menu-item
2375widget.</para>
2376
2377<para>
2378Then there are stock buttons. These are for use in your dialogs (see the next
2379section).
2380
2381<informalexample><programlisting>
2382#define GNOME_STOCK_BUTTON_OK     "Button_Ok"
2383#define GNOME_STOCK_BUTTON_CANCEL "Button_Cancel"
2384#define GNOME_STOCK_BUTTON_YES    "Button_Yes"
2385#define GNOME_STOCK_BUTTON_NO     "Button_No"
2386#define GNOME_STOCK_BUTTON_CLOSE  "Button_Close"
2387#define GNOME_STOCK_BUTTON_APPLY  "Button_Apply"
2388#define GNOME_STOCK_BUTTON_HELP   "Button_Help"
2389#define GNOME_STOCK_BUTTON_NEXT   "Button_Next"
2390#define GNOME_STOCK_BUTTON_PREV   "Button_Prev"
2391#define GNOME_STOCK_BUTTON_UP     "Button_Up"
2392#define GNOME_STOCK_BUTTON_DOWN   "Button_Down"
2393#define GNOME_STOCK_BUTTON_FONT   "Button_Font"
2394</programlisting></informalexample>
2395To get a button widget with the stock icon and text, you can just use the
2396function <emphasis>gnome_stock_button</emphasis> with the button type (one of the above
2397defines) as the argument. Now sometimes you want to create a mixture of
2398stock or ordinary buttons, what you can do is call the
2399<emphasis>gnome_stock_or_ordinary_button</emphasis> function with either the type of
2400a stock button or just a text for the button label. The function checks
2401if it is one of the above strings, and if it's not it creates an
2402ordinary button widget with the text as the label.</para></sect2>
2403
2404<sect2>
2405<title>Dialogs</title>
2406<sect3 id="testtest">
2407<title>Generic Dialogs</title>
2408
2409<para>
2410If you need to create you own custom dialog, <emphasis>gnome-dialog</emphasis> is the
2411way to do it. It can handle both modal and non-modal dialogs, although,
2412it's definitely much more friendly to the users of your program if
2413you use a non-modal dialog box, if at all possible, although non-modal
2414dialog boxes tend to have problems associated with them, and sometimes
2415can cause strange bugs, for example if a non-modal dialog box is associated
2416with a window, you'd better bind the <emphasis>destroy</emphasis> signal of the window
2417and set it to destroy the dialog box as well, since otherwise it could
2418hang around even though the window or document it was supposed to act on
2419is already dead. However modal dialogs (while definitely easier to program)
2420are usually pretty annoying to use, so avoid them if you at all can.</para>
2421
2422<para>
2423To make a new <emphasis>GnomeDialog</emphasis> widget, just use the <emphasis>gnome_dialog_new</emphasis>
2424function. You pass the title of the dialog as the first argument, and then
2425multiple arguments as the button titles terminated by a NULL. The button
2426titles can also be the <emphasis>GNOME_STOCK_BUTTON_*</emphasis> definitions if you want
2427stock buttons on your dialog. Then you need to add content to the dialog,
2428the dialog is created with a vertical box (<emphasis>GtkVBox</emphasis>) for you to use,
2429just by using <emphasis>GNOME_DIALOG(dialog)-&gt;vbox</emphasis>. Into that you add your
2430content. At this point you have to decide if you want to do a modal dialog
2431or a non-modal dialog.</para>
2432
2433<para>
2434In case you want to do a modal dialog, all you need to do is to call
2435<emphasis>gnome_dialog_run_and_close</emphasis> function and it will run the dialog,
2436wait for a user to press a button or close the dialog, and then close
2437the dialog. This function will return the number of the button that was
2438pressed or -1 if the dialog was just closed. In case you don't want to
2439close the dialog when just any button is pressed, you use the
2440<emphasis>gnome_dialog_run</emphasis> function, and after you get a result, do what you
2441need to do for that particular button press. Then if you want to run
2442the dialog more, you just loop back to <emphasis>gnome_dialog_run</emphasis>, and if
2443you want to close, you run <emphasis>gnome_dialog_close</emphasis>. Here's an example
2444of the second scheme.
2445
2446<informalexample><programlisting>
2447GtkWidget *dlg;
2448int i;
2449...
2450/*create a new dialog, DON'T forget the NULL on the end,
2451  it is very important!*/
2452dlg = gnome_dialog_new("A Dialog",
2453                       GNOME_STOCK_BUTTON_OK,
2454                       GNOME_STOCK_BUTTON_APPLY,
2455                       GNOME_STOCK_BUTTON_CLOSE,
2456                       NULL);
2457...
2458/*add some content to the dialog here*/
2459...
2460/*set up an infinite loop*/
2461for(;;) {
2462        i = gnome_dialog_run(GNOME_DIALOG(dlg));
2463        if(i == 0 || i == 2) {
2464                /*the user pressed OK or close, so we will get
2465                  out of the loop and close the dialog, or the
2466                  user pressed */
2467                gnome_dialog_close(GNOME_DIALOG(dlg));
2468                break;
2469        } else if(i &lt; 0) {
2470                /*the user closed the dialog from the window
2471                  manager*/
2472                break;
2473        } else if(i == 1) {
2474                /*user pressed apply we don't want to close*/
2475                ...
2476        }
2477}
2478</programlisting></informalexample>
2479By default the dialog is destroyed when closed, so you don't have to worry
2480about it's destruction. You can change this behavior if you wish though.</para>
2481
2482<para>
2483If you are doing a non-modal dialog box, things get a little more complicated.
2484You create the dialog as above, but then you bind the <emphasis>clicked</emphasis> signal
2485of the <emphasis>GnomeDialog</emphasis> widget. That signal has as it's second argument
2486the button number that was pressed. After that you should use the
2487<emphasis>gnome_dialog_set_close</emphasis> function to tell <emphasis>GnomeDialog</emphasis> that
2488we want to close the dialog when the user first presses any button, if
2489you want that behavior, otherwise you'll have to do <emphasis>gnome_dialog_close</emphasis>
2490in the <emphasis>clicked</emphasis> signal handler for the buttons you want to close on.
2491After that is set up you just <emphasis>gtk_widget_show</emphasis> the dialog. An
2492example follows:
2493
2494<informalexample><programlisting>
2495/*the clicked signal handler*/
2496static void
2497dialog_clicked(GnomeDialog *dlg, int button, gpointer data)
2498{
2499        switch(button) {
2500        case 1:
2501                /*user pressed apply*/
2502                ...
2503                return;
2504        case 0:
2505                /*user pressed OK*/
2506                ...
2507                /*fall though to close*/
2508        case 2:
2509                /*user pressed close*/
2510                gnome_dialog_close(dlg);
2511                break;
2512        }
2513}
2514
2515/*somewhere else in the source file*/
2516...
2517GtkWidget *dlg;
2518...
2519/*create a new dialog, DON'T forget the NULL on the end, it
2520  is very important!*/
2521dlg = gnome_dialog_new("A Dialog",
2522                       GNOME_STOCK_BUTTON_OK,
2523                       GNOME_STOCK_BUTTON_APPLY,
2524                       GNOME_STOCK_BUTTON_CLOSE,
2525                       NULL);
2526...
2527/*add some content to the dialog here*/
2528...
2529/*bind the clicked handler*/
2530gtk_signal_connect(GTK_OBJECT(dlg),"clicked",
2531                   GTK_SIGNAL_FUNC(dialog_clicked),
2532                   NULL);
2533/*show the dialog, note that this is not a modal dialog,
2534  so the program doesn't block here, but continues*/
2535gtk_widget_show(dlg);
2536</programlisting></informalexample>
2537This implements the same dialog as the modal example above, only non modal.</para></sect3>
2538
2539<sect3>
2540<title>Message Box</title>
2541
2542<para>
2543<emphasis>GnomeMessageBox</emphasis> is an object derived from <emphasis>GnomeDialog</emphasis>. As such
2544you use it in the exact same manner, the only difference here is that
2545it automatically sets up the insides of the dialog to be a single label
2546and an icon of the selected message box type. The message box types are
2547as follows:
2548
2549<informalexample><programlisting>
2550#define GNOME_MESSAGE_BOX_INFO      "info"
2551#define GNOME_MESSAGE_BOX_WARNING   "warning"
2552#define GNOME_MESSAGE_BOX_ERROR     "error"
2553#define GNOME_MESSAGE_BOX_QUESTION  "question"
2554#define GNOME_MESSAGE_BOX_GENERIC   "generic"
2555</programlisting></informalexample>
2556To create a message box, you use the function <emphasis>gnome_message_box_new</emphasis>
2557with the first argument being the message text, the second argument being the
2558type of the message box (one of the defines above), and then any number
2559of buttons terminated by a NULL exactly as in the <emphasis>GnomeDialog</emphasis>'s case.
2560After created it is again used exactly the same as <emphasis>GnomeDialog</emphasis>.</para></sect3>
2561
2562<sect3>
2563<title>Property Dialogs</title>
2564
2565<para>
2566If you have some properties to set in your application, you should use
2567a <emphasis>GnomePropertyBox</emphasis> dialog for the preferences to make the
2568applications more consistent. Again this object is derived from
2569<emphasis>GnomeDialog</emphasis> so it's use is similar. But <emphasis>GnomePropertyBox</emphasis>
2570defines some new signals, namely <emphasis>apply</emphasis> and <emphasis>help</emphasis>. They both
2571get passed the page number as the second argument. For help you should
2572use this to display the proper help page, however for apply, this was
2573created for adding a per-page apply button, which was not realized yet,
2574so you should ignore any <emphasis>apply</emphasis> signal with the page number other
2575then -1, which is the <emphasis>global</emphasis> apply. This can be done with a simple
2576if statement at the top of your apply routine. You can choose to be
2577per-page apply <emphasis>ready</emphasis>, by doing a per-page apply in your code, but
2578it is not sure if this code will ever get completed. It should be
2579safe to do just the global apply as that is the only thing implemented
2580in <emphasis>gnome-libs 1.0</emphasis>.</para>
2581
2582<para>
2583To use property dialogs, you call <emphasis>gnome_property_box_new</emphasis>,
2584which will create a completely new dialog for you with a notebook and the four
2585buttons.  <emphasis>OK</emphasis>, which will call your apply handler for all
2586pages and then for the -1 page, and then it will close the dialog,
2587<emphasis>Apply</emphasis>, which will call the apply handler for all pages and
2588then for the -1 page, <emphasis>Close</emphasis>, which will just close the
2589dialog, and <emphasis>Help</emphasis> which will call your help handler if you
2590bound it. You then connect the <emphasis>apply</emphasis> signal to your apply
2591handler, and most likely the <emphasis>destroy</emphasis> signal on the
2592property box to destroy the data associated with the property box when it
2593closes. You then create the different pages for your property box and add them
2594with, <emphasis>gnome_property_box_append_page</emphasis>, which takes your
2595page as the second argument and a label as the third (usually this will be just
2596a <emphasis>GtkLabel</emphasis>). You also want to connect the different
2597signals for the widgets on your pages, to mark the property box as changed
2598(otherwise the Apply and OK buttons will not be sensitive). You do this by
2599calling <emphasis>gnome_property_box_changed</emphasis> every time the user
2600changed something with the widgets. For example on entry (and derived) widgets
2601you connect to the <emphasis>changed</emphasis> signal. Example follows:
2602
2603<informalexample><programlisting>
2604/*apply handler*/
2605static void
2606property_apply(GnomePropertyBox *box, int page_num, gpointer data)
2607{
2608        /*ignore page numbers other then -1*/
2609        if(page_num!=-1)
2610                return;
2611        /*do your apply routine here*/
2612        ...
2613}
2614...
2615/*somewhere else in the source file*/
2616GtkWidget *pbox;
2617GtkWidget *widget;
2618...
2619pbox = gnome_property_box_new();
2620gtk_signal_connect(GTK_OBJECT(pbox),"apply",
2621                   GTK_SIGNAL_FUNC(property_apply),NULL);
2622...
2623/*you create a page for the property box and added it to the
2624  container called widget*/
2625gnome_property_box_append_page(GNOME_PROPERTY_BOX(pbox),
2626                               widget,
2627                               gtk_label_new("SomePage"));
2628/*then add other pages in similar manner*/
2629...
2630/*we show the dialog box*/
2631gtk_widget_show_all(pbox);
2632</programlisting></informalexample></para></sect3>
2633
2634<sect3>
2635<title>File Picking Dialog</title>
2636
2637<para>
2638Gnome doesn't have it's own file picking dialog, although this is planned for
2639the future, for now you need to use the regular <emphasis>GTK+</emphasis> file
2640dialog.</para>
2641
2642<para>
2643Use of the file dialog is very simple. You create the dialog with
2644<emphasis>gtk_file_selection_new</emphasis>, passing it the title of the dialog
2645box as the argument. After this you bind the clicked signal on the
2646<emphasis>OK</emphasis> and <emphasis>Cancel</emphasis> buttons. For example
2647for a loading dialog box, you could check that the file is of the correct type
2648when the user presses OK and if so then close the dialog (usually with
2649<emphasis>gtk_widget_destroy</emphasis>). Or for saving dialog, you could ask
2650if the file exists. File selection dialog boxes are usually safe and simple to
2651do non-modal. Just make sure you'd destroy the file dialog box when the object
2652or window it's supposed to work with. Here's the routine that invokes the save
2653as dialog for <emphasis>Achtung</emphasis>, which is a presentation program
2654we're working on.
2655
2656<informalexample><programlisting>
2657void
2658presentation_save_as (AchtungPresentation *p)
2659{
2660        GtkFileSelection *fsel;
2661       
2662        g_return_if_fail (p != NULL);
2663        g_return_if_fail (p-&gt;doc != NULL);
2664
2665        fsel = (GtkFileSelection *)
2666                gtk_file_selection_new (_("Save presentation as"));
2667        if (p-&gt;real_file &amp;&amp; p-&gt;filename)
2668                gtk_file_selection_set_filename (fsel, p-&gt;filename);
2669
2670        gtk_object_set_data(GTK_OBJECT(fsel),"p",p);
2671       
2672        /* Connect the signals for Ok and Cancel */
2673        gtk_signal_connect (GTK_OBJECT (fsel-&gt;ok_button), "clicked",
2674                            GTK_SIGNAL_FUNC (save_ok), fsel);
2675        gtk_signal_connect_object
2676                (GTK_OBJECT (fsel-&gt;cancel_button), "clicked",
2677                 GTK_SIGNAL_FUNC (gtk_widget_destroy),
2678                 GTK_OBJECT(fsel));
2679
2680        gtk_window_position (GTK_WINDOW (fsel), GTK_WIN_POS_MOUSE);
2681
2682        /*if the presentation dies so do it's dialogs*/
2683        gtk_signal_connect_object_while_alive
2684                (GTK_OBJECT (p), "destroy",
2685                 GTK_SIGNAL_FUNC (gtk_widget_destroy),
2686                 GTK_OBJECT(fsel));
2687
2688        gtk_widget_show (GTK_WIDGET (fsel));
2689}
2690</programlisting></informalexample>
2691This is actually a save_as method for <emphasis>AchtungPresentation</emphasis>
2692object in object oriented speak.  <emphasis>AchtungPresentation</emphasis> is a
2693GtkObject we use for storing all the presentation data (This is a nice example
2694of how to use GtkObject for things not directly related to widgets or GUI
2695programming). First we check the arguments to the function with
2696<emphasis>g_return_if_fail</emphasis> which is for debugging purposes. Then we
2697create a new <emphasis>GtkFileSelection</emphasis> with a title of "Save
2698presentation as". Ignore the <emphasis>_()</emphasis> macro around the string
2699for now, it's used for internationalization.  Afterwards we check if the
2700presentation already has a filename associated with it, and if so we set the
2701filename on the file selection dialog to that. After that we connect the the
2702<emphasis>OK</emphasis> button to a routine called <emphasis>save_ok</emphasis>
2703defined elsewhere in the file and pass the file selection dialog as a data
2704argument. Then we use <emphasis>connect_object</emphasis> to bind the
2705<emphasis>Cancel</emphasis> button to destroying the file selection dialog. The
2706<emphasis>connect_object</emphasis> method is similar to regular
2707<emphasis>connect</emphasis> but when it calls the function itself it will pass
2708the object from the data field as the first argument of the function. So
2709connecting to <emphasis>gtk_widget_destroy</emphasis> will destroy the object
2710passed in the data field, which is the file selection dialog. Then we position
2711the dialog near the mouse button. In the future when this dialog is derived
2712from <emphasis>GnomeDialog</emphasis>, you will not need to and actually should
2713not do that, as that will be done according to use preferences as for all the
2714other gnome dialogs. After this we use yet another signal connection method ...
2715this time <emphasis>gtk_signal_connect_object_while_alive</emphasis>, which is
2716similar to <emphasis>connect_object</emphasis>, but has a nice twist to it. The
2717signal will be disconnected when the object passed in the data field dies. This
2718needs to happen as the file dialog will most likely be destroyed before the the
2719presentation itself is, then when the presentation is destroyed itself, it
2720would try to destroy an already non-existent file selection dialog and most
2721likely cause a segmentation fault and crash. This way it is safe and if the
2722file selection dialog is still around when the presentation is destroyed, it is
2723destroyed with it.</para></sect3></sect2>
2724
2725<sect2>
2726<title>Entries</title>
2727
2728<para>
2729Sometimes, especially in properties dialogs, you want fields for entering
2730text, files, pixmaps, icons or double precision numbers. This is what the
2731<emphasis>gnome-*entry</emphasis> widgets do.</para>
2732
2733<sect3>
2734<title>GnomeEntry</title>
2735
2736<para>
2737This is an entry for regular text, but it includes history of previously
2738entered values. Note that this widget is not derived from
2739<emphasis>GtkEntry</emphasis>, but owns such a widget. This means that you
2740can't use <emphasis>GtkEntry</emphasis> methods on this object directly, but
2741you need to get a pointer to the <emphasis>GtkEntry</emphasis> object inside
2742<emphasis>GnomeEntry</emphasis>. When you call
2743<emphasis>gnome_entry_new</emphasis>, you pass a
2744<emphasis>history_id</emphasis> string to it. This is a unique identifier to
2745identify this entry, or this type of entries in your application. All the
2746entries that share this <emphasis>history_id</emphasis> will have common
2747history of values. After you create a <emphasis>GnomeEntry</emphasis> you use
2748the <emphasis>gnome_entry_gtk_entry</emphasis> function to get a pointer to the
2749<emphasis>GtkEntry</emphasis> object inside and bind any signals or manipulate
2750text with that instead. Here is an example:
2751
2752<informalexample><programlisting>
2753GtkWidget *gnome_e;
2754GtkWidget *gtk_e;
2755...
2756gnome_entry_new("text1");
2757gtk_e = gnome_entry_gtk_entry(GNOME_ENTRY(gnome_e));
2758gtk_signal_connect(GTK_OBJECT(gtk_e),"changed",
2759                   GTK_SIGNAL_FUNC(entry_changed), NULL);
2760</programlisting></informalexample></para></sect3>
2761
2762<sect3>
2763<title>GnomeFileEntry</title>
2764
2765<para>
2766<emphasis>GnomeEntry</emphasis> is a basis for
2767<emphasis>GnomeFileEntry</emphasis>. Again it is not derived, but
2768<emphasis>GnomeEntry</emphasis> is owned by
2769<emphasis>GnomeFileEntry</emphasis>. This type of hierarchy is throughout all
2770the gnome entry widgets. <emphasis>GnomeFileEntry</emphasis> adds a browse
2771button on the right side of the entry, and also accepts file drops from the
2772file manager for example. It's use is extremely similar to
2773<emphasis>GnomeEntry</emphasis>.  You create the entry with
2774<emphasis>gnome_file_entry_new</emphasis>. The first argument is the
2775<emphasis>history_id</emphasis> of the <emphasis>GnomeEntry</emphasis>, and the
2776second argument is the title of the browse dialog box. To get the
2777<emphasis>GtkEntry</emphasis>, you again use the gtk_entry method, named
2778<emphasis>gnome_file_entry_gtk_entry</emphasis>.  To finally get the filename,
2779you can get the exact text from the <emphasis>GtkEntry</emphasis>, or you might
2780use a convenience method, <emphasis>gnome_file_entry_get_full_path</emphasis>,
2781which takes a flag <emphasis>file_must_exist</emphasis> as it's second
2782argument. If this flag is set, the function returns NULL if the file doesn't
2783exists. If the flag is not set or the file does exist, the function returns the
2784full path to the file.</para></sect3>
2785
2786<sect3>
2787<title>GnomePixmapEntry</title>
2788
2789<para>
2790This is an entry for entering pixmaps (Images) of any size. It again includes
2791(not derives from) <emphasis>GnomeFileEntry</emphasis>, so it can do everything
2792the file entry can (including accepting drops). However this entry adds a
2793preview box for the pixmap above the entry. Also it's file selection dialog
2794includes a preview box to the right side of the file list.  It's use is again
2795very similar to the entries above. You call
2796<emphasis>gnome_pixmap_entry_new</emphasis> with the same arguments as
2797<emphasis>GnomeFileEntry</emphasis>, with an added flag,
2798<emphasis>do_preview</emphasis>. This flag specifies if the preview box is
2799visible or not. But be careful, it doesn't save memory not to show the preview,
2800it just saves space. Again you use a
2801<emphasis>gnome_pixmap_entry_gtk_entry</emphasis> to get the
2802<emphasis>GtkEntry</emphasis> widget.  To get a filename of the the pixmap, if
2803it could be loaded as an image for the preview (using imlib), you can use
2804<emphasis>gnome_pixmap_entry_get_filename</emphasis>, which returns NULL if the
2805pixmap files doesn't exist or could not be loaded, and the full filename
2806otherwise.
2807</para>
2808</sect3>
2809
2810<sect3>
2811<title>GnomeIconEntry</title>
2812
2813<para>
2814The icon entry is very similar to the <emphasis>GnomePixmapEntry</emphasis>,
2815but it is meant for images in the standard 48x48 icon size. Also instead of the
2816preview box, there is a button with the image scaled to 48x48. If you press the
2817button you get a listing of images from the same directory as the current icon.
2818To create an icon entry use <emphasis>gnome_icon_entry_new</emphasis> with
2819<emphasis>history_id</emphasis> and <emphasis>browse_dialog_title</emphasis>
2820string arguments. Once you need an existing icon that is a real image, you use
2821<emphasis>gnome_icon_entry_get_filename</emphasis> which works just like
2822<emphasis>gnome_pixmap_entry_get_filename</emphasis>. You can also get the
2823<emphasis>GtkEntry</emphasis> by using
2824<emphasis>gnome_icon_entry_gtk_entry</emphasis>.
2825</para>
2826</sect3>
2827
2828<sect3>
2829<title>GnomeNumberEntry</title>
2830
2831<para>
2832<emphasis>GnomeNumberEntry</emphasis> is an entry widget for entering double
2833precision numbers with a calculator. Most of the time for number entries you
2834want to use the <emphasis>GtkSpinButton</emphasis> widget, however for
2835applications such as mortgage calculators, or finance programs, where
2836calculations are necessary, you will want to use this entry type. Basically
2837it's a <emphasis>GnomeEntry</emphasis> widget with a button on the right side
2838of it which calls up a dialog with a calculator. The user can use the
2839calculator and press OK and the number entry is updated to what it was on the
2840calculator. To create a number entry widget, just use
2841<emphasis>gnome_number_entry_new</emphasis>, passing it the
2842<emphasis>history_id</emphasis> as the first argument and the title of the
2843calculator dialog as the second argument. To get the
2844<emphasis>GtkEntry</emphasis> widget just use
2845<emphasis>gnome_number_entry_gtk_entry</emphasis>. To get the number as a
2846<emphasis>double</emphasis> value, use
2847<emphasis>gnome_number_entry_get_number</emphasis>
2848method.
2849</para>
2850</sect3>
2851</sect2>
2852
2853<sect2>
2854<title>Using Images</title>
2855
2856<para>
2857When you need to use images in your apps, most likely you'll want the
2858<emphasis>GnomePixmap</emphasis> widget. It's advantage is that it makes using
2859images much easier without having to learn imlib, which is the image library
2860used by this widget.</para>
2861
2862<para>
2863There are numerous <emphasis>new</emphasis> functions for
2864<emphasis>GnomePixmap</emphasis>, depending on the source of the pixmap. The
2865most used will probably be <emphasis>gnome_pixmap_new_from_file</emphasis>
2866which takes a filename which is an image loadable by imlib and creates a pixmap
2867widget for you.  There is also
2868<emphasis>gnome_pixmap_new_from_file_at_size</emphasis> to which you pass also
2869the size to which the image should be scaled. If you have already loaded the
2870image with imlib (in case you wanted to do other things to the pixmap first),
2871you can use <emphasis>gnome_pixmap_new_from_imlib</emphasis> and
2872<emphasis>gnome_pixmap_new_from_imlib_at_size</emphasis>. Which take a
2873<emphasis>GdkImlibImage</emphasis> as the first argument. If you already have a
2874pixmap widget and want to change the image inside it, you can use the
2875<emphasis>gnome_pixmap_load_*</emphasis> which have almost the same syntax as
2876the new functions, except that you pass the <emphasis>GnomePixmap</emphasis> as
2877the first argument, and then the rest of the arguments as above, and of course
2878replace the _new_from_ for _load_.</para>
2879
2880<para>
2881Here's an example of it's use:
2882
2883<informalexample><programlisting>
2884GtkWidget *pix;
2885...
2886/*load somefile.png and scale it to 48x48*/
2887pix = gnome_pixmap_new_from_file_at_size("somefile.png",48,48);
2888/*now you can pack pix somewhere just like any other widget*/
2889...
2890/*now we want to change the files to otherfile.png and do no
2891  scaling*/
2892gnome_pixmap_load_file(GNOME_PIXMAP(pix),"otherfile.png");
2893</programlisting></informalexample></para></sect2>
2894
2895<sect2>
2896<title>Session Management</title>
2897
2898<para>
2899Your app should be able to save it's settings and restore them when the user
2900restarts your application, it should also be able to do this for several
2901different sessions. For instance the user might have a normal session, but
2902sometimes log into a special session where he has different settings in
2903applications. <emphasis>gnome-libs</emphasis> actually hides the ugly details
2904of this. For the most part you do not need to worry about the real details of
2905session management, unless you wish to do something very clever or if your app
2906does some complicated state saving. To do simple session saving all you need is
2907the following code (mostly taken from gnome-hello-4-SM example program):
2908
2909<informalexample><programlisting>
2910/*the save_yourself handler, you can safely ignore most of the
2911  parameters, and just save your session and return TRUE*/
2912static int
2913save_yourself(GnomeClient *client, int phase,
2914              GnomeSaveStyle save_style, int shutdown,
2915              GnomeInteractStyle interact_style, int fast,
2916              gpointer client_data)
2917{
2918        /*get the prefix for our config*/
2919        char *prefix= gnome_client_get_config_prefix (client);
2920
2921        /*this is a "discard" command for discarding data from
2922          a saved session, usually this will work*/
2923        char *argv[]= { "rm", "-r", NULL };
2924
2925        /* Save the state using gnome-config stuff. */
2926        gnome_config_push_prefix (prefix);
2927
2928        gnome_config_set_int("Section/Key",some_value);
2929        ...
2930        gnome_config_pop_prefix ();
2931        gnome_config_sync();
2932
2933        /* Here is the real SM code. We set the argv to the
2934           parameters needed to restart/discard the session that
2935           we've just saved and call the
2936           gnome_session_set_*_command to tell the session
2937           manager it. */
2938        argv[2]= gnome_config_get_real_path (prefix);
2939        gnome_client_set_discard_command (client, 3, argv);
2940
2941        /* Set commands to clone and restart this application.
2942           Note that we use the same values for both -- the
2943           session management code will automatically add
2944           whatever magic option is required to set the session
2945           id on startup. The client_data was set to the
2946           command used to start this application when
2947           save_yourself handler was connected. */
2948        argv[0]= (gchar*) client_data;
2949        gnome_client_set_clone_command (client, 1, argv);
2950        gnome_client_set_restart_command (client, 1, argv);
2951       
2952        return TRUE;
2953}
2954
2955static void
2956die (GnomeClient *client, gpointer client_data)
2957{
2958        /* Just exit in a friendly way.  We don't need to
2959           save any state here, because the session manager
2960           should have sent us a save_yourself-message
2961           before.  */
2962        gtk_exit (0);
2963}
2964
2965...
2966GnomeClient *client;
2967...
2968/*this is somewhere in your main function presumably.
2969  make sure this is done AFTER the gnome_init call!*/
2970
2971/* Get the master client, that was hopefully connected to the
2972   session manager int the 'gnome_init' call.  All communication
2973   to the session manager will be done with this master client. */
2974client = gnome_master_client ();
2975
2976/* Arrange to be told when something interesting happens.  */
2977gtk_signal_connect (GTK_OBJECT (client), "save_yourself",
2978                    GTK_SIGNAL_FUNC (save_yourself),
2979                    (gpointer) argv[0]);
2980gtk_signal_connect (GTK_OBJECT (client), "die",
2981                    GTK_SIGNAL_FUNC (die), NULL);
2982
2983/*check if we are connected to a session manager*/
2984if (GNOME_CLIENT_CONNECTED (client)) {
2985        /*we are connected, we will get the prefix under which
2986          we saved our session last time and load up our data*/
2987        gnome_config_push_prefix
2988                (gnome_client_get_config_prefix (client));
2989
2990        some_value = gnome_config_get_int("Section/Key=0");
2991
2992        gnome_config_pop_prefix ();
2993} else {
2994        /*we are not connected to any session manager, here you
2995          will just initialize your session like you normally
2996          do without a session manager*/
2997        ...
2998}
2999</programlisting></informalexample>
3000This is a very simple session management which will be enough for most
3001programs, for more information on session management, you should consult the
3002gnome developer documentation which should be available by now.</para></sect2>
3003
3004<sect2>
3005<title>Multiple Document Interface</title>
3006<sect3>
3007<title>The Main MDI Window</title>
3008
3009<para>
3010If your app handles documents, most likely you will want it to handle multiple
3011documents at one time. Gnome provides an MDI model that is customizable by the
3012user and simple to use. They can use three models of the document display.
3013Either a notebook style which is the most useful one, where documents can be
3014docked in notebooks, and can be dragged out into separate windows if desired.
3015Or a toplevel style where each document is a separate toplevel window. Or
3016finally a modal style where there is only one window and the documents must be
3017switched though a menu. (Note that the examples here are taken from the
3018<emphasis>gnome-hello-7-mdi</emphasis> example app in
3019<emphasis>gnome-libs</emphasis>, slightly modified)</para>
3020
3021<para>
3022To use the MDI features. You basically replace the the
3023<emphasis>gnome_app_new</emphasis> call with <emphasis>gnome_mdi_new</emphasis>
3024with the same arguments as <emphasis>gnome_app_new</emphasis>.  To add menus
3025and tool-bar, you use <emphasis>gnome_mdi_set_menubar_template</emphasis> and
3026<emphasis>gnome_mdi_set_toolbar_template</emphasis> with the GnomeUIInfo as the
3027argument.  For MDI, these aren't the actual menus, as it will add it's own
3028items to the menus of each child. After this you set where the menu additions
3029take place. You call <emphasis>gnome_mdi_set_child_menu_path</emphasis> to the
3030toplevel menu name after which the child's own menus are inserted. This is the
3031"File" menu in most cases. Then you want to specify the path (menu name) to the
3032menu into which you want to insert a list of the children, you do this by
3033calling <emphasis>gnome_mdi_set_child_list_path</emphasis> with the name of the
3034menu and add a '/' on the end of it to specify that you want to insert those
3035items into the menu, not after the menu. Example:
3036
3037<informalexample><programlisting>
3038GtkWidget *mdi;
3039...
3040mdi = gnome_mdi_new("gnome-hello-7-mdi", "GNOME MDI Hello");
3041...
3042/*main_menu and toolbar_info are the menu and tool-bar
3043  descriptions*/
3044gnome_mdi_set_menubar_template(mdi, main_menu);
3045gnome_mdi_set_toolbar_template(mdi, toolbar_info);
3046
3047/* and document menu and document list paths (see
3048   gnome-app-helper menu insertion routines for details)  */
3049gnome_mdi_set_child_menu_path(GNOME_MDI(mdi), "File");
3050gnome_mdi_set_child_list_path(GNOME_MDI(mdi), "Children/");
3051</programlisting></informalexample>
3052In our GnomeUIInfo structures we have defined a menu named "File" and a
3053menu named "Children". The children menu was not given any items, it's
3054just an empty menu.</para>
3055
3056<para>
3057Then you should open the main toplevel window with
3058<emphasis>gnome_mdi_open_toplevel</emphasis>. This will open a toplevel window
3059without any children. If you wish to use MDI's session management
3060functionality, you can define a function that creates a child given it's name.
3061This is done with the <emphasis>gnome_mdi_restore_state</emphasis> method,
3062which takes the config path as the second argument and a function pointer to a
3063function which takes a string and returns a new
3064<emphasis>GnomeMDIChild</emphasis> widget (a widget sub-classed from
3065<emphasis>GnomeMDIChild</emphasis> actually). Say for example you are using the
3066session management shown above, so you could use:
3067
3068<informalexample><programlisting>
3069gnome_config_push_prefix (gnome_client_get_config_prefix (client));
3070restart_ok = gnome_mdi_restore_state(GNOME_MDI(mdi), "MDI Session",
3071                                     my_child_new_from_config);
3072gnome_config_pop_prefix ();
3073</programlisting></informalexample>
3074The restart_ok is a boolean value telling you if the loading actually loaded
3075all the data correctly.</para>
3076
3077<para>
3078You should also bind the <emphasis>destroy</emphasis> signal of the mdi object
3079to do <emphasis>gtk_main_quit</emphasis> when the mdi is
3080destroyed.</para></sect3>
3081
3082<sect3>
3083<title>The MDI Children</title>
3084
3085<para>
3086For complicated apps, all children should be derived from the virtual
3087<emphasis>GnomeMDIChild</emphasis> object. For simple apps, you don't need to
3088derive a new object, you can just use the
3089<emphasis>GnomeMDIGenericChild</emphasis>, and use the fact that you can store
3090arbitrary data on arbitrary <emphasis>GtkObject</emphasis>s to store your own
3091data on the object.</para>
3092
3093<para>
3094To use the generic child object, you create it with
3095<emphasis>gnome_mdi_generic_child_new</emphasis> to which you pass the name of
3096the child. When you get the object, you will need to set it up for your use.
3097First you add a function for creating new views of the same data.  A view is
3098just a different window displaying the same file or data.  This is done with a
3099call to <emphasis>gnome_mdi_generic_child_set_view_creator</emphasis> to which
3100you pass a pointer to a creator function which takes the child widget and a
3101data pointer as arguments and returns a data widget, which is not the actual
3102child widget, but actually the child of the
3103<emphasis>GnomeMDIGenericChild</emphasis> widget. After this you set the
3104template for the child's menus with
3105<emphasis>gnome_mdi_child_set_menu_template</emphasis>, to which you pass the
3106<emphasis>GnomeUIInfo</emphasis> array pointer of the child menu definitions.
3107Then you should call
3108<emphasis>gnome_mdi_generic_child_set_config_func</emphasis> to set a function
3109which returns a newly allocated string to save in the config file. This string
3110will be used to load up the child next time you start and do the
3111<emphasis>gnome_mdi_restore_state</emphasis> call. It should probably be a
3112filename of the document, or some string from which you can completely recreate
3113that window/document. Then you need to call
3114<emphasis>gnome_mdi_generic_child_set_label_func</emphasis> with a pointer to a
3115function that takes the <emphasis>GnomeMDIGenericChild</emphasis> as the first
3116argument, the old label widget pointer as the second argument, which would be
3117null if no label widget was yet set, and a data argument. This function can
3118either create a new label and destroy the old one, or just set the label if the
3119label exists. The label can be any widget, for example the
3120<emphasis>gnome-hello-7-mdi</emphasis> example code uses a horizontal box
3121widget into which it adds a pixmap and a gtk label. After this if you need to
3122add the child to the mdi yourself, if you are loading a new file for example,
3123you use <emphasis>gnome_mdi_add_child</emphasis> and
3124<emphasis>gnome_mdi_add_view</emphasis>, to add a new child and a new view to
3125the mdi. If you are creating a new child from the
3126<emphasis>gnome_mdi_restore_state</emphasis> function, you should just return
3127the child, the mdi will take care of adding it and adding the appropriate
3128views.  You also probably want to set some data on the child widget at this
3129time to store your data with the object.</para>
3130
3131<para>
3132Here's a short example of creating a new child, for a more complete example
3133you should look at the <emphasis>gnome-hello-7-mdi</emphasis> included with
3134the gnome-libs distribution.
3135
3136<informalexample><programlisting>
3137GnomeMDI *mdi;
3138...     
3139GnomeMDIGenericChild *child;
3140...     
3141/*create a new child named 'name'*/
3142if((child = gnome_mdi_generic_child_new(name)) != NULL) {
3143        /*creator of a view*/
3144        gnome_mdi_generic_child_set_view_creator
3145                (child, my_child_create_view, NULL);
3146        /*set a menu template for child menu*/
3147        gnome_mdi_child_set_menu_template
3148                (GNOME_MDI_CHILD(child), main_child_menu);
3149        /*set function to get config string*/
3150        gnome_mdi_generic_child_set_config_func
3151                (child, my_child_get_config_string, NULL);
3152        /*set function that sets or creates a label*/
3153        gnome_mdi_generic_child_set_label_func
3154                (child, my_child_set_label, NULL);
3155
3156        /* add the child to MDI */
3157        gnome_mdi_add_child(mdi, GNOME_MDI_CHILD(child));
3158
3159        /* and add a new view of the child */
3160        gnome_mdi_add_view(mdi, GNOME_MDI_CHILD(child));
3161}
3162</programlisting></informalexample></para></sect3></sect2></sect1>
3163
3164<sect1 id="gnomecanvas-widget">
3165<title>GnomeCanvas Widget</title>
3166
3167<para>
3168While <emphasis>GnomeCanvas</emphasis> widget is inside the libgnomeui library,
3169it definitely deserves a separate chapter. The canvas is a very high level high
3170performance graphics drawing widget and on top of that it's easy to use. It
3171includes support for both Xlib drawn graphics, which is faster especially over
3172the network, and anti-aliased drawing for better looking results.</para>
3173
3174<sect2>
3175<title>Creating a Canvas Widget</title>
3176
3177<para>
3178To create a gnome canvas widget, you call the
3179<emphasis>gnome_canvas_new</emphasis>. You need to make sure that the canvas is
3180created with a proper visual and colormap. For example if you wish to draw
3181imlib images inside it, you should do this:
3182
3183<informalexample><programlisting>
3184GtkWidget *canvas;
3185...
3186gtk_widget_push_visual(gdk_imlib_get_visual());
3187gtk_widget_push_colormap(gdk_imlib_get_colormap());
3188canvas = gnome_canvas_new();
3189gtk_widget_pop_visual();
3190gtk_widget_pop_colormap();
3191</programlisting></informalexample>
3192After this you also want to call
3193<emphasis>gnome_canvas_set_pixels_per_unit</emphasis> to set the scale of the
3194canvas. You can then do <emphasis>gtk_widget_set_usize</emphasis> to set the
3195size of the widget, and <emphasis>gnome_canvas_set_scroll_region</emphasis> to
3196set the region in which you can scroll around in, this is given in (x1, y1, x2,
3197y2). Basically it's the outer limits of your drawing. So once the canvas was
3198created, you could do:
3199
3200<informalexample><programlisting>
3201GnomeCanvas *canvas;
3202...
3203/*already created a canvas, now set it up*/
3204gnome_canvas_set_pixels_per_unit(canvas,10);
3205gnome_canvas_set_scroll_region(canvas,0.0,0.0,50.0,50.0);
3206</programlisting></informalexample></para></sect2>
3207
3208<sect2>
3209<title>Groups and Items</title>
3210
3211<para>
3212In the canvas there are items, the actual objects that are on the canvas, and
3213groups, which are just groupings of items. A group is actually derived from a
3214base <emphasis>GnomeCanvasItem</emphasis> object, this is useful to applying
3215functions to all the items inside the group. Such as moving or hiding the
3216entire group. There is also one default group, the root group.  You can get
3217this group by calling <emphasis>gnome_canvas_root</emphasis>.
3218</para>
3219</sect2>
3220
3221<sect2>
3222<title>Creating Items</title>
3223
3224<para>
3225Creating items is slightly different usual. It's using the standard
3226GTK+ object model argument mechanism. Basically you call
3227<emphasis>gnome_canvas_item</emphasis>, with the parent canvas group as the first argument,
3228the type of object as the second argument, and then arguments given in
3229pairs (argument, value), terminated with a NULL. This is best illustrated by
3230an example:
3231
3232<informalexample><programlisting>
3233GnomeCanvas *canvas;
3234GnomeCanvasItem *item;
3235...
3236item = gnome_canvas_item_new(gnome_canvas_root(canvas),
3237                             GNOME_TYPE_CANVAS_RECT,
3238                             "x1", 1.0,
3239                             "y1", 1.0,
3240                             "x2", 23.0,
3241                             "y2", 20.0,
3242                             "fill_color", "black",
3243                             NULL);
3244</programlisting></informalexample>
3245Note that it's extremely important that the value be the exact type, since
3246the compiler won't do the cast for you. If you're doing any calculations and
3247aren't sure that you get the right type, just cast it. I believe most if not
3248all numbers for canvas items are doubles.</para>
3249
3250<para>
3251To find out the arguments that each item takes, consult the gnome documentation
3252or look into the <emphasis>libgnomeui/gnome-canvas*.h</emphasis> header files.
3253They contain a table at the top of the file just like the one that follows
3254(which was taken from
3255<emphasis>libgnomeui/gnome-canvas-rect-ellipse.h</emphasis>).
3256</para>
3257
3258<para>
3259For example here are arguments for rectangle (GNOME_TYPE_CANVAS_RECT) and
3260ellipse (GNOME_TYPE_CANVAS_ELLIPSE):
3261
3262<table>
3263<title>
3264Arguments for rectangle and ellipse canvas items
3265</title>
3266
3267<tgroup cols=4>
3268<thead>
3269<row>
3270<entry>Name</entry>
3271<entry>Type</entry>
3272<entry>Read/Write</entry>
3273<entry>Description</entry>
3274</row>
3275</thead>
3276<tbody>
3277
3278<row>
3279<entry>x1</entry>
3280<entry>double</entry>
3281<entry>RW</entry>
3282<entry>
3283Leftmost coordinate of rectangle or ellipse
3284</entry>
3285</row>
3286
3287<row>
3288<entry>y1</entry>
3289<entry>double</entry>
3290<entry>RW</entry>
3291<entry>
3292Topmost coordinate of rectangle or ellipse
3293</entry>
3294</row>
3295
3296<row>
3297<entry>x2</entry>
3298<entry>double</entry>
3299<entry>RW</entry>
3300<entry>
3301Rightmost coordinate of rectangle or ellipse
3302</entry>
3303</row>
3304
3305<row>
3306<entry>y2</entry>
3307<entry>double</entry>
3308<entry>RW</entry>
3309<entry>
3310Bottommost coordinate of rectangle or ellipse
3311</entry>
3312</row>
3313
3314<row>
3315<entry>fill_color</entry>
3316<entry>string</entry>
3317<entry>W</entry>
3318<entry>
3319X color specification for fill color, or NULL pointer for
3320no color (transparent)
3321</entry>
3322</row>
3323
3324<row>
3325<entry>fill_color_gdk</entry>
3326<entry>GdkColor*</entry>
3327<entry>RW</entry>
3328<entry>
3329Allocated GdkColor for fill
3330</entry>
3331</row>
3332
3333<row>
3334<entry>outline_color</entry>
3335<entry>string</entry>
3336<entry>W</entry>
3337<entry>
3338X color specification for outline color, or NULL pointer for
3339no color (transparent)
3340</entry>
3341</row>
3342
3343<row>
3344<entry>outline_color_gdk</entry>
3345<entry>GdkColor*</entry>
3346<entry>RW</entry>
3347<entry>
3348Allocated GdkColor for outline
3349</entry>
3350</row>
3351
3352<row>
3353<entry>fill_stipple</entry>
3354<entry>GdkBitmap*</entry>
3355<entry>RW</entry>
3356<entry>
3357Stipple pattern for fill
3358</entry>
3359</row>
3360
3361<row>
3362<entry>outline_stipple</entry>
3363<entry>GdkBitmap*</entry>
3364<entry>RW</entry>
3365<entry>
3366Stipple pattern for outline
3367</entry>
3368</row>
3369
3370<row>
3371<entry>width_pixels</entry>
3372<entry>uint</entry>
3373<entry>RW</entry>
3374<entry>
3375Width of the outline in pixels.  The outline will not be scaled
3376when the canvas zoom factor is changed.
3377</entry>
3378</row>
3379
3380<row>
3381<entry>width_units</entry>
3382<entry>double</entry>
3383<entry>RW</entry>
3384<entry>
3385Width of the outline in canvas units.  The outline will be scaled
3386when the canvas zoom factor is changed.
3387</entry>
3388</row>
3389
3390</tbody>
3391</tgroup>
3392</table>
3393
3394</para>
3395
3396<para>
3397Now suppose we want to change some of these properties. This is done with a
3398call to <emphasis>gnome_canvas_item_set</emphasis>. The first argument to this
3399function is the canvas item object pointer. The next arguments are the same
3400argument pairs as above when creating a new canvas object. For example if we
3401want to set the color to red on the rectangle we created above, we can do this:
3402
3403<informalexample><programlisting>
3404GnomeCanvas *canvas;
3405GnomeCanvasItem *item;
3406...
3407gnome_canvas_item_set(item
3408                      "fill_color", "red",
3409                      NULL);
3410</programlisting></informalexample></para>
3411
3412<para>
3413Then there are item methods for other operations on items. For example the
3414<emphasis>gnome_canvas_item_move</emphasis> method will take the x and y as
3415second and third argument, and will move the item relative to it's current
3416position by x and y. Or the <emphasis>gnome_canvas_item_hide</emphasis> and
3417<emphasis>gnome_canvas_item_show</emphasis>, which hide and show the item,
3418respectively. To control the z order of the items, you can use the methods
3419<emphasis>gnome_canvas_item_raise_to_top</emphasis> and
3420<emphasis>gnome_canvas_item_lower_to_bottom</emphasis> to raise or lower the
3421item to the top or bottom of it's parent group's z order. To have finer control
3422over z order you can use the <emphasis>gnome_canvas_item_raise</emphasis> and
3423<emphasis>gnome_canvas_item_lower</emphasis> methods which take an extra
3424integer argument which is 1 or larger, and specifies the number of levels the
3425item should move in the z order.
3426</para>
3427</sect2>
3428
3429<sect2>
3430<title>Anti-aliasing canvas</title>
3431
3432<para>
3433To create a canvas which uses anti aliasing for rendering of it's items,
3434instead of <emphasis>gnome_canvas_new</emphasis> function, you should use the
3435<emphasis>gnome_canvas_new_aa</emphasis>. You should also use the <emphasis>GdkRgb</emphasis>
3436visual and colormap. So you would do this to create a new anti-aliased
3437canvas:
3438
3439<informalexample><programlisting>
3440GtkWidget *canvas;
3441...
3442gtk_widget_push_visual (gdk_rgb_get_visual ());
3443gtk_widget_push_colormap (gdk_rgb_get_cmap ());
3444canvas = gnome_canvas_new_aa ();
3445gtk_widget_pop_colormap ();
3446gtk_widget_pop_visual ();
3447</programlisting></informalexample>
3448After this you can use the canvas in exactly the same manner as the normal
3449canvas.</para>
3450
3451<para>
3452Anti-aliased canvas items can generally do more then normal canvas items.
3453This is because of limitations of Xlib as a graphics library. It can for
3454example do any kind of affine transformation on it's objects, where on
3455and Xlib canvas you can only do affine transformations on some objects.</para></sect2></sect1>
3456
3457<sect1 id="drag-and-drop">
3458<title>Drag and Drop</title>
3459
3460<para>
3461While drag and drop belongs into GTK+ itself, I thought it would be better
3462to cover it after some parts of GNOME were discussed.</para>
3463
3464<sect2>
3465<title>Accepting Drops</title>
3466
3467<para>
3468You have already seen one drop handler back when we were discussing the
3469mime types. Basically, to accept drops, you have to decide which
3470mime type of data you want to be able to receive. You have already seen
3471one for "text/uri-list". Basically your handler will only receive data
3472of those mime types that you specify, so you only need to know how to
3473decode those.</para>
3474
3475<para>
3476To specify the mime types you want to receive, you create an array of
3477<emphasis>GtkTargetEntry</emphasis> structures, where the first element is a string
3478of mime type, the second is an integer flag and the third is an integer
3479info. You can leave the flags at 0. The info field can be used if you
3480have several entries you are accepting, as the info integer will be passed
3481to your drop handler, so you can create a switch statement to handle
3482the different types of data. If you have only one type, just leave this
3483at 0.</para>
3484
3485<para>
3486After this you need to set up the widget for dragging. You do this by calling
3487the <emphasis>gtk_drag_dest_set</emphasis> function. The first argument is the
3488widget you want to set up, the second is a flags argument for setting up which
3489types of default drag behavior to use, you can leave this at
3490<emphasis>GTK_DEST_DEFAULT_ALL</emphasis>. The next argument is the array of
3491<emphasis>GtkTargetEntry</emphasis> structures, the next argument is the number
3492of items in that array. The last argument is the type of action that you
3493accept.  The types can be any of the following ORed together:
3494<emphasis>GDK_ACTION_DEFAULT</emphasis>, <emphasis>GDK_ACTION_COPY</emphasis>,
3495<emphasis>GDK_ACTION_MOVE</emphasis>, <emphasis>GDK_ACTION_LINK</emphasis>,
3496<emphasis>GDK_ACTION_PRIVATE</emphasis> and
3497<emphasis>GDK_ACTION_ASK</emphasis>.  The most useful are
3498<emphasis>GDK_ACTION_COPY</emphasis> and <emphasis>GDK_ACTION_MOVE</emphasis>.
3499If you are for example passing around strings or other data, you will most
3500likely use <emphasis>GDK_ACTION_COPY</emphasis> only.</para>
3501
3502<para>
3503Then you need to set up and bind the drop handler. The drop handler
3504should have the following prototype:
3505
3506<informalexample><programlisting>
3507void 
3508target_drag_data_received  (GtkWidget          *widget,
3509                            GdkDragContext     *context,
3510                            gint                x,
3511                            gint                y,
3512                            GtkSelectionData   *data,
3513                            guint               info,
3514                            guint               time);
3515</programlisting></informalexample>
3516The data you have is in the structure <emphasis>GtkSelectionData</emphasis>,
3517in the <emphasis>data</emphasis> field. That's all you need to do for normal
3518DND. Here's and example:
3519
3520<informalexample><programlisting>
3521static void 
3522target_drag_data_received  (GtkWidget          *widget,
3523                            GdkDragContext     *context,
3524                            gint                x,
3525                            gint                y,
3526                            GtkSelectionData   *data,
3527                            guint               info,
3528                            guint               time)
3529{
3530        g_print("Got: %s\n",data-&gt;data);
3531}
3532...
3533static GtkTargetEntry target_table[] = {
3534        { "text/plain", 0, 0 }
3535}
3536...
3537gtk_drag_dest_set (widget,
3538                   GTK_DEST_DEFAULT_ALL,
3539                   target_table, 1,
3540                   GDK_ACTION_COPY);
3541gtk_signal_connect (GTK_OBJECT (widget), "drag_data_received",
3542                    GTK_SIGNAL_FUNC (target_drag_data_received),
3543                    NULL);
3544</programlisting></informalexample></para>
3545
3546<para>
3547For more information about drag and drop, you should see
3548<emphasis>GTK+</emphasis> documentation at <ulink
3549url="http://www.gtk.org/">www.gtk.org</ulink>.
3550</para>
3551</sect2>
3552
3553<sect2>
3554<title>Allowing Drags</title>
3555
3556<para>
3557Now let's look at the source side of DND. You set up the
3558<emphasis>GtkTargetEntry</emphasis> array, in the same manner as above. Then
3559instead of the <emphasis>flags</emphasis> argument you substitute a mask for
3560the start mouse button of the drag. This could be <emphasis>GDK_BUTTON1_MASK |
3561GDK_BUTTON3_MASK</emphasis> for 1st and 3rd mouse buttons. Then you need to
3562bind the <emphasis>drag_data_get</emphasis> signal that will send the data for
3563the drag on it's way, and <emphasis>drag_data_delete</emphasis> if the action
3564is <emphasis>GDK_ACTION_MOVE</emphasis>, to delete the data since the move was
3565successful.  Here's a simple example that will work with the above code snippet
3566for drop:
3567
3568<informalexample><programlisting>
3569static void 
3570source_drag_data_get  (GtkWidget          *widget,
3571                       GdkDragContext     *context,
3572                       GtkSelectionData   *selection_data,
3573                       guint               info,
3574                       guint               time,
3575                       gpointer            data)
3576{
3577        char string[] = "Some String!";
3578        gtk_selection_data_set (selection_data,
3579                                selection_data-&gt;target,
3580                                8, string, sizeof(string));
3581}
3582...
3583static GtkTargetEntry target_table[] = {
3584        { "text/plain", 0, 0 }
3585};
3586...
3587gtk_drag_source_set (widget,
3588                     GDK_BUTTON1_MASK|GDK_BUTTON3_MASK,
3589                     target_table, 1,
3590                     GDK_ACTION_COPY);
3591gtk_signal_connect (GTK_OBJECT (widget), "drag_data_get",
3592                    GTK_SIGNAL_FUNC (source_drag_data_get),
3593                    NULL);
3594</programlisting></informalexample>
3595The <emphasis>gtk_selection_data_set</emphasis> function copies the data into the selection
3596data, which is used for the transfer.</para></sect2></sect1></chapter>
3597
3598<chapter id="building-gnome-apps">
3599<title>Building GNOME Apps</title>
3600<sect1 id="using-a-simple-makefile">
3601<title>Using a Simple Makefile</title>
3602
3603<para>
3604Using a simple makefile is the fastest way to compile a small GNOME
3605application. If you require a more sophisticated build environment,
3606you should use an autoconf/automake setup, which I will briefly talk about
3607later.
3608</para>
3609
3610<sect2>
3611<title>The gnome-config Script</title>
3612
3613<para>
3614The command line to the C compiler for building a GNOME application can be
3615quite long and would be hard to figure out by hand. So gnome-libs installs a
3616script to simplify this. It is called <emphasis>gnome-config</emphasis> and
3617it takes two options, <emphasis>--cflags</emphasis> and
3618<emphasis>--libs</emphasis>. The --cflags option will give you the compiler
3619flags, needed for the compilation step, and --libs will give you the
3620libraries you need to pass to the linker. You also need to pass another
3621set of arguments to gnome-config. It needs to know what libraries you wish
3622to use. For our purposes, this is <emphasis>gnome</emphasis> and
3623<emphasis>gnomeui</emphasis>. So for example to get the compiler flags
3624for some program using the standard gnome and gnomeui libraries, you would
3625call "gnome-config --cflags gnome gnomeui".
3626</para>
3627
3628</sect2>
3629
3630<sect2>
3631<title>A Simple Example Makefile</title>
3632
3633<para>
3634Now to build a simple makefile, you can use variables
3635<emphasis>CFLAGS</emphasis> and <emphasis>LDFLAGS</emphasis> and the implicit
3636rules that at least GNU make supports (others probably do as well, but I'm
3637not familiar with other makes). So for example let's say you have an
3638application that has a main.c, main.h, extra.c and extra.h and the executable
3639is called gnome-foo.Now let's build a small Makefile for this app.
3640<informalexample><programlisting>
3641CFLAGS=-g -Wall `gnome-config --cflags gnome gnomeui`
3642LDFLAGS=`gnome-config --libs gnome gnomeui`
3643
3644all: gnome-foo
3645
3646gnome-foo: main.o extra.o
3647main.o: main.c main.h extra.h
3648extra.o: extra.c extra.h
3649
3650clean:
3651        rm -f core *.o gnome-foo
3652</programlisting></informalexample>
3653This is an extremely simple makefile, but it should get you started.
3654</para>
3655</sect2>
3656
3657</sect1>
3658
3659<sect1 id="using-autoconf-automake">
3660<title>Using automake/autoconf</title>
3661
3662<para>
3663Using automake and autoconf is really beyond the scope of this document,
3664but you should go read manuals online at
3665<ulink url="http://www.gnu.org/manual/manual.html">
3666http://www.gnu.org/manual/manual.html</ulink>, or read the info pages if
3667you have them installed with gnome-help-browser.
3668</para>
3669
3670<para>
3671There is now an example application which can help you get started with
3672autoconf/automake, the internationalization setup, and other build issues,
3673as well as serve as a good hello world example. You can get it at
3674any gnome ftp site mirror (go to
3675<ulink url="http://www.gnome.org/ftpmirrors.shtml">
3676http://www.gnome.org/ftpmirrors.shtml</ulink> for a list of mirrors) in the
3677<emphasis>sources/GnomeHello/</emphasis> directory.
3678</para>
3679
3680</sect1>
3681</chapter>
3682
3683
3684<chapter id="conclusion">
3685<title>Conclusion</title>
3686<sect1 id="getting-further-help">
3687<title>Getting Further Help</title>
3688
3689<para>
3690One of the best ways to get help with programming in gnome is probably
3691to first read the available documentation at
3692<ulink url="http://www.gnome.org/">www.gnome.org</ulink>, or the developer
3693web site at <ulink url="http://developer.gnome.org/">developer.gnome.org
3694</ulink>. You should also subscribe to the
3695<ulink url="mailto:gnome-devel-list@gnome.org">gnome-devel-list@gnome.org
3696</ulink>, to subscribe, send a message with <emphasis>subscribe</emphasis>
3697in the subject line to <ulink url="mailto:gnome-devel-list-request@gnome.org">
3698gnome-devel-list-request@gnome.org</ulink>. To reduce the traffic on the
3699list you should first consult the documentation before asking a question.
3700Also look at <ulink url="http://www.gnome.org/mailing-lists/">
3701www.gnome.org/mailing-lists/</ulink> for a list of all GNOME relevant
3702mailing lists, including the <emphasis>GTK+</emphasis> list.</para>
3703
3704<para>
3705However I still consider the header files for the libraries most helpful.
3706This is mostly as there isn't yet as much documentation out there as there
3707should be, but also the header files will always contain all of the
3708definitions and they will be up to date with the current version,
3709which a manual might not be. Most GTK+ and GNOME function names are very
3710descriptive and it's easy to figure out what they do. I use the header files
3711only. It's much easier to just look at the function prototype and figure out
3712what it does, then to hunt around in a reference manual. Then again you
3713usually have to know what header file to look at, which is not all
3714that hard, given that the header files are named by the objects or modules
3715they represent. For example the header file for <emphasis>gnome-config</emphasis> is
3716<emphasis>libgnome/gnome-config.h</emphasis>. The header file for <emphasis>GnomeCanvas</emphasis>
3717is <emphasis>libgnomeui/gnome-canvas.h</emphasis>.</para></sect1>
3718
3719<sect1 id="future-gnome-library-developments">
3720<title>Future GNOME Library Developments</title>
3721
3722<para>
3723This tutorial covers programming with version 1.0 of the gnome libraries.
3724But of course there is life after 1.0. There are many things still planned
3725for the libraries. But don't worry, we will try to keep as much compatibility
3726with the 1.0 version as humanely possible.</para>
3727
3728<para>
3729Here's a short list of things that will be or currently is worked on.
3730
3731
3732<variablelist>
3733<varlistentry><term></term>
3734<listitem><para>
3735More common dialogs, such as a native gnome file picker dialog.</para></listitem></varlistentry>
3736<varlistentry><term></term>
3737<listitem><para>
3738More corba integration of the entire desktop. This is including much
3739more corba support from the core libraries.</para></listitem></varlistentry>
3740<varlistentry><term></term>
3741<listitem><para>
3742Better canvas, including better alpha channel support and printing directly
3743from the canvas.</para></listitem></varlistentry>
3744<varlistentry><term></term>
3745<listitem><para>
3746Rewrite of the configuration setup.</para></listitem></varlistentry>
3747<varlistentry><term></term>
3748<listitem><para>
3749Much much more! ... Stuff we haven't even thought of yet!</para></listitem></varlistentry>
3750</variablelist></para></sect1></chapter>
3751
3752</book>
Note: See TracBrowser for help on using the repository browser.