]> Pileus Git - ~andy/gtk/blob - gtk/gtkassistant.c
Use a priv pointer for cheap access to the priv struct. (#327725,
[~andy/gtk] / gtk / gtkassistant.c
1 /* 
2  * GTK - The GIMP Toolkit
3  * Copyright (C) 1999  Red Hat, Inc.
4  * Copyright (C) 2002  Anders Carlsson <andersca@gnu.org>
5  * Copyright (C) 2003  Matthias Clasen <mclasen@redhat.com>
6  * Copyright (C) 2005  Carlos Garnacho Parro <carlosg@gnome.org>
7  *
8  * All rights reserved.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */
25
26 #include <config.h>
27
28 #include "gtkassistant.h"
29
30 #include "gtkbutton.h"
31 #include "gtkhbox.h"
32 #include "gtkimage.h"
33 #include "gtklabel.h"
34 #include "gtksizegroup.h"
35 #include "gtkstock.h"
36
37 #include "gtkintl.h"
38 #include "gtkprivate.h"
39
40 #include "gtkalias.h"
41
42 #define GTK_ASSISTANT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_ASSISTANT, GtkAssistantPrivate))
43
44 #define HEADER_SPACING 12
45
46 typedef struct _GtkAssistantPage GtkAssistantPage;
47
48 struct _GtkAssistantPage
49 {
50   GtkWidget *page;
51   GtkAssistantPageType type;
52   gboolean   complete;
53
54   GtkWidget *title;
55   GdkPixbuf *header_image;
56   GdkPixbuf *sidebar_image;
57 };
58
59 struct _GtkAssistantPrivate
60 {
61   GtkWidget *header_image;
62   GtkWidget *sidebar_image;
63
64   GtkWidget *action_area;
65
66   GList     *pages;
67
68   GtkAssistantPage *current_page;
69
70   GSList    *visited_pages;
71
72   GtkSizeGroup *size_group;
73
74   GtkAssistantPageFunc forward_function;
75   gpointer forward_function_data;
76   GDestroyNotify forward_data_destroy;
77 };
78
79 static void     gtk_assistant_class_init         (GtkAssistantClass *class);
80 static void     gtk_assistant_init               (GtkAssistant      *assistant);
81 static void     gtk_assistant_destroy            (GtkObject         *object);
82 static void     gtk_assistant_style_set          (GtkWidget         *widget,
83                                                   GtkStyle          *old_style);
84 static void     gtk_assistant_size_request       (GtkWidget         *widget,
85                                                   GtkRequisition    *requisition);
86 static void     gtk_assistant_size_allocate      (GtkWidget         *widget,
87                                                   GtkAllocation     *allocation);
88 static void     gtk_assistant_map                (GtkWidget         *widget);
89 static void     gtk_assistant_unmap              (GtkWidget         *widget);
90 static gboolean gtk_assistant_delete_event       (GtkWidget         *widget,
91                                                   GdkEventAny       *event);
92 static gboolean gtk_assistant_expose             (GtkWidget         *widget,
93                                                   GdkEventExpose    *event);
94 static void     gtk_assistant_add                (GtkContainer      *container,
95                                                   GtkWidget         *page);
96 static void     gtk_assistant_remove             (GtkContainer      *container,
97                                                   GtkWidget         *page);
98 static void     gtk_assistant_forall             (GtkContainer      *container,
99                                                   gboolean           include_internals,
100                                                   GtkCallback        callback,
101                                                   gpointer           callback_data);
102 static void     gtk_assistant_set_child_property (GtkContainer      *container,
103                                                   GtkWidget         *child,
104                                                   guint              property_id,
105                                                   const GValue      *value,
106                                                   GParamSpec        *pspec);
107 static void     gtk_assistant_get_child_property (GtkContainer      *container,
108                                                   GtkWidget         *child,
109                                                   guint              property_id,
110                                                   GValue            *value,
111                                                   GParamSpec        *pspec);
112
113 enum
114 {
115   CHILD_PROP_0,
116   CHILD_PROP_PAGE_TYPE,
117   CHILD_PROP_PAGE_TITLE,
118   CHILD_PROP_PAGE_HEADER_IMAGE,
119   CHILD_PROP_PAGE_SIDEBAR_IMAGE,
120   CHILD_PROP_PAGE_COMPLETE
121 };
122
123 enum
124 {
125   CANCEL,
126   PREPARE,
127   APPLY,
128   CLOSE,
129   LAST_SIGNAL
130 };
131
132 static guint signals [LAST_SIGNAL] = { 0 };
133
134
135 G_DEFINE_TYPE (GtkAssistant, gtk_assistant, GTK_TYPE_WINDOW);
136
137
138 static void
139 gtk_assistant_class_init (GtkAssistantClass *class)
140 {
141   GObjectClass *gobject_class;
142   GtkObjectClass *object_class;
143   GtkWidgetClass *widget_class;
144   GtkContainerClass *container_class;
145
146   gobject_class   = (GObjectClass *) class;
147   object_class    = (GtkObjectClass *) class;
148   widget_class    = (GtkWidgetClass *) class;
149   container_class = (GtkContainerClass *) class;
150
151   object_class->destroy = gtk_assistant_destroy;
152
153   widget_class->style_set = gtk_assistant_style_set;
154   widget_class->size_request = gtk_assistant_size_request;
155   widget_class->size_allocate = gtk_assistant_size_allocate;
156   widget_class->map = gtk_assistant_map;
157   widget_class->unmap = gtk_assistant_unmap;
158   widget_class->delete_event = gtk_assistant_delete_event;
159   widget_class->expose_event = gtk_assistant_expose;
160
161   container_class->add = gtk_assistant_add;
162   container_class->remove = gtk_assistant_remove;
163   container_class->forall = gtk_assistant_forall;
164   container_class->set_child_property = gtk_assistant_set_child_property;
165   container_class->get_child_property = gtk_assistant_get_child_property;
166
167   /**
168    * GtkAssistant::cancel:
169    * @assistant: the #GtkAssistant
170    * @page: the current page
171    *
172    * The ::cancel signal is emitted when then the cancel button is clicked.
173    *
174    * Since: 2.10
175    */
176   signals[CANCEL] =
177     g_signal_new (I_("cancel"),
178                   G_TYPE_FROM_CLASS (gobject_class),
179                   G_SIGNAL_RUN_LAST,
180                   G_STRUCT_OFFSET (GtkAssistantClass, cancel),
181                   NULL, NULL,
182                   g_cclosure_marshal_VOID__VOID,
183                   G_TYPE_NONE, 0);
184     
185   /**
186    * GtkAssistant::prepare:
187    * @assistant: the #GtkAssistant
188    * @page: the current page
189    *
190    * The ::prepared signal is emitted when a new page is set as the assistant's 
191    * current page, before making the new page visible. A handler for this signal 
192    * can do any preparation which are necessary before showing @page.
193    *
194    * Since: 2.10
195    */
196   signals[PREPARE] =
197     g_signal_new (I_("prepare"),
198                   G_TYPE_FROM_CLASS (gobject_class),
199                   G_SIGNAL_RUN_LAST,
200                   G_STRUCT_OFFSET (GtkAssistantClass, prepare),
201                   NULL, NULL,
202                   g_cclosure_marshal_VOID__OBJECT,
203                   G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
204
205   /**
206    * GtkAssistant::apply:
207    * @assistant: the @GtkAssistant
208    * @page: the current page
209    *
210    * The ::apply signal is emitted when the apply button is clicked. The default
211    * behavior of the #GtkAssistant is to switch to the page after the current page,
212    * unless the current page is the last one.
213    *
214    * A handler for the ::apply signal should carry out the actions for which the
215    * wizard has collected data. If the action takes a long time to complete, you
216    * might consider to put a page displaying the progress of the operation after the
217    * confirmation page with the apply button.
218    *
219    * Return value: %TRUE to suppress the default behavior
220    *
221    * Since: 2.10
222    */
223   signals[APPLY] =
224     g_signal_new (I_("apply"),
225                   G_TYPE_FROM_CLASS (gobject_class),
226                   G_SIGNAL_RUN_LAST,
227                   G_STRUCT_OFFSET (GtkAssistantClass, apply),
228                   NULL, NULL,
229                   g_cclosure_marshal_VOID__VOID,
230                   G_TYPE_NONE, 0);
231
232   /**
233    * GtkAssistant::close:
234    * @assistant: the #GtkAssistant
235    * @page: the current page
236    *
237    * The ::close signal is emitted when the close button is clicked.
238    *
239    * Since: 2.10
240    */
241   signals[CLOSE] =
242     g_signal_new (I_("close"),
243                   G_TYPE_FROM_CLASS (gobject_class),
244                   G_SIGNAL_RUN_LAST,
245                   G_STRUCT_OFFSET (GtkAssistantClass, close),
246                   NULL, NULL,
247                   g_cclosure_marshal_VOID__VOID,
248                   G_TYPE_NONE, 0);
249
250   gtk_widget_class_install_style_property (widget_class,
251                                            g_param_spec_int ("header-padding",
252                                                              P_("Header Padding"),
253                                                              P_("Number of pixels around the header."),
254                                                              0,
255                                                              G_MAXINT,
256                                                              6,
257                                                              GTK_PARAM_READABLE));
258   gtk_widget_class_install_style_property (widget_class,
259                                            g_param_spec_int ("content-padding",
260                                                              P_("Content Padding"),
261                                                              P_("Number of pixels around the content pages."),
262                                                              0,
263                                                              G_MAXINT,
264                                                              1,
265                                                              GTK_PARAM_READABLE));
266
267   /**
268    * GtkAssistant:page-type:
269    *
270    * The type of the assistant page. 
271    *
272    * Since: 2.10
273    */
274   gtk_container_class_install_child_property (container_class,
275                                               CHILD_PROP_PAGE_TYPE,
276                                               g_param_spec_enum ("page-type", 
277                                                                  P_("Page type"),
278                                                                  P_("The type of the assistant page"),
279                                                                  GTK_TYPE_ASSISTANT_PAGE_TYPE,
280                                                                  GTK_ASSISTANT_PAGE_CONTENT,
281                                                                  GTK_PARAM_READWRITE));
282
283   /**
284    * GtkAssistant:title:
285    *
286    * The title that is displayed in the page header. 
287    *
288    * If title and header-image are both %NULL, no header is displayed.
289    *
290    * Since: 2.10
291    */
292   gtk_container_class_install_child_property (container_class,
293                                               CHILD_PROP_PAGE_TITLE,
294                                               g_param_spec_string ("title", 
295                                                                    P_("Page title"),
296                                                                    P_("The title of the assistant page"),
297                                                                    NULL,
298                                                                    GTK_PARAM_READWRITE));
299
300   /**
301    * GtkAssistant:header-image:
302    *
303    * The image that is displayed next to the title in the page header.
304    *
305    * If title and header-image are both %NULL, no header is displayed.
306    *
307    * Since: 2.10
308    */
309   gtk_container_class_install_child_property (container_class,
310                                               CHILD_PROP_PAGE_HEADER_IMAGE,
311                                               g_param_spec_object ("header-image", 
312                                                                    P_("Header image"),
313                                                                    P_("Header image for the assistant page"),
314                                                                    GDK_TYPE_PIXBUF,
315                                                                    GTK_PARAM_READWRITE));
316
317   /**
318    * GtkAssistant:header-image:
319    *
320    * The image that is displayed next to the page. 
321    *
322    * Set this to %NULL to make the sidebar disappear.
323    *
324    * Since: 2.10
325    */
326   gtk_container_class_install_child_property (container_class,
327                                               CHILD_PROP_PAGE_SIDEBAR_IMAGE,
328                                               g_param_spec_object ("sidebar-image", 
329                                                                    P_("Sidebar image"),
330                                                                    P_("Sidebar image for the assistant page"),
331                                                                    GDK_TYPE_PIXBUF,
332                                                                    GTK_PARAM_READWRITE));
333   /**
334    * GtkAssistant:complete:
335    *
336    * Setting the "complete" child property to %TRUE marks a page as complete
337    * (i.e.: all the required fields are filled out). GTK+ uses this information
338    * to control the sensitivity of the navigation buttons.
339    *
340    * Since: 2.10
341    **/
342   gtk_container_class_install_child_property (container_class,
343                                               CHILD_PROP_PAGE_COMPLETE,
344                                               g_param_spec_boolean ("complete", 
345                                                                     P_("Page complete"),
346                                                                     P_("Whether all required fields on the page have been filled out"),
347                                                                     FALSE,
348                                                                     G_PARAM_READWRITE));
349
350   g_type_class_add_private (gobject_class, sizeof (GtkAssistantPrivate));
351 }
352
353 static gint
354 default_forward_function (gint current_page, gpointer data)
355 {
356   GtkAssistant *assistant;
357   GtkAssistantPrivate *priv;
358   GtkAssistantPage *page_info;
359   GList *page_node;
360
361   assistant = GTK_ASSISTANT (data);
362   priv = assistant->priv;
363
364   page_node = g_list_nth (priv->pages, ++current_page);
365
366   if (!page_node)
367     return -1;
368
369   page_info = (GtkAssistantPage *) page_node->data;
370
371   while (!GTK_WIDGET_VISIBLE (page_info->page))
372     {
373       page_node = page_node->next;
374       page_info = (GtkAssistantPage *) page_node->data;
375       current_page++;
376     }
377
378   return current_page;
379 }
380
381 static void
382 compute_last_button_state (GtkAssistant *assistant)
383 {
384   GtkAssistantPrivate *priv = assistant->priv;
385   GtkAssistantPage *page_info;
386   gint count, page_num, n_pages;
387
388   count = 0;
389   page_num = gtk_assistant_get_current_page (assistant);
390   n_pages  = gtk_assistant_get_n_pages (assistant);
391   page_info = g_list_nth_data (priv->pages, page_num);
392
393   while ((page_num > 0 && page_num < n_pages) &&
394          (page_info->type == GTK_ASSISTANT_PAGE_CONTENT) &&
395          (page_info->complete))
396     {
397       page_num  = (priv->forward_function) (page_num, priv->forward_function_data);
398       page_info = g_list_nth_data (priv->pages, page_num);
399       count++;
400     }
401
402   if (count > 1)
403     gtk_widget_show (assistant->last);
404   else
405     gtk_widget_hide (assistant->last);
406 }
407
408 static void
409 _set_assistant_header_image (GtkAssistant *assistant)
410 {
411   GtkAssistantPrivate *priv = assistant->priv;
412
413   gtk_image_set_from_pixbuf (GTK_IMAGE (priv->header_image),
414                              priv->current_page->header_image);
415 }
416
417 static void
418 _set_assistant_sidebar_image (GtkAssistant *assistant)
419 {
420   GtkAssistantPrivate *priv = assistant->priv;
421
422   gtk_image_set_from_pixbuf (GTK_IMAGE (priv->sidebar_image),
423                              priv->current_page->sidebar_image);
424
425   if (priv->current_page->sidebar_image)
426     gtk_widget_show (priv->sidebar_image);
427   else
428     gtk_widget_hide (priv->sidebar_image);
429 }
430
431 static void
432 _set_assistant_buttons_state (GtkAssistant *assistant)
433 {
434   GtkAssistantPrivate *priv = assistant->priv;
435
436   switch (priv->current_page->type)
437     {
438     case GTK_ASSISTANT_PAGE_INTRO:
439       gtk_widget_set_sensitive (assistant->cancel, TRUE);
440       gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
441       gtk_widget_show (assistant->cancel);
442       gtk_widget_show (assistant->forward);
443       gtk_widget_hide (assistant->back);
444       gtk_widget_hide (assistant->apply);
445       gtk_widget_hide (assistant->close);
446       compute_last_button_state (assistant);
447       break;
448     case GTK_ASSISTANT_PAGE_CONFIRM:
449       gtk_widget_set_sensitive (assistant->cancel, TRUE);
450       gtk_widget_set_sensitive (assistant->back, TRUE);
451       gtk_widget_set_sensitive (assistant->apply, priv->current_page->complete);
452       gtk_widget_show (assistant->cancel);
453       gtk_widget_show (assistant->back);
454       gtk_widget_show (assistant->apply);
455       gtk_widget_hide (assistant->forward);
456       gtk_widget_hide (assistant->close);
457       gtk_widget_hide (assistant->last);
458       break;
459     case GTK_ASSISTANT_PAGE_CONTENT:
460       gtk_widget_set_sensitive (assistant->cancel, TRUE);
461       gtk_widget_set_sensitive (assistant->back, TRUE);
462       gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
463       gtk_widget_show (assistant->cancel);
464       gtk_widget_show (assistant->back);
465       gtk_widget_show (assistant->forward);
466       gtk_widget_hide (assistant->apply);
467       gtk_widget_hide (assistant->close);
468       compute_last_button_state (assistant);
469       break;
470     case GTK_ASSISTANT_PAGE_SUMMARY:
471       gtk_widget_set_sensitive (assistant->close, TRUE);
472       gtk_widget_show (assistant->close);
473       gtk_widget_hide (assistant->cancel);
474       gtk_widget_hide (assistant->back);
475       gtk_widget_hide (assistant->forward);
476       gtk_widget_hide (assistant->apply);
477       gtk_widget_hide (assistant->last);
478       break;
479     case GTK_ASSISTANT_PAGE_PROGRESS:
480       gtk_widget_set_sensitive (assistant->cancel, priv->current_page->complete);
481       gtk_widget_set_sensitive (assistant->back, priv->current_page->complete);
482       gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
483       gtk_widget_show (assistant->cancel);
484       gtk_widget_show (assistant->back);
485       gtk_widget_show (assistant->forward);
486       gtk_widget_hide (assistant->apply);
487       gtk_widget_hide (assistant->close);
488       gtk_widget_hide (assistant->last);
489       break;
490     default:
491       g_assert_not_reached ();
492     }
493
494   /* this is quite general, we don't want to
495    * go back if it's the first page */
496   if (!priv->visited_pages)
497     gtk_widget_hide (assistant->back);
498 }
499
500 static void
501 _set_current_page (GtkAssistant     *assistant,
502                    GtkAssistantPage *page)
503 {
504   GtkAssistantPrivate *priv = assistant->priv;
505   GtkAssistantPage *old_page;
506
507   if (priv->current_page &&
508       GTK_WIDGET_DRAWABLE (priv->current_page->page))
509     old_page = priv->current_page;
510   else
511     old_page = NULL;
512
513   priv->current_page = page;
514
515   _set_assistant_buttons_state (assistant);
516   _set_assistant_header_image (assistant);
517   _set_assistant_sidebar_image (assistant);
518
519   g_signal_emit (assistant, signals [PREPARE], 0, priv->current_page->page);
520
521   if (GTK_WIDGET_VISIBLE (priv->current_page->page) && GTK_WIDGET_MAPPED (assistant))
522     {
523       gtk_widget_map (priv->current_page->page);
524       gtk_widget_map (priv->current_page->title);
525     }
526   
527   if (old_page && GTK_WIDGET_MAPPED (old_page->page))
528     {
529       gtk_widget_unmap (old_page->page);
530       gtk_widget_unmap (old_page->title);
531     }
532
533   gtk_widget_queue_resize (GTK_WIDGET (assistant));
534 }
535
536 static gint
537 compute_next_step (GtkAssistant *assistant)
538 {
539   GtkAssistantPrivate *priv = assistant->priv;
540   GtkAssistantPage *page_info;
541   gint current_page, n_pages, next_page;
542
543   current_page = gtk_assistant_get_current_page (assistant);
544   page_info = priv->current_page;
545   n_pages = gtk_assistant_get_n_pages (assistant);
546
547   next_page = (priv->forward_function) (current_page,
548                                         priv->forward_function_data);
549
550   if (next_page >= 0 && next_page < n_pages)
551     {
552       priv->visited_pages = g_slist_prepend (priv->visited_pages, page_info);
553       _set_current_page (assistant, g_list_nth_data (priv->pages, next_page));
554
555       return TRUE;
556     }
557
558   return FALSE;
559 }
560
561 static void
562 on_assistant_close (GtkWidget *widget, GtkAssistant *assistant)
563 {
564   g_signal_emit (assistant, signals [CLOSE], 0, NULL);
565 }
566
567 static void
568 on_assistant_apply (GtkWidget *widget, GtkAssistant *assistant)
569 {
570   GtkAssistantPrivate *priv = assistant->priv;
571   gboolean success;
572
573   success = compute_next_step (assistant);
574
575   g_signal_emit (assistant, signals [APPLY], 0, priv->current_page->page);
576
577   /* if the assistant hasn't switched to another page, just emit
578    * the CLOSE signal, it't the last page in the assistant flow
579    */
580   if (!success)
581     g_signal_emit (assistant, signals [CLOSE], 0, priv->current_page->page);
582 }
583
584 static void
585 on_assistant_forward (GtkWidget *widget, GtkAssistant *assistant)
586 {
587   if (!compute_next_step (assistant))
588     g_critical ("Page flow is broken, you may want to end it with a page of "
589                 "type GTK_ASSISTANT_PAGE_CONFIRM or GTK_ASSISTANT_PAGE_SUMMARY");
590 }
591
592 static void
593 on_assistant_back (GtkWidget *widget, GtkAssistant *assistant)
594 {
595   GtkAssistantPrivate *priv = assistant->priv;
596   GtkAssistantPage *page_info;
597   GSList *page_node;
598
599   /* skip the progress pages when going back */
600   do
601     {
602       page_node = priv->visited_pages;
603
604       g_return_if_fail (page_node != NULL);
605
606       priv->visited_pages = priv->visited_pages->next;
607       page_info = (GtkAssistantPage *) page_node->data;
608       g_slist_free_1 (page_node);
609     }
610   while (page_info->type == GTK_ASSISTANT_PAGE_PROGRESS ||
611          !GTK_WIDGET_VISIBLE (page_info->page));
612
613   _set_current_page (assistant, page_info);
614 }
615
616 static void
617 on_assistant_cancel (GtkWidget *widget, GtkAssistant *assistant)
618 {
619   g_signal_emit (assistant, signals [CANCEL], 0, NULL);
620 }
621
622 static void
623 on_assistant_last (GtkWidget *widget, GtkAssistant *assistant)
624 {
625   GtkAssistantPrivate *priv = assistant->priv;
626
627   while (priv->current_page->type == GTK_ASSISTANT_PAGE_CONTENT &&
628          priv->current_page->complete)
629     compute_next_step (assistant);
630 }
631
632 static gboolean
633 alternative_button_order (GtkAssistant *assistant)
634 {
635   GtkSettings *settings;
636   GdkScreen *screen;
637   gboolean result;
638
639   screen   = gtk_widget_get_screen (GTK_WIDGET (assistant));
640   settings = gtk_settings_get_for_screen (screen);
641
642   g_object_get (settings,
643                 "gtk-alternative-button-order", &result,
644                 NULL);
645   return result;
646 }
647
648 static void
649 gtk_assistant_init (GtkAssistant *assistant)
650 {
651   GtkAssistantPrivate *priv;
652
653   priv = assistant->priv = GTK_ASSISTANT_GET_PRIVATE (assistant);
654
655   gtk_widget_push_composite_child ();
656
657   /* Header */
658   priv->header_image = gtk_image_new ();
659   gtk_misc_set_alignment (GTK_MISC (priv->header_image), 1., 0.5);
660   gtk_widget_set_parent (priv->header_image, GTK_WIDGET (assistant));
661   gtk_widget_show (priv->header_image);
662
663   /* Sidebar */
664   priv->sidebar_image = gtk_image_new ();
665   gtk_misc_set_alignment (GTK_MISC (priv->sidebar_image), 0., 0.);
666   gtk_widget_set_parent (priv->sidebar_image, GTK_WIDGET (assistant));
667   gtk_widget_show (priv->sidebar_image);
668
669   /* Action area */
670   priv->action_area  = gtk_hbox_new (FALSE, 12);
671   gtk_container_set_border_width (GTK_CONTAINER (priv->action_area), 6);
672   assistant->close   = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
673   assistant->apply   = gtk_button_new_from_stock (GTK_STOCK_APPLY);
674   assistant->forward = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
675   assistant->back    = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
676   assistant->cancel  = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
677   assistant->last    = gtk_button_new_from_stock (GTK_STOCK_GOTO_LAST);
678
679   priv->size_group   = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
680   gtk_size_group_add_widget (priv->size_group, assistant->close);
681   gtk_size_group_add_widget (priv->size_group, assistant->apply);
682   gtk_size_group_add_widget (priv->size_group, assistant->forward);
683   gtk_size_group_add_widget (priv->size_group, assistant->back);
684   gtk_size_group_add_widget (priv->size_group, assistant->cancel);
685   gtk_size_group_add_widget (priv->size_group, assistant->last);
686
687   if (!alternative_button_order (assistant))
688     {
689       gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->close, FALSE, FALSE, 0);
690       gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->apply, FALSE, FALSE, 0);
691       gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->forward, FALSE, FALSE, 0);
692       gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->back, FALSE, FALSE, 0);
693       gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->cancel, FALSE, FALSE, 0);
694       gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->last, FALSE, FALSE, 0);
695     }
696   else
697     {
698       gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->cancel, FALSE, FALSE, 0);
699       gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->close, FALSE, FALSE, 0);
700       gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->apply, FALSE, FALSE, 0);
701       gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->forward, FALSE, FALSE, 0);
702       gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->back, FALSE, FALSE, 0);
703       gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->last, FALSE, FALSE, 0);
704     }
705
706   gtk_widget_set_parent (priv->action_area, GTK_WIDGET (assistant));
707   gtk_widget_show (assistant->forward);
708   gtk_widget_show (assistant->back);
709   gtk_widget_show (assistant->cancel);
710   gtk_widget_show (priv->action_area);
711
712   gtk_widget_pop_composite_child ();
713
714   priv->pages = NULL;
715   priv->current_page = NULL;
716   priv->visited_pages = NULL;
717
718   priv->forward_function = default_forward_function;
719   priv->forward_function_data = assistant;
720   priv->forward_data_destroy = NULL;
721
722   g_signal_connect (G_OBJECT (assistant->close), "clicked",
723                     G_CALLBACK (on_assistant_close), assistant);
724   g_signal_connect (G_OBJECT (assistant->apply), "clicked",
725                     G_CALLBACK (on_assistant_apply), assistant);
726   g_signal_connect (G_OBJECT (assistant->forward), "clicked",
727                     G_CALLBACK (on_assistant_forward), assistant);
728   g_signal_connect (G_OBJECT (assistant->back), "clicked",
729                     G_CALLBACK (on_assistant_back), assistant);
730   g_signal_connect (G_OBJECT (assistant->cancel), "clicked",
731                     G_CALLBACK (on_assistant_cancel), assistant);
732   g_signal_connect (G_OBJECT (assistant->last), "clicked",
733                     G_CALLBACK (on_assistant_last), assistant);
734 }
735
736 static void
737 gtk_assistant_set_child_property (GtkContainer    *container,
738                                   GtkWidget       *child,
739                                   guint            property_id,
740                                   const GValue    *value,
741                                   GParamSpec      *pspec)
742 {
743   switch (property_id)
744     {
745     case CHILD_PROP_PAGE_TYPE:
746       gtk_assistant_set_page_type (GTK_ASSISTANT (container), child,
747                                    g_value_get_enum (value));
748       break;
749     case CHILD_PROP_PAGE_TITLE:
750       gtk_assistant_set_page_title (GTK_ASSISTANT (container), child,
751                                     g_value_get_string (value));
752       break;
753     case CHILD_PROP_PAGE_HEADER_IMAGE:
754       gtk_assistant_set_page_header_image (GTK_ASSISTANT (container), child,
755                                            g_value_get_object (value));
756       break;
757     case CHILD_PROP_PAGE_SIDEBAR_IMAGE:
758       gtk_assistant_set_page_side_image (GTK_ASSISTANT (container), child,
759                                          g_value_get_object (value));
760       break;
761     case CHILD_PROP_PAGE_COMPLETE:
762       gtk_assistant_set_page_complete (GTK_ASSISTANT (container), child,
763                                        g_value_get_boolean (value));
764       break;
765     default:
766       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
767       break;
768     }
769 }
770
771 static void
772 gtk_assistant_get_child_property (GtkContainer *container,
773                                   GtkWidget    *child,
774                                   guint         property_id,
775                                   GValue       *value,
776                                   GParamSpec   *pspec)
777 {
778   switch (property_id)
779     {
780     case CHILD_PROP_PAGE_TYPE:
781       g_value_set_enum (value,
782                         gtk_assistant_get_page_type (GTK_ASSISTANT (container), child));
783       break;
784     case CHILD_PROP_PAGE_TITLE:
785       g_value_set_string (value,
786                           gtk_assistant_get_page_title (GTK_ASSISTANT (container), child));
787       break;
788     case CHILD_PROP_PAGE_HEADER_IMAGE:
789       g_value_set_object (value,
790                           gtk_assistant_get_page_header_image (GTK_ASSISTANT (container), child));
791       break;
792     case CHILD_PROP_PAGE_SIDEBAR_IMAGE:
793       g_value_set_object (value,
794                           gtk_assistant_get_page_side_image (GTK_ASSISTANT (container), child));
795       break;
796     case CHILD_PROP_PAGE_COMPLETE:
797       g_value_set_boolean (value,
798                            gtk_assistant_get_page_complete (GTK_ASSISTANT (container), child));
799       break;
800     default:
801       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
802       break;
803     }
804 }
805
806 static void
807 remove_page (GtkAssistant *assistant, 
808              GList        *element)
809 {
810   GtkAssistantPrivate *priv = assistant->priv;
811   GtkAssistantPage *page_info;
812
813   page_info = element->data;
814
815   /* If we are mapped and visible, we want to deal with changing the page. */
816   if ((GTK_WIDGET_MAPPED (page_info->page)) && (page_info == priv->current_page))
817     compute_next_step (assistant);
818
819   priv->pages = g_list_remove_link (priv->pages, element);
820
821   priv->visited_pages = g_slist_remove_all (priv->visited_pages, page_info);
822   gtk_widget_unparent (page_info->page);
823
824   if (page_info->header_image)
825     g_object_unref (page_info->header_image);
826
827   if (page_info->sidebar_image)
828     g_object_unref (page_info->sidebar_image);
829
830   gtk_widget_destroy (page_info->title);
831   g_free (page_info);
832   g_list_free_1 (element);
833 }
834
835 static void
836 gtk_assistant_destroy (GtkObject *object)
837 {
838   GtkAssistant *assistant = GTK_ASSISTANT (object);
839   GtkAssistantPrivate *priv = assistant->priv;
840
841   if (priv->header_image)
842     {
843       gtk_widget_destroy (priv->header_image);
844       priv->header_image = NULL;
845     }
846
847   if (priv->sidebar_image)
848     {
849       gtk_widget_destroy (priv->sidebar_image);
850       priv->sidebar_image = NULL;
851     }
852
853   if (priv->action_area)
854     {
855       gtk_widget_destroy (priv->action_area);
856       priv->action_area = NULL;
857     }
858
859   if (priv->size_group)
860     {
861       g_object_unref (priv->size_group);
862       priv->size_group = NULL;
863     }
864
865   if (priv->forward_function)
866     {
867       if (priv->forward_function_data &&
868           priv->forward_data_destroy)
869         priv->forward_data_destroy (priv->forward_function_data);
870
871       priv->forward_function = NULL;
872       priv->forward_function_data = NULL;
873       priv->forward_data_destroy = NULL;
874     }
875
876   if (priv->visited_pages)
877     {
878       g_slist_free (priv->visited_pages);
879       priv->visited_pages = NULL;
880     }
881
882   /* We set current to NULL so that the remove code doesn't try
883    * to do anything funny */
884   priv->current_page = NULL;
885
886   while (priv->pages)
887     remove_page (GTK_ASSISTANT (object), priv->pages);
888       
889   GTK_OBJECT_CLASS (gtk_assistant_parent_class)->destroy (object);
890 }
891
892 static GList*
893 find_page (GtkAssistant  *assistant,
894            GtkWidget     *page)
895 {
896   GtkAssistantPrivate *priv = assistant->priv;
897   GList *child = priv->pages;
898   
899   while (child)
900     {
901       GtkAssistantPage *page_info = child->data;
902       if (page_info->page == page)
903         return child;
904
905       child = child->next;
906     }
907   
908   return NULL;
909 }
910
911 static void
912 set_title_colors (GtkWidget *assistant,
913                   GtkWidget *title_label)
914 {
915   GtkStyle *style;
916
917   gtk_widget_ensure_style (assistant);
918   style = gtk_widget_get_style (assistant);
919
920   /* change colors schema, for making the header text visible */
921   gtk_widget_modify_bg (title_label, GTK_STATE_NORMAL, &style->bg[GTK_STATE_SELECTED]);
922   gtk_widget_modify_fg (title_label, GTK_STATE_NORMAL, &style->fg[GTK_STATE_SELECTED]);
923 }
924
925 static void
926 set_title_font (GtkWidget *assistant,
927                 GtkWidget *title_label)
928 {
929   PangoFontDescription *desc;
930   gint size;
931
932   desc = pango_font_description_new ();
933   size = pango_font_description_get_size (assistant->style->font_desc);
934
935   pango_font_description_set_weight (desc, PANGO_WEIGHT_ULTRABOLD);
936   pango_font_description_set_size   (desc, size * PANGO_SCALE_XX_LARGE);
937
938   gtk_widget_modify_font (title_label, desc);
939   pango_font_description_free (desc);
940 }
941
942 static void
943 gtk_assistant_style_set (GtkWidget *widget,
944                          GtkStyle  *old_style)
945 {
946   GtkAssistant *assistant = GTK_ASSISTANT (widget);
947   GtkAssistantPrivate *priv = assistant->priv;
948   GList *list;
949
950   list = priv->pages;
951
952   while (list)
953     {
954       GtkAssistantPage *page = list->data;
955
956       set_title_colors (widget, page->title);
957       set_title_font (widget, page->title);
958
959       list = list->next;
960     }
961 }
962
963 static void
964 gtk_assistant_size_request (GtkWidget      *widget,
965                             GtkRequisition *requisition)
966 {
967   GtkAssistant *assistant = GTK_ASSISTANT (widget);
968   GtkAssistantPrivate *priv = assistant->priv;
969   GtkRequisition child_requisition;
970   gint header_padding, content_padding;
971   gint width, height, header_width, header_height;
972   GList *list;
973
974   gtk_widget_style_get (widget,
975                         "header-padding", &header_padding,
976                         "content-padding", &content_padding,
977                         NULL);
978   width = height = 0;
979   header_width = header_height = 0;
980   list  = priv->pages;
981
982   while (list)
983     {
984       GtkAssistantPage *page = list->data;
985       gint w, h;
986
987       gtk_widget_size_request (page->page, &child_requisition);
988       width  = MAX (width,  child_requisition.width);
989       height = MAX (height, child_requisition.height);
990
991       gtk_widget_size_request (page->title, &child_requisition);
992       w = child_requisition.width;
993       h = child_requisition.height;
994
995       if (page->header_image)
996         {
997           w += gdk_pixbuf_get_width (page->header_image) + HEADER_SPACING;
998           h  = MAX (h, gdk_pixbuf_get_height (page->header_image));
999         }
1000
1001       header_width  = MAX (header_width, w);
1002       header_height = MAX (header_height, h);
1003
1004       list = list->next;
1005     }
1006
1007   gtk_widget_size_request (priv->sidebar_image, &child_requisition);
1008   width  += child_requisition.width;
1009   height  = MAX (height, child_requisition.height);
1010
1011   gtk_widget_set_size_request (priv->header_image, header_width, header_height);
1012   gtk_widget_size_request (priv->header_image, &child_requisition);
1013   width   = MAX (width, header_width) + 2 * header_padding;
1014   height += header_height + 2 * header_padding;
1015
1016   gtk_widget_size_request (priv->action_area, &child_requisition);
1017   width   = MAX (width, child_requisition.width);
1018   height += child_requisition.height;
1019
1020   width += GTK_CONTAINER (widget)->border_width * 2 + content_padding * 2;
1021   height += GTK_CONTAINER (widget)->border_width * 2 + content_padding * 2;
1022
1023   requisition->width = width;
1024   requisition->height = height;
1025 }
1026
1027 static void
1028 gtk_assistant_size_allocate (GtkWidget      *widget,
1029                              GtkAllocation  *allocation)
1030 {
1031   GtkAssistant *assistant = GTK_ASSISTANT (widget);
1032   GtkAssistantPrivate *priv = assistant->priv;
1033   GtkRequisition header_requisition;
1034   GtkAllocation child_allocation, header_allocation;
1035   gint header_padding, content_padding;
1036   gboolean rtl;
1037   GList *pages;
1038
1039   rtl   = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1040   pages = priv->pages;
1041
1042   gtk_widget_style_get (widget,
1043                         "header-padding", &header_padding,
1044                         "content-padding", &content_padding,
1045                         NULL);
1046
1047   widget->allocation = *allocation;
1048
1049   /* Header */
1050   gtk_widget_get_child_requisition (priv->header_image, &header_requisition);
1051
1052   header_allocation.x = allocation->x + GTK_CONTAINER (widget)->border_width + header_padding;
1053   header_allocation.y = allocation->y + GTK_CONTAINER (widget)->border_width + header_padding;
1054   header_allocation.width  = allocation->width - 2 * GTK_CONTAINER (widget)->border_width - 2 * header_padding;
1055   header_allocation.height = header_requisition.height;
1056
1057   gtk_widget_size_allocate (priv->header_image, &header_allocation);
1058
1059   /* Action area */
1060   child_allocation.x = allocation->x + GTK_CONTAINER (widget)->border_width;
1061   child_allocation.y = allocation->y + allocation->height -
1062     GTK_CONTAINER (widget)->border_width - priv->action_area->requisition.height;
1063   child_allocation.width  = allocation->width - 2 * GTK_CONTAINER (widget)->border_width;
1064   child_allocation.height = priv->action_area->requisition.height;
1065
1066   gtk_widget_size_allocate (priv->action_area, &child_allocation);
1067
1068   /* Sidebar */
1069   if (rtl)
1070     child_allocation.x = allocation->x + allocation->width -
1071       GTK_CONTAINER (widget)->border_width - priv->sidebar_image->requisition.width;
1072   else
1073     child_allocation.x = allocation->x + GTK_CONTAINER (widget)->border_width;
1074
1075   child_allocation.y = allocation->y + GTK_CONTAINER (widget)->border_width +
1076     priv->header_image->allocation.height + 2 * header_padding;
1077   child_allocation.width = priv->sidebar_image->requisition.width;
1078   child_allocation.height = allocation->height - 2 * GTK_CONTAINER (widget)->border_width -
1079     priv->header_image->allocation.height - 2 * header_padding - priv->action_area->allocation.height;
1080
1081   gtk_widget_size_allocate (priv->sidebar_image, &child_allocation);
1082
1083   /* Pages */
1084   child_allocation.x = allocation->x + GTK_CONTAINER (widget)->border_width + content_padding;
1085   child_allocation.y = allocation->y + GTK_CONTAINER (widget)->border_width +
1086     priv->header_image->allocation.height + 2 * header_padding + content_padding;
1087   child_allocation.width  = allocation->width - 2 * GTK_CONTAINER (widget)->border_width - 2 * content_padding;
1088   child_allocation.height = allocation->height - 2 * GTK_CONTAINER (widget)->border_width -
1089     priv->header_image->allocation.height - 2 * header_padding - priv->action_area->allocation.height - 2 * content_padding;
1090
1091   if (GTK_WIDGET_VISIBLE (priv->sidebar_image))
1092     {
1093       if (!rtl)
1094         child_allocation.x += priv->sidebar_image->allocation.width;
1095
1096       child_allocation.width -= priv->sidebar_image->allocation.width;
1097     }
1098
1099   while (pages)
1100     {
1101       GtkAssistantPage *page = pages->data;
1102
1103       gtk_widget_size_allocate (page->page, &child_allocation);
1104       gtk_widget_size_allocate (page->title, &header_allocation);
1105       pages = pages->next;
1106     }
1107 }
1108
1109 static void
1110 gtk_assistant_map (GtkWidget *widget)
1111 {
1112   GtkAssistant *assistant = GTK_ASSISTANT (widget);
1113   GtkAssistantPrivate *priv = assistant->priv;
1114   GList *page_node;
1115
1116   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1117
1118   gtk_widget_map (priv->header_image);
1119   gtk_widget_map (priv->action_area);
1120
1121   if (GTK_WIDGET_VISIBLE (priv->sidebar_image) &&
1122       !GTK_WIDGET_MAPPED (priv->sidebar_image))
1123     gtk_widget_map (priv->sidebar_image);
1124
1125   /* if there's no default page, pick the first one */
1126   if (!priv->current_page && priv->pages)
1127     {
1128       page_node = priv->pages;
1129
1130       while (!GTK_WIDGET_VISIBLE (((GtkAssistantPage *) page_node->data)->page))
1131         page_node = page_node->next;
1132
1133       if (page_node)
1134         priv->current_page = page_node->data;
1135     }
1136
1137   if (priv->current_page &&
1138       GTK_WIDGET_VISIBLE (priv->current_page->page) &&
1139       !GTK_WIDGET_MAPPED (priv->current_page->page))
1140     {
1141       _set_assistant_buttons_state ((GtkAssistant *) widget);
1142       _set_assistant_header_image ((GtkAssistant*) widget);
1143       _set_assistant_sidebar_image ((GtkAssistant*) widget);
1144
1145       g_signal_emit (widget, signals [PREPARE], 0, priv->current_page->page);
1146       gtk_widget_map (priv->current_page->page);
1147       gtk_widget_map (priv->current_page->title);
1148     }
1149
1150   GTK_WIDGET_CLASS (gtk_assistant_parent_class)->map (widget);
1151 }
1152
1153 static void
1154 gtk_assistant_unmap (GtkWidget *widget)
1155 {
1156   GtkAssistant *assistant = GTK_ASSISTANT (widget);
1157   GtkAssistantPrivate *priv = assistant->priv;
1158
1159   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1160
1161   gtk_widget_unmap (priv->header_image);
1162   gtk_widget_unmap (priv->action_area);
1163
1164   if (GTK_WIDGET_DRAWABLE (priv->sidebar_image))
1165     gtk_widget_unmap (priv->sidebar_image);
1166
1167   if (priv->current_page &&
1168       GTK_WIDGET_DRAWABLE (priv->current_page->page))
1169     gtk_widget_unmap (priv->current_page->page);
1170
1171   g_slist_free (priv->visited_pages);
1172   priv->visited_pages = NULL;
1173   priv->current_page  = NULL;
1174
1175   GTK_WIDGET_CLASS (gtk_assistant_parent_class)->unmap (widget);
1176 }
1177
1178 static gboolean
1179 gtk_assistant_delete_event (GtkWidget   *widget,
1180                             GdkEventAny *event)
1181 {
1182   GtkAssistant *assistant = GTK_ASSISTANT (widget);
1183   GtkAssistantPrivate *priv = assistant->priv;
1184
1185   /* Do not allow cancelling in the middle of a progress page */
1186   if (priv->current_page &&
1187       (priv->current_page->type != GTK_ASSISTANT_PAGE_PROGRESS ||
1188        priv->current_page->complete))
1189     g_signal_emit (widget, signals [CANCEL], 0, NULL);
1190
1191   return TRUE;
1192 }
1193
1194 static void
1195 assistant_paint_colored_box (GtkWidget *widget)
1196 {
1197   GtkAssistant *assistant = GTK_ASSISTANT (widget);
1198   GtkAssistantPrivate *priv = assistant->priv;
1199   gint header_padding, content_padding;
1200   cairo_t *cr;
1201   gint content_x, content_width;
1202   gboolean rtl;
1203
1204   cr   = gdk_cairo_create (widget->window);
1205   rtl  = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1206
1207   gtk_widget_style_get (widget,
1208                         "header-padding",  &header_padding,
1209                         "content-padding", &content_padding,
1210                         NULL);
1211
1212   /* colored box */
1213   gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_SELECTED]);
1214   cairo_rectangle (cr,
1215                    0, 0,
1216                    widget->allocation.width,
1217                    widget->allocation.height - priv->action_area->allocation.height);
1218   cairo_fill (cr);
1219
1220   /* content box */
1221   content_x = content_padding;
1222   content_width = widget->allocation.width - 2 * content_padding;
1223
1224   if (GTK_WIDGET_VISIBLE (priv->sidebar_image))
1225     {
1226       if (!rtl)
1227         content_x += priv->sidebar_image->allocation.width;
1228       content_width -= priv->sidebar_image->allocation.width;
1229     }
1230   
1231   gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_NORMAL]);
1232
1233   cairo_rectangle (cr,
1234                    content_x,
1235                    priv->header_image->allocation.height + content_padding + 2 * header_padding,
1236                    content_width,
1237                    widget->allocation.height - priv->action_area->allocation.height -
1238                    priv->header_image->allocation.height - 2 * content_padding - 2 * header_padding);
1239   cairo_fill (cr);
1240
1241   cairo_destroy (cr);
1242 }
1243
1244 static gboolean
1245 gtk_assistant_expose (GtkWidget      *widget,
1246                       GdkEventExpose *event)
1247 {
1248   GtkAssistant *assistant = GTK_ASSISTANT (widget);
1249   GtkAssistantPrivate *priv = assistant->priv;
1250   GtkContainer *container;
1251
1252   if (GTK_WIDGET_DRAWABLE (widget))
1253     {
1254       container = GTK_CONTAINER (widget);
1255
1256       assistant_paint_colored_box (widget);
1257
1258       gtk_container_propagate_expose (container, priv->header_image, event);
1259       gtk_container_propagate_expose (container, priv->sidebar_image, event);
1260       gtk_container_propagate_expose (container, priv->action_area, event);
1261
1262       if (priv->current_page)
1263         {
1264           gtk_container_propagate_expose (container, priv->current_page->page, event);
1265           gtk_container_propagate_expose (container, priv->current_page->title, event);
1266         }
1267     }
1268
1269   return FALSE;
1270 }
1271
1272 static void
1273 gtk_assistant_add (GtkContainer *container,
1274                    GtkWidget    *page)
1275 {
1276   g_return_if_fail (GTK_IS_WIDGET (page));
1277
1278   gtk_assistant_append_page (GTK_ASSISTANT (container), page);
1279 }
1280
1281 static void
1282 gtk_assistant_remove (GtkContainer *container,
1283                       GtkWidget    *page)
1284 {
1285   GtkAssistant *assistant;
1286   GList *element;
1287
1288   assistant = (GtkAssistant*) container;
1289
1290   element = find_page (assistant, page);
1291
1292   if (element)
1293     {
1294       remove_page (assistant, element);
1295       gtk_widget_queue_resize ((GtkWidget *) container);
1296     }
1297 }
1298
1299 static void
1300 gtk_assistant_forall (GtkContainer *container,
1301                       gboolean      include_internals,
1302                       GtkCallback   callback,
1303                       gpointer      callback_data)
1304 {
1305   GtkAssistant *assistant = (GtkAssistant*) container;
1306   GtkAssistantPrivate *priv = assistant->priv;
1307   GList *pages;
1308
1309   if (include_internals)
1310     {
1311       (*callback) (priv->header_image, callback_data);
1312       (*callback) (priv->sidebar_image, callback_data);
1313       (*callback) (priv->action_area, callback_data);
1314     }
1315
1316   pages = priv->pages;
1317
1318   while (pages)
1319     {
1320       GtkAssistantPage *page = (GtkAssistantPage *) pages->data;
1321
1322       (*callback) (page->page, callback_data);
1323
1324       if (include_internals)
1325         (*callback) (page->title, callback_data);
1326
1327       pages = pages->next;
1328     }
1329 }
1330
1331 /**
1332  * gtk_assistant_new:
1333  * 
1334  * Creates a new #GtkAssistant.
1335  *
1336  * Return value: a newly created #GtkAssistant
1337  *
1338  * Since: 2.10
1339  **/
1340 GtkWidget*
1341 gtk_assistant_new (void)
1342 {
1343   GtkWidget *assistant;
1344
1345   assistant = g_object_new (GTK_TYPE_ASSISTANT, NULL);
1346
1347   return assistant;
1348 }
1349
1350 /**
1351  * gtk_assistant_get_current_page:
1352  * @assistant: a #GtkAssistant
1353  *
1354  * Returns the page number of the current page
1355  *
1356  * Return value: The index (starting from 0) of the current page in
1357  * the @assistant, if the @assistant has no pages, -1 will be returned
1358  *
1359  * Since: 2.10
1360  **/
1361 gint
1362 gtk_assistant_get_current_page (GtkAssistant *assistant)
1363 {
1364   GtkAssistantPrivate *priv;
1365
1366   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), -1);
1367
1368   priv = assistant->priv;
1369
1370   if (!priv->pages || !priv->current_page)
1371     return -1;
1372
1373   return g_list_index (priv->pages, priv->current_page);
1374 }
1375
1376 /**
1377  * gtk_assistant_set_current_page:
1378  * @assistant: a #GtkAssistant
1379  * @page_num: index of the page to switch to, starting from 0.
1380  *            If negative, the last page will be used. If greater
1381  *            than the number of pages in the @assistant, nothing
1382  *            will be done.
1383  *
1384  * Switches the page to @page_num. Note that this will only be necessary
1385  * in custom buttons, as the @assistant flow can be set with
1386  * gtk_assistant_set_forward_page_func().
1387  *
1388  * Since: 2.10
1389  **/
1390 void
1391 gtk_assistant_set_current_page (GtkAssistant *assistant,
1392                                 gint          page_num)
1393 {
1394   GtkAssistantPrivate *priv;
1395   GtkAssistantPage *page;
1396
1397   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1398
1399   priv = assistant->priv;
1400
1401   if (page_num >= 0)
1402     page = (GtkAssistantPage *) g_list_nth_data (priv->pages, page_num);
1403   else
1404     page = (GtkAssistantPage *) g_list_last (priv->pages);
1405
1406   g_return_if_fail (page != NULL);
1407
1408   if (priv->current_page == page)
1409     return;
1410
1411   /* only add the page to the visited list if the
1412    * assistant is mapped, if not, just use it as an
1413    * initial page setting, for the cases where the
1414    * initial page is != to 0
1415    */
1416   if (GTK_WIDGET_MAPPED (assistant))
1417     priv->visited_pages = g_slist_prepend (priv->visited_pages, page);
1418
1419   _set_current_page (assistant, page);
1420 }
1421
1422 /**
1423  * gtk_assistant_get_n_pages:
1424  * @assistant: a #GtkAssistant
1425  *
1426  * Returns the number of pages in the @assistant
1427  *
1428  * Return value: The number of pages in the @assistant.
1429  *
1430  * Since: 2.10
1431  **/
1432 gint
1433 gtk_assistant_get_n_pages (GtkAssistant *assistant)
1434 {
1435   GtkAssistantPrivate *priv;
1436
1437   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
1438
1439   priv = assistant->priv;
1440
1441   return g_list_length (priv->pages);
1442 }
1443
1444 /**
1445  * gtk_assistant_get_nth_page:
1446  * @assistant: a #GtkAssistant
1447  * @page_num: The index of a page in the @assistant, or -1 to get the last page;
1448  *
1449  * Returns the child widget contained in page number @page_num.
1450  *
1451  * Return value: The child widget, or %NULL if @page_num is out of bounds.
1452  *
1453  * Since: 2.10
1454  **/
1455 GtkWidget*
1456 gtk_assistant_get_nth_page (GtkAssistant *assistant,
1457                             gint          page_num)
1458 {
1459   GtkAssistantPrivate *priv;
1460   GtkAssistantPage *page;
1461   GList *elem;
1462
1463   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
1464
1465   priv = assistant->priv;
1466
1467   elem = g_list_nth (priv->pages, page_num);
1468
1469   if (!elem)
1470     return NULL;
1471
1472   page = (GtkAssistantPage *) elem->data;
1473
1474   return page->page;
1475 }
1476
1477 /**
1478  * gtk_assistant_prepend_page:
1479  * @assistant: a #GtkAssistant
1480  * @page: a #GtkWidget
1481  *
1482  * Prepends a page to the @assistant.
1483  *
1484  * Return value: the index (starting at 0) of the inserted page
1485  *
1486  * Since: 2.10
1487  **/
1488 gint
1489 gtk_assistant_prepend_page (GtkAssistant *assistant,
1490                             GtkWidget    *page)
1491 {
1492   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
1493   g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
1494
1495   return gtk_assistant_insert_page (assistant, page, 0);
1496 }
1497
1498 /**
1499  * gtk_assistant_append_page:
1500  * @assistant: a #GtkAssistant
1501  * @page: a #GtkWidget
1502  *
1503  * Appends a page to the @assistant.
1504  *
1505  * Return value: the index (starting at 0) of the inserted page
1506  *
1507  * Since: 2.10
1508  **/
1509 gint
1510 gtk_assistant_append_page (GtkAssistant *assistant,
1511                            GtkWidget    *page)
1512 {
1513   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
1514   g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
1515
1516   return gtk_assistant_insert_page (assistant, page, -1);
1517 }
1518
1519 /**
1520  * gtk_assistant_insert_page:
1521  * @assistant: a #GtkAssistant
1522  * @page: a #GtkWidget
1523  * @position: the index (starting at 0) at which to insert the page,
1524  *            or -1 to append the page to the @assistant
1525  *
1526  * Inserts a page in the @assistant at a given position.
1527  *
1528  * Return value: the index (starting from 0) of the inserted page
1529  *
1530  * Since: 2.10
1531  **/
1532 gint
1533 gtk_assistant_insert_page (GtkAssistant *assistant,
1534                            GtkWidget    *page,
1535                            gint          position)
1536 {
1537   GtkAssistantPrivate *priv;
1538   GtkAssistantPage *page_info;
1539   gint n_pages;
1540
1541   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
1542   g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
1543   g_return_val_if_fail (page->parent == NULL, 0);
1544   g_return_val_if_fail (!GTK_WIDGET_TOPLEVEL (page), 0);
1545
1546   priv = assistant->priv;
1547
1548   page_info = g_new0 (GtkAssistantPage, 1);
1549   page_info->page  = page;
1550   page_info->title = gtk_label_new (NULL);
1551
1552   gtk_misc_set_alignment (GTK_MISC (page_info->title), 0.,0.5);
1553   set_title_colors (GTK_WIDGET (assistant), page_info->title);
1554   set_title_font   (GTK_WIDGET (assistant), page_info->title);
1555   gtk_widget_show  (page_info->title);
1556
1557   n_pages = g_list_length (priv->pages);
1558
1559   if (position < 0 || position > n_pages)
1560     position = n_pages;
1561
1562   priv->pages = g_list_insert (priv->pages, page_info, position);
1563
1564   gtk_widget_set_parent (page_info->page,  GTK_WIDGET (assistant));
1565   gtk_widget_set_parent (page_info->title, GTK_WIDGET (assistant));
1566
1567   if (GTK_WIDGET_REALIZED (GTK_WIDGET (assistant)))
1568     {
1569       gtk_widget_realize (page_info->page);
1570       gtk_widget_realize (page_info->title);
1571     }
1572
1573   gtk_widget_queue_resize (GTK_WIDGET (assistant));
1574
1575   return position;
1576 }
1577
1578 /**
1579  * gtk_assistant_set_forward_page_func:
1580  * @assistant: a #GtkAssistant
1581  * @page_func: the #GtkAssistantPageFunc, or %NULL to use the default one
1582  * @data: user data for @page_func
1583  * @destroy: destroy notifier for @data
1584  *
1585  * Sets the page forwarding function to be @page_func, this function will
1586  * be used to determine what will be the next page when the user presses
1587  * the forward button. Setting @page_func to %NULL will make the assistant
1588  * to use the default forward function, which just goes to the next visible 
1589  * page.
1590  *
1591  * Since: 2.10
1592  **/
1593 void
1594 gtk_assistant_set_forward_page_func (GtkAssistant         *assistant,
1595                                      GtkAssistantPageFunc  page_func,
1596                                      gpointer              data,
1597                                      GDestroyNotify        destroy)
1598 {
1599   GtkAssistantPrivate *priv;
1600
1601   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1602
1603   priv = assistant->priv;
1604
1605   if (priv->forward_data_destroy &&
1606       priv->forward_function_data)
1607     (*priv->forward_data_destroy) (priv->forward_function_data);
1608
1609   if (page_func)
1610     {
1611       priv->forward_function = page_func;
1612       priv->forward_function_data = data;
1613       priv->forward_data_destroy = destroy;
1614     }
1615   else
1616     {
1617       priv->forward_function = default_forward_function;
1618       priv->forward_function_data = assistant;
1619       priv->forward_data_destroy = NULL;
1620     }
1621 }
1622
1623 /**
1624  * gtk_assistant_add_action_widget:
1625  * @dialog: a #GtkAssistant
1626  * @child: a #GtkWidget
1627  * 
1628  * Adds a widget to the action area of a #GtkAssistant.
1629  *
1630  * Since: 2.10
1631  **/
1632 void
1633 gtk_assistant_add_action_widget (GtkAssistant *assistant,
1634                                  GtkWidget    *child)
1635 {
1636   GtkAssistantPrivate *priv;
1637
1638   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1639   g_return_if_fail (GTK_IS_WIDGET (child));
1640
1641   priv = assistant->priv;
1642
1643   if (GTK_IS_BUTTON (child))
1644     gtk_size_group_add_widget (priv->size_group, child);
1645
1646   gtk_box_pack_end (GTK_BOX (priv->action_area), child, FALSE, FALSE, 0);
1647 }
1648
1649 /**
1650  * gtk_assistant_remove_action_widget:
1651  * @dialog: a #GtkAssistant
1652  * @child: a #GtkWidget
1653  *
1654  * Removes a widget from the action area of a #GtkAssistant.
1655  *
1656  * Since: 2.10
1657  **/
1658 void
1659 gtk_assistant_remove_action_widget (GtkAssistant *assistant,
1660                                     GtkWidget    *child)
1661 {
1662   GtkAssistantPrivate *priv;
1663
1664   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1665   g_return_if_fail (GTK_IS_WIDGET (child));
1666
1667   priv = assistant->priv;
1668
1669   if (GTK_IS_BUTTON (child))
1670     gtk_size_group_remove_widget (priv->size_group, child);
1671
1672   gtk_container_remove (GTK_CONTAINER (priv->action_area), child);
1673 }
1674
1675 /**
1676  * gtk_assistant_set_page_title:
1677  * @assistant: a #GtkAssistant
1678  * @page: a page of @assitant
1679  * @title: the new title for @page
1680  * 
1681  * Sets a title for @page. The title is displayed in the header
1682  * area of the assistant when @page is the current page.
1683  *
1684  * Since: 2.10
1685  **/
1686 void
1687 gtk_assistant_set_page_title (GtkAssistant *assistant,
1688                               GtkWidget    *page,
1689                               const gchar  *title)
1690 {
1691   GtkAssistantPrivate *priv;
1692   GtkAssistantPage *page_info;
1693   GList *child;
1694
1695   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1696   g_return_if_fail (GTK_IS_WIDGET (page));
1697
1698   priv = assistant->priv;
1699   child = find_page (assistant, page);
1700
1701   g_return_if_fail (child != NULL);
1702
1703   page_info = (GtkAssistantPage*) child->data;
1704
1705   gtk_label_set_text ((GtkLabel*) page_info->title, title);
1706   gtk_widget_queue_resize (GTK_WIDGET (assistant));
1707   gtk_widget_child_notify (page, "title");
1708 }
1709
1710 /**
1711  * gtk_assistant_get_page_title:
1712  * @assistant: a #GtkAssistant
1713  * @page: a page of @assistant
1714  * 
1715  * Gets the title for @page. 
1716  * 
1717  * Return value: the title for @page.
1718  *
1719  * Since: 2.10
1720  **/
1721 G_CONST_RETURN gchar*
1722 gtk_assistant_get_page_title (GtkAssistant *assistant,
1723                               GtkWidget    *page)
1724 {
1725   GtkAssistantPrivate *priv;
1726   GtkAssistantPage *page_info;
1727   GList *child;
1728
1729   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
1730   g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
1731
1732   priv = assistant->priv;
1733   child = find_page (assistant, page);
1734
1735   g_return_val_if_fail (child != NULL, NULL);
1736
1737   page_info = (GtkAssistantPage*) child->data;
1738
1739   return gtk_label_get_text ((GtkLabel*) page_info->title);
1740 }
1741
1742 /**
1743  * gtk_assistant_set_page_type:
1744  * @assistant: a #GtkAssistant
1745  * @page: a page of @assitant
1746  * @type: the new type for @page
1747  * 
1748  * Sets the page type for @page. The page type determines the page
1749  * behavior in the @assistant.
1750  *
1751  * Since: 2.10
1752  **/
1753 void
1754 gtk_assistant_set_page_type (GtkAssistant         *assistant,
1755                              GtkWidget            *page,
1756                              GtkAssistantPageType  type)
1757 {
1758   GtkAssistantPrivate *priv;
1759   GtkAssistantPage *page_info;
1760   GList *child;
1761
1762   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1763   g_return_if_fail (GTK_IS_WIDGET (page));
1764
1765   priv = assistant->priv;
1766   child = find_page (assistant, page);
1767
1768   g_return_if_fail (child != NULL);
1769
1770   page_info = (GtkAssistantPage*) child->data;
1771
1772   if (type != page_info->type)
1773     {
1774       page_info->type = type;
1775
1776       /* Always set buttons state, a change in a future page
1777          might change current page buttons */
1778       if (priv->current_page)
1779         _set_assistant_buttons_state (assistant);
1780
1781       gtk_widget_child_notify (page, "page-type");
1782     }
1783 }
1784
1785 /**
1786  * gtk_assistant_get_page_type:
1787  * @assistant: a #GtkAssistant
1788  * @page: a page of @assistant
1789  *
1790  * Gets the page type of @page.
1791  *
1792  * Return value: the page type of @page.
1793  *
1794  * Since: 2.10
1795  **/
1796 GtkAssistantPageType
1797 gtk_assistant_get_page_type (GtkAssistant *assistant,
1798                              GtkWidget    *page)
1799 {
1800   GtkAssistantPrivate *priv;
1801   GtkAssistantPage *page_info;
1802   GList *child;
1803
1804   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), GTK_ASSISTANT_PAGE_CONTENT);
1805   g_return_val_if_fail (GTK_IS_WIDGET (page), GTK_ASSISTANT_PAGE_CONTENT);
1806
1807   priv = assistant->priv;
1808   child = find_page (assistant, page);
1809
1810   g_return_val_if_fail (child != NULL, GTK_ASSISTANT_PAGE_CONTENT);
1811
1812   page_info = (GtkAssistantPage*) child->data;
1813
1814   return page_info->type;
1815 }
1816
1817 /**
1818  * gtk_assistant_set_page_header_image:
1819  * @assistant: a #GtkAssistant
1820  * @page: a page of @assitant
1821  * @pixbuf: the new header image @page
1822  * 
1823  * Sets a header image for @page. This image is displayed in the header
1824  * area of the assistant when @page is the current page.
1825  *
1826  * Since: 2.10
1827  **/
1828 void
1829 gtk_assistant_set_page_header_image (GtkAssistant *assistant,
1830                                      GtkWidget    *page,
1831                                      GdkPixbuf    *pixbuf)
1832 {
1833   GtkAssistantPrivate *priv;
1834   GtkAssistantPage *page_info;
1835   GList *child;
1836
1837   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1838   g_return_if_fail (GTK_IS_WIDGET (page));
1839   g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
1840
1841   priv = assistant->priv;
1842   child = find_page (assistant, page);
1843
1844   g_return_if_fail (child != NULL);
1845
1846   page_info = (GtkAssistantPage*) child->data;
1847
1848   if (pixbuf != page_info->header_image)
1849     {
1850       if (page_info->header_image)
1851         {
1852           g_object_unref (page_info->header_image);
1853           page_info->header_image = NULL;
1854         }
1855
1856       if (pixbuf)
1857         page_info->header_image = g_object_ref (pixbuf);
1858
1859       if (page_info == priv->current_page)
1860         _set_assistant_header_image (assistant);
1861
1862       gtk_widget_child_notify (page, "header-image");
1863     }
1864 }
1865
1866 /**
1867  * gtk_assistant_get_page_header_image:
1868  * @assistant: a #GtkAssistant
1869  * @page: a page of @assistant
1870  * 
1871  * Gets the header image for @page. 
1872  * 
1873  * Return value: the header image for @page, or %NULL
1874  * if there's no header image for the page.
1875  *
1876  * Since: 2.10
1877  **/
1878 GdkPixbuf*
1879 gtk_assistant_get_page_header_image (GtkAssistant *assistant,
1880                                      GtkWidget    *page)
1881 {
1882   GtkAssistantPrivate *priv;
1883   GtkAssistantPage *page_info;
1884   GList *child;
1885
1886   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
1887   g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
1888
1889   priv = assistant->priv;
1890   child = find_page (assistant, page);
1891
1892   g_return_val_if_fail (child != NULL, NULL);
1893
1894   page_info = (GtkAssistantPage*) child->data;
1895
1896   return page_info->header_image;
1897 }
1898
1899 /**
1900  * gtk_assistant_set_page_side_image:
1901  * @assistant: a #GtkAssistant
1902  * @page: a page of @assitant
1903  * @pixbuf: the new header image @page
1904  * 
1905  * Sets a header image for @page. This image is displayed in the side
1906  * area of the assistant when @page is the current page.
1907  *
1908  * Since: 2.10
1909  **/
1910 void
1911 gtk_assistant_set_page_side_image (GtkAssistant *assistant,
1912                                    GtkWidget    *page,
1913                                    GdkPixbuf    *pixbuf)
1914 {
1915   GtkAssistantPrivate *priv;
1916   GtkAssistantPage *page_info;
1917   GList *child;
1918
1919   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1920   g_return_if_fail (GTK_IS_WIDGET (page));
1921   g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
1922
1923   priv = assistant->priv;
1924   child = find_page (assistant, page);
1925
1926   g_return_if_fail (child != NULL);
1927
1928   page_info = (GtkAssistantPage*) child->data;
1929
1930   if (pixbuf != page_info->sidebar_image)
1931     {
1932       if (page_info->sidebar_image)
1933         {
1934           g_object_unref (page_info->sidebar_image);
1935           page_info->sidebar_image = NULL;
1936         }
1937
1938       if (pixbuf)
1939         page_info->sidebar_image = g_object_ref (pixbuf);
1940
1941       if (page_info == priv->current_page)
1942         _set_assistant_sidebar_image (assistant);
1943
1944       gtk_widget_child_notify (page, "sidebar-image");
1945     }
1946 }
1947
1948 /**
1949  * gtk_assistant_get_page_side_image:
1950  * @assistant: a #GtkAssistant
1951  * @page: a page of @assistant
1952  * 
1953  * Gets the header image for @page. 
1954  * 
1955  * Return value: the side image for @page, or %NULL
1956  * if there's no side image for the page.
1957  *
1958  * Since: 2.10
1959  **/
1960 GdkPixbuf*
1961 gtk_assistant_get_page_side_image (GtkAssistant *assistant,
1962                                    GtkWidget    *page)
1963 {
1964   GtkAssistantPrivate *priv;
1965   GtkAssistantPage *page_info;
1966   GList *child;
1967
1968   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
1969   g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
1970
1971   priv = assistant->priv;
1972   child = find_page (assistant, page);
1973
1974   g_return_val_if_fail (child != NULL, NULL);
1975
1976   page_info = (GtkAssistantPage*) child->data;
1977
1978   return page_info->sidebar_image;
1979 }
1980
1981 /**
1982  * gtk_assistant_set_page_complete:
1983  * @assistant: a #GtkAssistant
1984  * @page: a page of @assitant
1985  * @pixbuf: the new header image @page
1986  * 
1987  * Sets whether @page contents are complete. This will make
1988  * @assistant update the buttons state to be able to continue the task.
1989  *
1990  * Since: 2.10
1991  **/
1992 void
1993 gtk_assistant_set_page_complete (GtkAssistant *assistant,
1994                                  GtkWidget    *page,
1995                                  gboolean      complete)
1996 {
1997   GtkAssistantPrivate *priv;
1998   GtkAssistantPage *page_info;
1999   GList *child;
2000
2001   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
2002   g_return_if_fail (GTK_IS_WIDGET (page));
2003
2004   priv = assistant->priv;
2005   child = find_page (assistant, page);
2006
2007   g_return_if_fail (child != NULL);
2008
2009   page_info = (GtkAssistantPage*) child->data;
2010
2011   if (complete != page_info->complete)
2012     {
2013       page_info->complete = complete;
2014
2015       /* Always set buttons state, a change in a future page
2016          might change current page buttons */
2017       if (priv->current_page)
2018         {
2019           /* Always set buttons state, a change in a future page
2020              might change current page buttons */
2021           _set_assistant_buttons_state (assistant);
2022         }
2023
2024       gtk_widget_child_notify (page, "complete");
2025     }
2026 }
2027
2028 /**
2029  * gtk_assistant_get_page_complete:
2030  * @assistant: a #GtkAssistant
2031  * @page: a page of @assistant
2032  * 
2033  * Gets whether @page is complete..
2034  * 
2035  * Return value: %TRUE if @page is complete.
2036  *
2037  * Since: 2.10
2038  **/
2039 gboolean
2040 gtk_assistant_get_page_complete (GtkAssistant *assistant,
2041                                  GtkWidget    *page)
2042 {
2043   GtkAssistantPrivate *priv;
2044   GtkAssistantPage *page_info;
2045   GList *child;
2046
2047   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), FALSE);
2048   g_return_val_if_fail (GTK_IS_WIDGET (page), FALSE);
2049
2050   priv = assistant->priv;
2051   child = find_page (assistant, page);
2052
2053   g_return_val_if_fail (child != NULL, FALSE);
2054
2055   page_info = (GtkAssistantPage*) child->data;
2056
2057   return page_info->complete;
2058 }
2059
2060
2061 #define __GTK_ASSISTANT_C__
2062 #include "gtkaliasdef.c"