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>
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.
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.
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.
28 #include "gtkassistant.h"
30 #include "gtkbutton.h"
35 #include "gtksizegroup.h"
39 #include "gtkprivate.h"
43 #define GTK_ASSISTANT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_ASSISTANT, GtkAssistantPrivate))
45 #define HEADER_SPACING 12
46 #define ACTION_AREA_SPACING 12
48 typedef struct _GtkAssistantPage GtkAssistantPage;
50 struct _GtkAssistantPage
53 GtkAssistantPageType type;
57 GdkPixbuf *header_image;
58 GdkPixbuf *sidebar_image;
61 struct _GtkAssistantPrivate
63 GtkWidget *header_image;
64 GtkWidget *sidebar_image;
66 GtkWidget *action_area;
70 GtkAssistantPage *current_page;
72 GSList *visited_pages;
74 GtkSizeGroup *size_group;
76 GtkAssistantPageFunc forward_function;
77 gpointer forward_function_data;
78 GDestroyNotify forward_data_destroy;
81 static void gtk_assistant_class_init (GtkAssistantClass *class);
82 static void gtk_assistant_init (GtkAssistant *assistant);
83 static void gtk_assistant_destroy (GtkObject *object);
84 static void gtk_assistant_style_set (GtkWidget *widget,
86 static void gtk_assistant_size_request (GtkWidget *widget,
87 GtkRequisition *requisition);
88 static void gtk_assistant_size_allocate (GtkWidget *widget,
89 GtkAllocation *allocation);
90 static void gtk_assistant_map (GtkWidget *widget);
91 static void gtk_assistant_unmap (GtkWidget *widget);
92 static gboolean gtk_assistant_delete_event (GtkWidget *widget,
94 static gboolean gtk_assistant_expose (GtkWidget *widget,
95 GdkEventExpose *event);
96 static gboolean gtk_assistant_focus (GtkWidget *widget,
97 GtkDirectionType direction);
98 static void gtk_assistant_add (GtkContainer *container,
100 static void gtk_assistant_remove (GtkContainer *container,
102 static void gtk_assistant_forall (GtkContainer *container,
103 gboolean include_internals,
104 GtkCallback callback,
105 gpointer callback_data);
106 static void gtk_assistant_set_child_property (GtkContainer *container,
111 static void gtk_assistant_get_child_property (GtkContainer *container,
120 CHILD_PROP_PAGE_TYPE,
121 CHILD_PROP_PAGE_TITLE,
122 CHILD_PROP_PAGE_HEADER_IMAGE,
123 CHILD_PROP_PAGE_SIDEBAR_IMAGE,
124 CHILD_PROP_PAGE_COMPLETE
136 static guint signals [LAST_SIGNAL] = { 0 };
139 G_DEFINE_TYPE (GtkAssistant, gtk_assistant, GTK_TYPE_WINDOW)
143 gtk_assistant_class_init (GtkAssistantClass *class)
145 GObjectClass *gobject_class;
146 GtkObjectClass *object_class;
147 GtkWidgetClass *widget_class;
148 GtkContainerClass *container_class;
150 gobject_class = (GObjectClass *) class;
151 object_class = (GtkObjectClass *) class;
152 widget_class = (GtkWidgetClass *) class;
153 container_class = (GtkContainerClass *) class;
155 object_class->destroy = gtk_assistant_destroy;
157 widget_class->style_set = gtk_assistant_style_set;
158 widget_class->size_request = gtk_assistant_size_request;
159 widget_class->size_allocate = gtk_assistant_size_allocate;
160 widget_class->map = gtk_assistant_map;
161 widget_class->unmap = gtk_assistant_unmap;
162 widget_class->delete_event = gtk_assistant_delete_event;
163 widget_class->expose_event = gtk_assistant_expose;
164 widget_class->focus = gtk_assistant_focus;
166 container_class->add = gtk_assistant_add;
167 container_class->remove = gtk_assistant_remove;
168 container_class->forall = gtk_assistant_forall;
169 container_class->set_child_property = gtk_assistant_set_child_property;
170 container_class->get_child_property = gtk_assistant_get_child_property;
173 * GtkAssistant::cancel:
174 * @assistant: the #GtkAssistant
176 * The ::cancel signal is emitted when then the cancel button is clicked.
181 g_signal_new (I_("cancel"),
182 G_TYPE_FROM_CLASS (gobject_class),
184 G_STRUCT_OFFSET (GtkAssistantClass, cancel),
186 g_cclosure_marshal_VOID__VOID,
190 * GtkAssistant::prepare:
191 * @assistant: the #GtkAssistant
192 * @page: the current page
194 * The ::prepared signal is emitted when a new page is set as the assistant's
195 * current page, before making the new page visible. A handler for this signal
196 * can do any preparation which are necessary before showing @page.
201 g_signal_new (I_("prepare"),
202 G_TYPE_FROM_CLASS (gobject_class),
204 G_STRUCT_OFFSET (GtkAssistantClass, prepare),
206 g_cclosure_marshal_VOID__OBJECT,
207 G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
210 * GtkAssistant::apply:
211 * @assistant: the @GtkAssistant
213 * The ::apply signal is emitted when the apply button is clicked. The default
214 * behavior of the #GtkAssistant is to switch to the page after the current page,
215 * unless the current page is the last one.
217 * A handler for the ::apply signal should carry out the actions for which the
218 * wizard has collected data. If the action takes a long time to complete, you
219 * might consider to put a page of type GTK_ASSISTANT_PAGE_PROGRESS after the
220 * confirmation page and handle this operation within the "prepare" signal of
226 g_signal_new (I_("apply"),
227 G_TYPE_FROM_CLASS (gobject_class),
229 G_STRUCT_OFFSET (GtkAssistantClass, apply),
231 g_cclosure_marshal_VOID__VOID,
235 * GtkAssistant::close:
236 * @assistant: the #GtkAssistant
238 * The ::close signal is emitted either when the close button of
239 * a summary page is clicked, or when the apply button in the last
240 * page in the flow (of type GTK_ASSISTANT_PAGE_CONFIRM) is clicked.
245 g_signal_new (I_("close"),
246 G_TYPE_FROM_CLASS (gobject_class),
248 G_STRUCT_OFFSET (GtkAssistantClass, close),
250 g_cclosure_marshal_VOID__VOID,
253 gtk_widget_class_install_style_property (widget_class,
254 g_param_spec_int ("header-padding",
255 P_("Header Padding"),
256 P_("Number of pixels around the header."),
260 GTK_PARAM_READABLE));
261 gtk_widget_class_install_style_property (widget_class,
262 g_param_spec_int ("content-padding",
263 P_("Content Padding"),
264 P_("Number of pixels around the content pages."),
268 GTK_PARAM_READABLE));
271 * GtkAssistant:page-type:
273 * The type of the assistant page.
277 gtk_container_class_install_child_property (container_class,
278 CHILD_PROP_PAGE_TYPE,
279 g_param_spec_enum ("page-type",
281 P_("The type of the assistant page"),
282 GTK_TYPE_ASSISTANT_PAGE_TYPE,
283 GTK_ASSISTANT_PAGE_CONTENT,
284 GTK_PARAM_READWRITE));
287 * GtkAssistant:title:
289 * The title that is displayed in the page header.
291 * If title and header-image are both %NULL, no header is displayed.
295 gtk_container_class_install_child_property (container_class,
296 CHILD_PROP_PAGE_TITLE,
297 g_param_spec_string ("title",
299 P_("The title of the assistant page"),
301 GTK_PARAM_READWRITE));
304 * GtkAssistant:header-image:
306 * The image that is displayed next to the title in the page header.
308 * If title and header-image are both %NULL, no header is displayed.
312 gtk_container_class_install_child_property (container_class,
313 CHILD_PROP_PAGE_HEADER_IMAGE,
314 g_param_spec_object ("header-image",
316 P_("Header image for the assistant page"),
318 GTK_PARAM_READWRITE));
321 * GtkAssistant:header-image:
323 * The image that is displayed next to the page.
325 * Set this to %NULL to make the sidebar disappear.
329 gtk_container_class_install_child_property (container_class,
330 CHILD_PROP_PAGE_SIDEBAR_IMAGE,
331 g_param_spec_object ("sidebar-image",
333 P_("Sidebar image for the assistant page"),
335 GTK_PARAM_READWRITE));
337 * GtkAssistant:complete:
339 * Setting the "complete" child property to %TRUE marks a page as complete
340 * (i.e.: all the required fields are filled out). GTK+ uses this information
341 * to control the sensitivity of the navigation buttons.
345 gtk_container_class_install_child_property (container_class,
346 CHILD_PROP_PAGE_COMPLETE,
347 g_param_spec_boolean ("complete",
349 P_("Whether all required fields on the page have been filled out"),
353 g_type_class_add_private (gobject_class, sizeof (GtkAssistantPrivate));
357 default_forward_function (gint current_page, gpointer data)
359 GtkAssistant *assistant;
360 GtkAssistantPrivate *priv;
361 GtkAssistantPage *page_info;
364 assistant = GTK_ASSISTANT (data);
365 priv = assistant->priv;
367 page_node = g_list_nth (priv->pages, ++current_page);
372 page_info = (GtkAssistantPage *) page_node->data;
374 while (page_node && !GTK_WIDGET_VISIBLE (page_info->page))
376 page_node = page_node->next;
380 page_info = (GtkAssistantPage *) page_node->data;
387 compute_last_button_state (GtkAssistant *assistant)
389 GtkAssistantPrivate *priv = assistant->priv;
390 GtkAssistantPage *page_info, *current_page_info;
391 gint count, page_num, n_pages;
394 page_num = gtk_assistant_get_current_page (assistant);
395 n_pages = gtk_assistant_get_n_pages (assistant);
396 current_page_info = page_info = g_list_nth_data (priv->pages, page_num);
398 while (page_num >= 0 && page_num < n_pages &&
399 page_info->type == GTK_ASSISTANT_PAGE_CONTENT &&
400 (count == 0 || page_info->complete) &&
403 page_num = (priv->forward_function) (page_num, priv->forward_function_data);
404 page_info = g_list_nth_data (priv->pages, page_num);
408 g_assert (page_info);
411 /* make the last button visible if we can skip multiple
412 * pages and end on a confirmation or summary page
415 (page_info->type == GTK_ASSISTANT_PAGE_CONFIRM ||
416 page_info->type == GTK_ASSISTANT_PAGE_SUMMARY))
418 gtk_widget_show (assistant->last);
419 gtk_widget_set_sensitive (assistant->last,
420 current_page_info->complete);
423 gtk_widget_hide (assistant->last);
427 set_assistant_header_image (GtkAssistant *assistant)
429 GtkAssistantPrivate *priv = assistant->priv;
431 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->header_image),
432 priv->current_page->header_image);
436 set_assistant_sidebar_image (GtkAssistant *assistant)
438 GtkAssistantPrivate *priv = assistant->priv;
440 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->sidebar_image),
441 priv->current_page->sidebar_image);
443 if (priv->current_page->sidebar_image)
444 gtk_widget_show (priv->sidebar_image);
446 gtk_widget_hide (priv->sidebar_image);
450 set_assistant_buttons_state (GtkAssistant *assistant)
452 GtkAssistantPrivate *priv = assistant->priv;
454 switch (priv->current_page->type)
456 case GTK_ASSISTANT_PAGE_INTRO:
457 gtk_widget_set_sensitive (assistant->cancel, TRUE);
458 gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
459 gtk_widget_show (assistant->cancel);
460 gtk_widget_show (assistant->forward);
461 gtk_widget_hide (assistant->back);
462 gtk_widget_hide (assistant->apply);
463 gtk_widget_hide (assistant->close);
464 compute_last_button_state (assistant);
466 case GTK_ASSISTANT_PAGE_CONFIRM:
467 gtk_widget_set_sensitive (assistant->cancel, TRUE);
468 gtk_widget_set_sensitive (assistant->back, TRUE);
469 gtk_widget_set_sensitive (assistant->apply, priv->current_page->complete);
470 gtk_widget_show (assistant->cancel);
471 gtk_widget_show (assistant->back);
472 gtk_widget_show (assistant->apply);
473 gtk_widget_hide (assistant->forward);
474 gtk_widget_hide (assistant->close);
475 gtk_widget_hide (assistant->last);
477 case GTK_ASSISTANT_PAGE_CONTENT:
478 gtk_widget_set_sensitive (assistant->cancel, TRUE);
479 gtk_widget_set_sensitive (assistant->back, TRUE);
480 gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
481 gtk_widget_show (assistant->cancel);
482 gtk_widget_show (assistant->back);
483 gtk_widget_show (assistant->forward);
484 gtk_widget_hide (assistant->apply);
485 gtk_widget_hide (assistant->close);
486 compute_last_button_state (assistant);
488 case GTK_ASSISTANT_PAGE_SUMMARY:
489 gtk_widget_set_sensitive (assistant->close, TRUE);
490 gtk_widget_show (assistant->close);
491 gtk_widget_hide (assistant->cancel);
492 gtk_widget_hide (assistant->back);
493 gtk_widget_hide (assistant->forward);
494 gtk_widget_hide (assistant->apply);
495 gtk_widget_hide (assistant->last);
497 case GTK_ASSISTANT_PAGE_PROGRESS:
498 gtk_widget_set_sensitive (assistant->cancel, priv->current_page->complete);
499 gtk_widget_set_sensitive (assistant->back, priv->current_page->complete);
500 gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
501 gtk_widget_show (assistant->cancel);
502 gtk_widget_show (assistant->back);
503 gtk_widget_show (assistant->forward);
504 gtk_widget_hide (assistant->apply);
505 gtk_widget_hide (assistant->close);
506 gtk_widget_hide (assistant->last);
509 g_assert_not_reached ();
512 /* this is quite general, we don't want to
513 * go back if it's the first page */
514 if (!priv->visited_pages)
515 gtk_widget_hide (assistant->back);
519 set_current_page (GtkAssistant *assistant,
520 GtkAssistantPage *page)
522 GtkAssistantPrivate *priv = assistant->priv;
523 GtkAssistantPage *old_page;
525 if (priv->current_page &&
526 GTK_WIDGET_DRAWABLE (priv->current_page->page))
527 old_page = priv->current_page;
531 priv->current_page = page;
533 set_assistant_buttons_state (assistant);
534 set_assistant_header_image (assistant);
535 set_assistant_sidebar_image (assistant);
537 g_signal_emit (assistant, signals [PREPARE], 0, priv->current_page->page);
539 if (GTK_WIDGET_VISIBLE (priv->current_page->page) && GTK_WIDGET_MAPPED (assistant))
541 gtk_widget_set_child_visible (priv->current_page->page, TRUE);
542 gtk_widget_map (priv->current_page->page);
543 gtk_widget_map (priv->current_page->title);
546 if (old_page && GTK_WIDGET_MAPPED (old_page->page))
548 gtk_widget_set_child_visible (old_page->page, FALSE);
549 gtk_widget_unmap (old_page->page);
550 gtk_widget_unmap (old_page->title);
553 gtk_widget_queue_resize (GTK_WIDGET (assistant));
557 compute_next_step (GtkAssistant *assistant)
559 GtkAssistantPrivate *priv = assistant->priv;
560 GtkAssistantPage *page_info;
561 gint current_page, n_pages, next_page;
563 current_page = gtk_assistant_get_current_page (assistant);
564 page_info = priv->current_page;
565 n_pages = gtk_assistant_get_n_pages (assistant);
567 next_page = (priv->forward_function) (current_page,
568 priv->forward_function_data);
570 if (next_page >= 0 && next_page < n_pages)
572 priv->visited_pages = g_slist_prepend (priv->visited_pages, page_info);
573 set_current_page (assistant, g_list_nth_data (priv->pages, next_page));
582 on_assistant_close (GtkWidget *widget, GtkAssistant *assistant)
584 g_signal_emit (assistant, signals [CLOSE], 0, NULL);
588 on_assistant_apply (GtkWidget *widget, GtkAssistant *assistant)
590 GtkAssistantPrivate *priv = assistant->priv;
593 success = compute_next_step (assistant);
595 g_signal_emit (assistant, signals [APPLY], 0, priv->current_page->page);
597 /* if the assistant hasn't switched to another page, just emit
598 * the CLOSE signal, it't the last page in the assistant flow
601 g_signal_emit (assistant, signals [CLOSE], 0, priv->current_page->page);
605 on_assistant_forward (GtkWidget *widget, GtkAssistant *assistant)
607 if (!compute_next_step (assistant))
608 g_critical ("Page flow is broken, you may want to end it with a page of "
609 "type GTK_ASSISTANT_PAGE_CONFIRM or GTK_ASSISTANT_PAGE_SUMMARY");
613 on_assistant_back (GtkWidget *widget, GtkAssistant *assistant)
615 GtkAssistantPrivate *priv = assistant->priv;
616 GtkAssistantPage *page_info;
619 /* skip the progress pages when going back */
622 page_node = priv->visited_pages;
624 g_return_if_fail (page_node != NULL);
626 priv->visited_pages = priv->visited_pages->next;
627 page_info = (GtkAssistantPage *) page_node->data;
628 g_slist_free_1 (page_node);
630 while (page_info->type == GTK_ASSISTANT_PAGE_PROGRESS ||
631 !GTK_WIDGET_VISIBLE (page_info->page));
633 set_current_page (assistant, page_info);
637 on_assistant_cancel (GtkWidget *widget, GtkAssistant *assistant)
639 g_signal_emit (assistant, signals [CANCEL], 0, NULL);
643 on_assistant_last (GtkWidget *widget, GtkAssistant *assistant)
645 GtkAssistantPrivate *priv = assistant->priv;
647 while (priv->current_page->type == GTK_ASSISTANT_PAGE_CONTENT &&
648 priv->current_page->complete)
649 compute_next_step (assistant);
653 alternative_button_order (GtkAssistant *assistant)
655 GtkSettings *settings;
659 screen = gtk_widget_get_screen (GTK_WIDGET (assistant));
660 settings = gtk_settings_get_for_screen (screen);
662 g_object_get (settings,
663 "gtk-alternative-button-order", &result,
669 gtk_assistant_init (GtkAssistant *assistant)
671 GtkAssistantPrivate *priv;
673 priv = assistant->priv = GTK_ASSISTANT_GET_PRIVATE (assistant);
675 gtk_widget_push_composite_child ();
678 priv->header_image = gtk_image_new ();
679 gtk_misc_set_alignment (GTK_MISC (priv->header_image), 1., 0.5);
680 gtk_widget_set_parent (priv->header_image, GTK_WIDGET (assistant));
681 gtk_widget_show (priv->header_image);
684 priv->sidebar_image = gtk_image_new ();
685 gtk_misc_set_alignment (GTK_MISC (priv->sidebar_image), 0., 0.);
686 gtk_widget_set_parent (priv->sidebar_image, GTK_WIDGET (assistant));
687 gtk_widget_show (priv->sidebar_image);
690 priv->action_area = gtk_hbox_new (FALSE, 6);
692 assistant->close = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
693 assistant->apply = gtk_button_new_from_stock (GTK_STOCK_APPLY);
694 assistant->forward = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
695 assistant->back = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
696 assistant->cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
697 assistant->last = gtk_button_new_from_stock (GTK_STOCK_GOTO_LAST);
699 priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
700 gtk_size_group_add_widget (priv->size_group, assistant->close);
701 gtk_size_group_add_widget (priv->size_group, assistant->apply);
702 gtk_size_group_add_widget (priv->size_group, assistant->forward);
703 gtk_size_group_add_widget (priv->size_group, assistant->back);
704 gtk_size_group_add_widget (priv->size_group, assistant->cancel);
705 gtk_size_group_add_widget (priv->size_group, assistant->last);
707 if (!alternative_button_order (assistant))
709 gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->apply, FALSE, FALSE, 0);
710 gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->forward, FALSE, FALSE, 0);
711 gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->back, FALSE, FALSE, 0);
712 gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->last, FALSE, FALSE, 0);
713 gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->cancel, FALSE, FALSE, 0);
714 gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->close, FALSE, FALSE, 0);
718 gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->close, FALSE, FALSE, 0);
719 gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->cancel, FALSE, FALSE, 0);
720 gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->last, FALSE, FALSE, 0);
721 gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->back, FALSE, FALSE, 0);
722 gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->forward, FALSE, FALSE, 0);
723 gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->apply, FALSE, FALSE, 0);
726 gtk_widget_set_parent (priv->action_area, GTK_WIDGET (assistant));
727 gtk_widget_show (assistant->forward);
728 gtk_widget_show (assistant->back);
729 gtk_widget_show (assistant->cancel);
730 gtk_widget_show (priv->action_area);
732 gtk_widget_pop_composite_child ();
735 priv->current_page = NULL;
736 priv->visited_pages = NULL;
738 priv->forward_function = default_forward_function;
739 priv->forward_function_data = assistant;
740 priv->forward_data_destroy = NULL;
742 g_signal_connect (G_OBJECT (assistant->close), "clicked",
743 G_CALLBACK (on_assistant_close), assistant);
744 g_signal_connect (G_OBJECT (assistant->apply), "clicked",
745 G_CALLBACK (on_assistant_apply), assistant);
746 g_signal_connect (G_OBJECT (assistant->forward), "clicked",
747 G_CALLBACK (on_assistant_forward), assistant);
748 g_signal_connect (G_OBJECT (assistant->back), "clicked",
749 G_CALLBACK (on_assistant_back), assistant);
750 g_signal_connect (G_OBJECT (assistant->cancel), "clicked",
751 G_CALLBACK (on_assistant_cancel), assistant);
752 g_signal_connect (G_OBJECT (assistant->last), "clicked",
753 G_CALLBACK (on_assistant_last), assistant);
757 gtk_assistant_set_child_property (GtkContainer *container,
765 case CHILD_PROP_PAGE_TYPE:
766 gtk_assistant_set_page_type (GTK_ASSISTANT (container), child,
767 g_value_get_enum (value));
769 case CHILD_PROP_PAGE_TITLE:
770 gtk_assistant_set_page_title (GTK_ASSISTANT (container), child,
771 g_value_get_string (value));
773 case CHILD_PROP_PAGE_HEADER_IMAGE:
774 gtk_assistant_set_page_header_image (GTK_ASSISTANT (container), child,
775 g_value_get_object (value));
777 case CHILD_PROP_PAGE_SIDEBAR_IMAGE:
778 gtk_assistant_set_page_side_image (GTK_ASSISTANT (container), child,
779 g_value_get_object (value));
781 case CHILD_PROP_PAGE_COMPLETE:
782 gtk_assistant_set_page_complete (GTK_ASSISTANT (container), child,
783 g_value_get_boolean (value));
786 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
792 gtk_assistant_get_child_property (GtkContainer *container,
800 case CHILD_PROP_PAGE_TYPE:
801 g_value_set_enum (value,
802 gtk_assistant_get_page_type (GTK_ASSISTANT (container), child));
804 case CHILD_PROP_PAGE_TITLE:
805 g_value_set_string (value,
806 gtk_assistant_get_page_title (GTK_ASSISTANT (container), child));
808 case CHILD_PROP_PAGE_HEADER_IMAGE:
809 g_value_set_object (value,
810 gtk_assistant_get_page_header_image (GTK_ASSISTANT (container), child));
812 case CHILD_PROP_PAGE_SIDEBAR_IMAGE:
813 g_value_set_object (value,
814 gtk_assistant_get_page_side_image (GTK_ASSISTANT (container), child));
816 case CHILD_PROP_PAGE_COMPLETE:
817 g_value_set_boolean (value,
818 gtk_assistant_get_page_complete (GTK_ASSISTANT (container), child));
821 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
827 on_page_notify_visibility (GtkWidget *widget,
831 GtkAssistant *assistant = GTK_ASSISTANT (data);
833 /* update buttons state, flow may have changed */
834 if (GTK_WIDGET_MAPPED (assistant))
835 set_assistant_buttons_state (assistant);
839 remove_page (GtkAssistant *assistant,
842 GtkAssistantPrivate *priv = assistant->priv;
843 GtkAssistantPage *page_info;
845 page_info = element->data;
847 /* If we are mapped and visible, we want to deal with changing the page. */
848 if ((GTK_WIDGET_MAPPED (page_info->page)) && (page_info == priv->current_page))
849 compute_next_step (assistant);
851 priv->pages = g_list_remove_link (priv->pages, element);
852 priv->visited_pages = g_slist_remove_all (priv->visited_pages, page_info);
854 g_signal_handlers_disconnect_by_func (page_info->page, on_page_notify_visibility, assistant);
855 gtk_widget_unparent (page_info->page);
857 if (page_info->header_image)
858 g_object_unref (page_info->header_image);
860 if (page_info->sidebar_image)
861 g_object_unref (page_info->sidebar_image);
863 gtk_widget_destroy (page_info->title);
865 g_list_free_1 (element);
869 gtk_assistant_destroy (GtkObject *object)
871 GtkAssistant *assistant = GTK_ASSISTANT (object);
872 GtkAssistantPrivate *priv = assistant->priv;
874 if (priv->header_image)
876 gtk_widget_destroy (priv->header_image);
877 priv->header_image = NULL;
880 if (priv->sidebar_image)
882 gtk_widget_destroy (priv->sidebar_image);
883 priv->sidebar_image = NULL;
886 if (priv->action_area)
888 gtk_widget_destroy (priv->action_area);
889 priv->action_area = NULL;
892 if (priv->size_group)
894 g_object_unref (priv->size_group);
895 priv->size_group = NULL;
898 if (priv->forward_function)
900 if (priv->forward_function_data &&
901 priv->forward_data_destroy)
902 priv->forward_data_destroy (priv->forward_function_data);
904 priv->forward_function = NULL;
905 priv->forward_function_data = NULL;
906 priv->forward_data_destroy = NULL;
909 if (priv->visited_pages)
911 g_slist_free (priv->visited_pages);
912 priv->visited_pages = NULL;
915 /* We set current to NULL so that the remove code doesn't try
916 * to do anything funny */
917 priv->current_page = NULL;
920 remove_page (GTK_ASSISTANT (object), priv->pages);
922 GTK_OBJECT_CLASS (gtk_assistant_parent_class)->destroy (object);
926 find_page (GtkAssistant *assistant,
929 GtkAssistantPrivate *priv = assistant->priv;
930 GList *child = priv->pages;
934 GtkAssistantPage *page_info = child->data;
935 if (page_info->page == page)
945 set_title_colors (GtkWidget *assistant,
946 GtkWidget *title_label)
950 gtk_widget_ensure_style (assistant);
951 style = gtk_widget_get_style (assistant);
953 /* change colors schema, for making the header text visible */
954 gtk_widget_modify_bg (title_label, GTK_STATE_NORMAL, &style->bg[GTK_STATE_SELECTED]);
955 gtk_widget_modify_fg (title_label, GTK_STATE_NORMAL, &style->fg[GTK_STATE_SELECTED]);
959 set_title_font (GtkWidget *assistant,
960 GtkWidget *title_label)
962 PangoFontDescription *desc;
965 desc = pango_font_description_new ();
966 size = pango_font_description_get_size (assistant->style->font_desc);
968 pango_font_description_set_weight (desc, PANGO_WEIGHT_ULTRABOLD);
969 pango_font_description_set_size (desc, size * PANGO_SCALE_XX_LARGE);
971 gtk_widget_modify_font (title_label, desc);
972 pango_font_description_free (desc);
976 gtk_assistant_style_set (GtkWidget *widget,
979 GtkAssistant *assistant = GTK_ASSISTANT (widget);
980 GtkAssistantPrivate *priv = assistant->priv;
987 GtkAssistantPage *page = list->data;
989 set_title_colors (widget, page->title);
990 set_title_font (widget, page->title);
997 gtk_assistant_size_request (GtkWidget *widget,
998 GtkRequisition *requisition)
1000 GtkAssistant *assistant = GTK_ASSISTANT (widget);
1001 GtkAssistantPrivate *priv = assistant->priv;
1002 GtkRequisition child_requisition;
1003 gint header_padding, content_padding;
1004 gint width, height, header_width, header_height;
1007 gtk_widget_style_get (widget,
1008 "header-padding", &header_padding,
1009 "content-padding", &content_padding,
1012 header_width = header_height = 0;
1017 GtkAssistantPage *page = list->data;
1020 gtk_widget_size_request (page->page, &child_requisition);
1021 width = MAX (width, child_requisition.width);
1022 height = MAX (height, child_requisition.height);
1024 gtk_widget_size_request (page->title, &child_requisition);
1025 w = child_requisition.width;
1026 h = child_requisition.height;
1028 if (page->header_image)
1030 w += gdk_pixbuf_get_width (page->header_image) + HEADER_SPACING;
1031 h = MAX (h, gdk_pixbuf_get_height (page->header_image));
1034 header_width = MAX (header_width, w);
1035 header_height = MAX (header_height, h);
1040 gtk_widget_size_request (priv->sidebar_image, &child_requisition);
1041 width += child_requisition.width;
1042 height = MAX (height, child_requisition.height);
1044 gtk_widget_set_size_request (priv->header_image, header_width, header_height);
1045 gtk_widget_size_request (priv->header_image, &child_requisition);
1046 width = MAX (width, header_width) + 2 * header_padding;
1047 height += header_height + 2 * header_padding;
1049 gtk_widget_size_request (priv->action_area, &child_requisition);
1050 width = MAX (width, child_requisition.width);
1051 height += child_requisition.height + ACTION_AREA_SPACING;
1053 width += GTK_CONTAINER (widget)->border_width * 2 + content_padding * 2;
1054 height += GTK_CONTAINER (widget)->border_width * 2 + content_padding * 2;
1056 requisition->width = width;
1057 requisition->height = height;
1061 gtk_assistant_size_allocate (GtkWidget *widget,
1062 GtkAllocation *allocation)
1064 GtkAssistant *assistant = GTK_ASSISTANT (widget);
1065 GtkAssistantPrivate *priv = assistant->priv;
1066 GtkRequisition header_requisition;
1067 GtkAllocation child_allocation, header_allocation;
1068 gint header_padding, content_padding;
1072 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1073 pages = priv->pages;
1075 gtk_widget_style_get (widget,
1076 "header-padding", &header_padding,
1077 "content-padding", &content_padding,
1080 widget->allocation = *allocation;
1083 gtk_widget_get_child_requisition (priv->header_image, &header_requisition);
1085 header_allocation.x = allocation->x + GTK_CONTAINER (widget)->border_width + header_padding;
1086 header_allocation.y = allocation->y + GTK_CONTAINER (widget)->border_width + header_padding;
1087 header_allocation.width = allocation->width - 2 * GTK_CONTAINER (widget)->border_width - 2 * header_padding;
1088 header_allocation.height = header_requisition.height;
1090 gtk_widget_size_allocate (priv->header_image, &header_allocation);
1093 child_allocation.x = allocation->x + GTK_CONTAINER (widget)->border_width;
1094 child_allocation.y = allocation->y + allocation->height -
1095 GTK_CONTAINER (widget)->border_width - priv->action_area->requisition.height;
1096 child_allocation.width = allocation->width - 2 * GTK_CONTAINER (widget)->border_width;
1097 child_allocation.height = priv->action_area->requisition.height;
1099 gtk_widget_size_allocate (priv->action_area, &child_allocation);
1103 child_allocation.x = allocation->x + allocation->width -
1104 GTK_CONTAINER (widget)->border_width - priv->sidebar_image->requisition.width;
1106 child_allocation.x = allocation->x + GTK_CONTAINER (widget)->border_width;
1108 child_allocation.y = allocation->y + GTK_CONTAINER (widget)->border_width +
1109 priv->header_image->allocation.height + 2 * header_padding;
1110 child_allocation.width = priv->sidebar_image->requisition.width;
1111 child_allocation.height = allocation->height - 2 * GTK_CONTAINER (widget)->border_width -
1112 priv->header_image->allocation.height - 2 * header_padding - priv->action_area->allocation.height;
1114 gtk_widget_size_allocate (priv->sidebar_image, &child_allocation);
1117 child_allocation.x = allocation->x + GTK_CONTAINER (widget)->border_width + content_padding;
1118 child_allocation.y = allocation->y + GTK_CONTAINER (widget)->border_width +
1119 priv->header_image->allocation.height + 2 * header_padding + content_padding;
1120 child_allocation.width = allocation->width - 2 * GTK_CONTAINER (widget)->border_width - 2 * content_padding;
1121 child_allocation.height = allocation->height - 2 * GTK_CONTAINER (widget)->border_width -
1122 priv->header_image->allocation.height - 2 * header_padding - ACTION_AREA_SPACING - priv->action_area->allocation.height - 2 * content_padding;
1124 if (GTK_WIDGET_VISIBLE (priv->sidebar_image))
1127 child_allocation.x += priv->sidebar_image->allocation.width;
1129 child_allocation.width -= priv->sidebar_image->allocation.width;
1134 GtkAssistantPage *page = pages->data;
1136 gtk_widget_size_allocate (page->page, &child_allocation);
1137 gtk_widget_size_allocate (page->title, &header_allocation);
1138 pages = pages->next;
1143 gtk_assistant_map (GtkWidget *widget)
1145 GtkAssistant *assistant = GTK_ASSISTANT (widget);
1146 GtkAssistantPrivate *priv = assistant->priv;
1149 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1151 gtk_widget_map (priv->header_image);
1152 gtk_widget_map (priv->action_area);
1154 if (GTK_WIDGET_VISIBLE (priv->sidebar_image) &&
1155 !GTK_WIDGET_MAPPED (priv->sidebar_image))
1156 gtk_widget_map (priv->sidebar_image);
1158 /* if there's no default page, pick the first one */
1159 if (!priv->current_page && priv->pages)
1161 page_node = priv->pages;
1163 while (page_node && !GTK_WIDGET_VISIBLE (((GtkAssistantPage *) page_node->data)->page))
1164 page_node = page_node->next;
1167 priv->current_page = page_node->data;
1170 if (priv->current_page &&
1171 GTK_WIDGET_VISIBLE (priv->current_page->page) &&
1172 !GTK_WIDGET_MAPPED (priv->current_page->page))
1174 set_assistant_buttons_state ((GtkAssistant *) widget);
1175 set_assistant_header_image ((GtkAssistant*) widget);
1176 set_assistant_sidebar_image ((GtkAssistant*) widget);
1178 g_signal_emit (widget, signals [PREPARE], 0, priv->current_page->page);
1179 gtk_widget_set_child_visible (priv->current_page->page, TRUE);
1180 gtk_widget_map (priv->current_page->page);
1181 gtk_widget_map (priv->current_page->title);
1184 GTK_WIDGET_CLASS (gtk_assistant_parent_class)->map (widget);
1188 gtk_assistant_unmap (GtkWidget *widget)
1190 GtkAssistant *assistant = GTK_ASSISTANT (widget);
1191 GtkAssistantPrivate *priv = assistant->priv;
1193 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1195 gtk_widget_unmap (priv->header_image);
1196 gtk_widget_unmap (priv->action_area);
1198 if (GTK_WIDGET_DRAWABLE (priv->sidebar_image))
1199 gtk_widget_unmap (priv->sidebar_image);
1201 if (priv->current_page &&
1202 GTK_WIDGET_DRAWABLE (priv->current_page->page))
1203 gtk_widget_unmap (priv->current_page->page);
1205 g_slist_free (priv->visited_pages);
1206 priv->visited_pages = NULL;
1207 priv->current_page = NULL;
1209 GTK_WIDGET_CLASS (gtk_assistant_parent_class)->unmap (widget);
1213 gtk_assistant_delete_event (GtkWidget *widget,
1216 GtkAssistant *assistant = GTK_ASSISTANT (widget);
1217 GtkAssistantPrivate *priv = assistant->priv;
1219 /* Do not allow cancelling in the middle of a progress page */
1220 if (priv->current_page &&
1221 (priv->current_page->type != GTK_ASSISTANT_PAGE_PROGRESS ||
1222 priv->current_page->complete))
1223 g_signal_emit (widget, signals [CANCEL], 0, NULL);
1229 assistant_paint_colored_box (GtkWidget *widget)
1231 GtkAssistant *assistant = GTK_ASSISTANT (widget);
1232 GtkAssistantPrivate *priv = assistant->priv;
1233 gint border_width, header_padding, content_padding;
1235 gint content_x, content_width;
1238 cr = gdk_cairo_create (widget->window);
1239 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1240 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1242 gtk_widget_style_get (widget,
1243 "header-padding", &header_padding,
1244 "content-padding", &content_padding,
1248 gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_SELECTED]);
1249 cairo_rectangle (cr,
1252 widget->allocation.width - 2 * border_width,
1253 widget->allocation.height - priv->action_area->allocation.height - 2 * border_width - ACTION_AREA_SPACING);
1257 content_x = content_padding + border_width;
1258 content_width = widget->allocation.width - 2 * content_padding - 2 * border_width;
1260 if (GTK_WIDGET_VISIBLE (priv->sidebar_image))
1263 content_x += priv->sidebar_image->allocation.width;
1264 content_width -= priv->sidebar_image->allocation.width;
1267 gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_NORMAL]);
1269 cairo_rectangle (cr,
1271 priv->header_image->allocation.height + content_padding + 2 * header_padding + border_width,
1273 widget->allocation.height - 2 * border_width - priv->action_area->allocation.height -
1274 priv->header_image->allocation.height - 2 * content_padding - 2 * header_padding - ACTION_AREA_SPACING);
1281 gtk_assistant_expose (GtkWidget *widget,
1282 GdkEventExpose *event)
1284 GtkAssistant *assistant = GTK_ASSISTANT (widget);
1285 GtkAssistantPrivate *priv = assistant->priv;
1286 GtkContainer *container;
1288 if (GTK_WIDGET_DRAWABLE (widget))
1290 container = GTK_CONTAINER (widget);
1292 assistant_paint_colored_box (widget);
1294 gtk_container_propagate_expose (container, priv->header_image, event);
1295 gtk_container_propagate_expose (container, priv->sidebar_image, event);
1296 gtk_container_propagate_expose (container, priv->action_area, event);
1298 if (priv->current_page)
1300 gtk_container_propagate_expose (container, priv->current_page->page, event);
1301 gtk_container_propagate_expose (container, priv->current_page->title, event);
1309 gtk_assistant_focus (GtkWidget *widget,
1310 GtkDirectionType direction)
1312 GtkAssistantPrivate *priv;
1313 GtkContainer *container;
1315 container = GTK_CONTAINER (widget);
1316 priv = GTK_ASSISTANT (widget)->priv;
1318 /* we only have to care about 2 widgets, action area and the current page */
1319 if (container->focus_child == priv->action_area)
1321 if (!gtk_widget_child_focus (priv->action_area, direction) &&
1322 !gtk_widget_child_focus (priv->current_page->page, direction))
1324 /* if we're leaving the action area and the current page hasn't
1325 any focusable widget, clear focus and go back to the action area */
1326 gtk_container_set_focus_child (GTK_CONTAINER (priv->action_area), NULL);
1327 gtk_widget_child_focus (priv->action_area, direction);
1332 if (!gtk_widget_child_focus (priv->current_page->page, direction) &&
1333 !gtk_widget_child_focus (priv->action_area, direction))
1335 /* if we're leaving the current page and there isn't nothing focusable
1336 in the action area, try to clear focus and go back to the page */
1337 gtk_window_set_focus (GTK_WINDOW (widget), NULL);
1338 gtk_widget_child_focus (priv->current_page->page, direction);
1346 gtk_assistant_add (GtkContainer *container,
1349 g_return_if_fail (GTK_IS_WIDGET (page));
1351 gtk_assistant_append_page (GTK_ASSISTANT (container), page);
1355 gtk_assistant_remove (GtkContainer *container,
1358 GtkAssistant *assistant;
1361 assistant = (GtkAssistant*) container;
1363 element = find_page (assistant, page);
1367 remove_page (assistant, element);
1368 gtk_widget_queue_resize ((GtkWidget *) container);
1373 gtk_assistant_forall (GtkContainer *container,
1374 gboolean include_internals,
1375 GtkCallback callback,
1376 gpointer callback_data)
1378 GtkAssistant *assistant = (GtkAssistant*) container;
1379 GtkAssistantPrivate *priv = assistant->priv;
1382 if (include_internals)
1384 (*callback) (priv->header_image, callback_data);
1385 (*callback) (priv->sidebar_image, callback_data);
1386 (*callback) (priv->action_area, callback_data);
1389 pages = priv->pages;
1393 GtkAssistantPage *page = (GtkAssistantPage *) pages->data;
1395 (*callback) (page->page, callback_data);
1397 if (include_internals)
1398 (*callback) (page->title, callback_data);
1400 pages = pages->next;
1405 * gtk_assistant_new:
1407 * Creates a new #GtkAssistant.
1409 * Return value: a newly created #GtkAssistant
1414 gtk_assistant_new (void)
1416 GtkWidget *assistant;
1418 assistant = g_object_new (GTK_TYPE_ASSISTANT,
1425 * gtk_assistant_get_current_page:
1426 * @assistant: a #GtkAssistant
1428 * Returns the page number of the current page
1430 * Return value: The index (starting from 0) of the current page in
1431 * the @assistant, if the @assistant has no pages, -1 will be returned
1436 gtk_assistant_get_current_page (GtkAssistant *assistant)
1438 GtkAssistantPrivate *priv;
1440 g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), -1);
1442 priv = assistant->priv;
1444 if (!priv->pages || !priv->current_page)
1447 return g_list_index (priv->pages, priv->current_page);
1451 * gtk_assistant_set_current_page:
1452 * @assistant: a #GtkAssistant
1453 * @page_num: index of the page to switch to, starting from 0.
1454 * If negative, the last page will be used. If greater
1455 * than the number of pages in the @assistant, nothing
1458 * Switches the page to @page_num. Note that this will only be necessary
1459 * in custom buttons, as the @assistant flow can be set with
1460 * gtk_assistant_set_forward_page_func().
1465 gtk_assistant_set_current_page (GtkAssistant *assistant,
1468 GtkAssistantPrivate *priv;
1469 GtkAssistantPage *page;
1471 g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1473 priv = assistant->priv;
1476 page = (GtkAssistantPage *) g_list_nth_data (priv->pages, page_num);
1478 page = (GtkAssistantPage *) g_list_last (priv->pages);
1480 g_return_if_fail (page != NULL);
1482 if (priv->current_page == page)
1485 /* only add the page to the visited list if the
1486 * assistant is mapped, if not, just use it as an
1487 * initial page setting, for the cases where the
1488 * initial page is != to 0
1490 if (GTK_WIDGET_MAPPED (assistant))
1491 priv->visited_pages = g_slist_prepend (priv->visited_pages, page);
1493 set_current_page (assistant, page);
1497 * gtk_assistant_get_n_pages:
1498 * @assistant: a #GtkAssistant
1500 * Returns the number of pages in the @assistant
1502 * Return value: The number of pages in the @assistant.
1507 gtk_assistant_get_n_pages (GtkAssistant *assistant)
1509 GtkAssistantPrivate *priv;
1511 g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
1513 priv = assistant->priv;
1515 return g_list_length (priv->pages);
1519 * gtk_assistant_get_nth_page:
1520 * @assistant: a #GtkAssistant
1521 * @page_num: The index of a page in the @assistant, or -1 to get the last page;
1523 * Returns the child widget contained in page number @page_num.
1525 * Return value: The child widget, or %NULL if @page_num is out of bounds.
1530 gtk_assistant_get_nth_page (GtkAssistant *assistant,
1533 GtkAssistantPrivate *priv;
1534 GtkAssistantPage *page;
1537 g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
1539 priv = assistant->priv;
1541 elem = g_list_nth (priv->pages, page_num);
1546 page = (GtkAssistantPage *) elem->data;
1552 * gtk_assistant_prepend_page:
1553 * @assistant: a #GtkAssistant
1554 * @page: a #GtkWidget
1556 * Prepends a page to the @assistant.
1558 * Return value: the index (starting at 0) of the inserted page
1563 gtk_assistant_prepend_page (GtkAssistant *assistant,
1566 g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
1567 g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
1569 return gtk_assistant_insert_page (assistant, page, 0);
1573 * gtk_assistant_append_page:
1574 * @assistant: a #GtkAssistant
1575 * @page: a #GtkWidget
1577 * Appends a page to the @assistant.
1579 * Return value: the index (starting at 0) of the inserted page
1584 gtk_assistant_append_page (GtkAssistant *assistant,
1587 g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
1588 g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
1590 return gtk_assistant_insert_page (assistant, page, -1);
1594 * gtk_assistant_insert_page:
1595 * @assistant: a #GtkAssistant
1596 * @page: a #GtkWidget
1597 * @position: the index (starting at 0) at which to insert the page,
1598 * or -1 to append the page to the @assistant
1600 * Inserts a page in the @assistant at a given position.
1602 * Return value: the index (starting from 0) of the inserted page
1607 gtk_assistant_insert_page (GtkAssistant *assistant,
1611 GtkAssistantPrivate *priv;
1612 GtkAssistantPage *page_info;
1615 g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
1616 g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
1617 g_return_val_if_fail (page->parent == NULL, 0);
1618 g_return_val_if_fail (!GTK_WIDGET_TOPLEVEL (page), 0);
1620 priv = assistant->priv;
1622 page_info = g_new0 (GtkAssistantPage, 1);
1623 page_info->page = page;
1624 page_info->title = gtk_label_new (NULL);
1626 g_signal_connect (G_OBJECT (page), "notify::visible",
1627 G_CALLBACK (on_page_notify_visibility), assistant);
1629 gtk_misc_set_alignment (GTK_MISC (page_info->title), 0.,0.5);
1630 set_title_colors (GTK_WIDGET (assistant), page_info->title);
1631 set_title_font (GTK_WIDGET (assistant), page_info->title);
1632 gtk_widget_show (page_info->title);
1634 n_pages = g_list_length (priv->pages);
1636 if (position < 0 || position > n_pages)
1639 priv->pages = g_list_insert (priv->pages, page_info, position);
1641 gtk_widget_set_child_visible (page_info->page, FALSE);
1642 gtk_widget_set_parent (page_info->page, GTK_WIDGET (assistant));
1643 gtk_widget_set_parent (page_info->title, GTK_WIDGET (assistant));
1645 if (GTK_WIDGET_REALIZED (GTK_WIDGET (assistant)))
1647 gtk_widget_realize (page_info->page);
1648 gtk_widget_realize (page_info->title);
1651 gtk_widget_queue_resize (GTK_WIDGET (assistant));
1657 * gtk_assistant_set_forward_page_func:
1658 * @assistant: a #GtkAssistant
1659 * @page_func: the #GtkAssistantPageFunc, or %NULL to use the default one
1660 * @data: user data for @page_func
1661 * @destroy: destroy notifier for @data
1663 * Sets the page forwarding function to be @page_func, this function will
1664 * be used to determine what will be the next page when the user presses
1665 * the forward button. Setting @page_func to %NULL will make the assistant
1666 * to use the default forward function, which just goes to the next visible
1672 gtk_assistant_set_forward_page_func (GtkAssistant *assistant,
1673 GtkAssistantPageFunc page_func,
1675 GDestroyNotify destroy)
1677 GtkAssistantPrivate *priv;
1679 g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1681 priv = assistant->priv;
1683 if (priv->forward_data_destroy &&
1684 priv->forward_function_data)
1685 (*priv->forward_data_destroy) (priv->forward_function_data);
1689 priv->forward_function = page_func;
1690 priv->forward_function_data = data;
1691 priv->forward_data_destroy = destroy;
1695 priv->forward_function = default_forward_function;
1696 priv->forward_function_data = assistant;
1697 priv->forward_data_destroy = NULL;
1700 /* Page flow has possibly changed, so the
1701 buttons state might need to change too */
1702 if (priv->current_page)
1703 set_assistant_buttons_state (assistant);
1707 * gtk_assistant_add_action_widget:
1708 * @assistant: a #GtkAssistant
1709 * @child: a #GtkWidget
1711 * Adds a widget to the action area of a #GtkAssistant.
1716 gtk_assistant_add_action_widget (GtkAssistant *assistant,
1719 GtkAssistantPrivate *priv;
1721 g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1722 g_return_if_fail (GTK_IS_WIDGET (child));
1724 priv = assistant->priv;
1726 if (GTK_IS_BUTTON (child))
1727 gtk_size_group_add_widget (priv->size_group, child);
1729 gtk_box_pack_end (GTK_BOX (priv->action_area), child, FALSE, FALSE, 0);
1733 * gtk_assistant_remove_action_widget:
1734 * @assistant: a #GtkAssistant
1735 * @child: a #GtkWidget
1737 * Removes a widget from the action area of a #GtkAssistant.
1742 gtk_assistant_remove_action_widget (GtkAssistant *assistant,
1745 GtkAssistantPrivate *priv;
1747 g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1748 g_return_if_fail (GTK_IS_WIDGET (child));
1750 priv = assistant->priv;
1752 if (GTK_IS_BUTTON (child))
1753 gtk_size_group_remove_widget (priv->size_group, child);
1755 gtk_container_remove (GTK_CONTAINER (priv->action_area), child);
1759 * gtk_assistant_set_page_title:
1760 * @assistant: a #GtkAssistant
1761 * @page: a page of @assitant
1762 * @title: the new title for @page
1764 * Sets a title for @page. The title is displayed in the header
1765 * area of the assistant when @page is the current page.
1770 gtk_assistant_set_page_title (GtkAssistant *assistant,
1774 GtkAssistantPrivate *priv;
1775 GtkAssistantPage *page_info;
1778 g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1779 g_return_if_fail (GTK_IS_WIDGET (page));
1781 priv = assistant->priv;
1782 child = find_page (assistant, page);
1784 g_return_if_fail (child != NULL);
1786 page_info = (GtkAssistantPage*) child->data;
1788 gtk_label_set_text ((GtkLabel*) page_info->title, title);
1789 gtk_widget_queue_resize (GTK_WIDGET (assistant));
1790 gtk_widget_child_notify (page, "title");
1794 * gtk_assistant_get_page_title:
1795 * @assistant: a #GtkAssistant
1796 * @page: a page of @assistant
1798 * Gets the title for @page.
1800 * Return value: the title for @page.
1804 G_CONST_RETURN gchar*
1805 gtk_assistant_get_page_title (GtkAssistant *assistant,
1808 GtkAssistantPrivate *priv;
1809 GtkAssistantPage *page_info;
1812 g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
1813 g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
1815 priv = assistant->priv;
1816 child = find_page (assistant, page);
1818 g_return_val_if_fail (child != NULL, NULL);
1820 page_info = (GtkAssistantPage*) child->data;
1822 return gtk_label_get_text ((GtkLabel*) page_info->title);
1826 * gtk_assistant_set_page_type:
1827 * @assistant: a #GtkAssistant
1828 * @page: a page of @assitant
1829 * @type: the new type for @page
1831 * Sets the page type for @page. The page type determines the page
1832 * behavior in the @assistant.
1837 gtk_assistant_set_page_type (GtkAssistant *assistant,
1839 GtkAssistantPageType type)
1841 GtkAssistantPrivate *priv;
1842 GtkAssistantPage *page_info;
1845 g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1846 g_return_if_fail (GTK_IS_WIDGET (page));
1848 priv = assistant->priv;
1849 child = find_page (assistant, page);
1851 g_return_if_fail (child != NULL);
1853 page_info = (GtkAssistantPage*) child->data;
1855 if (type != page_info->type)
1857 page_info->type = type;
1859 /* Always set buttons state, a change in a future page
1860 might change current page buttons */
1861 if (priv->current_page)
1862 set_assistant_buttons_state (assistant);
1864 gtk_widget_child_notify (page, "page-type");
1869 * gtk_assistant_get_page_type:
1870 * @assistant: a #GtkAssistant
1871 * @page: a page of @assistant
1873 * Gets the page type of @page.
1875 * Return value: the page type of @page.
1879 GtkAssistantPageType
1880 gtk_assistant_get_page_type (GtkAssistant *assistant,
1883 GtkAssistantPrivate *priv;
1884 GtkAssistantPage *page_info;
1887 g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), GTK_ASSISTANT_PAGE_CONTENT);
1888 g_return_val_if_fail (GTK_IS_WIDGET (page), GTK_ASSISTANT_PAGE_CONTENT);
1890 priv = assistant->priv;
1891 child = find_page (assistant, page);
1893 g_return_val_if_fail (child != NULL, GTK_ASSISTANT_PAGE_CONTENT);
1895 page_info = (GtkAssistantPage*) child->data;
1897 return page_info->type;
1901 * gtk_assistant_set_page_header_image:
1902 * @assistant: a #GtkAssistant
1903 * @page: a page of @assitant
1904 * @pixbuf: the new header image @page
1906 * Sets a header image for @page. This image is displayed in the header
1907 * area of the assistant when @page is the current page.
1912 gtk_assistant_set_page_header_image (GtkAssistant *assistant,
1916 GtkAssistantPrivate *priv;
1917 GtkAssistantPage *page_info;
1920 g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1921 g_return_if_fail (GTK_IS_WIDGET (page));
1922 g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
1924 priv = assistant->priv;
1925 child = find_page (assistant, page);
1927 g_return_if_fail (child != NULL);
1929 page_info = (GtkAssistantPage*) child->data;
1931 if (pixbuf != page_info->header_image)
1933 if (page_info->header_image)
1935 g_object_unref (page_info->header_image);
1936 page_info->header_image = NULL;
1940 page_info->header_image = g_object_ref (pixbuf);
1942 if (page_info == priv->current_page)
1943 set_assistant_header_image (assistant);
1945 gtk_widget_child_notify (page, "header-image");
1950 * gtk_assistant_get_page_header_image:
1951 * @assistant: a #GtkAssistant
1952 * @page: a page of @assistant
1954 * Gets the header image for @page.
1956 * Return value: the header image for @page, or %NULL
1957 * if there's no header image for the page.
1962 gtk_assistant_get_page_header_image (GtkAssistant *assistant,
1965 GtkAssistantPrivate *priv;
1966 GtkAssistantPage *page_info;
1969 g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
1970 g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
1972 priv = assistant->priv;
1973 child = find_page (assistant, page);
1975 g_return_val_if_fail (child != NULL, NULL);
1977 page_info = (GtkAssistantPage*) child->data;
1979 return page_info->header_image;
1983 * gtk_assistant_set_page_side_image:
1984 * @assistant: a #GtkAssistant
1985 * @page: a page of @assitant
1986 * @pixbuf: the new header image @page
1988 * Sets a header image for @page. This image is displayed in the side
1989 * area of the assistant when @page is the current page.
1994 gtk_assistant_set_page_side_image (GtkAssistant *assistant,
1998 GtkAssistantPrivate *priv;
1999 GtkAssistantPage *page_info;
2002 g_return_if_fail (GTK_IS_ASSISTANT (assistant));
2003 g_return_if_fail (GTK_IS_WIDGET (page));
2004 g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
2006 priv = assistant->priv;
2007 child = find_page (assistant, page);
2009 g_return_if_fail (child != NULL);
2011 page_info = (GtkAssistantPage*) child->data;
2013 if (pixbuf != page_info->sidebar_image)
2015 if (page_info->sidebar_image)
2017 g_object_unref (page_info->sidebar_image);
2018 page_info->sidebar_image = NULL;
2022 page_info->sidebar_image = g_object_ref (pixbuf);
2024 if (page_info == priv->current_page)
2025 set_assistant_sidebar_image (assistant);
2027 gtk_widget_child_notify (page, "sidebar-image");
2032 * gtk_assistant_get_page_side_image:
2033 * @assistant: a #GtkAssistant
2034 * @page: a page of @assistant
2036 * Gets the header image for @page.
2038 * Return value: the side image for @page, or %NULL
2039 * if there's no side image for the page.
2044 gtk_assistant_get_page_side_image (GtkAssistant *assistant,
2047 GtkAssistantPrivate *priv;
2048 GtkAssistantPage *page_info;
2051 g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
2052 g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
2054 priv = assistant->priv;
2055 child = find_page (assistant, page);
2057 g_return_val_if_fail (child != NULL, NULL);
2059 page_info = (GtkAssistantPage*) child->data;
2061 return page_info->sidebar_image;
2065 * gtk_assistant_set_page_complete:
2066 * @assistant: a #GtkAssistant
2067 * @page: a page of @assitant
2068 * @complete: the completeness status of the page
2070 * Sets whether @page contents are complete. This will make
2071 * @assistant update the buttons state to be able to continue the task.
2076 gtk_assistant_set_page_complete (GtkAssistant *assistant,
2080 GtkAssistantPrivate *priv;
2081 GtkAssistantPage *page_info;
2084 g_return_if_fail (GTK_IS_ASSISTANT (assistant));
2085 g_return_if_fail (GTK_IS_WIDGET (page));
2087 priv = assistant->priv;
2088 child = find_page (assistant, page);
2090 g_return_if_fail (child != NULL);
2092 page_info = (GtkAssistantPage*) child->data;
2094 if (complete != page_info->complete)
2096 page_info->complete = complete;
2098 /* Always set buttons state, a change in a future page
2099 might change current page buttons */
2100 if (priv->current_page)
2101 set_assistant_buttons_state (assistant);
2103 gtk_widget_child_notify (page, "complete");
2108 * gtk_assistant_get_page_complete:
2109 * @assistant: a #GtkAssistant
2110 * @page: a page of @assistant
2112 * Gets whether @page is complete..
2114 * Return value: %TRUE if @page is complete.
2119 gtk_assistant_get_page_complete (GtkAssistant *assistant,
2122 GtkAssistantPrivate *priv;
2123 GtkAssistantPage *page_info;
2126 g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), FALSE);
2127 g_return_val_if_fail (GTK_IS_WIDGET (page), FALSE);
2129 priv = assistant->priv;
2130 child = find_page (assistant, page);
2132 g_return_val_if_fail (child != NULL, FALSE);
2134 page_info = (GtkAssistantPage*) child->data;
2136 return page_info->complete;
2140 * gtk_assistant_update_buttons_state:
2141 * @assistant: a #GtkAssistant
2143 * Forces @assistant to recompute the buttons state.
2145 * GTK+ automatically takes care of this in most situations,
2146 * e.g. when the user goes to a different page, or when the
2147 * visibility or completeness of a page changes.
2149 * One situation where it can be necessary to call this
2150 * function is when changing a value on the current page
2151 * affects the future page flow of the assistant.
2156 gtk_assistant_update_buttons_state (GtkAssistant *assistant)
2158 g_return_if_fail (GTK_IS_ASSISTANT (assistant));
2160 set_assistant_buttons_state (assistant);
2164 #define __GTK_ASSISTANT_C__
2165 #include "gtkaliasdef.c"