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.
27
* SECTION:gtkassistant
28
* @Short_description: A widget used to guide users through multi-step operations
29
* @Title: GtkAssistant
31
* A #GtkAssistant is a widget used to represent a generally complex
32
* operation splitted in several steps, guiding the user through its pages
33
* and controlling the page flow to collect the necessary data.
35
* <refsect2 id="GtkAssistant-BUILDER-UI">
36
* <title>GtkAssistant as GtkBuildable</title>
38
* The GtkAssistant implementation of the GtkBuildable interface exposes the
39
* @action_area as internal children with the name "action_area".
41
* To add pages to an assistant in GtkBuilder, simply add it as a
42
* <child> to the GtkAssistant object, and set its child properties
52
#include "gtkassistant.h"
54
#include "gtkaccessible.h"
55
#include "gtkbutton.h"
60
#include "gtksizegroup.h"
64
#include "gtkprivate.h"
65
#include "gtkbuildable.h"
69
#define GTK_ASSISTANT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_ASSISTANT, GtkAssistantPrivate))
71
#define HEADER_SPACING 12
72
#define ACTION_AREA_SPACING 12
74
typedef struct _GtkAssistantPage GtkAssistantPage;
76
struct _GtkAssistantPage
79
GtkAssistantPageType type;
81
guint complete_set : 1;
84
GdkPixbuf *header_image;
85
GdkPixbuf *sidebar_image;
88
struct _GtkAssistantPrivate
90
GtkWidget *header_image;
91
GtkWidget *sidebar_image;
93
GtkWidget *action_area;
97
GtkAssistantPage *current_page;
99
GSList *visited_pages;
101
GtkSizeGroup *size_group;
103
GtkAssistantPageFunc forward_function;
104
gpointer forward_function_data;
105
GDestroyNotify forward_data_destroy;
110
static void gtk_assistant_class_init (GtkAssistantClass *class);
111
static void gtk_assistant_init (GtkAssistant *assistant);
112
static void gtk_assistant_destroy (GtkObject *object);
113
static void gtk_assistant_style_set (GtkWidget *widget,
114
GtkStyle *old_style);
115
static void gtk_assistant_size_request (GtkWidget *widget,
116
GtkRequisition *requisition);
117
static void gtk_assistant_size_allocate (GtkWidget *widget,
118
GtkAllocation *allocation);
119
static void gtk_assistant_map (GtkWidget *widget);
120
static void gtk_assistant_unmap (GtkWidget *widget);
121
static gboolean gtk_assistant_delete_event (GtkWidget *widget,
123
static gboolean gtk_assistant_expose (GtkWidget *widget,
124
GdkEventExpose *event);
125
static gboolean gtk_assistant_focus (GtkWidget *widget,
126
GtkDirectionType direction);
127
static void gtk_assistant_add (GtkContainer *container,
129
static void gtk_assistant_remove (GtkContainer *container,
131
static void gtk_assistant_forall (GtkContainer *container,
132
gboolean include_internals,
133
GtkCallback callback,
134
gpointer callback_data);
135
static void gtk_assistant_set_child_property (GtkContainer *container,
140
static void gtk_assistant_get_child_property (GtkContainer *container,
146
static AtkObject *gtk_assistant_get_accessible (GtkWidget *widget);
148
static void gtk_assistant_buildable_interface_init (GtkBuildableIface *iface);
149
static GObject *gtk_assistant_buildable_get_internal_child (GtkBuildable *buildable,
151
const gchar *childname);
152
static gboolean gtk_assistant_buildable_custom_tag_start (GtkBuildable *buildable,
155
const gchar *tagname,
156
GMarkupParser *parser,
158
static void gtk_assistant_buildable_custom_finished (GtkBuildable *buildable,
161
const gchar *tagname,
164
static GList* find_page (GtkAssistant *assistant,
170
CHILD_PROP_PAGE_TYPE,
171
CHILD_PROP_PAGE_TITLE,
172
CHILD_PROP_PAGE_HEADER_IMAGE,
173
CHILD_PROP_PAGE_SIDEBAR_IMAGE,
174
CHILD_PROP_PAGE_COMPLETE
186
static guint signals [LAST_SIGNAL] = { 0 };
189
G_DEFINE_TYPE_WITH_CODE (GtkAssistant, gtk_assistant, GTK_TYPE_WINDOW,
190
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
191
gtk_assistant_buildable_interface_init))
195
gtk_assistant_class_init (GtkAssistantClass *class)
197
GObjectClass *gobject_class;
198
GtkObjectClass *object_class;
199
GtkWidgetClass *widget_class;
200
GtkContainerClass *container_class;
202
gobject_class = (GObjectClass *) class;
203
object_class = (GtkObjectClass *) class;
204
widget_class = (GtkWidgetClass *) class;
205
container_class = (GtkContainerClass *) class;
207
object_class->destroy = gtk_assistant_destroy;
209
widget_class->style_set = gtk_assistant_style_set;
210
widget_class->size_request = gtk_assistant_size_request;
211
widget_class->size_allocate = gtk_assistant_size_allocate;
212
widget_class->map = gtk_assistant_map;
213
widget_class->unmap = gtk_assistant_unmap;
214
widget_class->delete_event = gtk_assistant_delete_event;
215
widget_class->expose_event = gtk_assistant_expose;
216
widget_class->focus = gtk_assistant_focus;
217
widget_class->get_accessible = gtk_assistant_get_accessible;
219
container_class->add = gtk_assistant_add;
220
container_class->remove = gtk_assistant_remove;
221
container_class->forall = gtk_assistant_forall;
222
container_class->set_child_property = gtk_assistant_set_child_property;
223
container_class->get_child_property = gtk_assistant_get_child_property;
226
* GtkAssistant::cancel:
227
* @assistant: the #GtkAssistant
229
* The ::cancel signal is emitted when then the cancel button is clicked.
234
g_signal_new (I_("cancel"),
235
G_TYPE_FROM_CLASS (gobject_class),
237
G_STRUCT_OFFSET (GtkAssistantClass, cancel),
239
g_cclosure_marshal_VOID__VOID,
243
* GtkAssistant::prepare:
244
* @assistant: the #GtkAssistant
245
* @page: the current page
247
* The ::prepare signal is emitted when a new page is set as the assistant's
248
* current page, before making the new page visible. A handler for this signal
249
* can do any preparation which are necessary before showing @page.
254
g_signal_new (I_("prepare"),
255
G_TYPE_FROM_CLASS (gobject_class),
257
G_STRUCT_OFFSET (GtkAssistantClass, prepare),
259
g_cclosure_marshal_VOID__OBJECT,
260
G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
263
* GtkAssistant::apply:
264
* @assistant: the #GtkAssistant
266
* The ::apply signal is emitted when the apply button is clicked. The default
267
* behavior of the #GtkAssistant is to switch to the page after the current
268
* page, unless the current page is the last one.
270
* A handler for the ::apply signal should carry out the actions for which
271
* the wizard has collected data. If the action takes a long time to complete,
272
* you might consider putting a page of type %GTK_ASSISTANT_PAGE_PROGRESS
273
* after the confirmation page and handle this operation within the
274
* #GtkAssistant::prepare signal of the progress page.
279
g_signal_new (I_("apply"),
280
G_TYPE_FROM_CLASS (gobject_class),
282
G_STRUCT_OFFSET (GtkAssistantClass, apply),
284
g_cclosure_marshal_VOID__VOID,
288
* GtkAssistant::close:
289
* @assistant: the #GtkAssistant
291
* The ::close signal is emitted either when the close button of
292
* a summary page is clicked, or when the apply button in the last
293
* page in the flow (of type %GTK_ASSISTANT_PAGE_CONFIRM) is clicked.
298
g_signal_new (I_("close"),
299
G_TYPE_FROM_CLASS (gobject_class),
301
G_STRUCT_OFFSET (GtkAssistantClass, close),
303
g_cclosure_marshal_VOID__VOID,
306
gtk_widget_class_install_style_property (widget_class,
307
g_param_spec_int ("header-padding",
308
P_("Header Padding"),
309
P_("Number of pixels around the header."),
313
GTK_PARAM_READABLE));
314
gtk_widget_class_install_style_property (widget_class,
315
g_param_spec_int ("content-padding",
316
P_("Content Padding"),
317
P_("Number of pixels around the content pages."),
321
GTK_PARAM_READABLE));
324
* GtkAssistant:page-type:
326
* The type of the assistant page.
330
gtk_container_class_install_child_property (container_class,
331
CHILD_PROP_PAGE_TYPE,
332
g_param_spec_enum ("page-type",
334
P_("The type of the assistant page"),
335
GTK_TYPE_ASSISTANT_PAGE_TYPE,
336
GTK_ASSISTANT_PAGE_CONTENT,
337
GTK_PARAM_READWRITE));
340
* GtkAssistant:title:
342
* The title that is displayed in the page header.
344
* If title and header-image are both %NULL, no header is displayed.
348
gtk_container_class_install_child_property (container_class,
349
CHILD_PROP_PAGE_TITLE,
350
g_param_spec_string ("title",
352
P_("The title of the assistant page"),
354
GTK_PARAM_READWRITE));
357
* GtkAssistant:header-image:
359
* The image that is displayed next to the title in the page header.
361
* If title and header-image are both %NULL, no header is displayed.
365
gtk_container_class_install_child_property (container_class,
366
CHILD_PROP_PAGE_HEADER_IMAGE,
367
g_param_spec_object ("header-image",
369
P_("Header image for the assistant page"),
371
GTK_PARAM_READWRITE));
374
* GtkAssistant:header-image:
376
* The image that is displayed next to the page.
378
* Set this to %NULL to make the sidebar disappear.
382
gtk_container_class_install_child_property (container_class,
383
CHILD_PROP_PAGE_SIDEBAR_IMAGE,
384
g_param_spec_object ("sidebar-image",
386
P_("Sidebar image for the assistant page"),
388
GTK_PARAM_READWRITE));
390
* GtkAssistant:complete:
392
* Setting the "complete" child property to %TRUE marks a page as complete
393
* (i.e.: all the required fields are filled out). GTK+ uses this information
394
* to control the sensitivity of the navigation buttons.
398
gtk_container_class_install_child_property (container_class,
399
CHILD_PROP_PAGE_COMPLETE,
400
g_param_spec_boolean ("complete",
402
P_("Whether all required fields on the page have been filled out"),
406
g_type_class_add_private (gobject_class, sizeof (GtkAssistantPrivate));
410
default_forward_function (gint current_page, gpointer data)
412
GtkAssistant *assistant;
413
GtkAssistantPrivate *priv;
414
GtkAssistantPage *page_info;
417
assistant = GTK_ASSISTANT (data);
418
priv = assistant->priv;
420
page_node = g_list_nth (priv->pages, ++current_page);
425
page_info = (GtkAssistantPage *) page_node->data;
427
while (page_node && !gtk_widget_get_visible (page_info->page))
429
page_node = page_node->next;
433
page_info = (GtkAssistantPage *) page_node->data;
440
compute_last_button_state (GtkAssistant *assistant)
442
GtkAssistantPrivate *priv = assistant->priv;
443
GtkAssistantPage *page_info, *current_page_info;
444
gint count, page_num, n_pages;
447
page_num = gtk_assistant_get_current_page (assistant);
448
n_pages = gtk_assistant_get_n_pages (assistant);
449
current_page_info = page_info = g_list_nth_data (priv->pages, page_num);
451
while (page_num >= 0 && page_num < n_pages &&
452
page_info->type == GTK_ASSISTANT_PAGE_CONTENT &&
453
(count == 0 || page_info->complete) &&
456
page_num = (priv->forward_function) (page_num, priv->forward_function_data);
457
page_info = g_list_nth_data (priv->pages, page_num);
462
/* make the last button visible if we can skip multiple
463
* pages and end on a confirmation or summary page
465
if (count > 1 && page_info &&
466
(page_info->type == GTK_ASSISTANT_PAGE_CONFIRM ||
467
page_info->type == GTK_ASSISTANT_PAGE_SUMMARY))
469
gtk_widget_show (assistant->last);
470
gtk_widget_set_sensitive (assistant->last,
471
current_page_info->complete);
474
gtk_widget_hide (assistant->last);
478
compute_progress_state (GtkAssistant *assistant)
480
GtkAssistantPrivate *priv = assistant->priv;
481
gint page_num, n_pages;
483
n_pages = gtk_assistant_get_n_pages (assistant);
484
page_num = gtk_assistant_get_current_page (assistant);
486
page_num = (priv->forward_function) (page_num, priv->forward_function_data);
488
if (page_num >= 0 && page_num < n_pages)
489
gtk_widget_show (assistant->forward);
491
gtk_widget_hide (assistant->forward);
495
set_assistant_header_image (GtkAssistant *assistant)
497
GtkAssistantPrivate *priv = assistant->priv;
499
gtk_image_set_from_pixbuf (GTK_IMAGE (priv->header_image),
500
priv->current_page->header_image);
504
set_assistant_sidebar_image (GtkAssistant *assistant)
506
GtkAssistantPrivate *priv = assistant->priv;
508
gtk_image_set_from_pixbuf (GTK_IMAGE (priv->sidebar_image),
509
priv->current_page->sidebar_image);
511
if (priv->current_page->sidebar_image)
512
gtk_widget_show (priv->sidebar_image);
514
gtk_widget_hide (priv->sidebar_image);
518
set_assistant_buttons_state (GtkAssistant *assistant)
520
GtkAssistantPrivate *priv = assistant->priv;
522
if (!priv->current_page)
525
switch (priv->current_page->type)
527
case GTK_ASSISTANT_PAGE_INTRO:
528
gtk_widget_set_sensitive (assistant->cancel, TRUE);
529
gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
530
gtk_widget_grab_default (assistant->forward);
531
gtk_widget_show (assistant->forward);
532
gtk_widget_hide (assistant->back);
533
gtk_widget_hide (assistant->apply);
534
gtk_widget_hide (assistant->close);
535
compute_last_button_state (assistant);
537
case GTK_ASSISTANT_PAGE_CONFIRM:
538
gtk_widget_set_sensitive (assistant->cancel, TRUE);
539
gtk_widget_set_sensitive (assistant->back, TRUE);
540
gtk_widget_set_sensitive (assistant->apply, priv->current_page->complete);
541
gtk_widget_grab_default (assistant->apply);
542
gtk_widget_show (assistant->back);
543
gtk_widget_show (assistant->apply);
544
gtk_widget_hide (assistant->forward);
545
gtk_widget_hide (assistant->close);
546
gtk_widget_hide (assistant->last);
548
case GTK_ASSISTANT_PAGE_CONTENT:
549
gtk_widget_set_sensitive (assistant->cancel, TRUE);
550
gtk_widget_set_sensitive (assistant->back, TRUE);
551
gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
552
gtk_widget_grab_default (assistant->forward);
553
gtk_widget_show (assistant->back);
554
gtk_widget_show (assistant->forward);
555
gtk_widget_hide (assistant->apply);
556
gtk_widget_hide (assistant->close);
557
compute_last_button_state (assistant);
559
case GTK_ASSISTANT_PAGE_SUMMARY:
560
gtk_widget_set_sensitive (assistant->close, priv->current_page->complete);
561
gtk_widget_grab_default (assistant->close);
562
gtk_widget_show (assistant->close);
563
gtk_widget_hide (assistant->back);
564
gtk_widget_hide (assistant->forward);
565
gtk_widget_hide (assistant->apply);
566
gtk_widget_hide (assistant->last);
568
case GTK_ASSISTANT_PAGE_PROGRESS:
569
gtk_widget_set_sensitive (assistant->cancel, priv->current_page->complete);
570
gtk_widget_set_sensitive (assistant->back, priv->current_page->complete);
571
gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
572
gtk_widget_grab_default (assistant->forward);
573
gtk_widget_show (assistant->back);
574
gtk_widget_hide (assistant->apply);
575
gtk_widget_hide (assistant->close);
576
gtk_widget_hide (assistant->last);
577
compute_progress_state (assistant);
580
g_assert_not_reached ();
584
gtk_widget_hide (assistant->cancel);
585
else if (priv->current_page->type == GTK_ASSISTANT_PAGE_SUMMARY)
586
gtk_widget_hide (assistant->cancel);
588
gtk_widget_show (assistant->cancel);
590
/* this is quite general, we don't want to
591
* go back if it's the first page */
592
if (!priv->visited_pages)
593
gtk_widget_hide (assistant->back);
597
set_current_page (GtkAssistant *assistant,
598
GtkAssistantPage *page)
600
GtkAssistantPrivate *priv = assistant->priv;
601
GtkAssistantPage *old_page;
603
if (priv->current_page &&
604
gtk_widget_is_drawable (priv->current_page->page))
605
old_page = priv->current_page;
609
priv->current_page = page;
611
set_assistant_buttons_state (assistant);
612
set_assistant_header_image (assistant);
613
set_assistant_sidebar_image (assistant);
615
g_signal_emit (assistant, signals [PREPARE], 0, priv->current_page->page);
617
if (gtk_widget_get_visible (priv->current_page->page) && gtk_widget_get_mapped (GTK_WIDGET (assistant)))
619
gtk_widget_set_child_visible (priv->current_page->page, TRUE);
620
gtk_widget_map (priv->current_page->page);
621
gtk_widget_map (priv->current_page->title);
624
if (old_page && gtk_widget_get_mapped (old_page->page))
626
gtk_widget_set_child_visible (old_page->page, FALSE);
627
gtk_widget_unmap (old_page->page);
628
gtk_widget_unmap (old_page->title);
631
if (!gtk_widget_child_focus (priv->current_page->page, GTK_DIR_TAB_FORWARD))
633
GtkWidget *button[6];
636
/* find the best button to focus */
637
button[0] = assistant->apply;
638
button[1] = assistant->close;
639
button[2] = assistant->forward;
640
button[3] = assistant->back;
641
button[4] = assistant->cancel;
642
button[5] = assistant->last;
643
for (i = 0; i < 6; i++)
645
if (gtk_widget_get_visible (button[i]) && gtk_widget_get_sensitive (button[i]))
647
gtk_widget_grab_focus (button[i]);
653
gtk_widget_queue_resize (GTK_WIDGET (assistant));
657
compute_next_step (GtkAssistant *assistant)
659
GtkAssistantPrivate *priv = assistant->priv;
660
GtkAssistantPage *page_info;
661
gint current_page, n_pages, next_page;
663
current_page = gtk_assistant_get_current_page (assistant);
664
page_info = priv->current_page;
665
n_pages = gtk_assistant_get_n_pages (assistant);
667
next_page = (priv->forward_function) (current_page,
668
priv->forward_function_data);
670
if (next_page >= 0 && next_page < n_pages)
672
priv->visited_pages = g_slist_prepend (priv->visited_pages, page_info);
673
set_current_page (assistant, g_list_nth_data (priv->pages, next_page));
682
on_assistant_close (GtkWidget *widget,
683
GtkAssistant *assistant)
685
g_signal_emit (assistant, signals [CLOSE], 0, NULL);
689
on_assistant_apply (GtkWidget *widget,
690
GtkAssistant *assistant)
694
g_signal_emit (assistant, signals [APPLY], 0);
696
success = compute_next_step (assistant);
698
/* if the assistant hasn't switched to another page, just emit
699
* the CLOSE signal, it't the last page in the assistant flow
702
g_signal_emit (assistant, signals [CLOSE], 0);
706
on_assistant_forward (GtkWidget *widget,
707
GtkAssistant *assistant)
709
if (!compute_next_step (assistant))
710
g_critical ("Page flow is broken, you may want to end it with a page of "
711
"type GTK_ASSISTANT_PAGE_CONFIRM or GTK_ASSISTANT_PAGE_SUMMARY");
715
on_assistant_back (GtkWidget *widget,
716
GtkAssistant *assistant)
718
GtkAssistantPrivate *priv = assistant->priv;
719
GtkAssistantPage *page_info;
722
/* skip the progress pages when going back */
725
page_node = priv->visited_pages;
727
g_return_if_fail (page_node != NULL);
729
priv->visited_pages = priv->visited_pages->next;
730
page_info = (GtkAssistantPage *) page_node->data;
731
g_slist_free_1 (page_node);
733
while (page_info->type == GTK_ASSISTANT_PAGE_PROGRESS ||
734
!gtk_widget_get_visible (page_info->page));
736
set_current_page (assistant, page_info);
740
on_assistant_cancel (GtkWidget *widget,
741
GtkAssistant *assistant)
743
g_signal_emit (assistant, signals [CANCEL], 0, NULL);
747
on_assistant_last (GtkWidget *widget,
748
GtkAssistant *assistant)
750
GtkAssistantPrivate *priv = assistant->priv;
752
while (priv->current_page->type == GTK_ASSISTANT_PAGE_CONTENT &&
753
priv->current_page->complete)
754
compute_next_step (assistant);
758
alternative_button_order (GtkAssistant *assistant)
760
GtkSettings *settings;
764
screen = gtk_widget_get_screen (GTK_WIDGET (assistant));
765
settings = gtk_settings_get_for_screen (screen);
767
g_object_get (settings,
768
"gtk-alternative-button-order", &result,
774
gtk_assistant_init (GtkAssistant *assistant)
776
GtkAssistantPrivate *priv;
778
priv = assistant->priv = GTK_ASSISTANT_GET_PRIVATE (assistant);
780
gtk_container_set_reallocate_redraws (GTK_CONTAINER (assistant), TRUE);
781
gtk_container_set_border_width (GTK_CONTAINER (assistant), 12);
783
gtk_widget_push_composite_child ();
786
priv->header_image = gtk_image_new ();
787
gtk_misc_set_alignment (GTK_MISC (priv->header_image), 1., 0.5);
788
gtk_widget_set_parent (priv->header_image, GTK_WIDGET (assistant));
789
gtk_widget_show (priv->header_image);
792
priv->sidebar_image = gtk_image_new ();
793
gtk_misc_set_alignment (GTK_MISC (priv->sidebar_image), 0., 0.);
794
gtk_widget_set_parent (priv->sidebar_image, GTK_WIDGET (assistant));
795
gtk_widget_show (priv->sidebar_image);
798
priv->action_area = gtk_hbox_new (FALSE, 6);
800
assistant->close = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
801
assistant->apply = gtk_button_new_from_stock (GTK_STOCK_APPLY);
802
assistant->forward = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
803
assistant->back = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
804
assistant->cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
805
assistant->last = gtk_button_new_from_stock (GTK_STOCK_GOTO_LAST);
806
gtk_widget_set_can_default (assistant->close, TRUE);
807
gtk_widget_set_can_default (assistant->apply, TRUE);
808
gtk_widget_set_can_default (assistant->forward, TRUE);
810
priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
811
gtk_size_group_add_widget (priv->size_group, assistant->close);
812
gtk_size_group_add_widget (priv->size_group, assistant->apply);
813
gtk_size_group_add_widget (priv->size_group, assistant->forward);
814
gtk_size_group_add_widget (priv->size_group, assistant->back);
815
gtk_size_group_add_widget (priv->size_group, assistant->cancel);
816
gtk_size_group_add_widget (priv->size_group, assistant->last);
818
if (!alternative_button_order (assistant))
820
gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->apply, FALSE, FALSE, 0);
821
gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->forward, FALSE, FALSE, 0);
822
gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->back, FALSE, FALSE, 0);
823
gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->last, FALSE, FALSE, 0);
824
gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->cancel, FALSE, FALSE, 0);
825
gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->close, FALSE, FALSE, 0);
829
gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->close, FALSE, FALSE, 0);
830
gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->cancel, FALSE, FALSE, 0);
831
gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->apply, FALSE, FALSE, 0);
832
gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->forward, FALSE, FALSE, 0);
833
gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->back, FALSE, FALSE, 0);
834
gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->last, FALSE, FALSE, 0);
837
gtk_widget_set_parent (priv->action_area, GTK_WIDGET (assistant));
838
gtk_widget_show (assistant->forward);
839
gtk_widget_show (assistant->back);
840
gtk_widget_show (assistant->cancel);
841
gtk_widget_show (priv->action_area);
843
gtk_widget_pop_composite_child ();
846
priv->current_page = NULL;
847
priv->visited_pages = NULL;
849
priv->forward_function = default_forward_function;
850
priv->forward_function_data = assistant;
851
priv->forward_data_destroy = NULL;
853
g_signal_connect (G_OBJECT (assistant->close), "clicked",
854
G_CALLBACK (on_assistant_close), assistant);
855
g_signal_connect (G_OBJECT (assistant->apply), "clicked",
856
G_CALLBACK (on_assistant_apply), assistant);
857
g_signal_connect (G_OBJECT (assistant->forward), "clicked",
858
G_CALLBACK (on_assistant_forward), assistant);
859
g_signal_connect (G_OBJECT (assistant->back), "clicked",
860
G_CALLBACK (on_assistant_back), assistant);
861
g_signal_connect (G_OBJECT (assistant->cancel), "clicked",
862
G_CALLBACK (on_assistant_cancel), assistant);
863
g_signal_connect (G_OBJECT (assistant->last), "clicked",
864
G_CALLBACK (on_assistant_last), assistant);
868
gtk_assistant_set_child_property (GtkContainer *container,
876
case CHILD_PROP_PAGE_TYPE:
877
gtk_assistant_set_page_type (GTK_ASSISTANT (container), child,
878
g_value_get_enum (value));
880
case CHILD_PROP_PAGE_TITLE:
881
gtk_assistant_set_page_title (GTK_ASSISTANT (container), child,
882
g_value_get_string (value));
884
case CHILD_PROP_PAGE_HEADER_IMAGE:
885
gtk_assistant_set_page_header_image (GTK_ASSISTANT (container), child,
886
g_value_get_object (value));
888
case CHILD_PROP_PAGE_SIDEBAR_IMAGE:
889
gtk_assistant_set_page_side_image (GTK_ASSISTANT (container), child,
890
g_value_get_object (value));
892
case CHILD_PROP_PAGE_COMPLETE:
893
gtk_assistant_set_page_complete (GTK_ASSISTANT (container), child,
894
g_value_get_boolean (value));
897
GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
903
gtk_assistant_get_child_property (GtkContainer *container,
911
case CHILD_PROP_PAGE_TYPE:
912
g_value_set_enum (value,
913
gtk_assistant_get_page_type (GTK_ASSISTANT (container), child));
915
case CHILD_PROP_PAGE_TITLE:
916
g_value_set_string (value,
917
gtk_assistant_get_page_title (GTK_ASSISTANT (container), child));
919
case CHILD_PROP_PAGE_HEADER_IMAGE:
920
g_value_set_object (value,
921
gtk_assistant_get_page_header_image (GTK_ASSISTANT (container), child));
923
case CHILD_PROP_PAGE_SIDEBAR_IMAGE:
924
g_value_set_object (value,
925
gtk_assistant_get_page_side_image (GTK_ASSISTANT (container), child));
927
case CHILD_PROP_PAGE_COMPLETE:
928
g_value_set_boolean (value,
929
gtk_assistant_get_page_complete (GTK_ASSISTANT (container), child));
932
GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
938
on_page_notify_visibility (GtkWidget *widget,
942
GtkAssistant *assistant = GTK_ASSISTANT (data);
944
/* update buttons state, flow may have changed */
945
if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
946
set_assistant_buttons_state (assistant);
950
remove_page (GtkAssistant *assistant,
953
GtkAssistantPrivate *priv = assistant->priv;
954
GtkAssistantPage *page_info;
957
page_info = element->data;
959
/* If this is the current page, we need to switch away. */
960
if (page_info == priv->current_page)
962
if (!compute_next_step (assistant))
964
/* The best we can do at this point is probably to pick the first
967
page_node = priv->pages;
969
while (page_node && !gtk_widget_get_visible (((GtkAssistantPage *) page_node->data)->page))
970
page_node = page_node->next;
972
if (page_node == element)
973
page_node = page_node->next;
976
priv->current_page = page_node->data;
978
priv->current_page = NULL;
982
priv->pages = g_list_remove_link (priv->pages, element);
983
priv->visited_pages = g_slist_remove_all (priv->visited_pages, page_info);
985
g_signal_handlers_disconnect_by_func (page_info->page, on_page_notify_visibility, assistant);
986
gtk_widget_unparent (page_info->page);
988
if (page_info->header_image)
989
g_object_unref (page_info->header_image);
991
if (page_info->sidebar_image)
992
g_object_unref (page_info->sidebar_image);
994
gtk_widget_destroy (page_info->title);
995
g_slice_free (GtkAssistantPage, page_info);
996
g_list_free_1 (element);
1000
gtk_assistant_destroy (GtkObject *object)
1002
GtkAssistant *assistant = GTK_ASSISTANT (object);
1003
GtkAssistantPrivate *priv = assistant->priv;
1005
if (priv->header_image)
1007
gtk_widget_destroy (priv->header_image);
1008
priv->header_image = NULL;
1011
if (priv->sidebar_image)
1013
gtk_widget_destroy (priv->sidebar_image);
1014
priv->sidebar_image = NULL;
1017
if (priv->action_area)
1019
gtk_widget_destroy (priv->action_area);
1020
priv->action_area = NULL;
1023
if (priv->size_group)
1025
g_object_unref (priv->size_group);
1026
priv->size_group = NULL;
1029
if (priv->forward_function)
1031
if (priv->forward_function_data &&
1032
priv->forward_data_destroy)
1033
priv->forward_data_destroy (priv->forward_function_data);
1035
priv->forward_function = NULL;
1036
priv->forward_function_data = NULL;
1037
priv->forward_data_destroy = NULL;
1040
if (priv->visited_pages)
1042
g_slist_free (priv->visited_pages);
1043
priv->visited_pages = NULL;
1046
/* We set current to NULL so that the remove code doesn't try
1047
* to do anything funny */
1048
priv->current_page = NULL;
1051
remove_page (GTK_ASSISTANT (object), priv->pages);
1053
GTK_OBJECT_CLASS (gtk_assistant_parent_class)->destroy (object);
1057
find_page (GtkAssistant *assistant,
1060
GtkAssistantPrivate *priv = assistant->priv;
1061
GList *child = priv->pages;
1065
GtkAssistantPage *page_info = child->data;
1066
if (page_info->page == page)
1069
child = child->next;
1076
set_title_colors (GtkWidget *assistant,
1077
GtkWidget *title_label)
1081
gtk_widget_ensure_style (assistant);
1082
style = gtk_widget_get_style (assistant);
1084
/* change colors schema, for making the header text visible */
1085
gtk_widget_modify_bg (title_label, GTK_STATE_NORMAL, &style->bg[GTK_STATE_SELECTED]);
1086
gtk_widget_modify_fg (title_label, GTK_STATE_NORMAL, &style->fg[GTK_STATE_SELECTED]);
1090
set_title_font (GtkWidget *assistant,
1091
GtkWidget *title_label)
1093
PangoFontDescription *desc;
1096
desc = pango_font_description_new ();
1097
size = pango_font_description_get_size (assistant->style->font_desc);
1099
pango_font_description_set_weight (desc, PANGO_WEIGHT_ULTRABOLD);
1100
pango_font_description_set_size (desc, size * PANGO_SCALE_XX_LARGE);
1102
gtk_widget_modify_font (title_label, desc);
1103
pango_font_description_free (desc);
1107
gtk_assistant_style_set (GtkWidget *widget,
1108
GtkStyle *old_style)
1110
GtkAssistant *assistant = GTK_ASSISTANT (widget);
1111
GtkAssistantPrivate *priv = assistant->priv;
1118
GtkAssistantPage *page = list->data;
1120
set_title_colors (widget, page->title);
1121
set_title_font (widget, page->title);
1128
gtk_assistant_size_request (GtkWidget *widget,
1129
GtkRequisition *requisition)
1131
GtkAssistant *assistant = GTK_ASSISTANT (widget);
1132
GtkAssistantPrivate *priv = assistant->priv;
1133
GtkRequisition child_requisition;
1134
gint header_padding, content_padding;
1135
gint width, height, header_width, header_height;
1138
gtk_widget_style_get (widget,
1139
"header-padding", &header_padding,
1140
"content-padding", &content_padding,
1143
header_width = header_height = 0;
1148
GtkAssistantPage *page = list->data;
1151
gtk_widget_size_request (page->page, &child_requisition);
1152
width = MAX (width, child_requisition.width);
1153
height = MAX (height, child_requisition.height);
1155
gtk_widget_size_request (page->title, &child_requisition);
1156
w = child_requisition.width;
1157
h = child_requisition.height;
1159
if (page->header_image)
1161
w += gdk_pixbuf_get_width (page->header_image) + HEADER_SPACING;
1162
h = MAX (h, gdk_pixbuf_get_height (page->header_image));
1165
header_width = MAX (header_width, w);
1166
header_height = MAX (header_height, h);
1171
gtk_widget_size_request (priv->sidebar_image, &child_requisition);
1172
width += child_requisition.width;
1173
height = MAX (height, child_requisition.height);
1175
gtk_widget_set_size_request (priv->header_image, header_width, header_height);
1176
gtk_widget_size_request (priv->header_image, &child_requisition);
1177
width = MAX (width, header_width) + 2 * header_padding;
1178
height += header_height + 2 * header_padding;
1180
gtk_widget_size_request (priv->action_area, &child_requisition);
1181
width = MAX (width, child_requisition.width);
1182
height += child_requisition.height + ACTION_AREA_SPACING;
1184
width += GTK_CONTAINER (widget)->border_width * 2 + content_padding * 2;
1185
height += GTK_CONTAINER (widget)->border_width * 2 + content_padding * 2;
1187
requisition->width = width;
1188
requisition->height = height;
1192
gtk_assistant_size_allocate (GtkWidget *widget,
1193
GtkAllocation *allocation)
1195
GtkAssistant *assistant = GTK_ASSISTANT (widget);
1196
GtkAssistantPrivate *priv = assistant->priv;
1197
GtkRequisition header_requisition;
1198
GtkAllocation child_allocation, header_allocation;
1199
gint header_padding, content_padding;
1203
rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1204
pages = priv->pages;
1206
gtk_widget_style_get (widget,
1207
"header-padding", &header_padding,
1208
"content-padding", &content_padding,
1211
widget->allocation = *allocation;
1214
gtk_widget_get_child_requisition (priv->header_image, &header_requisition);
1216
header_allocation.x = GTK_CONTAINER (widget)->border_width + header_padding;
1217
header_allocation.y = GTK_CONTAINER (widget)->border_width + header_padding;
1218
header_allocation.width = allocation->width - 2 * GTK_CONTAINER (widget)->border_width - 2 * header_padding;
1219
header_allocation.height = header_requisition.height;
1221
gtk_widget_size_allocate (priv->header_image, &header_allocation);
1224
child_allocation.x = GTK_CONTAINER (widget)->border_width;
1225
child_allocation.y = allocation->height -
1226
GTK_CONTAINER (widget)->border_width - priv->action_area->requisition.height;
1227
child_allocation.width = allocation->width - 2 * GTK_CONTAINER (widget)->border_width;
1228
child_allocation.height = priv->action_area->requisition.height;
1230
gtk_widget_size_allocate (priv->action_area, &child_allocation);
1234
child_allocation.x = allocation->width -
1235
GTK_CONTAINER (widget)->border_width - priv->sidebar_image->requisition.width;
1237
child_allocation.x = GTK_CONTAINER (widget)->border_width;
1239
child_allocation.y = GTK_CONTAINER (widget)->border_width +
1240
priv->header_image->allocation.height + 2 * header_padding;
1241
child_allocation.width = priv->sidebar_image->requisition.width;
1242
child_allocation.height = allocation->height - 2 * GTK_CONTAINER (widget)->border_width -
1243
priv->header_image->allocation.height - 2 * header_padding - priv->action_area->allocation.height;
1245
gtk_widget_size_allocate (priv->sidebar_image, &child_allocation);
1248
child_allocation.x = GTK_CONTAINER (widget)->border_width + content_padding;
1249
child_allocation.y = GTK_CONTAINER (widget)->border_width +
1250
priv->header_image->allocation.height + 2 * header_padding + content_padding;
1251
child_allocation.width = allocation->width - 2 * GTK_CONTAINER (widget)->border_width - 2 * content_padding;
1252
child_allocation.height = allocation->height - 2 * GTK_CONTAINER (widget)->border_width -
1253
priv->header_image->allocation.height - 2 * header_padding - ACTION_AREA_SPACING - priv->action_area->allocation.height - 2 * content_padding;
1255
if (gtk_widget_get_visible (priv->sidebar_image))
1258
child_allocation.x += priv->sidebar_image->allocation.width;
1260
child_allocation.width -= priv->sidebar_image->allocation.width;
1265
GtkAssistantPage *page = pages->data;
1267
gtk_widget_size_allocate (page->page, &child_allocation);
1268
gtk_widget_size_allocate (page->title, &header_allocation);
1269
pages = pages->next;
1274
gtk_assistant_map (GtkWidget *widget)
1276
GtkAssistant *assistant = GTK_ASSISTANT (widget);
1277
GtkAssistantPrivate *priv = assistant->priv;
1279
GtkAssistantPage *page;
1281
gtk_widget_set_mapped (widget, TRUE);
1283
gtk_widget_map (priv->header_image);
1284
gtk_widget_map (priv->action_area);
1286
if (gtk_widget_get_visible (priv->sidebar_image) &&
1287
!gtk_widget_get_mapped (priv->sidebar_image))
1288
gtk_widget_map (priv->sidebar_image);
1290
/* if there's no default page, pick the first one */
1292
if (!priv->current_page)
1294
page_node = priv->pages;
1296
while (page_node && !gtk_widget_get_visible (((GtkAssistantPage *) page_node->data)->page))
1297
page_node = page_node->next;
1300
page = page_node->data;
1304
gtk_widget_get_visible (page->page) &&
1305
!gtk_widget_get_mapped (page->page))
1306
set_current_page (assistant, page);
1308
GTK_WIDGET_CLASS (gtk_assistant_parent_class)->map (widget);
1312
gtk_assistant_unmap (GtkWidget *widget)
1314
GtkAssistant *assistant = GTK_ASSISTANT (widget);
1315
GtkAssistantPrivate *priv = assistant->priv;
1317
gtk_widget_set_mapped (widget, FALSE);
1319
gtk_widget_unmap (priv->header_image);
1320
gtk_widget_unmap (priv->action_area);
1322
if (gtk_widget_is_drawable (priv->sidebar_image))
1323
gtk_widget_unmap (priv->sidebar_image);
1325
if (priv->current_page &&
1326
gtk_widget_is_drawable (priv->current_page->page))
1327
gtk_widget_unmap (priv->current_page->page);
1329
g_slist_free (priv->visited_pages);
1330
priv->visited_pages = NULL;
1331
priv->current_page = NULL;
1333
GTK_WIDGET_CLASS (gtk_assistant_parent_class)->unmap (widget);
1337
gtk_assistant_delete_event (GtkWidget *widget,
1340
GtkAssistant *assistant = GTK_ASSISTANT (widget);
1341
GtkAssistantPrivate *priv = assistant->priv;
1343
/* Do not allow cancelling in the middle of a progress page */
1344
if (priv->current_page &&
1345
(priv->current_page->type != GTK_ASSISTANT_PAGE_PROGRESS ||
1346
priv->current_page->complete))
1347
g_signal_emit (widget, signals [CANCEL], 0, NULL);
1353
assistant_paint_colored_box (GtkWidget *widget)
1355
GtkAssistant *assistant = GTK_ASSISTANT (widget);
1356
GtkAssistantPrivate *priv = assistant->priv;
1357
gint border_width, header_padding, content_padding;
1359
gint content_x, content_width;
1362
cr = gdk_cairo_create (widget->window);
1363
rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1364
border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1366
gtk_widget_style_get (widget,
1367
"header-padding", &header_padding,
1368
"content-padding", &content_padding,
1372
gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_SELECTED]);
1373
cairo_rectangle (cr,
1376
widget->allocation.width - 2 * border_width,
1377
widget->allocation.height - priv->action_area->allocation.height - 2 * border_width - ACTION_AREA_SPACING);
1381
content_x = content_padding + border_width;
1382
content_width = widget->allocation.width - 2 * content_padding - 2 * border_width;
1384
if (gtk_widget_get_visible (priv->sidebar_image))
1387
content_x += priv->sidebar_image->allocation.width;
1388
content_width -= priv->sidebar_image->allocation.width;
1391
gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_NORMAL]);
1393
cairo_rectangle (cr,
1395
priv->header_image->allocation.height + content_padding + 2 * header_padding + border_width,
1397
widget->allocation.height - 2 * border_width - priv->action_area->allocation.height -
1398
priv->header_image->allocation.height - 2 * content_padding - 2 * header_padding - ACTION_AREA_SPACING);
1405
gtk_assistant_expose (GtkWidget *widget,
1406
GdkEventExpose *event)
1408
GtkAssistant *assistant = GTK_ASSISTANT (widget);
1409
GtkAssistantPrivate *priv = assistant->priv;
1410
GtkContainer *container;
1412
if (gtk_widget_is_drawable (widget))
1414
container = GTK_CONTAINER (widget);
1416
assistant_paint_colored_box (widget);
1418
gtk_container_propagate_expose (container, priv->header_image, event);
1419
gtk_container_propagate_expose (container, priv->sidebar_image, event);
1420
gtk_container_propagate_expose (container, priv->action_area, event);
1422
if (priv->current_page)
1424
gtk_container_propagate_expose (container, priv->current_page->page, event);
1425
gtk_container_propagate_expose (container, priv->current_page->title, event);
1433
gtk_assistant_focus (GtkWidget *widget,
1434
GtkDirectionType direction)
1436
GtkAssistantPrivate *priv;
1437
GtkContainer *container;
1439
container = GTK_CONTAINER (widget);
1440
priv = GTK_ASSISTANT (widget)->priv;
1442
/* we only have to care about 2 widgets, action area and the current page */
1443
if (container->focus_child == priv->action_area)
1445
if (!gtk_widget_child_focus (priv->action_area, direction) &&
1446
(priv->current_page == NULL ||
1447
!gtk_widget_child_focus (priv->current_page->page, direction)))
1449
/* if we're leaving the action area and the current page hasn't
1450
any focusable widget, clear focus and go back to the action area */
1451
gtk_container_set_focus_child (GTK_CONTAINER (priv->action_area), NULL);
1452
gtk_widget_child_focus (priv->action_area, direction);
1457
if ((priv->current_page == NULL ||
1458
!gtk_widget_child_focus (priv->current_page->page, direction)) &&
1459
!gtk_widget_child_focus (priv->action_area, direction))
1461
/* if we're leaving the current page and there isn't nothing focusable
1462
in the action area, try to clear focus and go back to the page */
1463
gtk_window_set_focus (GTK_WINDOW (widget), NULL);
1464
if (priv->current_page != NULL)
1465
gtk_widget_child_focus (priv->current_page->page, direction);
1473
gtk_assistant_add (GtkContainer *container,
1476
gtk_assistant_append_page (GTK_ASSISTANT (container), page);
1480
gtk_assistant_remove (GtkContainer *container,
1483
GtkAssistant *assistant = (GtkAssistant*) container;
1486
element = find_page (assistant, page);
1490
remove_page (assistant, element);
1491
gtk_widget_queue_resize ((GtkWidget *) container);
1496
gtk_assistant_forall (GtkContainer *container,
1497
gboolean include_internals,
1498
GtkCallback callback,
1499
gpointer callback_data)
1501
GtkAssistant *assistant = (GtkAssistant*) container;
1502
GtkAssistantPrivate *priv = assistant->priv;
1505
if (include_internals)
1507
(*callback) (priv->header_image, callback_data);
1508
(*callback) (priv->sidebar_image, callback_data);
1509
(*callback) (priv->action_area, callback_data);
1512
pages = priv->pages;
1516
GtkAssistantPage *page = (GtkAssistantPage *) pages->data;
1518
(*callback) (page->page, callback_data);
1520
if (include_internals)
1521
(*callback) (page->title, callback_data);
1523
pages = pages->next;
1528
* gtk_assistant_new:
1530
* Creates a new #GtkAssistant.
1532
* Return value: a newly created #GtkAssistant
1537
gtk_assistant_new (void)
1539
GtkWidget *assistant;
1541
assistant = g_object_new (GTK_TYPE_ASSISTANT, NULL);
1547
* gtk_assistant_get_current_page:
1548
* @assistant: a #GtkAssistant
1550
* Returns the page number of the current page
1552
* Return value: The index (starting from 0) of the current page in
1553
* the @assistant, if the @assistant has no pages, -1 will be returned
1558
gtk_assistant_get_current_page (GtkAssistant *assistant)
1560
GtkAssistantPrivate *priv;
1562
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), -1);
1564
priv = assistant->priv;
1566
if (!priv->pages || !priv->current_page)
1569
return g_list_index (priv->pages, priv->current_page);
1573
* gtk_assistant_set_current_page:
1574
* @assistant: a #GtkAssistant
1575
* @page_num: index of the page to switch to, starting from 0.
1576
* If negative, the last page will be used. If greater
1577
* than the number of pages in the @assistant, nothing
1580
* Switches the page to @page_num. Note that this will only be necessary
1581
* in custom buttons, as the @assistant flow can be set with
1582
* gtk_assistant_set_forward_page_func().
1587
gtk_assistant_set_current_page (GtkAssistant *assistant,
1590
GtkAssistantPrivate *priv;
1591
GtkAssistantPage *page;
1593
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1595
priv = assistant->priv;
1598
page = (GtkAssistantPage *) g_list_nth_data (priv->pages, page_num);
1600
page = (GtkAssistantPage *) g_list_last (priv->pages)->data;
1602
g_return_if_fail (page != NULL);
1604
if (priv->current_page == page)
1607
/* only add the page to the visited list if the
1608
* assistant is mapped, if not, just use it as an
1609
* initial page setting, for the cases where the
1610
* initial page is != to 0
1612
if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
1613
priv->visited_pages = g_slist_prepend (priv->visited_pages,
1614
priv->current_page);
1616
set_current_page (assistant, page);
1620
* gtk_assistant_get_n_pages:
1621
* @assistant: a #GtkAssistant
1623
* Returns the number of pages in the @assistant
1625
* Return value: The number of pages in the @assistant.
1630
gtk_assistant_get_n_pages (GtkAssistant *assistant)
1632
GtkAssistantPrivate *priv;
1634
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
1636
priv = assistant->priv;
1638
return g_list_length (priv->pages);
1642
* gtk_assistant_get_nth_page:
1643
* @assistant: a #GtkAssistant
1644
* @page_num: The index of a page in the @assistant, or -1 to get the last page;
1646
* Returns the child widget contained in page number @page_num.
1648
* Return value: (transfer none): The child widget, or %NULL
1649
* if @page_num is out of bounds.
1654
gtk_assistant_get_nth_page (GtkAssistant *assistant,
1657
GtkAssistantPrivate *priv;
1658
GtkAssistantPage *page;
1661
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
1662
g_return_val_if_fail (page_num >= -1, NULL);
1664
priv = assistant->priv;
1667
elem = g_list_last (priv->pages);
1669
elem = g_list_nth (priv->pages, page_num);
1674
page = (GtkAssistantPage *) elem->data;
1680
* gtk_assistant_prepend_page:
1681
* @assistant: a #GtkAssistant
1682
* @page: a #GtkWidget
1684
* Prepends a page to the @assistant.
1686
* Return value: the index (starting at 0) of the inserted page
1691
gtk_assistant_prepend_page (GtkAssistant *assistant,
1694
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
1695
g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
1697
return gtk_assistant_insert_page (assistant, page, 0);
1701
* gtk_assistant_append_page:
1702
* @assistant: a #GtkAssistant
1703
* @page: a #GtkWidget
1705
* Appends a page to the @assistant.
1707
* Return value: the index (starting at 0) of the inserted page
1712
gtk_assistant_append_page (GtkAssistant *assistant,
1715
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
1716
g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
1718
return gtk_assistant_insert_page (assistant, page, -1);
1722
* gtk_assistant_insert_page:
1723
* @assistant: a #GtkAssistant
1724
* @page: a #GtkWidget
1725
* @position: the index (starting at 0) at which to insert the page,
1726
* or -1 to append the page to the @assistant
1728
* Inserts a page in the @assistant at a given position.
1730
* Return value: the index (starting from 0) of the inserted page
1735
gtk_assistant_insert_page (GtkAssistant *assistant,
1739
GtkAssistantPrivate *priv;
1740
GtkAssistantPage *page_info;
1743
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
1744
g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
1745
g_return_val_if_fail (page->parent == NULL, 0);
1746
g_return_val_if_fail (!gtk_widget_is_toplevel (page), 0);
1748
priv = assistant->priv;
1750
page_info = g_slice_new0 (GtkAssistantPage);
1751
page_info->page = page;
1752
page_info->title = gtk_label_new (NULL);
1754
g_signal_connect (G_OBJECT (page), "notify::visible",
1755
G_CALLBACK (on_page_notify_visibility), assistant);
1757
gtk_misc_set_alignment (GTK_MISC (page_info->title), 0.,0.5);
1758
set_title_colors (GTK_WIDGET (assistant), page_info->title);
1759
set_title_font (GTK_WIDGET (assistant), page_info->title);
1760
gtk_widget_show (page_info->title);
1762
n_pages = g_list_length (priv->pages);
1764
if (position < 0 || position > n_pages)
1767
priv->pages = g_list_insert (priv->pages, page_info, position);
1769
gtk_widget_set_child_visible (page_info->page, FALSE);
1770
gtk_widget_set_parent (page_info->page, GTK_WIDGET (assistant));
1771
gtk_widget_set_parent (page_info->title, GTK_WIDGET (assistant));
1773
if (gtk_widget_get_realized (GTK_WIDGET (assistant)))
1775
gtk_widget_realize (page_info->page);
1776
gtk_widget_realize (page_info->title);
1779
gtk_widget_queue_resize (GTK_WIDGET (assistant));
1785
* gtk_assistant_set_forward_page_func:
1786
* @assistant: a #GtkAssistant
1787
* @page_func: (allow-none): the #GtkAssistantPageFunc, or %NULL to use the default one
1788
* @data: user data for @page_func
1789
* @destroy: destroy notifier for @data
1791
* Sets the page forwarding function to be @page_func, this function will
1792
* be used to determine what will be the next page when the user presses
1793
* the forward button. Setting @page_func to %NULL will make the assistant
1794
* to use the default forward function, which just goes to the next visible
1800
gtk_assistant_set_forward_page_func (GtkAssistant *assistant,
1801
GtkAssistantPageFunc page_func,
1803
GDestroyNotify destroy)
1805
GtkAssistantPrivate *priv;
1807
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1809
priv = assistant->priv;
1811
if (priv->forward_data_destroy &&
1812
priv->forward_function_data)
1813
(*priv->forward_data_destroy) (priv->forward_function_data);
1817
priv->forward_function = page_func;
1818
priv->forward_function_data = data;
1819
priv->forward_data_destroy = destroy;
1823
priv->forward_function = default_forward_function;
1824
priv->forward_function_data = assistant;
1825
priv->forward_data_destroy = NULL;
1828
/* Page flow has possibly changed, so the
1829
buttons state might need to change too */
1830
set_assistant_buttons_state (assistant);
1834
* gtk_assistant_add_action_widget:
1835
* @assistant: a #GtkAssistant
1836
* @child: a #GtkWidget
1838
* Adds a widget to the action area of a #GtkAssistant.
1843
gtk_assistant_add_action_widget (GtkAssistant *assistant,
1846
GtkAssistantPrivate *priv;
1848
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1849
g_return_if_fail (GTK_IS_WIDGET (child));
1851
priv = assistant->priv;
1853
if (GTK_IS_BUTTON (child))
1854
gtk_size_group_add_widget (priv->size_group, child);
1856
gtk_box_pack_end (GTK_BOX (priv->action_area), child, FALSE, FALSE, 0);
1860
* gtk_assistant_remove_action_widget:
1861
* @assistant: a #GtkAssistant
1862
* @child: a #GtkWidget
1864
* Removes a widget from the action area of a #GtkAssistant.
1869
gtk_assistant_remove_action_widget (GtkAssistant *assistant,
1872
GtkAssistantPrivate *priv;
1874
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1875
g_return_if_fail (GTK_IS_WIDGET (child));
1877
priv = assistant->priv;
1879
if (GTK_IS_BUTTON (child))
1880
gtk_size_group_remove_widget (priv->size_group, child);
1882
gtk_container_remove (GTK_CONTAINER (priv->action_area), child);
1886
* gtk_assistant_set_page_title:
1887
* @assistant: a #GtkAssistant
1888
* @page: a page of @assistant
1889
* @title: the new title for @page
1891
* Sets a title for @page. The title is displayed in the header
1892
* area of the assistant when @page is the current page.
1897
gtk_assistant_set_page_title (GtkAssistant *assistant,
1901
GtkAssistantPage *page_info;
1904
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1905
g_return_if_fail (GTK_IS_WIDGET (page));
1907
child = find_page (assistant, page);
1909
g_return_if_fail (child != NULL);
1911
page_info = (GtkAssistantPage*) child->data;
1913
gtk_label_set_text ((GtkLabel*) page_info->title, title);
1914
gtk_widget_queue_resize (GTK_WIDGET (assistant));
1915
gtk_widget_child_notify (page, "title");
1919
* gtk_assistant_get_page_title:
1920
* @assistant: a #GtkAssistant
1921
* @page: a page of @assistant
1923
* Gets the title for @page.
1925
* Return value: the title for @page.
1930
gtk_assistant_get_page_title (GtkAssistant *assistant,
1933
GtkAssistantPage *page_info;
1936
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
1937
g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
1939
child = find_page (assistant, page);
1941
g_return_val_if_fail (child != NULL, NULL);
1943
page_info = (GtkAssistantPage*) child->data;
1945
return gtk_label_get_text ((GtkLabel*) page_info->title);
1949
* gtk_assistant_set_page_type:
1950
* @assistant: a #GtkAssistant
1951
* @page: a page of @assistant
1952
* @type: the new type for @page
1954
* Sets the page type for @page. The page type determines the page
1955
* behavior in the @assistant.
1960
gtk_assistant_set_page_type (GtkAssistant *assistant,
1962
GtkAssistantPageType type)
1964
GtkAssistantPrivate *priv;
1965
GtkAssistantPage *page_info;
1968
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
1969
g_return_if_fail (GTK_IS_WIDGET (page));
1971
priv = assistant->priv;
1972
child = find_page (assistant, page);
1974
g_return_if_fail (child != NULL);
1976
page_info = (GtkAssistantPage*) child->data;
1978
if (type != page_info->type)
1980
page_info->type = type;
1982
/* backwards compatibility to the era before fixing bug 604289 */
1983
if (type == GTK_ASSISTANT_PAGE_SUMMARY && !page_info->complete_set)
1985
gtk_assistant_set_page_complete (assistant, page, TRUE);
1986
page_info->complete_set = FALSE;
1989
/* Always set buttons state, a change in a future page
1990
might change current page buttons */
1991
set_assistant_buttons_state (assistant);
1993
gtk_widget_child_notify (page, "page-type");
1998
* gtk_assistant_get_page_type:
1999
* @assistant: a #GtkAssistant
2000
* @page: a page of @assistant
2002
* Gets the page type of @page.
2004
* Return value: the page type of @page.
2008
GtkAssistantPageType
2009
gtk_assistant_get_page_type (GtkAssistant *assistant,
2012
GtkAssistantPage *page_info;
2015
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), GTK_ASSISTANT_PAGE_CONTENT);
2016
g_return_val_if_fail (GTK_IS_WIDGET (page), GTK_ASSISTANT_PAGE_CONTENT);
2018
child = find_page (assistant, page);
2020
g_return_val_if_fail (child != NULL, GTK_ASSISTANT_PAGE_CONTENT);
2022
page_info = (GtkAssistantPage*) child->data;
2024
return page_info->type;
2028
* gtk_assistant_set_page_header_image:
2029
* @assistant: a #GtkAssistant
2030
* @page: a page of @assistant
2031
* @pixbuf: (allow-none): the new header image @page
2033
* Sets a header image for @page. This image is displayed in the header
2034
* area of the assistant when @page is the current page.
2039
gtk_assistant_set_page_header_image (GtkAssistant *assistant,
2043
GtkAssistantPrivate *priv;
2044
GtkAssistantPage *page_info;
2047
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
2048
g_return_if_fail (GTK_IS_WIDGET (page));
2049
g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
2051
priv = assistant->priv;
2052
child = find_page (assistant, page);
2054
g_return_if_fail (child != NULL);
2056
page_info = (GtkAssistantPage*) child->data;
2058
if (pixbuf != page_info->header_image)
2060
if (page_info->header_image)
2062
g_object_unref (page_info->header_image);
2063
page_info->header_image = NULL;
2067
page_info->header_image = g_object_ref (pixbuf);
2069
if (page_info == priv->current_page)
2070
set_assistant_header_image (assistant);
2072
gtk_widget_child_notify (page, "header-image");
2077
* gtk_assistant_get_page_header_image:
2078
* @assistant: a #GtkAssistant
2079
* @page: a page of @assistant
2081
* Gets the header image for @page.
2083
* Return value: (transfer none): the header image for @page, or %NULL
2084
* if there's no header image for the page.
2089
gtk_assistant_get_page_header_image (GtkAssistant *assistant,
2092
GtkAssistantPage *page_info;
2095
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
2096
g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
2098
child = find_page (assistant, page);
2100
g_return_val_if_fail (child != NULL, NULL);
2102
page_info = (GtkAssistantPage*) child->data;
2104
return page_info->header_image;
2108
* gtk_assistant_set_page_side_image:
2109
* @assistant: a #GtkAssistant
2110
* @page: a page of @assistant
2111
* @pixbuf: (allow-none): the new header image @page
2113
* Sets a header image for @page. This image is displayed in the side
2114
* area of the assistant when @page is the current page.
2119
gtk_assistant_set_page_side_image (GtkAssistant *assistant,
2123
GtkAssistantPrivate *priv;
2124
GtkAssistantPage *page_info;
2127
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
2128
g_return_if_fail (GTK_IS_WIDGET (page));
2129
g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
2131
priv = assistant->priv;
2132
child = find_page (assistant, page);
2134
g_return_if_fail (child != NULL);
2136
page_info = (GtkAssistantPage*) child->data;
2138
if (pixbuf != page_info->sidebar_image)
2140
if (page_info->sidebar_image)
2142
g_object_unref (page_info->sidebar_image);
2143
page_info->sidebar_image = NULL;
2147
page_info->sidebar_image = g_object_ref (pixbuf);
2149
if (page_info == priv->current_page)
2150
set_assistant_sidebar_image (assistant);
2152
gtk_widget_child_notify (page, "sidebar-image");
2157
* gtk_assistant_get_page_side_image:
2158
* @assistant: a #GtkAssistant
2159
* @page: a page of @assistant
2161
* Gets the header image for @page.
2163
* Return value: (transfer none): the side image for @page, or %NULL
2164
* if there's no side image for the page.
2169
gtk_assistant_get_page_side_image (GtkAssistant *assistant,
2172
GtkAssistantPage *page_info;
2175
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
2176
g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
2178
child = find_page (assistant, page);
2180
g_return_val_if_fail (child != NULL, NULL);
2182
page_info = (GtkAssistantPage*) child->data;
2184
return page_info->sidebar_image;
2188
* gtk_assistant_set_page_complete:
2189
* @assistant: a #GtkAssistant
2190
* @page: a page of @assistant
2191
* @complete: the completeness status of the page
2193
* Sets whether @page contents are complete. This will make
2194
* @assistant update the buttons state to be able to continue the task.
2199
gtk_assistant_set_page_complete (GtkAssistant *assistant,
2203
GtkAssistantPrivate *priv;
2204
GtkAssistantPage *page_info;
2207
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
2208
g_return_if_fail (GTK_IS_WIDGET (page));
2210
priv = assistant->priv;
2211
child = find_page (assistant, page);
2213
g_return_if_fail (child != NULL);
2215
page_info = (GtkAssistantPage*) child->data;
2217
if (complete != page_info->complete)
2219
page_info->complete = complete;
2220
page_info->complete_set = TRUE;
2222
/* Always set buttons state, a change in a future page
2223
might change current page buttons */
2224
set_assistant_buttons_state (assistant);
2226
gtk_widget_child_notify (page, "complete");
2231
* gtk_assistant_get_page_complete:
2232
* @assistant: a #GtkAssistant
2233
* @page: a page of @assistant
2235
* Gets whether @page is complete.
2237
* Return value: %TRUE if @page is complete.
2242
gtk_assistant_get_page_complete (GtkAssistant *assistant,
2245
GtkAssistantPage *page_info;
2248
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), FALSE);
2249
g_return_val_if_fail (GTK_IS_WIDGET (page), FALSE);
2251
child = find_page (assistant, page);
2253
g_return_val_if_fail (child != NULL, FALSE);
2255
page_info = (GtkAssistantPage*) child->data;
2257
return page_info->complete;
2261
* gtk_assistant_update_buttons_state:
2262
* @assistant: a #GtkAssistant
2264
* Forces @assistant to recompute the buttons state.
2266
* GTK+ automatically takes care of this in most situations,
2267
* e.g. when the user goes to a different page, or when the
2268
* visibility or completeness of a page changes.
2270
* One situation where it can be necessary to call this
2271
* function is when changing a value on the current page
2272
* affects the future page flow of the assistant.
2277
gtk_assistant_update_buttons_state (GtkAssistant *assistant)
2279
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
2281
set_assistant_buttons_state (assistant);
2285
* gtk_assistant_commit:
2286
* @assistant: a #GtkAssistant
2288
* Erases the visited page history so the back button is not
2289
* shown on the current page, and removes the cancel button
2290
* from subsequent pages.
2292
* Use this when the information provided up to the current
2293
* page is hereafter deemed permanent and cannot be modified
2294
* or undone. For example, showing a progress page to track
2295
* a long-running, unreversible operation after the user has
2296
* clicked apply on a confirmation page.
2301
gtk_assistant_commit (GtkAssistant *assistant)
2303
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
2305
g_slist_free (assistant->priv->visited_pages);
2306
assistant->priv->visited_pages = NULL;
2308
assistant->priv->committed = TRUE;
2310
set_assistant_buttons_state (assistant);
2315
/* accessible implementation */
2318
gtk_assistant_accessible_get_n_children (AtkObject *accessible)
2320
GtkAssistant *assistant;
2323
widget = GTK_ACCESSIBLE (accessible)->widget;
2328
assistant = GTK_ASSISTANT (widget);
2330
return g_list_length (assistant->priv->pages) + 1;
2335
gtk_assistant_accessible_ref_child (AtkObject *accessible,
2338
GtkAssistant *assistant;
2339
GtkAssistantPrivate *priv;
2340
GtkWidget *widget, *child;
2345
widget = GTK_ACCESSIBLE (accessible)->widget;
2349
assistant = GTK_ASSISTANT (widget);
2350
priv = assistant->priv;
2351
n_pages = g_list_length (priv->pages);
2355
else if (index < n_pages)
2357
GtkAssistantPage *page = g_list_nth_data (priv->pages, index);
2360
title = gtk_assistant_get_page_title (assistant, child);
2362
else if (index == n_pages)
2364
child = priv->action_area;
2370
obj = gtk_widget_get_accessible (child);
2373
atk_object_set_name (obj, title);
2375
return g_object_ref (obj);
2379
gtk_assistant_accessible_class_init (AtkObjectClass *class)
2381
class->get_n_children = gtk_assistant_accessible_get_n_children;
2382
class->ref_child = gtk_assistant_accessible_ref_child;
2386
gtk_assistant_accessible_get_type (void)
2388
static GType type = 0;
2393
* Figure out the size of the class and instance
2394
* we are deriving from
2396
AtkObjectFactory *factory;
2399
GType derived_atk_type;
2401
derived_type = g_type_parent (GTK_TYPE_ASSISTANT);
2402
factory = atk_registry_get_factory (atk_get_default_registry (),
2404
derived_atk_type = atk_object_factory_get_accessible_type (factory);
2405
g_type_query (derived_atk_type, &query);
2407
type = g_type_register_static_simple (derived_atk_type,
2408
I_("GtkAssistantAccessible"),
2410
(GClassInitFunc) gtk_assistant_accessible_class_init,
2411
query.instance_size,
2419
gtk_assistant_accessible_new (GObject *obj)
2421
AtkObject *accessible;
2423
g_return_val_if_fail (GTK_IS_ASSISTANT (obj), NULL);
2425
accessible = g_object_new (gtk_assistant_accessible_get_type (), NULL);
2426
atk_object_initialize (accessible, obj);
2432
gtk_assistant_accessible_factory_get_accessible_type (void)
2434
return gtk_assistant_accessible_get_type ();
2438
gtk_assistant_accessible_factory_create_accessible (GObject *obj)
2440
return gtk_assistant_accessible_new (obj);
2444
gtk_assistant_accessible_factory_class_init (AtkObjectFactoryClass *class)
2446
class->create_accessible = gtk_assistant_accessible_factory_create_accessible;
2447
class->get_accessible_type = gtk_assistant_accessible_factory_get_accessible_type;
2451
gtk_assistant_accessible_factory_get_type (void)
2453
static GType type = 0;
2457
type = g_type_register_static_simple (ATK_TYPE_OBJECT_FACTORY,
2458
I_("GtkAssistantAccessibleFactory"),
2459
sizeof (AtkObjectFactoryClass),
2460
(GClassInitFunc) gtk_assistant_accessible_factory_class_init,
2461
sizeof (AtkObjectFactory),
2469
gtk_assistant_get_accessible (GtkWidget *widget)
2471
static gboolean first_time = TRUE;
2475
AtkObjectFactory *factory;
2476
AtkRegistry *registry;
2478
GType derived_atk_type;
2481
* Figure out whether accessibility is enabled by looking at the
2482
* type of the accessible object which would be created for
2483
* the parent type of GtkAssistant.
2485
derived_type = g_type_parent (GTK_TYPE_ASSISTANT);
2487
registry = atk_get_default_registry ();
2488
factory = atk_registry_get_factory (registry,
2490
derived_atk_type = atk_object_factory_get_accessible_type (factory);
2491
if (g_type_is_a (derived_atk_type, GTK_TYPE_ACCESSIBLE))
2493
atk_registry_set_factory_type (registry,
2495
gtk_assistant_accessible_factory_get_type ());
2500
return GTK_WIDGET_CLASS (gtk_assistant_parent_class)->get_accessible (widget);
2504
static GtkBuildableIface *parent_buildable_iface;
2507
gtk_assistant_buildable_interface_init (GtkBuildableIface *iface)
2509
parent_buildable_iface = g_type_interface_peek_parent (iface);
2510
iface->get_internal_child = gtk_assistant_buildable_get_internal_child;
2511
iface->custom_tag_start = gtk_assistant_buildable_custom_tag_start;
2512
iface->custom_finished = gtk_assistant_buildable_custom_finished;
2516
gtk_assistant_buildable_get_internal_child (GtkBuildable *buildable,
2517
GtkBuilder *builder,
2518
const gchar *childname)
2520
if (strcmp (childname, "action_area") == 0)
2521
return G_OBJECT (GTK_ASSISTANT (buildable)->priv->action_area);
2523
return parent_buildable_iface->get_internal_child (buildable,
2529
gtk_assistant_buildable_custom_tag_start (GtkBuildable *buildable,
2530
GtkBuilder *builder,
2532
const gchar *tagname,
2533
GMarkupParser *parser,
2536
return parent_buildable_iface->custom_tag_start (buildable, builder, child,
2537
tagname, parser, data);
2541
gtk_assistant_buildable_custom_finished (GtkBuildable *buildable,
2542
GtkBuilder *builder,
2544
const gchar *tagname,
2547
parent_buildable_iface->custom_finished (buildable, builder, child,
2548
tagname, user_data);
2552
#define __GTK_ASSISTANT_C__
2553
#include "gtkaliasdef.c"