source: trunk/third/gtk/docs/html/gtk_tut-10.html @ 14810

Revision 14810, 66.9 KB checked in by ghudson, 25 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14809, which included commits to RCS files with non-trunk default branches.
Line 
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
2<HTML>
3<HEAD>
4 <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
5 <TITLE>GTK v1.2 Tutorial: Container Widgets</TITLE>
6 <LINK HREF="gtk_tut-11.html" REL=next>
7 <LINK HREF="gtk_tut-9.html" REL=previous>
8 <LINK HREF="gtk_tut.html#toc10" REL=contents>
9</HEAD>
10<BODY BGCOLOR="#FFFFFF">
11<A HREF="gtk_tut-11.html">Next</A>
12<A HREF="gtk_tut-9.html">Previous</A>
13<A HREF="gtk_tut.html#toc10">Contents</A>
14<HR NOSHADE>
15<H2><A NAME="s10">10. Container Widgets</A> </H2>
16
17<H2><A NAME="sec_EventBox"></A> <A NAME="ss10.1">10.1 The EventBox </A>
18</H2>
19
20<P> 
21Some GTK widgets don't have associated X windows, so they just draw on
22their parents. Because of this, they cannot receive events and if they
23are incorrectly sized, they don't clip so you can get messy
24overwriting, etc. If you require more from these widgets, the EventBox
25is for you.
26<P>At first glance, the EventBox widget might appear to be totally
27useless. It draws nothing on the screen and responds to no
28events. However, it does serve a function - it provides an X window
29for its child widget. This is important as many GTK widgets do not
30have an associated X window. Not having an X window saves memory and
31improves performance, but also has some drawbacks. A widget without an
32X window cannot receive events, and does not perform any clipping on
33its contents. Although the name <EM>EventBox</EM> emphasizes the
34event-handling function, the widget can also be used for clipping.
35(and more, see the example below).
36<P>To create a new EventBox widget, use:
37<P>
38<BLOCKQUOTE><CODE>
39<PRE>
40GtkWidget *gtk_event_box_new( void );
41</PRE>
42</CODE></BLOCKQUOTE>
43<P>A child widget can then be added to this EventBox:
44<P>
45<BLOCKQUOTE><CODE>
46<PRE>
47    gtk_container_add( GTK_CONTAINER(event_box), child_widget );
48</PRE>
49</CODE></BLOCKQUOTE>
50<P>The following example demonstrates both uses of an EventBox - a label
51is created that is clipped to a small box, and set up so that a
52mouse-click on the label causes the program to exit. Resizing the
53window reveals varying amounts of the label.
54<P>
55<BLOCKQUOTE><CODE>
56<PRE>
57/* example-start eventbox eventbox.c */
58
59#include &lt;gtk/gtk.h>
60
61int main( int argc,
62          char *argv[] )
63{
64    GtkWidget *window;
65    GtkWidget *event_box;
66    GtkWidget *label;
67   
68    gtk_init (&amp;argc, &amp;argv);
69   
70    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
71   
72    gtk_window_set_title (GTK_WINDOW (window), "Event Box");
73   
74    gtk_signal_connect (GTK_OBJECT (window), "destroy",
75                        GTK_SIGNAL_FUNC (gtk_exit), NULL);
76   
77    gtk_container_set_border_width (GTK_CONTAINER (window), 10);
78   
79    /* Create an EventBox and add it to our toplevel window */
80   
81    event_box = gtk_event_box_new ();
82    gtk_container_add (GTK_CONTAINER(window), event_box);
83    gtk_widget_show (event_box);
84   
85    /* Create a long label */
86   
87    label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
88    gtk_container_add (GTK_CONTAINER (event_box), label);
89    gtk_widget_show (label);
90   
91    /* Clip it short. */
92    gtk_widget_set_usize (label, 110, 20);
93   
94    /* And bind an action to it */
95    gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
96    gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
97                        GTK_SIGNAL_FUNC (gtk_exit), NULL);
98   
99    /* Yet one more thing you need an X window for ... */
100   
101    gtk_widget_realize (event_box);
102    gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
103   
104    gtk_widget_show (window);
105   
106    gtk_main ();
107   
108    return(0);
109}
110/* example-end */
111</PRE>
112</CODE></BLOCKQUOTE>
113<P>  
114<H2><A NAME="sec_Alignment"></A> <A NAME="ss10.2">10.2 The Alignment widget </A>
115</H2>
116
117<P>The alignment widget allows you to place a widget within its window at
118a position and size relative to the size of the Alignment widget
119itself. For example, it can be very useful for centering a widget
120within the window.
121<P>There are only two functions associated with the Alignment widget:
122<P>
123<BLOCKQUOTE><CODE>
124<PRE>
125GtkWidget* gtk_alignment_new( gfloat xalign,
126                              gfloat yalign,
127                              gfloat xscale,
128                              gfloat yscale );
129
130void gtk_alignment_set( GtkAlignment *alignment,
131                        gfloat        xalign,
132                        gfloat        yalign,
133                        gfloat        xscale,
134                        gfloat        yscale );
135</PRE>
136</CODE></BLOCKQUOTE>
137<P>The first function creates a new Alignment widget with the specified
138parameters. The second function allows the alignment paramters of an
139exisiting Alignment widget to be altered.
140<P>All four alignment parameters are floating point numbers which can
141range from 0.0 to 1.0. The <CODE>xalign</CODE> and <CODE>yalign</CODE> arguments
142affect the position of the widget placed within the Alignment
143widget. The <CODE>xscale</CODE> and <CODE>yscale</CODE> arguments effect the amount of
144space allocated to the widget.
145<P>A child widget can be added to this Alignment widget using:
146<P>
147<BLOCKQUOTE><CODE>
148<PRE>
149    gtk_container_add( GTK_CONTAINER(alignment), child_widget );
150</PRE>
151</CODE></BLOCKQUOTE>
152<P>For an example of using an Alignment widget, refer to the example for
153the
154<A HREF="gtk_tut-9.html#sec_ProgressBar">Progress Bar</A> widget.
155<P>
156<H2><A NAME="ss10.3">10.3 Fixed Container</A>
157</H2>
158
159<P>The Fixed container allows you to place widgets at a fixed position
160within its window, relative to its upper left hand corner. The
161position of the widgets can be changed dynamically.
162<P>There are only three functions associated with the fixed widget:
163<P>
164<BLOCKQUOTE><CODE>
165<PRE>
166GtkWidget* gtk_fixed_new( void );
167
168void gtk_fixed_put( GtkFixed  *fixed,
169                    GtkWidget *widget,
170                    gint16     x,
171                    gint16     y );
172
173void gtk_fixed_move( GtkFixed  *fixed,
174                     GtkWidget *widget,
175                     gint16     x,
176                     gint16     y );
177</PRE>
178</CODE></BLOCKQUOTE>
179<P>The function <CODE>gtk_fixed_new</CODE> allows you to create a new Fixed
180container.
181<P><CODE>gtk_fixed_put</CODE> places <CODE>widget</CODE> in the container <CODE>fixed</CODE> at
182the position specified by <CODE>x</CODE> and <CODE>y</CODE>.
183<P><CODE>gtk_fixed_move</CODE> allows the specified widget to be moved to a new
184position.
185<P>The following example illustrates how to use the Fixed Container.
186<P>
187<BLOCKQUOTE><CODE>
188<PRE>
189/* example-start fixed fixed.c */
190
191#include &lt;gtk/gtk.h>
192
193/* I'm going to be lazy and use some global variables to
194 * store the position of the widget within the fixed
195 * container */
196gint x=50;
197gint y=50;
198
199/* This callback function moves the button to a new position
200 * in the Fixed container. */
201void move_button( GtkWidget *widget,
202                  GtkWidget *fixed )
203{
204  x = (x+30)%300;
205  y = (y+50)%300;
206  gtk_fixed_move( GTK_FIXED(fixed), widget, x, y);
207}
208
209int main( int   argc,
210          char *argv[] )
211{
212  /* GtkWidget is the storage type for widgets */
213  GtkWidget *window;
214  GtkWidget *fixed;
215  GtkWidget *button;
216  gint i;
217
218  /* Initialise GTK */
219  gtk_init(&amp;argc, &amp;argv);
220   
221  /* Create a new window */
222  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
223  gtk_window_set_title(GTK_WINDOW(window), "Fixed Container");
224
225  /* Here we connect the "destroy" event to a signal handler */
226  gtk_signal_connect (GTK_OBJECT (window), "destroy",
227                      GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
228 
229  /* Sets the border width of the window. */
230  gtk_container_set_border_width (GTK_CONTAINER (window), 10);
231
232  /* Create a Fixed Container */
233  fixed = gtk_fixed_new();
234  gtk_container_add(GTK_CONTAINER(window), fixed);
235  gtk_widget_show(fixed);
236 
237  for (i = 1 ; i &lt;= 3 ; i++) {
238    /* Creates a new button with the label "Press me" */
239    button = gtk_button_new_with_label ("Press me");
240 
241    /* When the button receives the "clicked" signal, it will call the
242     * function move_button() passing it the Fixed Container as its
243     * argument. */
244    gtk_signal_connect (GTK_OBJECT (button), "clicked",
245                        GTK_SIGNAL_FUNC (move_button), fixed);
246 
247    /* This packs the button into the fixed containers window. */
248    gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50);
249 
250    /* The final step is to display this newly created widget. */
251    gtk_widget_show (button);
252  }
253
254  /* Display the window */
255  gtk_widget_show (window);
256   
257  /* Enter the event loop */
258  gtk_main ();
259   
260  return(0);
261}
262/* example-end */
263</PRE>
264</CODE></BLOCKQUOTE>
265<P>
266<H2><A NAME="ss10.4">10.4 Layout Container</A>
267</H2>
268
269<P>The Layout container is similar to the Fixed container except that it
270implements an infinite (where infinity is less than 2^32) scrolling
271area. The X window system has a limitation where windows can be at
272most 32767 pixels wide or tall. The Layout container gets around this
273limitation by doing some exotic stuff using window and bit gravities,
274so that you can have smooth scrolling even when you have many child
275widgets in your scrolling area.
276<P>A Layout container is created using:
277<P>
278<BLOCKQUOTE><CODE>
279<PRE>
280GtkWidget *gtk_layout_new( GtkAdjustment *hadjustment,
281                           GtkAdjustment *vadjustment );
282</PRE>
283</CODE></BLOCKQUOTE>
284<P>As you can see, you can optionally specify the Adjustment objects that
285the Layout widget will use for its scrolling.
286<P>You can add and move widgets in the Layout container using the
287following two functions:
288<P>
289<BLOCKQUOTE><CODE>
290<PRE>
291void gtk_layout_put( GtkLayout *layout,
292                     GtkWidget *widget,
293                     gint       x,
294                     gint       y );
295
296void gtk_layout_move( GtkLayout *layout,
297                      GtkWidget *widget,
298                      gint       x,
299                      gint       y );
300</PRE>
301</CODE></BLOCKQUOTE>
302<P>The size of the Layout container can be set using the next function:
303<P>
304<BLOCKQUOTE><CODE>
305<PRE>
306void gtk_layout_set_size( GtkLayout *layout,
307                          guint      width,
308                          guint      height );
309</PRE>
310</CODE></BLOCKQUOTE>
311<P>Layout containers are one of the very few widgets in the GTK widget
312set that actively repaint themselves on screen as they are changed
313using the above functions (the vast majority of widgets queue
314requests which are then processed when control returns to the
315<CODE>gtk_main()</CODE> function).
316<P>When you want to make a large number of changes to a Layout container,
317you can use the following two functions to disable and re-enable this
318repainting functionality:
319<P>
320<BLOCKQUOTE><CODE>
321<PRE>
322void gtk_layout_freeze( GtkLayout *layout );
323
324void gtk_layout_thaw( GtkLayout *layout );
325</PRE>
326</CODE></BLOCKQUOTE>
327<P>The final four functions for use with Layout widgets are for
328manipulating the horizontal and vertical adjustment widgets:
329<P>
330<BLOCKQUOTE><CODE>
331<PRE>
332GtkAdjustment* gtk_layout_get_hadjustment( GtkLayout *layout );
333
334GtkAdjustment* gtk_layout_get_vadjustment( GtkLayout *layout );
335
336void gtk_layout_set_hadjustment( GtkLayout     *layout,
337                                 GtkAdjustment *adjustment );
338
339void gtk_layout_set_vadjustment( GtkLayout     *layout,
340                                 GtkAdjustment *adjustment);
341</PRE>
342</CODE></BLOCKQUOTE>
343<P>
344<H2><A NAME="sec_Frames"></A> <A NAME="ss10.5">10.5 Frames </A>
345</H2>
346
347<P>Frames can be used to enclose one or a group of widgets with a box
348which can optionally be labelled. The position of the label and the
349style of the box can be altered to suit.
350<P>A Frame can be created with the following function:
351<P>
352<BLOCKQUOTE><CODE>
353<PRE>
354GtkWidget *gtk_frame_new( const gchar *label );
355</PRE>
356</CODE></BLOCKQUOTE>
357<P>The label is by default placed in the upper left hand corner of the
358frame. A value of NULL for the <CODE>label</CODE> argument will result in no
359label being displayed. The text of the label can be changed using the
360next function.
361<P>
362<BLOCKQUOTE><CODE>
363<PRE>
364void gtk_frame_set_label( GtkFrame    *frame,
365                          const gchar *label );
366</PRE>
367</CODE></BLOCKQUOTE>
368<P>The position of the label can be changed using this function:
369<P>
370<BLOCKQUOTE><CODE>
371<PRE>
372void gtk_frame_set_label_align( GtkFrame *frame,
373                                gfloat    xalign,
374                                gfloat    yalign );
375</PRE>
376</CODE></BLOCKQUOTE>
377<P><CODE>xalign</CODE> and <CODE>yalign</CODE> take values between 0.0 and 1.0. <CODE>xalign</CODE>
378indicates the position of the label along the top horizontal of the
379frame. <CODE>yalign</CODE> is not currently used. The default value of xalign
380is 0.0 which places the label at the left hand end of the frame.
381<P>The next function alters the style of the box that is used to outline
382the frame.
383<P>
384<BLOCKQUOTE><CODE>
385<PRE>
386void gtk_frame_set_shadow_type( GtkFrame      *frame,
387                                GtkShadowType  type);
388</PRE>
389</CODE></BLOCKQUOTE>
390<P>The <CODE>type</CODE> argument can take one of the following values:
391<BLOCKQUOTE><CODE>
392<PRE>
393  GTK_SHADOW_NONE
394  GTK_SHADOW_IN
395  GTK_SHADOW_OUT
396  GTK_SHADOW_ETCHED_IN (the default)
397  GTK_SHADOW_ETCHED_OUT
398</PRE>
399</CODE></BLOCKQUOTE>
400<P>The following code example illustrates the use of the Frame widget.
401<P>
402<BLOCKQUOTE><CODE>
403<PRE>
404/* example-start frame frame.c */
405
406#include &lt;gtk/gtk.h>
407
408int main( int   argc,
409          char *argv[] )
410{
411  /* GtkWidget is the storage type for widgets */
412  GtkWidget *window;
413  GtkWidget *frame;
414  GtkWidget *button;
415  gint i;
416
417  /* Initialise GTK */
418  gtk_init(&amp;argc, &amp;argv);
419   
420  /* Create a new window */
421  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
422  gtk_window_set_title(GTK_WINDOW(window), "Frame Example");
423
424  /* Here we connect the "destroy" event to a signal handler */
425  gtk_signal_connect (GTK_OBJECT (window), "destroy",
426                      GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
427
428  gtk_widget_set_usize(window, 300, 300);
429  /* Sets the border width of the window. */
430  gtk_container_set_border_width (GTK_CONTAINER (window), 10);
431
432  /* Create a Frame */
433  frame = gtk_frame_new(NULL);
434  gtk_container_add(GTK_CONTAINER(window), frame);
435
436  /* Set the frame's label */
437  gtk_frame_set_label( GTK_FRAME(frame), "GTK Frame Widget" );
438
439  /* Align the label at the right of the frame */
440  gtk_frame_set_label_align( GTK_FRAME(frame), 1.0, 0.0);
441
442  /* Set the style of the frame */
443  gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
444
445  gtk_widget_show(frame);
446 
447  /* Display the window */
448  gtk_widget_show (window);
449   
450  /* Enter the event loop */
451  gtk_main ();
452   
453  return(0);
454}
455/* example-end */
456</PRE>
457</CODE></BLOCKQUOTE>
458<P>  
459<H2><A NAME="ss10.6">10.6 Aspect Frames</A>
460</H2>
461
462<P>The aspect frame widget is like a frame widget, except that it also
463enforces the aspect ratio (that is, the ratio of the width to the
464height) of the child widget to have a certain value, adding extra
465space if necessary. This is useful, for instance, if you want to
466preview a larger image. The size of the preview should vary when the
467user resizes the window, but the aspect ratio needs to always match
468the original image.
469<P>To create a new aspect frame use:
470<P>
471<BLOCKQUOTE><CODE>
472<PRE>
473GtkWidget *gtk_aspect_frame_new( const gchar *label,
474                                 gfloat       xalign,
475                                 gfloat       yalign,
476                                 gfloat       ratio,
477                                 gint         obey_child);
478</PRE>
479</CODE></BLOCKQUOTE>
480<P><CODE>xalign</CODE> and <CODE>yalign</CODE> specify alignment as with Alignment
481widgets. If <CODE>obey_child</CODE> is true, the aspect ratio of a child
482widget will match the aspect ratio of the ideal size it requests.
483Otherwise, it is given by <CODE>ratio</CODE>.
484<P>To change the options of an existing aspect frame, you can use:
485<P>
486<BLOCKQUOTE><CODE>
487<PRE>
488void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
489                           gfloat          xalign,
490                           gfloat          yalign,
491                           gfloat          ratio,
492                           gint            obey_child);
493</PRE>
494</CODE></BLOCKQUOTE>
495<P>As an example, the following program uses an AspectFrame to present a
496drawing area whose aspect ratio will always be 2:1, no matter how the
497user resizes the top-level window.
498<P>
499<BLOCKQUOTE><CODE>
500<PRE>
501/* example-start aspectframe aspectframe.c */
502
503#include &lt;gtk/gtk.h>
504   
505int main( int argc,
506          char *argv[] )
507{
508    GtkWidget *window;
509    GtkWidget *aspect_frame;
510    GtkWidget *drawing_area;
511    gtk_init (&amp;argc, &amp;argv);
512   
513    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
514    gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
515    gtk_signal_connect (GTK_OBJECT (window), "destroy",
516                        GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
517    gtk_container_set_border_width (GTK_CONTAINER (window), 10);
518   
519    /* Create an aspect_frame and add it to our toplevel window */
520   
521    aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
522                                         0.5, /* center x */
523                                         0.5, /* center y */
524                                         2, /* xsize/ysize = 2 */
525                                         FALSE /* ignore child's aspect */);
526   
527    gtk_container_add (GTK_CONTAINER(window), aspect_frame);
528    gtk_widget_show (aspect_frame);
529   
530    /* Now add a child widget to the aspect frame */
531   
532    drawing_area = gtk_drawing_area_new ();
533   
534    /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
535     * window since we are forcing a 2x1 aspect ratio */
536    gtk_widget_set_usize (drawing_area, 200, 200);
537    gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
538    gtk_widget_show (drawing_area);
539   
540    gtk_widget_show (window);
541    gtk_main ();
542    return 0;
543}
544/* example-end */
545</PRE>
546</CODE></BLOCKQUOTE>
547<P>  
548<H2><A NAME="ss10.7">10.7 Paned Window Widgets</A>
549</H2>
550
551<P>The paned window widgets are useful when you want to divide an area
552into two parts, with the relative size of the two parts controlled by
553the user. A groove is drawn between the two portions with a handle
554that the user can drag to change the ratio. The division can either be
555horizontal (HPaned) or vertical (VPaned).
556<P>To create a new paned window, call one of:
557<P>
558<BLOCKQUOTE><CODE>
559<PRE>
560GtkWidget *gtk_hpaned_new (void);
561
562GtkWidget *gtk_vpaned_new (void);
563</PRE>
564</CODE></BLOCKQUOTE>
565<P>After creating the paned window widget, you need to add child widgets
566to its two halves. To do this, use the functions:
567<P>
568<BLOCKQUOTE><CODE>
569<PRE>
570void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
571
572void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
573</PRE>
574</CODE></BLOCKQUOTE>
575<P><CODE>gtk_paned_add1()</CODE> adds the child widget to the left or top half of
576the paned window. <CODE>gtk_paned_add2()</CODE> adds the child widget to the
577right or bottom half of the paned window.
578<P>A paned widget can be changed visually using the following two
579functions.
580<P>
581<BLOCKQUOTE><CODE>
582<PRE>
583void gtk_paned_set_handle_size( GtkPaned *paned,
584                                guint16   size);
585
586void gtk_paned_set_gutter_size( GtkPaned *paned,
587                                guint16   size);
588</PRE>
589</CODE></BLOCKQUOTE>
590<P>The first of these sets the size of the handle and the second sets the
591size of the gutter that is between the two parts of the paned window.
592<P>As an example, we will create part of the user interface of an
593imaginary email program. A window is divided into two portions
594vertically, with the top portion being a list of email messages and
595the bottom portion the text of the email message. Most of the program
596is pretty straightforward. A couple of points to note: text can't be
597added to a Text widget until it is realized. This could be done by
598calling <CODE>gtk_widget_realize()</CODE>, but as a demonstration of an
599alternate technique, we connect a handler to the "realize" signal to
600add the text. Also, we need to add the <CODE>GTK_SHRINK</CODE> option to some
601of the items in the table containing the text window and its
602scrollbars, so that when the bottom portion is made smaller, the
603correct portions shrink instead of being pushed off the bottom of the
604window.
605<P>
606<BLOCKQUOTE><CODE>
607<PRE>
608/* example-start paned paned.c */
609
610#include &lt;stdio.h>
611#include &lt;gtk/gtk.h>
612   
613/* Create the list of "messages" */
614GtkWidget *create_list( void )
615{
616
617    GtkWidget *scrolled_window;
618    GtkWidget *list;
619    GtkWidget *list_item;
620   
621    int i;
622    char buffer[16];
623   
624    /* Create a new scrolled window, with scrollbars only if needed */
625    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
626    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
627                                    GTK_POLICY_AUTOMATIC,
628                                    GTK_POLICY_AUTOMATIC);
629   
630    /* Create a new list and put it in the scrolled window */
631    list = gtk_list_new ();
632    gtk_scrolled_window_add_with_viewport (
633               GTK_SCROLLED_WINDOW (scrolled_window), list);
634    gtk_widget_show (list);
635   
636    /* Add some messages to the window */
637    for (i=0; i&lt;10; i++) {
638
639        sprintf(buffer,"Message #%d",i);
640        list_item = gtk_list_item_new_with_label (buffer);
641        gtk_container_add (GTK_CONTAINER(list), list_item);
642        gtk_widget_show (list_item);
643
644    }
645   
646    return scrolled_window;
647}
648   
649/* Add some text to our text widget - this is a callback that is invoked
650when our window is realized. We could also force our window to be
651realized with gtk_widget_realize, but it would have to be part of
652a hierarchy first */
653
654void realize_text( GtkWidget *text,
655                   gpointer data )
656{
657    gtk_text_freeze (GTK_TEXT (text));
658    gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
659    "From: pathfinder@nasa.gov\n"
660    "To: mom@nasa.gov\n"
661    "Subject: Made it!\n"
662    "\n"
663    "We just got in this morning. The weather has been\n"
664    "great - clear but cold, and there are lots of fun sights.\n"
665    "Sojourner says hi. See you soon.\n"
666    " -Path\n", -1);
667   
668    gtk_text_thaw (GTK_TEXT (text));
669}
670   
671/* Create a scrolled text area that displays a "message" */
672GtkWidget *create_text( void )
673{
674    GtkWidget *table;
675    GtkWidget *text;
676    GtkWidget *hscrollbar;
677    GtkWidget *vscrollbar;
678   
679    /* Create a table to hold the text widget and scrollbars */
680    table = gtk_table_new (2, 2, FALSE);
681   
682    /* Put a text widget in the upper left hand corner. Note the use of
683     * GTK_SHRINK in the y direction */
684    text = gtk_text_new (NULL, NULL);
685    gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
686                      GTK_FILL | GTK_EXPAND,
687                      GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
688    gtk_widget_show (text);
689   
690    /* Put a HScrollbar in the lower left hand corner */
691    hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
692    gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
693                      GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
694    gtk_widget_show (hscrollbar);
695   
696    /* And a VScrollbar in the upper right */
697    vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
698    gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
699                      GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
700    gtk_widget_show (vscrollbar);
701   
702    /* Add a handler to put a message in the text widget when it is realized */
703    gtk_signal_connect (GTK_OBJECT (text), "realize",
704                        GTK_SIGNAL_FUNC (realize_text), NULL);
705   
706    return table;
707}
708   
709int main( int   argc,
710          char *argv[] )
711{
712    GtkWidget *window;
713    GtkWidget *vpaned;
714    GtkWidget *list;
715    GtkWidget *text;
716
717    gtk_init (&amp;argc, &amp;argv);
718   
719    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
720    gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
721    gtk_signal_connect (GTK_OBJECT (window), "destroy",
722                        GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
723    gtk_container_set_border_width (GTK_CONTAINER (window), 10);
724    gtk_widget_set_usize (GTK_WIDGET(window), 450, 400);
725
726    /* create a vpaned widget and add it to our toplevel window */
727   
728    vpaned = gtk_vpaned_new ();
729    gtk_container_add (GTK_CONTAINER(window), vpaned);
730    gtk_paned_set_handle_size (GTK_PANED(vpaned),
731                               10);
732    gtk_paned_set_gutter_size (GTK_PANED(vpaned),
733                               15);                       
734    gtk_widget_show (vpaned);
735   
736    /* Now create the contents of the two halves of the window */
737   
738    list = create_list ();
739    gtk_paned_add1 (GTK_PANED(vpaned), list);
740    gtk_widget_show (list);
741   
742    text = create_text ();
743    gtk_paned_add2 (GTK_PANED(vpaned), text);
744    gtk_widget_show (text);
745    gtk_widget_show (window);
746    gtk_main ();
747    return 0;
748}
749/* example-end */
750</PRE>
751</CODE></BLOCKQUOTE>
752<P>
753<H2><A NAME="sec_Viewports"></A> <A NAME="ss10.8">10.8 Viewports </A>
754</H2>
755
756<P>It is unlikely that you will ever need to use the Viewport widget
757directly. You are much more likely to use the
758<A HREF="#sec_ScrolledWindow">Scrolled Window</A> widget which
759itself uses the Viewport.
760<P>A viewport widget allows you to place a larger widget within it such
761that you can view a part of it at a time. It uses
762<A HREF="gtk_tut-7.html#sec_Adjustment">Adjustments</A> to define the area that
763is currently in view.
764<P>A Viewport is created with the function
765<P>
766<BLOCKQUOTE><CODE>
767<PRE>
768GtkWidget *gtk_viewport_new( GtkAdjustment *hadjustment,
769                             GtkAdjustment *vadjustment );
770</PRE>
771</CODE></BLOCKQUOTE>
772<P>As you can see you can specify the horizontal and vertical Adjustments
773that the widget is to use when you create the widget. It will create
774its own if you pass NULL as the value of the arguments.
775<P>You can get and set the adjustments after the widget has been created
776using the following four functions:
777<P>
778<BLOCKQUOTE><CODE>
779<PRE>
780GtkAdjustment *gtk_viewport_get_hadjustment (GtkViewport *viewport );
781
782GtkAdjustment *gtk_viewport_get_vadjustment (GtkViewport *viewport );
783
784void gtk_viewport_set_hadjustment( GtkViewport   *viewport,
785                                   GtkAdjustment *adjustment );
786
787void gtk_viewport_set_vadjustment( GtkViewport   *viewport,
788                                   GtkAdjustment *adjustment );
789</PRE>
790</CODE></BLOCKQUOTE>
791<P>The only other viewport function is used to alter its appearance:
792<P>
793<BLOCKQUOTE><CODE>
794<PRE>
795void gtk_viewport_set_shadow_type( GtkViewport   *viewport,
796                                   GtkShadowType  type );
797</PRE>
798</CODE></BLOCKQUOTE>
799<P>Possible values for the <CODE>type</CODE> parameter are:
800<BLOCKQUOTE><CODE>
801<PRE>
802  GTK_SHADOW_NONE,
803  GTK_SHADOW_IN,
804  GTK_SHADOW_OUT,
805  GTK_SHADOW_ETCHED_IN,
806  GTK_SHADOW_ETCHED_OUT
807</PRE>
808</CODE></BLOCKQUOTE>
809<P>
810<H2><A NAME="sec_ScrolledWindow"></A> <A NAME="ss10.9">10.9 Scrolled Windows </A>
811</H2>
812
813<P>Scrolled windows are used to create a scrollable area with another
814widget inside it. You may insert any type of widget into a scrolled
815window, and it will be accessible regardless of the size by using the
816scrollbars.
817<P>The following function is used to create a new scrolled window.
818<P>
819<BLOCKQUOTE><CODE>
820<PRE>
821GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
822                                    GtkAdjustment *vadjustment );
823</PRE>
824</CODE></BLOCKQUOTE>
825<P>Where the first argument is the adjustment for the horizontal
826direction, and the second, the adjustment for the vertical direction.
827These are almost always set to NULL.
828<P>
829<BLOCKQUOTE><CODE>
830<PRE>
831void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
832                                     GtkPolicyType      hscrollbar_policy,
833                                     GtkPolicyType      vscrollbar_policy );
834</PRE>
835</CODE></BLOCKQUOTE>
836<P>This sets the policy to be used with respect to the scrollbars.
837The first argument is the scrolled window you wish to change. The second
838sets the policy for the horizontal scrollbar, and the third the policy for
839the vertical scrollbar.
840<P>The policy may be one of <CODE>GTK_POLICY_AUTOMATIC</CODE> or
841<CODE>GTK_POLICY_ALWAYS</CODE>. <CODE>GTK_POLICY_AUTOMATIC</CODE> will automatically
842decide whether you need scrollbars, whereas <CODE>GTK_POLICY_ALWAYS</CODE>
843will always leave the scrollbars there.
844<P>You can then place your object into the scrolled window using the
845following function.
846<P>
847<BLOCKQUOTE><CODE>
848<PRE>
849void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
850                                            GtkWidget         *child);
851</PRE>
852</CODE></BLOCKQUOTE>
853<P>Here is a simple example that packs a table eith 100 toggle buttons
854into a scrolled window. I've only commented on the parts that may be
855new to you.
856<P>
857<BLOCKQUOTE><CODE>
858<PRE>
859/* example-start scrolledwin scrolledwin.c */
860
861#include &lt;stdio.h>
862#include &lt;gtk/gtk.h>
863
864void destroy( GtkWidget *widget,
865              gpointer   data )
866{
867    gtk_main_quit();
868}
869
870int main( int   argc,
871          char *argv[] )
872{
873    static GtkWidget *window;
874    GtkWidget *scrolled_window;
875    GtkWidget *table;
876    GtkWidget *button;
877    char buffer[32];
878    int i, j;
879   
880    gtk_init (&amp;argc, &amp;argv);
881   
882    /* Create a new dialog window for the scrolled window to be
883     * packed into.  */
884    window = gtk_dialog_new ();
885    gtk_signal_connect (GTK_OBJECT (window), "destroy",
886                        (GtkSignalFunc) destroy, NULL);
887    gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
888    gtk_container_set_border_width (GTK_CONTAINER (window), 0);
889    gtk_widget_set_usize(window, 300, 300);
890   
891    /* create a new scrolled window. */
892    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
893   
894    gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
895   
896    /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
897     * GTK_POLICY_AUTOMATIC will automatically decide whether you need
898     * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
899     * there.  The first one is the horizontal scrollbar, the second,
900     * the vertical. */
901    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
902                                    GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
903    /* The dialog window is created with a vbox packed into it. */                                                             
904    gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window,
905                        TRUE, TRUE, 0);
906    gtk_widget_show (scrolled_window);
907   
908    /* create a table of 10 by 10 squares. */
909    table = gtk_table_new (10, 10, FALSE);
910   
911    /* set the spacing to 10 on x and 10 on y */
912    gtk_table_set_row_spacings (GTK_TABLE (table), 10);
913    gtk_table_set_col_spacings (GTK_TABLE (table), 10);
914   
915    /* pack the table into the scrolled window */
916    gtk_scrolled_window_add_with_viewport (
917                   GTK_SCROLLED_WINDOW (scrolled_window), table);
918    gtk_widget_show (table);
919   
920    /* this simply creates a grid of toggle buttons on the table
921     * to demonstrate the scrolled window. */
922    for (i = 0; i &lt; 10; i++)
923       for (j = 0; j &lt; 10; j++) {
924          sprintf (buffer, "button (%d,%d)\n", i, j);
925          button = gtk_toggle_button_new_with_label (buffer);
926          gtk_table_attach_defaults (GTK_TABLE (table), button,
927                                     i, i+1, j, j+1);
928          gtk_widget_show (button);
929       }
930   
931    /* Add a "close" button to the bottom of the dialog */
932    button = gtk_button_new_with_label ("close");
933    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
934                               (GtkSignalFunc) gtk_widget_destroy,
935                               GTK_OBJECT (window));
936   
937    /* this makes it so the button is the default. */
938   
939    GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
940    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
941   
942    /* This grabs this button to be the default button. Simply hitting
943     * the "Enter" key will cause this button to activate. */
944    gtk_widget_grab_default (button);
945    gtk_widget_show (button);
946   
947    gtk_widget_show (window);
948   
949    gtk_main();
950   
951    return(0);
952}
953/* example-end */
954</PRE>
955</CODE></BLOCKQUOTE>
956<P>Try playing with resizing the window. You'll notice how the scrollbars
957react. You may also wish to use the gtk_widget_set_usize() call to set
958the default size of the window or other widgets.
959<P>  
960<H2><A NAME="ss10.10">10.10 Button Boxes</A>
961</H2>
962
963<P>Button Boxes are a convenient way to quickly layout a group of
964buttons. They come in both horizontal and vertical flavours. You
965create a new Button Box with one of the following calls, which create
966a horizontal or vertical box, respectively:
967<P>
968<BLOCKQUOTE><CODE>
969<PRE>
970GtkWidget *gtk_hbutton_box_new( void );
971
972GtkWidget *gtk_vbutton_box_new( void );
973</PRE>
974</CODE></BLOCKQUOTE>
975<P>The only attributes pertaining to button boxes effect how the buttons
976are laid out. You can change the spacing between the buttons with:
977<P>
978<BLOCKQUOTE><CODE>
979<PRE>
980void gtk_hbutton_box_set_spacing_default( gint spacing );
981
982void gtk_vbutton_box_set_spacing_default( gint spacing );
983</PRE>
984</CODE></BLOCKQUOTE>
985<P>Similarly, the current spacing values can be queried using:
986<P>
987<BLOCKQUOTE><CODE>
988<PRE>
989gint gtk_hbutton_box_get_spacing_default( void );
990
991gint gtk_vbutton_box_get_spacing_default( void );
992</PRE>
993</CODE></BLOCKQUOTE>
994<P>The second attribute that we can access effects the layout of the
995buttons within the box. It is set using one of:
996<P>
997<BLOCKQUOTE><CODE>
998<PRE>
999void gtk_hbutton_box_set_layout_default( GtkButtonBoxStyle layout );
1000
1001void gtk_vbutton_box_set_layout_default( GtkButtonBoxStyle layout );
1002</PRE>
1003</CODE></BLOCKQUOTE>
1004<P>The <CODE>layout</CODE> argument can take one of the following values:
1005<P>
1006<BLOCKQUOTE><CODE>
1007<PRE>
1008  GTK_BUTTONBOX_DEFAULT_STYLE
1009  GTK_BUTTONBOX_SPREAD
1010  GTK_BUTTONBOX_EDGE
1011  GTK_BUTTONBOX_START
1012  GTK_BUTTONBOX_END
1013</PRE>
1014</CODE></BLOCKQUOTE>
1015<P>The current layout setting can be retrieved using:
1016<P>
1017<BLOCKQUOTE><CODE>
1018<PRE>
1019GtkButtonBoxStyle gtk_hbutton_box_get_layout_default( void );
1020
1021GtkButtonBoxStyle gtk_vbutton_box_get_layout_default( void );
1022</PRE>
1023</CODE></BLOCKQUOTE>
1024<P>Buttons are added to a Button Box using the usual function:
1025<P>
1026<BLOCKQUOTE><CODE>
1027<PRE>
1028    gtk_container_add( GTK_CONTAINER(button_box), child_widget );
1029</PRE>
1030</CODE></BLOCKQUOTE>
1031<P>Here's an example that illustrates all the different layout settings
1032for Button Boxes.
1033<P>
1034<BLOCKQUOTE><CODE>
1035<PRE>
1036/* example-start buttonbox buttonbox.c */
1037
1038#include &lt;gtk/gtk.h>
1039
1040/* Create a Button Box with the specified parameters */
1041GtkWidget *create_bbox( gint  horizontal,
1042                        char *title,
1043                        gint  spacing,
1044                        gint  child_w,
1045                        gint  child_h,
1046                        gint  layout )
1047{
1048  GtkWidget *frame;
1049  GtkWidget *bbox;
1050  GtkWidget *button;
1051
1052  frame = gtk_frame_new (title);
1053
1054  if (horizontal)
1055    bbox = gtk_hbutton_box_new ();
1056  else
1057    bbox = gtk_vbutton_box_new ();
1058
1059  gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
1060  gtk_container_add (GTK_CONTAINER (frame), bbox);
1061
1062  /* Set the appearance of the Button Box */
1063  gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
1064  gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), spacing);
1065  gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
1066
1067  button = gtk_button_new_with_label ("OK");
1068  gtk_container_add (GTK_CONTAINER (bbox), button);
1069
1070  button = gtk_button_new_with_label ("Cancel");
1071  gtk_container_add (GTK_CONTAINER (bbox), button);
1072
1073  button = gtk_button_new_with_label ("Help");
1074  gtk_container_add (GTK_CONTAINER (bbox), button);
1075
1076  return(frame);
1077}
1078
1079int main( int   argc,
1080          char *argv[] )
1081{
1082  static GtkWidget* window = NULL;
1083  GtkWidget *main_vbox;
1084  GtkWidget *vbox;
1085  GtkWidget *hbox;
1086  GtkWidget *frame_horz;
1087  GtkWidget *frame_vert;
1088
1089  /* Initialize GTK */
1090  gtk_init( &amp;argc, &amp;argv );
1091
1092  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1093  gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
1094
1095  gtk_signal_connect (GTK_OBJECT (window), "destroy",
1096                      GTK_SIGNAL_FUNC(gtk_main_quit),
1097                      NULL);
1098
1099  gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1100
1101  main_vbox = gtk_vbox_new (FALSE, 0);
1102  gtk_container_add (GTK_CONTAINER (window), main_vbox);
1103
1104  frame_horz = gtk_frame_new ("Horizontal Button Boxes");
1105  gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
1106
1107  vbox = gtk_vbox_new (FALSE, 0);
1108  gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
1109  gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
1110
1111  gtk_box_pack_start (GTK_BOX (vbox),
1112           create_bbox (TRUE, "Spread (spacing 40)", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
1113                      TRUE, TRUE, 0);
1114
1115  gtk_box_pack_start (GTK_BOX (vbox),
1116           create_bbox (TRUE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
1117                      TRUE, TRUE, 5);
1118
1119  gtk_box_pack_start (GTK_BOX (vbox),
1120           create_bbox (TRUE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
1121                      TRUE, TRUE, 5);
1122
1123  gtk_box_pack_start (GTK_BOX (vbox),
1124           create_bbox (TRUE, "End (spacing 10)", 10, 85, 20, GTK_BUTTONBOX_END),
1125                      TRUE, TRUE, 5);
1126
1127  frame_vert = gtk_frame_new ("Vertical Button Boxes");
1128  gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
1129
1130  hbox = gtk_hbox_new (FALSE, 0);
1131  gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
1132  gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
1133
1134  gtk_box_pack_start (GTK_BOX (hbox),
1135           create_bbox (FALSE, "Spread (spacing 5)", 5, 85, 20, GTK_BUTTONBOX_SPREAD),
1136                      TRUE, TRUE, 0);
1137
1138  gtk_box_pack_start (GTK_BOX (hbox),
1139           create_bbox (FALSE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
1140                      TRUE, TRUE, 5);
1141
1142  gtk_box_pack_start (GTK_BOX (hbox),
1143           create_bbox (FALSE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
1144                      TRUE, TRUE, 5);
1145
1146  gtk_box_pack_start (GTK_BOX (hbox),
1147           create_bbox (FALSE, "End (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_END),
1148                      TRUE, TRUE, 5);
1149
1150  gtk_widget_show_all (window);
1151
1152  /* Enter the event loop */
1153  gtk_main ();
1154   
1155  return(0);
1156}
1157/* example-end */
1158</PRE>
1159</CODE></BLOCKQUOTE>
1160<P>  
1161<H2><A NAME="ss10.11">10.11 Toolbar</A>
1162</H2>
1163
1164<P>Toolbars are usually used to group some number of widgets in order to
1165simplify customization of their look and layout. Typically a toolbar
1166consists of buttons with icons, labels and tooltips, but any other
1167widget can also be put inside a toolbar. Finally, items can be
1168arranged horizontally or vertically and buttons can be displayed with
1169icons, labels, or both.
1170<P>Creating a toolbar is (as one may already suspect) done with the
1171following function:
1172<P>
1173<BLOCKQUOTE><CODE>
1174<PRE>
1175GtkWidget *gtk_toolbar_new( GtkOrientation orientation,
1176                            GtkToolbarStyle  style );
1177</PRE>
1178</CODE></BLOCKQUOTE>
1179<P>where orientation may be one of:
1180<P>
1181<BLOCKQUOTE><CODE>
1182<PRE>
1183  GTK_ORIENTATION_HORIZONTAL   
1184  GTK_ORIENTATION_VERTICAL
1185</PRE>
1186</CODE></BLOCKQUOTE>
1187<P>and style one of:
1188<P>
1189<BLOCKQUOTE><CODE>
1190<PRE>
1191  GTK_TOOLBAR_TEXT
1192  GTK_TOOLBAR_ICONS
1193  GTK_TOOLBAR_BOTH
1194</PRE>
1195</CODE></BLOCKQUOTE>
1196<P>The style applies to all the buttons created with the `item' functions
1197(not to buttons inserted into toolbar as separate widgets).
1198<P>After creating a toolbar one can append, prepend and insert items
1199(that means simple text strings) or elements (that means any widget
1200types) into the toolbar. To describe an item we need a label text, a
1201tooltip text, a private tooltip text, an icon for the button and a
1202callback function for it. For example, to append or prepend an item
1203you may use the following functions:
1204<P>
1205<BLOCKQUOTE><CODE>
1206<PRE>
1207GtkWidget *gtk_toolbar_append_item( GtkToolbar    *toolbar,
1208                                    const char    *text,
1209                                    const char    *tooltip_text,
1210                                    const char    *tooltip_private_text,
1211                                    GtkWidget     *icon,
1212                                    GtkSignalFunc  callback,
1213                                    gpointer       user_data );
1214
1215GtkWidget *gtk_toolbar_prepend_item( GtkToolbar    *toolbar,
1216                                     const char    *text,
1217                                     const char    *tooltip_text,
1218                                     const char    *tooltip_private_text,
1219                                     GtkWidget     *icon,
1220                                     GtkSignalFunc  callback,
1221                                     gpointer       user_data );
1222</PRE>
1223</CODE></BLOCKQUOTE>
1224<P>If you want to use gtk_toolbar_insert_item, the only additional
1225parameter which must be specified is the position in which the item
1226should be inserted, thus:
1227<P>
1228<BLOCKQUOTE><CODE>
1229<PRE>
1230GtkWidget *gtk_toolbar_insert_item( GtkToolbar    *toolbar,
1231                                    const char    *text,
1232                                    const char    *tooltip_text,
1233                                    const char    *tooltip_private_text,
1234                                    GtkWidget     *icon,
1235                                    GtkSignalFunc  callback,
1236                                    gpointer       user_data,
1237                                    gint           position );
1238</PRE>
1239</CODE></BLOCKQUOTE>
1240<P>To simplify adding spaces between toolbar items, you may use the
1241following functions:
1242<P>
1243<BLOCKQUOTE><CODE>
1244<PRE>
1245void gtk_toolbar_append_space( GtkToolbar *toolbar );
1246
1247void gtk_toolbar_prepend_space( GtkToolbar *toolbar );
1248
1249void gtk_toolbar_insert_space( GtkToolbar *toolbar,
1250                               gint        position );
1251 
1252</PRE>
1253</CODE></BLOCKQUOTE>
1254<P>While the size of the added space can be set globally for a
1255whole toolbar with the function:
1256<P>
1257<BLOCKQUOTE><CODE>
1258<PRE>
1259void gtk_toolbar_set_space_size( GtkToolbar *toolbar,
1260                                 gint        space_size) ;
1261</PRE>
1262</CODE></BLOCKQUOTE>
1263<P>If it's required, the orientation of a toolbar and its style can be
1264changed "on the fly" using the following functions:
1265<P>
1266<BLOCKQUOTE><CODE>
1267<PRE>
1268void gtk_toolbar_set_orientation( GtkToolbar     *toolbar,
1269                                  GtkOrientation  orientation );
1270
1271void gtk_toolbar_set_style( GtkToolbar      *toolbar,
1272                            GtkToolbarStyle  style );
1273
1274void gtk_toolbar_set_tooltips( GtkToolbar *toolbar,
1275                               gint        enable );
1276</PRE>
1277</CODE></BLOCKQUOTE>
1278<P>Where <CODE>orientation</CODE> is one of <CODE>GTK_ORIENTATION_HORIZONTAL</CODE> or
1279<CODE>GTK_ORIENTATION_VERTICAL</CODE>. The <CODE>style</CODE> is used to set
1280appearance of the toolbar items by using one of
1281<CODE>GTK_TOOLBAR_ICONS</CODE>, <CODE>GTK_TOOLBAR_TEXT</CODE>, or
1282<CODE>GTK_TOOLBAR_BOTH</CODE>.
1283<P>To show some other things that can be done with a toolbar, let's take
1284the following program (we'll interrupt the listing with some
1285additional explanations):
1286<P>
1287<BLOCKQUOTE><CODE>
1288<PRE>
1289#include &lt;gtk/gtk.h>
1290
1291#include "gtk.xpm"
1292
1293/* This function is connected to the Close button or
1294 * closing the window from the WM */
1295gint delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
1296{
1297  gtk_main_quit ();
1298  return(FALSE);
1299}
1300</PRE>
1301</CODE></BLOCKQUOTE>
1302<P>The above beginning seems for sure familiar to you if it's not your first
1303GTK program. There is one additional thing though, we include a nice XPM
1304picture to serve as an icon for all of the buttons.
1305<P>
1306<BLOCKQUOTE><CODE>
1307<PRE>
1308GtkWidget* close_button; /* This button will emit signal to close
1309                          * application */
1310GtkWidget* tooltips_button; /* to enable/disable tooltips */
1311GtkWidget* text_button,
1312         * icon_button,
1313         * both_button; /* radio buttons for toolbar style */
1314GtkWidget* entry; /* a text entry to show packing any widget into
1315                   * toolbar */
1316</PRE>
1317</CODE></BLOCKQUOTE>
1318<P>In fact not all of the above widgets are needed here, but to make things
1319clearer I put them all together.
1320<P>
1321<BLOCKQUOTE><CODE>
1322<PRE>
1323/* that's easy... when one of the buttons is toggled, we just
1324 * check which one is active and set the style of the toolbar
1325 * accordingly
1326 * ATTENTION: our toolbar is passed as data to callback ! */
1327void radio_event (GtkWidget *widget, gpointer data)
1328{
1329  if (GTK_TOGGLE_BUTTON (text_button)->active)
1330    gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_TEXT);
1331  else if (GTK_TOGGLE_BUTTON (icon_button)->active)
1332    gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_ICONS);
1333  else if (GTK_TOGGLE_BUTTON (both_button)->active)
1334    gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_BOTH);
1335}
1336
1337/* even easier, just check given toggle button and enable/disable
1338 * tooltips */
1339void toggle_event (GtkWidget *widget, gpointer data)
1340{
1341  gtk_toolbar_set_tooltips (GTK_TOOLBAR ( data ),
1342                            GTK_TOGGLE_BUTTON (widget)->active );
1343}
1344</PRE>
1345</CODE></BLOCKQUOTE>
1346<P>The above are just two callback functions that will be called when
1347one of the buttons on a toolbar is pressed. You should already be
1348familiar with things like this if you've already used toggle buttons (and
1349radio buttons).
1350<P>
1351<BLOCKQUOTE><CODE>
1352<PRE>
1353int main (int argc, char *argv[])
1354{
1355  /* Here is our main window (a dialog) and a handle for the handlebox */
1356  GtkWidget* dialog;
1357  GtkWidget* handlebox;
1358
1359  /* Ok, we need a toolbar, an icon with a mask (one for all of
1360     the buttons) and an icon widget to put this icon in (but
1361     we'll create a separate widget for each button) */
1362  GtkWidget * toolbar;
1363  GdkPixmap * icon;
1364  GdkBitmap * mask;
1365  GtkWidget * iconw;
1366
1367  /* this is called in all GTK application. */
1368  gtk_init (&amp;argc, &amp;argv);
1369 
1370  /* create a new window with a given title, and nice size */
1371  dialog = gtk_dialog_new ();
1372  gtk_window_set_title ( GTK_WINDOW ( dialog ) , "GTKToolbar Tutorial");
1373  gtk_widget_set_usize( GTK_WIDGET ( dialog ) , 600 , 300 );
1374  GTK_WINDOW ( dialog ) ->allow_shrink = TRUE;
1375
1376  /* typically we quit if someone tries to close us */
1377  gtk_signal_connect ( GTK_OBJECT ( dialog ), "delete_event",
1378                       GTK_SIGNAL_FUNC ( delete_event ), NULL);
1379
1380  /* we need to realize the window because we use pixmaps for
1381   * items on the toolbar in the context of it */
1382  gtk_widget_realize ( dialog );
1383
1384  /* to make it nice we'll put the toolbar into the handle box,
1385   * so that it can be detached from the main window */
1386  handlebox = gtk_handle_box_new ();
1387  gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(dialog)->vbox ),
1388                       handlebox, FALSE, FALSE, 5 );
1389</PRE>
1390</CODE></BLOCKQUOTE>
1391<P>The above should be similar to any other GTK application. Just
1392initialization of GTK, creating the window, etc. There is only one
1393thing that probably needs some explanation: a handle box. A handle box
1394is just another box that can be used to pack widgets in to. The
1395difference between it and typical boxes is that it can be detached
1396from a parent window (or, in fact, the handle box remains in the
1397parent, but it is reduced to a very small rectangle, while all of its
1398contents are reparented to a new freely floating window). It is
1399usually nice to have a detachable toolbar, so these two widgets occur
1400together quite often.
1401<P>
1402<BLOCKQUOTE><CODE>
1403<PRE>
1404  /* toolbar will be horizontal, with both icons and text, and
1405   * with 5pxl spaces between items and finally,
1406   * we'll also put it into our handlebox */
1407  toolbar = gtk_toolbar_new ( GTK_ORIENTATION_HORIZONTAL,
1408                              GTK_TOOLBAR_BOTH );
1409  gtk_container_set_border_width ( GTK_CONTAINER ( toolbar ) , 5 );
1410  gtk_toolbar_set_space_size ( GTK_TOOLBAR ( toolbar ), 5 );
1411  gtk_container_add ( GTK_CONTAINER ( handlebox ) , toolbar );
1412
1413  /* now we create icon with mask: we'll reuse it to create
1414   * icon widgets for toolbar items */
1415  icon = gdk_pixmap_create_from_xpm_d ( dialog->window, &amp;mask,
1416      &amp;dialog->style->white, gtk_xpm );
1417</PRE>
1418</CODE></BLOCKQUOTE>
1419<P>Well, what we do above is just a straightforward initialization of
1420the toolbar widget and creation of a GDK pixmap with its mask. If you
1421want to know something more about using pixmaps, refer to GDK
1422documentation or to the
1423<A HREF="gtk_tut-9.html#sec_Pixmaps">Pixmaps</A> section
1424earlier in this tutorial.
1425<P>
1426<BLOCKQUOTE><CODE>
1427<PRE>
1428  /* our first item is &lt;close> button */
1429  iconw = gtk_pixmap_new ( icon, mask ); /* icon widget */
1430  close_button =
1431    gtk_toolbar_append_item ( GTK_TOOLBAR (toolbar), /* our toolbar */
1432                              "Close",               /* button label */
1433                              "Closes this app",     /* this button's tooltip */
1434                              "Private",             /* tooltip private info */
1435                              iconw,                 /* icon widget */
1436                              GTK_SIGNAL_FUNC (delete_event), /* a signal */
1437                               NULL );
1438  gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); /* space after item */
1439</PRE>
1440</CODE></BLOCKQUOTE>
1441<P>In the above code you see the simplest case: adding a button to
1442toolbar.  Just before appending a new item, we have to construct a
1443pixmap widget to serve as an icon for this item; this step will have
1444to be repeated for each new item. Just after the item we also add a
1445space, so the following items will not touch each other. As you see
1446gtk_toolbar_append_item returns a pointer to our newly created button
1447widget, so that we can work with it in the normal way.
1448<P>
1449<BLOCKQUOTE><CODE>
1450<PRE>
1451  /* now, let's make our radio buttons group... */
1452  iconw = gtk_pixmap_new ( icon, mask );
1453  icon_button = gtk_toolbar_append_element(
1454                    GTK_TOOLBAR(toolbar),
1455                    GTK_TOOLBAR_CHILD_RADIOBUTTON, /* a type of element */
1456                    NULL,                          /* pointer to widget */
1457                    "Icon",                        /* label */
1458                    "Only icons in toolbar",       /* tooltip */
1459                    "Private",                     /* tooltip private string */
1460                    iconw,                         /* icon */
1461                    GTK_SIGNAL_FUNC (radio_event), /* signal */
1462                    toolbar);                      /* data for signal */
1463  gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
1464</PRE>
1465</CODE></BLOCKQUOTE>
1466<P>Here we begin creating a radio buttons group. To do this we use
1467gtk_toolbar_append_element.  In fact, using this function one can also
1468+add simple items or even spaces (type = <CODE>GTK_TOOLBAR_CHILD_SPACE</CODE>
1469or +<CODE>GTK_TOOLBAR_CHILD_BUTTON</CODE>). In the above case we start
1470creating a radio group. In creating other radio buttons for this group
1471a pointer to the previous button in the group is required, so that a
1472list of buttons can be easily constructed (see the section on
1473<A HREF="gtk_tut-6.html#sec_Radio_Buttons">Radio Buttons</A> earlier in this
1474tutorial).
1475<P>
1476<BLOCKQUOTE><CODE>
1477<PRE>
1478  /* following radio buttons refer to previous ones */
1479  iconw = gtk_pixmap_new ( icon, mask );
1480  text_button =
1481    gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
1482                               GTK_TOOLBAR_CHILD_RADIOBUTTON,
1483                               icon_button,
1484                               "Text",
1485                               "Only texts in toolbar",
1486                               "Private",
1487                               iconw,
1488                               GTK_SIGNAL_FUNC (radio_event),
1489                               toolbar);
1490  gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
1491                                         
1492  iconw = gtk_pixmap_new ( icon, mask );
1493  both_button =
1494    gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
1495                               GTK_TOOLBAR_CHILD_RADIOBUTTON,
1496                               text_button,
1497                               "Both",
1498                               "Icons and text in toolbar",
1499                               "Private",
1500                               iconw,
1501                               GTK_SIGNAL_FUNC (radio_event),
1502                               toolbar);
1503  gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
1504  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_button),TRUE);
1505</PRE>
1506</CODE></BLOCKQUOTE>
1507<P>In the end we have to set the state of one of the buttons manually
1508(otherwise they all stay in active state, preventing us from switching
1509between them).
1510<P>
1511<BLOCKQUOTE><CODE>
1512<PRE>
1513  /* here we have just a simple toggle button */
1514  iconw = gtk_pixmap_new ( icon, mask );
1515  tooltips_button =
1516    gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
1517                               GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
1518                               NULL,
1519                               "Tooltips",
1520                               "Toolbar with or without tips",
1521                               "Private",
1522                               iconw,
1523                               GTK_SIGNAL_FUNC (toggle_event),
1524                               toolbar);
1525  gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
1526  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltips_button),TRUE);
1527</PRE>
1528</CODE></BLOCKQUOTE>
1529<P>A toggle button can be created in the obvious way (if one knows how to create
1530radio buttons already).
1531<P>
1532<BLOCKQUOTE><CODE>
1533<PRE>
1534  /* to pack a widget into toolbar, we only have to
1535   * create it and append it with an appropriate tooltip */
1536  entry = gtk_entry_new ();
1537  gtk_toolbar_append_widget( GTK_TOOLBAR (toolbar),
1538                             entry,
1539                             "This is just an entry",
1540                             "Private" );
1541
1542  /* well, it isn't created within thetoolbar, so we must still show it */
1543  gtk_widget_show ( entry );
1544</PRE>
1545</CODE></BLOCKQUOTE>
1546<P>As you see, adding any kind of widget to a toolbar is simple. The
1547one thing you have to remember is that this widget must be shown manually
1548(contrary to other items which will be shown together with the toolbar).
1549<P>
1550<BLOCKQUOTE><CODE>
1551<PRE>
1552  /* that's it ! let's show everything. */
1553  gtk_widget_show ( toolbar );
1554  gtk_widget_show (handlebox);
1555  gtk_widget_show ( dialog );
1556
1557  /* rest in gtk_main and wait for the fun to begin! */
1558  gtk_main ();
1559 
1560  return 0;
1561}
1562</PRE>
1563</CODE></BLOCKQUOTE>
1564<P>So, here we are at the end of toolbar tutorial. Of course, to appreciate
1565it in full you need also this nice XPM icon, so here it is:
1566<P>
1567<BLOCKQUOTE><CODE>
1568<PRE>
1569/* XPM */
1570static char * gtk_xpm[] = {
1571"32 39 5 1",
1572".      c none",
1573"+      c black",
1574"@      c #3070E0",
1575"#      c #F05050",
1576"$      c #35E035",
1577"................+...............",
1578"..............+++++.............",
1579"............+++++@@++...........",
1580"..........+++++@@@@@@++.........",
1581"........++++@@@@@@@@@@++........",
1582"......++++@@++++++++@@@++.......",
1583".....+++@@@+++++++++++@@@++.....",
1584"...+++@@@@+++@@@@@@++++@@@@+....",
1585"..+++@@@@+++@@@@@@@@+++@@@@@++..",
1586".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
1587".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
1588".+##++@@@@+++@@@+++++@@@@@@@@$@.",
1589".+###++@@@@+++@@@+++@@@@@++$$$@.",
1590".+####+++@@@+++++++@@@@@+@$$$$@.",
1591".+#####+++@@@@+++@@@@++@$$$$$$+.",
1592".+######++++@@@@@@@++@$$$$$$$$+.",
1593".+#######+##+@@@@+++$$$$$$@@$$+.",
1594".+###+++##+##+@@++@$$$$$$++$$$+.",
1595".+###++++##+##+@@$$$$$$$@+@$$@+.",
1596".+###++++++#+++@$$@+@$$@++$$$@+.",
1597".+####+++++++#++$$@+@$$++$$$$+..",
1598".++####++++++#++$$@+@$++@$$$$+..",
1599".+#####+++++##++$$++@+++$$$$$+..",
1600".++####+++##+#++$$+++++@$$$$$+..",
1601".++####+++####++$$++++++@$$$@+..",
1602".+#####++#####++$$+++@++++@$@+..",
1603".+#####++#####++$$++@$$@+++$@@..",
1604".++####++#####++$$++$$$$$+@$@++.",
1605".++####++#####++$$++$$$$$$$$+++.",
1606".+++####+#####++$$++$$$$$$$@+++.",
1607"..+++#########+@$$+@$$$$$$+++...",
1608"...+++########+@$$$$$$$$@+++....",
1609".....+++######+@$$$$$$$+++......",
1610"......+++#####+@$$$$$@++........",
1611".......+++####+@$$$$+++.........",
1612".........++###+$$$@++...........",
1613"..........++##+$@+++............",
1614"...........+++++++..............",
1615".............++++..............."};
1616</PRE>
1617</CODE></BLOCKQUOTE>
1618<P>
1619<H2><A NAME="ss10.12">10.12 Notebooks</A>
1620</H2>
1621
1622<P>The NoteBook Widget is a collection of "pages" that overlap each
1623other, each page contains different information with only one page
1624visible at a time. This widget has become more common lately in GUI
1625programming, and it is a good way to show blocks of similar
1626information that warrant separation in their display.
1627<P>The first function call you will need to know, as you can probably
1628guess by now, is used to create a new notebook widget.
1629<P>
1630<BLOCKQUOTE><CODE>
1631<PRE>
1632GtkWidget *gtk_notebook_new( void );
1633</PRE>
1634</CODE></BLOCKQUOTE>
1635<P>Once the notebook has been created, there are a number of functions
1636that operate on the notebook widget. Let's look at them individually.
1637<P>The first one we will look at is how to position the page indicators.
1638These page indicators or "tabs" as they are referred to, can be
1639positioned in four ways: top, bottom, left, or right.
1640<P>
1641<BLOCKQUOTE><CODE>
1642<PRE>
1643void gtk_notebook_set_tab_pos( GtkNotebook     *notebook,
1644                               GtkPositionType  pos );
1645</PRE>
1646</CODE></BLOCKQUOTE>
1647<P>GtkPositionType will be one of the following, which are pretty self
1648explanatory:
1649<BLOCKQUOTE><CODE>
1650<PRE>
1651  GTK_POS_LEFT
1652  GTK_POS_RIGHT
1653  GTK_POS_TOP
1654  GTK_POS_BOTTOM
1655</PRE>
1656</CODE></BLOCKQUOTE>
1657<P><CODE>GTK_POS_TOP</CODE> is the default.
1658<P>Next we will look at how to add pages to the notebook. There are three
1659ways to add pages to the NoteBook. Let's look at the first two
1660together as they are quite similar.
1661<P>
1662<BLOCKQUOTE><CODE>
1663<PRE>
1664void gtk_notebook_append_page( GtkNotebook *notebook,
1665                               GtkWidget   *child,
1666                               GtkWidget   *tab_label );
1667
1668void gtk_notebook_prepend_page( GtkNotebook *notebook,
1669                                GtkWidget   *child,
1670                                GtkWidget   *tab_label );
1671</PRE>
1672</CODE></BLOCKQUOTE>
1673<P>These functions add pages to the notebook by inserting them from the
1674back of the notebook (append), or the front of the notebook (prepend).
1675<CODE>child</CODE> is the widget that is placed within the notebook page, and
1676<CODE>tab_label</CODE> is the label for the page being added. The <CODE>child</CODE>
1677widget must be created separately, and is typically a set of options
1678setup witin one of the other container widgets, such as a table.
1679<P>The final function for adding a page to the notebook contains all of
1680the properties of the previous two, but it allows you to specify what
1681position you want the page to be in the notebook.
1682<P>
1683<BLOCKQUOTE><CODE>
1684<PRE>
1685void gtk_notebook_insert_page( GtkNotebook *notebook,
1686                               GtkWidget   *child,
1687                               GtkWidget   *tab_label,
1688                               gint         position );
1689</PRE>
1690</CODE></BLOCKQUOTE>
1691<P>The parameters are the same as _append_ and _prepend_ except it
1692contains an extra parameter, <CODE>position</CODE>.  This parameter is used to
1693specify what place this page will be inserted into the first page
1694having position zero.
1695<P>Now that we know how to add a page, lets see how we can remove a page
1696from the notebook.
1697<P>
1698<BLOCKQUOTE><CODE>
1699<PRE>
1700void gtk_notebook_remove_page( GtkNotebook *notebook,
1701                               gint         page_num );
1702</PRE>
1703</CODE></BLOCKQUOTE>
1704<P>This function takes the page specified by <CODE>page_num</CODE> and removes it
1705from the widget pointed to by <CODE>notebook</CODE>.
1706<P>To find out what the current page is in a notebook use the function:
1707<P>
1708<BLOCKQUOTE><CODE>
1709<PRE>
1710gint gtk_notebook_get_current_page( GtkNotebook *notebook );
1711</PRE>
1712</CODE></BLOCKQUOTE>
1713<P>These next two functions are simple calls to move the notebook page
1714forward or backward. Simply provide the respective function call with
1715the notebook widget you wish to operate on. Note: When the NoteBook is
1716currently on the last page, and gtk_notebook_next_page is called, the
1717notebook will wrap back to the first page. Likewise, if the NoteBook
1718is on the first page, and gtk_notebook_prev_page is called, the
1719notebook will wrap to the last page.
1720<P>
1721<BLOCKQUOTE><CODE>
1722<PRE>
1723void gtk_notebook_next_page( GtkNoteBook *notebook );
1724
1725void gtk_notebook_prev_page( GtkNoteBook *notebook );
1726</PRE>
1727</CODE></BLOCKQUOTE>
1728<P>This next function sets the "active" page. If you wish the notebook to
1729be opened to page 5 for example, you would use this function.  Without
1730using this function, the notebook defaults to the first page.
1731<P>
1732<BLOCKQUOTE><CODE>
1733<PRE>
1734void gtk_notebook_set_page( GtkNotebook *notebook,
1735                            gint         page_num );
1736</PRE>
1737</CODE></BLOCKQUOTE>
1738<P>The next two functions add or remove the notebook page tabs and the
1739notebook border respectively.
1740<P>
1741<BLOCKQUOTE><CODE>
1742<PRE>
1743void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
1744                                 gboolean     show_tabs);
1745
1746void gtk_notebook_set_show_border( GtkNotebook *notebook,
1747                                   gboolean     show_border );
1748</PRE>
1749</CODE></BLOCKQUOTE>
1750<P>The next function is useful when the you have a large number of pages,
1751and the tabs don't fit on the page. It allows the tabs to be scrolled
1752through using two arrow buttons.
1753<P>
1754<BLOCKQUOTE><CODE>
1755<PRE>
1756void gtk_notebook_set_scrollable( GtkNotebook *notebook,
1757                                  gboolean     scrollable );
1758</PRE>
1759</CODE></BLOCKQUOTE>
1760<P><CODE>show_tabs</CODE>, <CODE>show_border</CODE> and <CODE>scrollable</CODE> can be either
1761TRUE or FALSE.
1762<P>Now let's look at an example, it is expanded from the testgtk.c code
1763that comes with the GTK distribution. This small program creates a
1764window with a notebook and six buttons. The notebook contains 11
1765pages, added in three different ways, appended, inserted, and
1766prepended. The buttons allow you rotate the tab positions, add/remove
1767the tabs and border, remove a page, change pages in both a forward and
1768backward manner, and exit the program.
1769<P>
1770<BLOCKQUOTE><CODE>
1771<PRE>
1772/* example-start notebook notebook.c */
1773
1774#include &lt;stdio.h>
1775#include &lt;gtk/gtk.h>
1776
1777/* This function rotates the position of the tabs */
1778void rotate_book( GtkButton   *button,
1779                  GtkNotebook *notebook )
1780{
1781    gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
1782}
1783
1784/* Add/Remove the page tabs and the borders */
1785void tabsborder_book( GtkButton   *button,
1786                      GtkNotebook *notebook )
1787{
1788    gint tval = FALSE;
1789    gint bval = FALSE;
1790    if (notebook->show_tabs == 0)
1791            tval = TRUE;
1792    if (notebook->show_border == 0)
1793            bval = TRUE;
1794   
1795    gtk_notebook_set_show_tabs (notebook, tval);
1796    gtk_notebook_set_show_border (notebook, bval);
1797}
1798
1799/* Remove a page from the notebook */
1800void remove_book( GtkButton   *button,
1801                  GtkNotebook *notebook )
1802{
1803    gint page;
1804   
1805    page = gtk_notebook_get_current_page(notebook);
1806    gtk_notebook_remove_page (notebook, page);
1807    /* Need to refresh the widget --
1808     This forces the widget to redraw itself. */
1809    gtk_widget_draw(GTK_WIDGET(notebook), NULL);
1810}
1811
1812gint delete( GtkWidget *widget,
1813             GtkWidget *event,
1814             gpointer   data )
1815{
1816    gtk_main_quit();
1817    return(FALSE);
1818}
1819
1820int main( int argc,
1821          char *argv[] )
1822{
1823    GtkWidget *window;
1824    GtkWidget *button;
1825    GtkWidget *table;
1826    GtkWidget *notebook;
1827    GtkWidget *frame;
1828    GtkWidget *label;
1829    GtkWidget *checkbutton;
1830    int i;
1831    char bufferf[32];
1832    char bufferl[32];
1833   
1834    gtk_init (&amp;argc, &amp;argv);
1835   
1836    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1837   
1838    gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1839                        GTK_SIGNAL_FUNC (delete), NULL);
1840   
1841    gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1842
1843    table = gtk_table_new(3,6,FALSE);
1844    gtk_container_add (GTK_CONTAINER (window), table);
1845   
1846    /* Create a new notebook, place the position of the tabs */
1847    notebook = gtk_notebook_new ();
1848    gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
1849    gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
1850    gtk_widget_show(notebook);
1851   
1852    /* Let's append a bunch of pages to the notebook */
1853    for (i=0; i &lt; 5; i++) {
1854        sprintf(bufferf, "Append Frame %d", i+1);
1855        sprintf(bufferl, "Page %d", i+1);
1856       
1857        frame = gtk_frame_new (bufferf);
1858        gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
1859        gtk_widget_set_usize (frame, 100, 75);
1860        gtk_widget_show (frame);
1861       
1862        label = gtk_label_new (bufferf);
1863        gtk_container_add (GTK_CONTAINER (frame), label);
1864        gtk_widget_show (label);
1865       
1866        label = gtk_label_new (bufferl);
1867        gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
1868    }
1869     
1870    /* Now let's add a page to a specific spot */
1871    checkbutton = gtk_check_button_new_with_label ("Check me please!");
1872    gtk_widget_set_usize(checkbutton, 100, 75);
1873    gtk_widget_show (checkbutton);
1874   
1875    label = gtk_label_new ("Add page");
1876    gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
1877   
1878    /* Now finally let's prepend pages to the notebook */
1879    for (i=0; i &lt; 5; i++) {
1880        sprintf(bufferf, "Prepend Frame %d", i+1);
1881        sprintf(bufferl, "PPage %d", i+1);
1882       
1883        frame = gtk_frame_new (bufferf);
1884        gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
1885        gtk_widget_set_usize (frame, 100, 75);
1886        gtk_widget_show (frame);
1887       
1888        label = gtk_label_new (bufferf);
1889        gtk_container_add (GTK_CONTAINER (frame), label);
1890        gtk_widget_show (label);
1891       
1892        label = gtk_label_new (bufferl);
1893        gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
1894    }
1895   
1896    /* Set what page to start at (page 4) */
1897    gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
1898
1899    /* Create a bunch of buttons */
1900    button = gtk_button_new_with_label ("close");
1901    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1902                               GTK_SIGNAL_FUNC (delete), NULL);
1903    gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
1904    gtk_widget_show(button);
1905   
1906    button = gtk_button_new_with_label ("next page");
1907    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1908                               (GtkSignalFunc) gtk_notebook_next_page,
1909                               GTK_OBJECT (notebook));
1910    gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
1911    gtk_widget_show(button);
1912   
1913    button = gtk_button_new_with_label ("prev page");
1914    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1915                               (GtkSignalFunc) gtk_notebook_prev_page,
1916                               GTK_OBJECT (notebook));
1917    gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
1918    gtk_widget_show(button);
1919   
1920    button = gtk_button_new_with_label ("tab position");
1921    gtk_signal_connect (GTK_OBJECT (button), "clicked",
1922                        (GtkSignalFunc) rotate_book,
1923                        GTK_OBJECT(notebook));
1924    gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
1925    gtk_widget_show(button);
1926   
1927    button = gtk_button_new_with_label ("tabs/border on/off");
1928    gtk_signal_connect (GTK_OBJECT (button), "clicked",
1929                        (GtkSignalFunc) tabsborder_book,
1930                        GTK_OBJECT (notebook));
1931    gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
1932    gtk_widget_show(button);
1933   
1934    button = gtk_button_new_with_label ("remove page");
1935    gtk_signal_connect (GTK_OBJECT (button), "clicked",
1936                        (GtkSignalFunc) remove_book,
1937                        GTK_OBJECT(notebook));
1938    gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
1939    gtk_widget_show(button);
1940   
1941    gtk_widget_show(table);
1942    gtk_widget_show(window);
1943   
1944    gtk_main ();
1945   
1946    return(0);
1947}
1948/* example-end */
1949</PRE>
1950</CODE></BLOCKQUOTE>
1951<P>I hope this helps you on your way with creating notebooks for your
1952GTK applications.
1953<P>
1954<HR NOSHADE>
1955<A HREF="gtk_tut-11.html">Next</A>
1956<A HREF="gtk_tut-9.html">Previous</A>
1957<A HREF="gtk_tut.html#toc10">Contents</A>
1958</BODY>
1959</HTML>
Note: See TracBrowser for help on using the repository browser.