~ubuntu-branches/ubuntu/precise/gtk+2.0/precise-proposed

« back to all changes in this revision

Viewing changes to .pc/044_grips.patch/gtk/gtkassistant.c

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher
  • Date: 2012-02-23 22:24:09 UTC
  • Revision ID: package-import@ubuntu.com-20120223222409-p6e5zvz25r0q8cut
Tags: 2.24.10-0ubuntu4
* debian/patches/044_grips.patch:
  - revert dropping, there is a public api in there and we need to fix the
    rdepends before dropping it

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * GTK - The GIMP Toolkit
 
3
 * Copyright (C) 1999  Red Hat, Inc.
 
4
 * Copyright (C) 2002  Anders Carlsson <andersca@gnu.org>
 
5
 * Copyright (C) 2003  Matthias Clasen <mclasen@redhat.com>
 
6
 * Copyright (C) 2005  Carlos Garnacho Parro <carlosg@gnome.org>
 
7
 *
 
8
 * All rights reserved.
 
9
 *
 
10
 * This library is free software; you can redistribute it and/or
 
11
 * modify it under the terms of the GNU Lesser General Public
 
12
 * License as published by the Free Software Foundation; either
 
13
 * version 2 of the License, or (at your option) any later version.
 
14
 *
 
15
 * This library is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
 * Lesser General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU Lesser General Public
 
21
 * License along with this library; if not, write to the
 
22
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
23
 * Boston, MA 02111-1307, USA.
 
24
 */
 
25
 
 
26
/**
 
27
 * SECTION:gtkassistant
 
28
 * @Short_description: A widget used to guide users through multi-step operations
 
29
 * @Title: GtkAssistant
 
30
 *
 
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.
 
34
 *
 
35
 * <refsect2 id="GtkAssistant-BUILDER-UI">
 
36
 * <title>GtkAssistant as GtkBuildable</title>
 
37
 * <para>
 
38
 * The GtkAssistant implementation of the GtkBuildable interface exposes the
 
39
 * @action_area as internal children with the name "action_area".
 
40
 *
 
41
 * To add pages to an assistant in GtkBuilder, simply add it as a
 
42
 * &lt;child&gt; to the GtkAssistant object, and set its child properties
 
43
 * as necessary.
 
44
 * </para>
 
45
 * </refsect2>
 
46
 */
 
47
 
 
48
#include "config.h"
 
49
 
 
50
#include <atk/atk.h>
 
51
 
 
52
#include "gtkassistant.h"
 
53
 
 
54
#include "gtkaccessible.h"
 
55
#include "gtkbutton.h"
 
56
#include "gtkhbox.h"
 
57
#include "gtkhbbox.h"
 
58
#include "gtkimage.h"
 
59
#include "gtklabel.h"
 
60
#include "gtksizegroup.h"
 
61
#include "gtkstock.h"
 
62
 
 
63
#include "gtkintl.h"
 
64
#include "gtkprivate.h"
 
65
#include "gtkbuildable.h"
 
66
 
 
67
#include "gtkalias.h"
 
68
 
 
69
#define GTK_ASSISTANT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_ASSISTANT, GtkAssistantPrivate))
 
70
 
 
71
#define HEADER_SPACING 12
 
72
#define ACTION_AREA_SPACING 12
 
73
 
 
74
typedef struct _GtkAssistantPage GtkAssistantPage;
 
75
 
 
76
struct _GtkAssistantPage
 
77
{
 
78
  GtkWidget *page;
 
79
  GtkAssistantPageType type;
 
80
  guint      complete : 1;
 
81
  guint      complete_set : 1;
 
82
 
 
83
  GtkWidget *title;
 
84
  GdkPixbuf *header_image;
 
85
  GdkPixbuf *sidebar_image;
 
86
};
 
87
 
 
88
struct _GtkAssistantPrivate
 
89
{
 
90
  GtkWidget *header_image;
 
91
  GtkWidget *sidebar_image;
 
92
 
 
93
  GtkWidget *action_area;
 
94
 
 
95
  GList     *pages;
 
96
 
 
97
  GtkAssistantPage *current_page;
 
98
 
 
99
  GSList    *visited_pages;
 
100
 
 
101
  GtkSizeGroup *size_group;
 
102
 
 
103
  GtkAssistantPageFunc forward_function;
 
104
  gpointer forward_function_data;
 
105
  GDestroyNotify forward_data_destroy;
 
106
 
 
107
  guint committed : 1;
 
108
};
 
109
 
 
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,
 
122
                                                  GdkEventAny       *event);
 
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,
 
128
                                                  GtkWidget         *page);
 
129
static void     gtk_assistant_remove             (GtkContainer      *container,
 
130
                                                  GtkWidget         *page);
 
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,
 
136
                                                  GtkWidget         *child,
 
137
                                                  guint              property_id,
 
138
                                                  const GValue      *value,
 
139
                                                  GParamSpec        *pspec);
 
140
static void     gtk_assistant_get_child_property (GtkContainer      *container,
 
141
                                                  GtkWidget         *child,
 
142
                                                  guint              property_id,
 
143
                                                  GValue            *value,
 
144
                                                  GParamSpec        *pspec);
 
145
 
 
146
static AtkObject *gtk_assistant_get_accessible   (GtkWidget         *widget);
 
147
 
 
148
static void       gtk_assistant_buildable_interface_init     (GtkBuildableIface *iface);
 
149
static GObject   *gtk_assistant_buildable_get_internal_child (GtkBuildable  *buildable,
 
150
                                                              GtkBuilder    *builder,
 
151
                                                              const gchar   *childname);
 
152
static gboolean   gtk_assistant_buildable_custom_tag_start   (GtkBuildable  *buildable,
 
153
                                                              GtkBuilder    *builder,
 
154
                                                              GObject       *child,
 
155
                                                              const gchar   *tagname,
 
156
                                                              GMarkupParser *parser,
 
157
                                                              gpointer      *data);
 
158
static void       gtk_assistant_buildable_custom_finished    (GtkBuildable  *buildable,
 
159
                                                              GtkBuilder    *builder,
 
160
                                                              GObject       *child,
 
161
                                                              const gchar   *tagname,
 
162
                                                              gpointer       user_data);
 
163
 
 
164
static GList*     find_page                                  (GtkAssistant  *assistant,
 
165
                                                              GtkWidget     *page);
 
166
 
 
167
enum
 
168
{
 
169
  CHILD_PROP_0,
 
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
 
175
};
 
176
 
 
177
enum
 
178
{
 
179
  CANCEL,
 
180
  PREPARE,
 
181
  APPLY,
 
182
  CLOSE,
 
183
  LAST_SIGNAL
 
184
};
 
185
 
 
186
static guint signals [LAST_SIGNAL] = { 0 };
 
187
 
 
188
 
 
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))
 
192
 
 
193
 
 
194
static void
 
195
gtk_assistant_class_init (GtkAssistantClass *class)
 
196
{
 
197
  GObjectClass *gobject_class;
 
198
  GtkObjectClass *object_class;
 
199
  GtkWidgetClass *widget_class;
 
200
  GtkContainerClass *container_class;
 
201
 
 
202
  gobject_class   = (GObjectClass *) class;
 
203
  object_class    = (GtkObjectClass *) class;
 
204
  widget_class    = (GtkWidgetClass *) class;
 
205
  container_class = (GtkContainerClass *) class;
 
206
 
 
207
  object_class->destroy = gtk_assistant_destroy;
 
208
 
 
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;
 
218
 
 
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;
 
224
 
 
225
  /**
 
226
   * GtkAssistant::cancel:
 
227
   * @assistant: the #GtkAssistant
 
228
   *
 
229
   * The ::cancel signal is emitted when then the cancel button is clicked.
 
230
   *
 
231
   * Since: 2.10
 
232
   */
 
233
  signals[CANCEL] =
 
234
    g_signal_new (I_("cancel"),
 
235
                  G_TYPE_FROM_CLASS (gobject_class),
 
236
                  G_SIGNAL_RUN_LAST,
 
237
                  G_STRUCT_OFFSET (GtkAssistantClass, cancel),
 
238
                  NULL, NULL,
 
239
                  g_cclosure_marshal_VOID__VOID,
 
240
                  G_TYPE_NONE, 0);
 
241
    
 
242
  /**
 
243
   * GtkAssistant::prepare:
 
244
   * @assistant: the #GtkAssistant
 
245
   * @page: the current page
 
246
   *
 
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.
 
250
   *
 
251
   * Since: 2.10
 
252
   */
 
253
  signals[PREPARE] =
 
254
    g_signal_new (I_("prepare"),
 
255
                  G_TYPE_FROM_CLASS (gobject_class),
 
256
                  G_SIGNAL_RUN_LAST,
 
257
                  G_STRUCT_OFFSET (GtkAssistantClass, prepare),
 
258
                  NULL, NULL,
 
259
                  g_cclosure_marshal_VOID__OBJECT,
 
260
                  G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
 
261
 
 
262
  /**
 
263
   * GtkAssistant::apply:
 
264
   * @assistant: the #GtkAssistant
 
265
   *
 
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.
 
269
   *
 
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.
 
275
   *
 
276
   * Since: 2.10
 
277
   */
 
278
  signals[APPLY] =
 
279
    g_signal_new (I_("apply"),
 
280
                  G_TYPE_FROM_CLASS (gobject_class),
 
281
                  G_SIGNAL_RUN_LAST,
 
282
                  G_STRUCT_OFFSET (GtkAssistantClass, apply),
 
283
                  NULL, NULL,
 
284
                  g_cclosure_marshal_VOID__VOID,
 
285
                  G_TYPE_NONE, 0);
 
286
 
 
287
  /**
 
288
   * GtkAssistant::close:
 
289
   * @assistant: the #GtkAssistant
 
290
   *
 
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.
 
294
   *
 
295
   * Since: 2.10
 
296
   */
 
297
  signals[CLOSE] =
 
298
    g_signal_new (I_("close"),
 
299
                  G_TYPE_FROM_CLASS (gobject_class),
 
300
                  G_SIGNAL_RUN_LAST,
 
301
                  G_STRUCT_OFFSET (GtkAssistantClass, close),
 
302
                  NULL, NULL,
 
303
                  g_cclosure_marshal_VOID__VOID,
 
304
                  G_TYPE_NONE, 0);
 
305
 
 
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."),
 
310
                                                             0,
 
311
                                                             G_MAXINT,
 
312
                                                             6,
 
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."),
 
318
                                                             0,
 
319
                                                             G_MAXINT,
 
320
                                                             1,
 
321
                                                             GTK_PARAM_READABLE));
 
322
 
 
323
  /**
 
324
   * GtkAssistant:page-type:
 
325
   *
 
326
   * The type of the assistant page.
 
327
   *
 
328
   * Since: 2.10
 
329
   */
 
330
  gtk_container_class_install_child_property (container_class,
 
331
                                              CHILD_PROP_PAGE_TYPE,
 
332
                                              g_param_spec_enum ("page-type", 
 
333
                                                                 P_("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));
 
338
 
 
339
  /**
 
340
   * GtkAssistant:title:
 
341
   *
 
342
   * The title that is displayed in the page header.
 
343
   *
 
344
   * If title and header-image are both %NULL, no header is displayed.
 
345
   *
 
346
   * Since: 2.10
 
347
   */
 
348
  gtk_container_class_install_child_property (container_class,
 
349
                                              CHILD_PROP_PAGE_TITLE,
 
350
                                              g_param_spec_string ("title", 
 
351
                                                                   P_("Page title"),
 
352
                                                                   P_("The title of the assistant page"),
 
353
                                                                   NULL,
 
354
                                                                   GTK_PARAM_READWRITE));
 
355
 
 
356
  /**
 
357
   * GtkAssistant:header-image:
 
358
   *
 
359
   * The image that is displayed next to the title in the page header.
 
360
   *
 
361
   * If title and header-image are both %NULL, no header is displayed.
 
362
   *
 
363
   * Since: 2.10
 
364
   */
 
365
  gtk_container_class_install_child_property (container_class,
 
366
                                              CHILD_PROP_PAGE_HEADER_IMAGE,
 
367
                                              g_param_spec_object ("header-image", 
 
368
                                                                   P_("Header image"),
 
369
                                                                   P_("Header image for the assistant page"),
 
370
                                                                   GDK_TYPE_PIXBUF,
 
371
                                                                   GTK_PARAM_READWRITE));
 
372
 
 
373
  /**
 
374
   * GtkAssistant:header-image:
 
375
   *
 
376
   * The image that is displayed next to the page.
 
377
   *
 
378
   * Set this to %NULL to make the sidebar disappear.
 
379
   *
 
380
   * Since: 2.10
 
381
   */
 
382
  gtk_container_class_install_child_property (container_class,
 
383
                                              CHILD_PROP_PAGE_SIDEBAR_IMAGE,
 
384
                                              g_param_spec_object ("sidebar-image", 
 
385
                                                                   P_("Sidebar image"),
 
386
                                                                   P_("Sidebar image for the assistant page"),
 
387
                                                                   GDK_TYPE_PIXBUF,
 
388
                                                                   GTK_PARAM_READWRITE));
 
389
  /**
 
390
   * GtkAssistant:complete:
 
391
   *
 
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.
 
395
   *
 
396
   * Since: 2.10
 
397
   **/
 
398
  gtk_container_class_install_child_property (container_class,
 
399
                                              CHILD_PROP_PAGE_COMPLETE,
 
400
                                              g_param_spec_boolean ("complete", 
 
401
                                                                    P_("Page complete"),
 
402
                                                                    P_("Whether all required fields on the page have been filled out"),
 
403
                                                                    FALSE,
 
404
                                                                    G_PARAM_READWRITE));
 
405
 
 
406
  g_type_class_add_private (gobject_class, sizeof (GtkAssistantPrivate));
 
407
}
 
408
 
 
409
static gint
 
410
default_forward_function (gint current_page, gpointer data)
 
411
{
 
412
  GtkAssistant *assistant;
 
413
  GtkAssistantPrivate *priv;
 
414
  GtkAssistantPage *page_info;
 
415
  GList *page_node;
 
416
 
 
417
  assistant = GTK_ASSISTANT (data);
 
418
  priv = assistant->priv;
 
419
 
 
420
  page_node = g_list_nth (priv->pages, ++current_page);
 
421
 
 
422
  if (!page_node)
 
423
    return -1;
 
424
 
 
425
  page_info = (GtkAssistantPage *) page_node->data;
 
426
 
 
427
  while (page_node && !gtk_widget_get_visible (page_info->page))
 
428
    {
 
429
      page_node = page_node->next;
 
430
      current_page++;
 
431
 
 
432
      if (page_node)
 
433
        page_info = (GtkAssistantPage *) page_node->data;
 
434
    }
 
435
 
 
436
  return current_page;
 
437
}
 
438
 
 
439
static void
 
440
compute_last_button_state (GtkAssistant *assistant)
 
441
{
 
442
  GtkAssistantPrivate *priv = assistant->priv;
 
443
  GtkAssistantPage *page_info, *current_page_info;
 
444
  gint count, page_num, n_pages;
 
445
 
 
446
  count = 0;
 
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);
 
450
 
 
451
  while (page_num >= 0 && page_num < n_pages &&
 
452
         page_info->type == GTK_ASSISTANT_PAGE_CONTENT &&
 
453
         (count == 0 || page_info->complete) &&
 
454
         count < n_pages)
 
455
    {
 
456
      page_num = (priv->forward_function) (page_num, priv->forward_function_data);
 
457
      page_info = g_list_nth_data (priv->pages, page_num);
 
458
 
 
459
      count++;
 
460
    }
 
461
 
 
462
  /* make the last button visible if we can skip multiple
 
463
   * pages and end on a confirmation or summary page
 
464
   */
 
465
  if (count > 1 && page_info &&
 
466
      (page_info->type == GTK_ASSISTANT_PAGE_CONFIRM ||
 
467
       page_info->type == GTK_ASSISTANT_PAGE_SUMMARY))
 
468
    {
 
469
      gtk_widget_show (assistant->last);
 
470
      gtk_widget_set_sensitive (assistant->last,
 
471
                                current_page_info->complete);
 
472
    }
 
473
  else
 
474
    gtk_widget_hide (assistant->last);
 
475
}
 
476
 
 
477
static void
 
478
compute_progress_state (GtkAssistant *assistant)
 
479
{
 
480
  GtkAssistantPrivate *priv = assistant->priv;
 
481
  gint page_num, n_pages;
 
482
 
 
483
  n_pages = gtk_assistant_get_n_pages (assistant);
 
484
  page_num = gtk_assistant_get_current_page (assistant);
 
485
 
 
486
  page_num = (priv->forward_function) (page_num, priv->forward_function_data);
 
487
 
 
488
  if (page_num >= 0 && page_num < n_pages)
 
489
    gtk_widget_show (assistant->forward);
 
490
  else
 
491
    gtk_widget_hide (assistant->forward);
 
492
}
 
493
 
 
494
static void
 
495
set_assistant_header_image (GtkAssistant *assistant)
 
496
{
 
497
  GtkAssistantPrivate *priv = assistant->priv;
 
498
 
 
499
  gtk_image_set_from_pixbuf (GTK_IMAGE (priv->header_image),
 
500
                             priv->current_page->header_image);
 
501
}
 
502
 
 
503
static void
 
504
set_assistant_sidebar_image (GtkAssistant *assistant)
 
505
{
 
506
  GtkAssistantPrivate *priv = assistant->priv;
 
507
 
 
508
  gtk_image_set_from_pixbuf (GTK_IMAGE (priv->sidebar_image),
 
509
                             priv->current_page->sidebar_image);
 
510
 
 
511
  if (priv->current_page->sidebar_image)
 
512
    gtk_widget_show (priv->sidebar_image);
 
513
  else
 
514
    gtk_widget_hide (priv->sidebar_image);
 
515
}
 
516
 
 
517
static void
 
518
set_assistant_buttons_state (GtkAssistant *assistant)
 
519
{
 
520
  GtkAssistantPrivate *priv = assistant->priv;
 
521
 
 
522
  if (!priv->current_page)
 
523
    return;
 
524
  
 
525
  switch (priv->current_page->type)
 
526
    {
 
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);
 
536
      break;
 
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);
 
547
      break;
 
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);
 
558
      break;
 
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);
 
567
      break;
 
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);
 
578
      break;
 
579
    default:
 
580
      g_assert_not_reached ();
 
581
    }
 
582
 
 
583
  if (priv->committed)
 
584
    gtk_widget_hide (assistant->cancel);
 
585
  else if (priv->current_page->type == GTK_ASSISTANT_PAGE_SUMMARY)
 
586
    gtk_widget_hide (assistant->cancel);
 
587
  else
 
588
    gtk_widget_show (assistant->cancel);
 
589
 
 
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);
 
594
}
 
595
 
 
596
static void
 
597
set_current_page (GtkAssistant     *assistant,
 
598
                  GtkAssistantPage *page)
 
599
{
 
600
  GtkAssistantPrivate *priv = assistant->priv;
 
601
  GtkAssistantPage *old_page;
 
602
 
 
603
  if (priv->current_page &&
 
604
      gtk_widget_is_drawable (priv->current_page->page))
 
605
    old_page = priv->current_page;
 
606
  else
 
607
    old_page = NULL;
 
608
 
 
609
  priv->current_page = page;
 
610
 
 
611
  set_assistant_buttons_state (assistant);
 
612
  set_assistant_header_image (assistant);
 
613
  set_assistant_sidebar_image (assistant);
 
614
 
 
615
  g_signal_emit (assistant, signals [PREPARE], 0, priv->current_page->page);
 
616
 
 
617
  if (gtk_widget_get_visible (priv->current_page->page) && gtk_widget_get_mapped (GTK_WIDGET (assistant)))
 
618
    {
 
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);
 
622
    }
 
623
  
 
624
  if (old_page && gtk_widget_get_mapped (old_page->page))
 
625
    {
 
626
      gtk_widget_set_child_visible (old_page->page, FALSE);
 
627
      gtk_widget_unmap (old_page->page);
 
628
      gtk_widget_unmap (old_page->title);
 
629
    }
 
630
 
 
631
  if (!gtk_widget_child_focus (priv->current_page->page, GTK_DIR_TAB_FORWARD))
 
632
    {
 
633
      GtkWidget *button[6];
 
634
      gint i;
 
635
 
 
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++)
 
644
        {
 
645
          if (gtk_widget_get_visible (button[i]) && gtk_widget_get_sensitive (button[i]))
 
646
            {
 
647
              gtk_widget_grab_focus (button[i]);
 
648
              break;
 
649
            }
 
650
        }
 
651
    }
 
652
 
 
653
  gtk_widget_queue_resize (GTK_WIDGET (assistant));
 
654
}
 
655
 
 
656
static gint
 
657
compute_next_step (GtkAssistant *assistant)
 
658
{
 
659
  GtkAssistantPrivate *priv = assistant->priv;
 
660
  GtkAssistantPage *page_info;
 
661
  gint current_page, n_pages, next_page;
 
662
 
 
663
  current_page = gtk_assistant_get_current_page (assistant);
 
664
  page_info = priv->current_page;
 
665
  n_pages = gtk_assistant_get_n_pages (assistant);
 
666
 
 
667
  next_page = (priv->forward_function) (current_page,
 
668
                                        priv->forward_function_data);
 
669
 
 
670
  if (next_page >= 0 && next_page < n_pages)
 
671
    {
 
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));
 
674
 
 
675
      return TRUE;
 
676
    }
 
677
 
 
678
  return FALSE;
 
679
}
 
680
 
 
681
static void
 
682
on_assistant_close (GtkWidget    *widget,
 
683
                    GtkAssistant *assistant)
 
684
{
 
685
  g_signal_emit (assistant, signals [CLOSE], 0, NULL);
 
686
}
 
687
 
 
688
static void
 
689
on_assistant_apply (GtkWidget    *widget,
 
690
                    GtkAssistant *assistant)
 
691
{
 
692
  gboolean success;
 
693
 
 
694
  g_signal_emit (assistant, signals [APPLY], 0);
 
695
 
 
696
  success = compute_next_step (assistant);
 
697
 
 
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
 
700
   */
 
701
  if (!success)
 
702
    g_signal_emit (assistant, signals [CLOSE], 0);
 
703
}
 
704
 
 
705
static void
 
706
on_assistant_forward (GtkWidget    *widget,
 
707
                      GtkAssistant *assistant)
 
708
{
 
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");
 
712
}
 
713
 
 
714
static void
 
715
on_assistant_back (GtkWidget    *widget,
 
716
                   GtkAssistant *assistant)
 
717
{
 
718
  GtkAssistantPrivate *priv = assistant->priv;
 
719
  GtkAssistantPage *page_info;
 
720
  GSList *page_node;
 
721
 
 
722
  /* skip the progress pages when going back */
 
723
  do
 
724
    {
 
725
      page_node = priv->visited_pages;
 
726
 
 
727
      g_return_if_fail (page_node != NULL);
 
728
 
 
729
      priv->visited_pages = priv->visited_pages->next;
 
730
      page_info = (GtkAssistantPage *) page_node->data;
 
731
      g_slist_free_1 (page_node);
 
732
    }
 
733
  while (page_info->type == GTK_ASSISTANT_PAGE_PROGRESS ||
 
734
         !gtk_widget_get_visible (page_info->page));
 
735
 
 
736
  set_current_page (assistant, page_info);
 
737
}
 
738
 
 
739
static void
 
740
on_assistant_cancel (GtkWidget    *widget,
 
741
                     GtkAssistant *assistant)
 
742
{
 
743
  g_signal_emit (assistant, signals [CANCEL], 0, NULL);
 
744
}
 
745
 
 
746
static void
 
747
on_assistant_last (GtkWidget    *widget,
 
748
                   GtkAssistant *assistant)
 
749
{
 
750
  GtkAssistantPrivate *priv = assistant->priv;
 
751
 
 
752
  while (priv->current_page->type == GTK_ASSISTANT_PAGE_CONTENT &&
 
753
         priv->current_page->complete)
 
754
    compute_next_step (assistant);
 
755
}
 
756
 
 
757
static gboolean
 
758
alternative_button_order (GtkAssistant *assistant)
 
759
{
 
760
  GtkSettings *settings;
 
761
  GdkScreen *screen;
 
762
  gboolean result;
 
763
 
 
764
  screen   = gtk_widget_get_screen (GTK_WIDGET (assistant));
 
765
  settings = gtk_settings_get_for_screen (screen);
 
766
 
 
767
  g_object_get (settings,
 
768
                "gtk-alternative-button-order", &result,
 
769
                NULL);
 
770
  return result;
 
771
}
 
772
 
 
773
static void
 
774
gtk_assistant_init (GtkAssistant *assistant)
 
775
{
 
776
  GtkAssistantPrivate *priv;
 
777
 
 
778
  priv = assistant->priv = GTK_ASSISTANT_GET_PRIVATE (assistant);
 
779
 
 
780
  gtk_container_set_reallocate_redraws (GTK_CONTAINER (assistant), TRUE);
 
781
  gtk_container_set_border_width (GTK_CONTAINER (assistant), 12);
 
782
 
 
783
  gtk_widget_push_composite_child ();
 
784
 
 
785
  /* Header */
 
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);
 
790
 
 
791
  /* Sidebar */
 
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);
 
796
 
 
797
  /* Action area  */
 
798
  priv->action_area  = gtk_hbox_new (FALSE, 6);
 
799
  
 
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);
 
809
 
 
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);
 
817
 
 
818
  if (!alternative_button_order (assistant))
 
819
    {
 
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);
 
826
    }
 
827
  else
 
828
    {
 
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);
 
835
    }
 
836
 
 
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);
 
842
 
 
843
  gtk_widget_pop_composite_child ();
 
844
 
 
845
  priv->pages = NULL;
 
846
  priv->current_page = NULL;
 
847
  priv->visited_pages = NULL;
 
848
 
 
849
  priv->forward_function = default_forward_function;
 
850
  priv->forward_function_data = assistant;
 
851
  priv->forward_data_destroy = NULL;
 
852
 
 
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);
 
865
}
 
866
 
 
867
static void
 
868
gtk_assistant_set_child_property (GtkContainer    *container,
 
869
                                  GtkWidget       *child,
 
870
                                  guint            property_id,
 
871
                                  const GValue    *value,
 
872
                                  GParamSpec      *pspec)
 
873
{
 
874
  switch (property_id)
 
875
    {
 
876
    case CHILD_PROP_PAGE_TYPE:
 
877
      gtk_assistant_set_page_type (GTK_ASSISTANT (container), child,
 
878
                                   g_value_get_enum (value));
 
879
      break;
 
880
    case CHILD_PROP_PAGE_TITLE:
 
881
      gtk_assistant_set_page_title (GTK_ASSISTANT (container), child,
 
882
                                    g_value_get_string (value));
 
883
      break;
 
884
    case CHILD_PROP_PAGE_HEADER_IMAGE:
 
885
      gtk_assistant_set_page_header_image (GTK_ASSISTANT (container), child,
 
886
                                           g_value_get_object (value));
 
887
      break;
 
888
    case CHILD_PROP_PAGE_SIDEBAR_IMAGE:
 
889
      gtk_assistant_set_page_side_image (GTK_ASSISTANT (container), child,
 
890
                                         g_value_get_object (value));
 
891
      break;
 
892
    case CHILD_PROP_PAGE_COMPLETE:
 
893
      gtk_assistant_set_page_complete (GTK_ASSISTANT (container), child,
 
894
                                       g_value_get_boolean (value));
 
895
      break;
 
896
    default:
 
897
      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
 
898
      break;
 
899
    }
 
900
}
 
901
 
 
902
static void
 
903
gtk_assistant_get_child_property (GtkContainer *container,
 
904
                                  GtkWidget    *child,
 
905
                                  guint         property_id,
 
906
                                  GValue       *value,
 
907
                                  GParamSpec   *pspec)
 
908
{
 
909
  switch (property_id)
 
910
    {
 
911
    case CHILD_PROP_PAGE_TYPE:
 
912
      g_value_set_enum (value,
 
913
                        gtk_assistant_get_page_type (GTK_ASSISTANT (container), child));
 
914
      break;
 
915
    case CHILD_PROP_PAGE_TITLE:
 
916
      g_value_set_string (value,
 
917
                          gtk_assistant_get_page_title (GTK_ASSISTANT (container), child));
 
918
      break;
 
919
    case CHILD_PROP_PAGE_HEADER_IMAGE:
 
920
      g_value_set_object (value,
 
921
                          gtk_assistant_get_page_header_image (GTK_ASSISTANT (container), child));
 
922
      break;
 
923
    case CHILD_PROP_PAGE_SIDEBAR_IMAGE:
 
924
      g_value_set_object (value,
 
925
                          gtk_assistant_get_page_side_image (GTK_ASSISTANT (container), child));
 
926
      break;
 
927
    case CHILD_PROP_PAGE_COMPLETE:
 
928
      g_value_set_boolean (value,
 
929
                           gtk_assistant_get_page_complete (GTK_ASSISTANT (container), child));
 
930
      break;
 
931
    default:
 
932
      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
 
933
      break;
 
934
    }
 
935
}
 
936
 
 
937
static void
 
938
on_page_notify_visibility (GtkWidget  *widget,
 
939
                           GParamSpec *arg,
 
940
                           gpointer    data)
 
941
{
 
942
  GtkAssistant *assistant = GTK_ASSISTANT (data);
 
943
 
 
944
  /* update buttons state, flow may have changed */
 
945
  if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
 
946
    set_assistant_buttons_state (assistant);
 
947
}
 
948
 
 
949
static void
 
950
remove_page (GtkAssistant *assistant, 
 
951
             GList        *element)
 
952
{
 
953
  GtkAssistantPrivate *priv = assistant->priv;
 
954
  GtkAssistantPage *page_info;
 
955
  GList *page_node;
 
956
 
 
957
  page_info = element->data;
 
958
 
 
959
  /* If this is the current page, we need to switch away. */
 
960
  if (page_info == priv->current_page)
 
961
    {
 
962
      if (!compute_next_step (assistant))
 
963
        {
 
964
          /* The best we can do at this point is probably to pick the first
 
965
           * visible page.
 
966
           */
 
967
          page_node = priv->pages;
 
968
 
 
969
          while (page_node && !gtk_widget_get_visible (((GtkAssistantPage *) page_node->data)->page))
 
970
            page_node = page_node->next;
 
971
 
 
972
          if (page_node == element)
 
973
            page_node = page_node->next;
 
974
 
 
975
          if (page_node)
 
976
            priv->current_page = page_node->data;
 
977
          else
 
978
            priv->current_page = NULL;
 
979
        }
 
980
    }
 
981
 
 
982
  priv->pages = g_list_remove_link (priv->pages, element);
 
983
  priv->visited_pages = g_slist_remove_all (priv->visited_pages, page_info);
 
984
 
 
985
  g_signal_handlers_disconnect_by_func (page_info->page, on_page_notify_visibility, assistant);
 
986
  gtk_widget_unparent (page_info->page);
 
987
 
 
988
  if (page_info->header_image)
 
989
    g_object_unref (page_info->header_image);
 
990
 
 
991
  if (page_info->sidebar_image)
 
992
    g_object_unref (page_info->sidebar_image);
 
993
 
 
994
  gtk_widget_destroy (page_info->title);
 
995
  g_slice_free (GtkAssistantPage, page_info);
 
996
  g_list_free_1 (element);
 
997
}
 
998
 
 
999
static void
 
1000
gtk_assistant_destroy (GtkObject *object)
 
1001
{
 
1002
  GtkAssistant *assistant = GTK_ASSISTANT (object);
 
1003
  GtkAssistantPrivate *priv = assistant->priv;
 
1004
 
 
1005
  if (priv->header_image)
 
1006
    {
 
1007
      gtk_widget_destroy (priv->header_image);
 
1008
      priv->header_image = NULL;
 
1009
    }
 
1010
 
 
1011
  if (priv->sidebar_image)
 
1012
    {
 
1013
      gtk_widget_destroy (priv->sidebar_image);
 
1014
      priv->sidebar_image = NULL;
 
1015
    }
 
1016
 
 
1017
  if (priv->action_area)
 
1018
    {
 
1019
      gtk_widget_destroy (priv->action_area);
 
1020
      priv->action_area = NULL;
 
1021
    }
 
1022
 
 
1023
  if (priv->size_group)
 
1024
    {
 
1025
      g_object_unref (priv->size_group);
 
1026
      priv->size_group = NULL;
 
1027
    }
 
1028
 
 
1029
  if (priv->forward_function)
 
1030
    {
 
1031
      if (priv->forward_function_data &&
 
1032
          priv->forward_data_destroy)
 
1033
        priv->forward_data_destroy (priv->forward_function_data);
 
1034
 
 
1035
      priv->forward_function = NULL;
 
1036
      priv->forward_function_data = NULL;
 
1037
      priv->forward_data_destroy = NULL;
 
1038
    }
 
1039
 
 
1040
  if (priv->visited_pages)
 
1041
    {
 
1042
      g_slist_free (priv->visited_pages);
 
1043
      priv->visited_pages = NULL;
 
1044
    }
 
1045
 
 
1046
  /* We set current to NULL so that the remove code doesn't try
 
1047
   * to do anything funny */
 
1048
  priv->current_page = NULL;
 
1049
 
 
1050
  while (priv->pages)
 
1051
    remove_page (GTK_ASSISTANT (object), priv->pages);
 
1052
      
 
1053
  GTK_OBJECT_CLASS (gtk_assistant_parent_class)->destroy (object);
 
1054
}
 
1055
 
 
1056
static GList*
 
1057
find_page (GtkAssistant  *assistant,
 
1058
           GtkWidget     *page)
 
1059
{
 
1060
  GtkAssistantPrivate *priv = assistant->priv;
 
1061
  GList *child = priv->pages;
 
1062
  
 
1063
  while (child)
 
1064
    {
 
1065
      GtkAssistantPage *page_info = child->data;
 
1066
      if (page_info->page == page)
 
1067
        return child;
 
1068
 
 
1069
      child = child->next;
 
1070
    }
 
1071
  
 
1072
  return NULL;
 
1073
}
 
1074
 
 
1075
static void
 
1076
set_title_colors (GtkWidget *assistant,
 
1077
                  GtkWidget *title_label)
 
1078
{
 
1079
  GtkStyle *style;
 
1080
 
 
1081
  gtk_widget_ensure_style (assistant);
 
1082
  style = gtk_widget_get_style (assistant);
 
1083
 
 
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]);
 
1087
}
 
1088
 
 
1089
static void
 
1090
set_title_font (GtkWidget *assistant,
 
1091
                GtkWidget *title_label)
 
1092
{
 
1093
  PangoFontDescription *desc;
 
1094
  gint size;
 
1095
 
 
1096
  desc = pango_font_description_new ();
 
1097
  size = pango_font_description_get_size (assistant->style->font_desc);
 
1098
 
 
1099
  pango_font_description_set_weight (desc, PANGO_WEIGHT_ULTRABOLD);
 
1100
  pango_font_description_set_size   (desc, size * PANGO_SCALE_XX_LARGE);
 
1101
 
 
1102
  gtk_widget_modify_font (title_label, desc);
 
1103
  pango_font_description_free (desc);
 
1104
}
 
1105
 
 
1106
static void
 
1107
gtk_assistant_style_set (GtkWidget *widget,
 
1108
                         GtkStyle  *old_style)
 
1109
{
 
1110
  GtkAssistant *assistant = GTK_ASSISTANT (widget);
 
1111
  GtkAssistantPrivate *priv = assistant->priv;
 
1112
  GList *list;
 
1113
 
 
1114
  list = priv->pages;
 
1115
 
 
1116
  while (list)
 
1117
    {
 
1118
      GtkAssistantPage *page = list->data;
 
1119
 
 
1120
      set_title_colors (widget, page->title);
 
1121
      set_title_font (widget, page->title);
 
1122
 
 
1123
      list = list->next;
 
1124
    }
 
1125
}
 
1126
 
 
1127
static void
 
1128
gtk_assistant_size_request (GtkWidget      *widget,
 
1129
                            GtkRequisition *requisition)
 
1130
{
 
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;
 
1136
  GList *list;
 
1137
 
 
1138
  gtk_widget_style_get (widget,
 
1139
                        "header-padding", &header_padding,
 
1140
                        "content-padding", &content_padding,
 
1141
                        NULL);
 
1142
  width = height = 0;
 
1143
  header_width = header_height = 0;
 
1144
  list  = priv->pages;
 
1145
 
 
1146
  while (list)
 
1147
    {
 
1148
      GtkAssistantPage *page = list->data;
 
1149
      gint w, h;
 
1150
 
 
1151
      gtk_widget_size_request (page->page, &child_requisition);
 
1152
      width  = MAX (width,  child_requisition.width);
 
1153
      height = MAX (height, child_requisition.height);
 
1154
 
 
1155
      gtk_widget_size_request (page->title, &child_requisition);
 
1156
      w = child_requisition.width;
 
1157
      h = child_requisition.height;
 
1158
 
 
1159
      if (page->header_image)
 
1160
        {
 
1161
          w += gdk_pixbuf_get_width (page->header_image) + HEADER_SPACING;
 
1162
          h  = MAX (h, gdk_pixbuf_get_height (page->header_image));
 
1163
        }
 
1164
 
 
1165
      header_width  = MAX (header_width, w);
 
1166
      header_height = MAX (header_height, h);
 
1167
 
 
1168
      list = list->next;
 
1169
    }
 
1170
 
 
1171
  gtk_widget_size_request (priv->sidebar_image, &child_requisition);
 
1172
  width  += child_requisition.width;
 
1173
  height  = MAX (height, child_requisition.height);
 
1174
 
 
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;
 
1179
 
 
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;
 
1183
 
 
1184
  width += GTK_CONTAINER (widget)->border_width * 2 + content_padding * 2;
 
1185
  height += GTK_CONTAINER (widget)->border_width * 2 + content_padding * 2;
 
1186
 
 
1187
  requisition->width = width;
 
1188
  requisition->height = height;
 
1189
}
 
1190
 
 
1191
static void
 
1192
gtk_assistant_size_allocate (GtkWidget      *widget,
 
1193
                             GtkAllocation  *allocation)
 
1194
{
 
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;
 
1200
  gboolean rtl;
 
1201
  GList *pages;
 
1202
 
 
1203
  rtl   = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
 
1204
  pages = priv->pages;
 
1205
 
 
1206
  gtk_widget_style_get (widget,
 
1207
                        "header-padding", &header_padding,
 
1208
                        "content-padding", &content_padding,
 
1209
                        NULL);
 
1210
 
 
1211
  widget->allocation = *allocation;
 
1212
 
 
1213
  /* Header */
 
1214
  gtk_widget_get_child_requisition (priv->header_image, &header_requisition);
 
1215
 
 
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;
 
1220
 
 
1221
  gtk_widget_size_allocate (priv->header_image, &header_allocation);
 
1222
 
 
1223
  /* Action area */
 
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;
 
1229
 
 
1230
  gtk_widget_size_allocate (priv->action_area, &child_allocation);
 
1231
 
 
1232
  /* Sidebar */
 
1233
  if (rtl)
 
1234
    child_allocation.x = allocation->width -
 
1235
      GTK_CONTAINER (widget)->border_width - priv->sidebar_image->requisition.width;
 
1236
  else
 
1237
    child_allocation.x = GTK_CONTAINER (widget)->border_width;
 
1238
 
 
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;
 
1244
 
 
1245
  gtk_widget_size_allocate (priv->sidebar_image, &child_allocation);
 
1246
 
 
1247
  /* Pages */
 
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;
 
1254
 
 
1255
  if (gtk_widget_get_visible (priv->sidebar_image))
 
1256
    {
 
1257
      if (!rtl)
 
1258
        child_allocation.x += priv->sidebar_image->allocation.width;
 
1259
 
 
1260
      child_allocation.width -= priv->sidebar_image->allocation.width;
 
1261
    }
 
1262
 
 
1263
  while (pages)
 
1264
    {
 
1265
      GtkAssistantPage *page = pages->data;
 
1266
 
 
1267
      gtk_widget_size_allocate (page->page, &child_allocation);
 
1268
      gtk_widget_size_allocate (page->title, &header_allocation);
 
1269
      pages = pages->next;
 
1270
    }
 
1271
}
 
1272
 
 
1273
static void
 
1274
gtk_assistant_map (GtkWidget *widget)
 
1275
{
 
1276
  GtkAssistant *assistant = GTK_ASSISTANT (widget);
 
1277
  GtkAssistantPrivate *priv = assistant->priv;
 
1278
  GList *page_node;
 
1279
  GtkAssistantPage *page;
 
1280
 
 
1281
  gtk_widget_set_mapped (widget, TRUE);
 
1282
 
 
1283
  gtk_widget_map (priv->header_image);
 
1284
  gtk_widget_map (priv->action_area);
 
1285
 
 
1286
  if (gtk_widget_get_visible (priv->sidebar_image) &&
 
1287
      !gtk_widget_get_mapped (priv->sidebar_image))
 
1288
    gtk_widget_map (priv->sidebar_image);
 
1289
 
 
1290
  /* if there's no default page, pick the first one */
 
1291
  page = NULL;
 
1292
  if (!priv->current_page)
 
1293
    {
 
1294
      page_node = priv->pages;
 
1295
 
 
1296
      while (page_node && !gtk_widget_get_visible (((GtkAssistantPage *) page_node->data)->page))
 
1297
        page_node = page_node->next;
 
1298
 
 
1299
      if (page_node)
 
1300
        page = page_node->data;
 
1301
    }
 
1302
 
 
1303
  if (page &&
 
1304
      gtk_widget_get_visible (page->page) &&
 
1305
      !gtk_widget_get_mapped (page->page))
 
1306
    set_current_page (assistant, page);
 
1307
 
 
1308
  GTK_WIDGET_CLASS (gtk_assistant_parent_class)->map (widget);
 
1309
}
 
1310
 
 
1311
static void
 
1312
gtk_assistant_unmap (GtkWidget *widget)
 
1313
{
 
1314
  GtkAssistant *assistant = GTK_ASSISTANT (widget);
 
1315
  GtkAssistantPrivate *priv = assistant->priv;
 
1316
 
 
1317
  gtk_widget_set_mapped (widget, FALSE);
 
1318
 
 
1319
  gtk_widget_unmap (priv->header_image);
 
1320
  gtk_widget_unmap (priv->action_area);
 
1321
 
 
1322
  if (gtk_widget_is_drawable (priv->sidebar_image))
 
1323
    gtk_widget_unmap (priv->sidebar_image);
 
1324
 
 
1325
  if (priv->current_page &&
 
1326
      gtk_widget_is_drawable (priv->current_page->page))
 
1327
    gtk_widget_unmap (priv->current_page->page);
 
1328
 
 
1329
  g_slist_free (priv->visited_pages);
 
1330
  priv->visited_pages = NULL;
 
1331
  priv->current_page  = NULL;
 
1332
 
 
1333
  GTK_WIDGET_CLASS (gtk_assistant_parent_class)->unmap (widget);
 
1334
}
 
1335
 
 
1336
static gboolean
 
1337
gtk_assistant_delete_event (GtkWidget   *widget,
 
1338
                            GdkEventAny *event)
 
1339
{
 
1340
  GtkAssistant *assistant = GTK_ASSISTANT (widget);
 
1341
  GtkAssistantPrivate *priv = assistant->priv;
 
1342
 
 
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);
 
1348
 
 
1349
  return TRUE;
 
1350
}
 
1351
 
 
1352
static void
 
1353
assistant_paint_colored_box (GtkWidget *widget)
 
1354
{
 
1355
  GtkAssistant *assistant = GTK_ASSISTANT (widget);
 
1356
  GtkAssistantPrivate *priv = assistant->priv;
 
1357
  gint border_width, header_padding, content_padding;
 
1358
  cairo_t *cr;
 
1359
  gint content_x, content_width;
 
1360
  gboolean rtl;
 
1361
 
 
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));
 
1365
 
 
1366
  gtk_widget_style_get (widget,
 
1367
                        "header-padding",  &header_padding,
 
1368
                        "content-padding", &content_padding,
 
1369
                        NULL);
 
1370
 
 
1371
  /* colored box */
 
1372
  gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_SELECTED]);
 
1373
  cairo_rectangle (cr,
 
1374
                   border_width,
 
1375
                   border_width,
 
1376
                   widget->allocation.width - 2 * border_width,
 
1377
                   widget->allocation.height - priv->action_area->allocation.height - 2 * border_width - ACTION_AREA_SPACING);
 
1378
  cairo_fill (cr);
 
1379
 
 
1380
  /* content box */
 
1381
  content_x = content_padding + border_width;
 
1382
  content_width = widget->allocation.width - 2 * content_padding - 2 * border_width;
 
1383
 
 
1384
  if (gtk_widget_get_visible (priv->sidebar_image))
 
1385
    {
 
1386
      if (!rtl)
 
1387
        content_x += priv->sidebar_image->allocation.width;
 
1388
      content_width -= priv->sidebar_image->allocation.width;
 
1389
    }
 
1390
  
 
1391
  gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_NORMAL]);
 
1392
 
 
1393
  cairo_rectangle (cr,
 
1394
                   content_x,
 
1395
                   priv->header_image->allocation.height + content_padding + 2 * header_padding + border_width,
 
1396
                   content_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);
 
1399
  cairo_fill (cr);
 
1400
 
 
1401
  cairo_destroy (cr);
 
1402
}
 
1403
 
 
1404
static gboolean
 
1405
gtk_assistant_expose (GtkWidget      *widget,
 
1406
                      GdkEventExpose *event)
 
1407
{
 
1408
  GtkAssistant *assistant = GTK_ASSISTANT (widget);
 
1409
  GtkAssistantPrivate *priv = assistant->priv;
 
1410
  GtkContainer *container;
 
1411
 
 
1412
  if (gtk_widget_is_drawable (widget))
 
1413
    {
 
1414
      container = GTK_CONTAINER (widget);
 
1415
 
 
1416
      assistant_paint_colored_box (widget);
 
1417
 
 
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);
 
1421
 
 
1422
      if (priv->current_page)
 
1423
        {
 
1424
          gtk_container_propagate_expose (container, priv->current_page->page, event);
 
1425
          gtk_container_propagate_expose (container, priv->current_page->title, event);
 
1426
        }
 
1427
    }
 
1428
 
 
1429
  return FALSE;
 
1430
}
 
1431
 
 
1432
static gboolean
 
1433
gtk_assistant_focus (GtkWidget        *widget,
 
1434
                     GtkDirectionType  direction)
 
1435
{
 
1436
  GtkAssistantPrivate *priv;
 
1437
  GtkContainer *container;
 
1438
 
 
1439
  container = GTK_CONTAINER (widget);
 
1440
  priv = GTK_ASSISTANT (widget)->priv;
 
1441
 
 
1442
  /* we only have to care about 2 widgets, action area and the current page */
 
1443
  if (container->focus_child == priv->action_area)
 
1444
    {
 
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)))
 
1448
        {
 
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);
 
1453
        }
 
1454
    }
 
1455
  else
 
1456
    {
 
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))
 
1460
        {
 
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);
 
1466
        }
 
1467
    }
 
1468
 
 
1469
  return TRUE;
 
1470
}
 
1471
 
 
1472
static void
 
1473
gtk_assistant_add (GtkContainer *container,
 
1474
                   GtkWidget    *page)
 
1475
{
 
1476
  gtk_assistant_append_page (GTK_ASSISTANT (container), page);
 
1477
}
 
1478
 
 
1479
static void
 
1480
gtk_assistant_remove (GtkContainer *container,
 
1481
                      GtkWidget    *page)
 
1482
{
 
1483
  GtkAssistant *assistant = (GtkAssistant*) container;
 
1484
  GList *element;
 
1485
 
 
1486
  element = find_page (assistant, page);
 
1487
 
 
1488
  if (element)
 
1489
    {
 
1490
      remove_page (assistant, element);
 
1491
      gtk_widget_queue_resize ((GtkWidget *) container);
 
1492
    }
 
1493
}
 
1494
 
 
1495
static void
 
1496
gtk_assistant_forall (GtkContainer *container,
 
1497
                      gboolean      include_internals,
 
1498
                      GtkCallback   callback,
 
1499
                      gpointer      callback_data)
 
1500
{
 
1501
  GtkAssistant *assistant = (GtkAssistant*) container;
 
1502
  GtkAssistantPrivate *priv = assistant->priv;
 
1503
  GList *pages;
 
1504
 
 
1505
  if (include_internals)
 
1506
    {
 
1507
      (*callback) (priv->header_image, callback_data);
 
1508
      (*callback) (priv->sidebar_image, callback_data);
 
1509
      (*callback) (priv->action_area, callback_data);
 
1510
    }
 
1511
 
 
1512
  pages = priv->pages;
 
1513
 
 
1514
  while (pages)
 
1515
    {
 
1516
      GtkAssistantPage *page = (GtkAssistantPage *) pages->data;
 
1517
 
 
1518
      (*callback) (page->page, callback_data);
 
1519
 
 
1520
      if (include_internals)
 
1521
        (*callback) (page->title, callback_data);
 
1522
 
 
1523
      pages = pages->next;
 
1524
    }
 
1525
}
 
1526
 
 
1527
/**
 
1528
 * gtk_assistant_new:
 
1529
 * 
 
1530
 * Creates a new #GtkAssistant.
 
1531
 *
 
1532
 * Return value: a newly created #GtkAssistant
 
1533
 *
 
1534
 * Since: 2.10
 
1535
 **/
 
1536
GtkWidget*
 
1537
gtk_assistant_new (void)
 
1538
{
 
1539
  GtkWidget *assistant;
 
1540
 
 
1541
  assistant = g_object_new (GTK_TYPE_ASSISTANT, NULL);
 
1542
 
 
1543
  return assistant;
 
1544
}
 
1545
 
 
1546
/**
 
1547
 * gtk_assistant_get_current_page:
 
1548
 * @assistant: a #GtkAssistant
 
1549
 *
 
1550
 * Returns the page number of the current page
 
1551
 *
 
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
 
1554
 *
 
1555
 * Since: 2.10
 
1556
 **/
 
1557
gint
 
1558
gtk_assistant_get_current_page (GtkAssistant *assistant)
 
1559
{
 
1560
  GtkAssistantPrivate *priv;
 
1561
 
 
1562
  g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), -1);
 
1563
 
 
1564
  priv = assistant->priv;
 
1565
 
 
1566
  if (!priv->pages || !priv->current_page)
 
1567
    return -1;
 
1568
 
 
1569
  return g_list_index (priv->pages, priv->current_page);
 
1570
}
 
1571
 
 
1572
/**
 
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
 
1578
 *            will be done.
 
1579
 *
 
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().
 
1583
 *
 
1584
 * Since: 2.10
 
1585
 **/
 
1586
void
 
1587
gtk_assistant_set_current_page (GtkAssistant *assistant,
 
1588
                                gint          page_num)
 
1589
{
 
1590
  GtkAssistantPrivate *priv;
 
1591
  GtkAssistantPage *page;
 
1592
 
 
1593
  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
 
1594
 
 
1595
  priv = assistant->priv;
 
1596
 
 
1597
  if (page_num >= 0)
 
1598
    page = (GtkAssistantPage *) g_list_nth_data (priv->pages, page_num);
 
1599
  else
 
1600
    page = (GtkAssistantPage *) g_list_last (priv->pages)->data;
 
1601
 
 
1602
  g_return_if_fail (page != NULL);
 
1603
 
 
1604
  if (priv->current_page == page)
 
1605
    return;
 
1606
 
 
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
 
1611
   */
 
1612
  if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
 
1613
    priv->visited_pages = g_slist_prepend (priv->visited_pages,
 
1614
                                           priv->current_page);
 
1615
 
 
1616
  set_current_page (assistant, page);
 
1617
}
 
1618
 
 
1619
/**
 
1620
 * gtk_assistant_get_n_pages:
 
1621
 * @assistant: a #GtkAssistant
 
1622
 *
 
1623
 * Returns the number of pages in the @assistant
 
1624
 *
 
1625
 * Return value: The number of pages in the @assistant.
 
1626
 *
 
1627
 * Since: 2.10
 
1628
 **/
 
1629
gint
 
1630
gtk_assistant_get_n_pages (GtkAssistant *assistant)
 
1631
{
 
1632
  GtkAssistantPrivate *priv;
 
1633
 
 
1634
  g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
 
1635
 
 
1636
  priv = assistant->priv;
 
1637
 
 
1638
  return g_list_length (priv->pages);
 
1639
}
 
1640
 
 
1641
/**
 
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;
 
1645
 *
 
1646
 * Returns the child widget contained in page number @page_num.
 
1647
 *
 
1648
 * Return value: (transfer none): The child widget, or %NULL
 
1649
 *     if @page_num is out of bounds.
 
1650
 *
 
1651
 * Since: 2.10
 
1652
 **/
 
1653
GtkWidget*
 
1654
gtk_assistant_get_nth_page (GtkAssistant *assistant,
 
1655
                            gint          page_num)
 
1656
{
 
1657
  GtkAssistantPrivate *priv;
 
1658
  GtkAssistantPage *page;
 
1659
  GList *elem;
 
1660
 
 
1661
  g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
 
1662
  g_return_val_if_fail (page_num >= -1, NULL);
 
1663
 
 
1664
  priv = assistant->priv;
 
1665
 
 
1666
  if (page_num == -1)
 
1667
    elem = g_list_last (priv->pages);
 
1668
  else
 
1669
    elem = g_list_nth (priv->pages, page_num);
 
1670
 
 
1671
  if (!elem)
 
1672
    return NULL;
 
1673
 
 
1674
  page = (GtkAssistantPage *) elem->data;
 
1675
 
 
1676
  return page->page;
 
1677
}
 
1678
 
 
1679
/**
 
1680
 * gtk_assistant_prepend_page:
 
1681
 * @assistant: a #GtkAssistant
 
1682
 * @page: a #GtkWidget
 
1683
 *
 
1684
 * Prepends a page to the @assistant.
 
1685
 *
 
1686
 * Return value: the index (starting at 0) of the inserted page
 
1687
 *
 
1688
 * Since: 2.10
 
1689
 **/
 
1690
gint
 
1691
gtk_assistant_prepend_page (GtkAssistant *assistant,
 
1692
                            GtkWidget    *page)
 
1693
{
 
1694
  g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
 
1695
  g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
 
1696
 
 
1697
  return gtk_assistant_insert_page (assistant, page, 0);
 
1698
}
 
1699
 
 
1700
/**
 
1701
 * gtk_assistant_append_page:
 
1702
 * @assistant: a #GtkAssistant
 
1703
 * @page: a #GtkWidget
 
1704
 *
 
1705
 * Appends a page to the @assistant.
 
1706
 *
 
1707
 * Return value: the index (starting at 0) of the inserted page
 
1708
 *
 
1709
 * Since: 2.10
 
1710
 **/
 
1711
gint
 
1712
gtk_assistant_append_page (GtkAssistant *assistant,
 
1713
                           GtkWidget    *page)
 
1714
{
 
1715
  g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
 
1716
  g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
 
1717
 
 
1718
  return gtk_assistant_insert_page (assistant, page, -1);
 
1719
}
 
1720
 
 
1721
/**
 
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
 
1727
 *
 
1728
 * Inserts a page in the @assistant at a given position.
 
1729
 *
 
1730
 * Return value: the index (starting from 0) of the inserted page
 
1731
 *
 
1732
 * Since: 2.10
 
1733
 **/
 
1734
gint
 
1735
gtk_assistant_insert_page (GtkAssistant *assistant,
 
1736
                           GtkWidget    *page,
 
1737
                           gint          position)
 
1738
{
 
1739
  GtkAssistantPrivate *priv;
 
1740
  GtkAssistantPage *page_info;
 
1741
  gint n_pages;
 
1742
 
 
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);
 
1747
 
 
1748
  priv = assistant->priv;
 
1749
 
 
1750
  page_info = g_slice_new0 (GtkAssistantPage);
 
1751
  page_info->page  = page;
 
1752
  page_info->title = gtk_label_new (NULL);
 
1753
 
 
1754
  g_signal_connect (G_OBJECT (page), "notify::visible",
 
1755
                    G_CALLBACK (on_page_notify_visibility), assistant);
 
1756
 
 
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);
 
1761
 
 
1762
  n_pages = g_list_length (priv->pages);
 
1763
 
 
1764
  if (position < 0 || position > n_pages)
 
1765
    position = n_pages;
 
1766
 
 
1767
  priv->pages = g_list_insert (priv->pages, page_info, position);
 
1768
 
 
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));
 
1772
 
 
1773
  if (gtk_widget_get_realized (GTK_WIDGET (assistant)))
 
1774
    {
 
1775
      gtk_widget_realize (page_info->page);
 
1776
      gtk_widget_realize (page_info->title);
 
1777
    }
 
1778
 
 
1779
  gtk_widget_queue_resize (GTK_WIDGET (assistant));
 
1780
 
 
1781
  return position;
 
1782
}
 
1783
 
 
1784
/**
 
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
 
1790
 *
 
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 
 
1795
 * page.
 
1796
 *
 
1797
 * Since: 2.10
 
1798
 **/
 
1799
void
 
1800
gtk_assistant_set_forward_page_func (GtkAssistant         *assistant,
 
1801
                                     GtkAssistantPageFunc  page_func,
 
1802
                                     gpointer              data,
 
1803
                                     GDestroyNotify        destroy)
 
1804
{
 
1805
  GtkAssistantPrivate *priv;
 
1806
 
 
1807
  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
 
1808
 
 
1809
  priv = assistant->priv;
 
1810
 
 
1811
  if (priv->forward_data_destroy &&
 
1812
      priv->forward_function_data)
 
1813
    (*priv->forward_data_destroy) (priv->forward_function_data);
 
1814
 
 
1815
  if (page_func)
 
1816
    {
 
1817
      priv->forward_function = page_func;
 
1818
      priv->forward_function_data = data;
 
1819
      priv->forward_data_destroy = destroy;
 
1820
    }
 
1821
  else
 
1822
    {
 
1823
      priv->forward_function = default_forward_function;
 
1824
      priv->forward_function_data = assistant;
 
1825
      priv->forward_data_destroy = NULL;
 
1826
    }
 
1827
 
 
1828
  /* Page flow has possibly changed, so the
 
1829
     buttons state might need to change too */
 
1830
  set_assistant_buttons_state (assistant);
 
1831
}
 
1832
 
 
1833
/**
 
1834
 * gtk_assistant_add_action_widget:
 
1835
 * @assistant: a #GtkAssistant
 
1836
 * @child: a #GtkWidget
 
1837
 * 
 
1838
 * Adds a widget to the action area of a #GtkAssistant.
 
1839
 *
 
1840
 * Since: 2.10
 
1841
 **/
 
1842
void
 
1843
gtk_assistant_add_action_widget (GtkAssistant *assistant,
 
1844
                                 GtkWidget    *child)
 
1845
{
 
1846
  GtkAssistantPrivate *priv;
 
1847
 
 
1848
  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
 
1849
  g_return_if_fail (GTK_IS_WIDGET (child));
 
1850
 
 
1851
  priv = assistant->priv;
 
1852
 
 
1853
  if (GTK_IS_BUTTON (child))
 
1854
    gtk_size_group_add_widget (priv->size_group, child);
 
1855
 
 
1856
  gtk_box_pack_end (GTK_BOX (priv->action_area), child, FALSE, FALSE, 0);
 
1857
}
 
1858
 
 
1859
/**
 
1860
 * gtk_assistant_remove_action_widget:
 
1861
 * @assistant: a #GtkAssistant
 
1862
 * @child: a #GtkWidget
 
1863
 *
 
1864
 * Removes a widget from the action area of a #GtkAssistant.
 
1865
 *
 
1866
 * Since: 2.10
 
1867
 **/
 
1868
void
 
1869
gtk_assistant_remove_action_widget (GtkAssistant *assistant,
 
1870
                                    GtkWidget    *child)
 
1871
{
 
1872
  GtkAssistantPrivate *priv;
 
1873
 
 
1874
  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
 
1875
  g_return_if_fail (GTK_IS_WIDGET (child));
 
1876
 
 
1877
  priv = assistant->priv;
 
1878
 
 
1879
  if (GTK_IS_BUTTON (child))
 
1880
    gtk_size_group_remove_widget (priv->size_group, child);
 
1881
 
 
1882
  gtk_container_remove (GTK_CONTAINER (priv->action_area), child);
 
1883
}
 
1884
 
 
1885
/**
 
1886
 * gtk_assistant_set_page_title:
 
1887
 * @assistant: a #GtkAssistant
 
1888
 * @page: a page of @assistant
 
1889
 * @title: the new title for @page
 
1890
 * 
 
1891
 * Sets a title for @page. The title is displayed in the header
 
1892
 * area of the assistant when @page is the current page.
 
1893
 *
 
1894
 * Since: 2.10
 
1895
 **/
 
1896
void
 
1897
gtk_assistant_set_page_title (GtkAssistant *assistant,
 
1898
                              GtkWidget    *page,
 
1899
                              const gchar  *title)
 
1900
{
 
1901
  GtkAssistantPage *page_info;
 
1902
  GList *child;
 
1903
 
 
1904
  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
 
1905
  g_return_if_fail (GTK_IS_WIDGET (page));
 
1906
 
 
1907
  child = find_page (assistant, page);
 
1908
 
 
1909
  g_return_if_fail (child != NULL);
 
1910
 
 
1911
  page_info = (GtkAssistantPage*) child->data;
 
1912
 
 
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");
 
1916
}
 
1917
 
 
1918
/**
 
1919
 * gtk_assistant_get_page_title:
 
1920
 * @assistant: a #GtkAssistant
 
1921
 * @page: a page of @assistant
 
1922
 * 
 
1923
 * Gets the title for @page. 
 
1924
 * 
 
1925
 * Return value: the title for @page.
 
1926
 *
 
1927
 * Since: 2.10
 
1928
 **/
 
1929
const gchar*
 
1930
gtk_assistant_get_page_title (GtkAssistant *assistant,
 
1931
                              GtkWidget    *page)
 
1932
{
 
1933
  GtkAssistantPage *page_info;
 
1934
  GList *child;
 
1935
 
 
1936
  g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
 
1937
  g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
 
1938
 
 
1939
  child = find_page (assistant, page);
 
1940
 
 
1941
  g_return_val_if_fail (child != NULL, NULL);
 
1942
 
 
1943
  page_info = (GtkAssistantPage*) child->data;
 
1944
 
 
1945
  return gtk_label_get_text ((GtkLabel*) page_info->title);
 
1946
}
 
1947
 
 
1948
/**
 
1949
 * gtk_assistant_set_page_type:
 
1950
 * @assistant: a #GtkAssistant
 
1951
 * @page: a page of @assistant
 
1952
 * @type: the new type for @page
 
1953
 * 
 
1954
 * Sets the page type for @page. The page type determines the page
 
1955
 * behavior in the @assistant.
 
1956
 *
 
1957
 * Since: 2.10
 
1958
 **/
 
1959
void
 
1960
gtk_assistant_set_page_type (GtkAssistant         *assistant,
 
1961
                             GtkWidget            *page,
 
1962
                             GtkAssistantPageType  type)
 
1963
{
 
1964
  GtkAssistantPrivate *priv;
 
1965
  GtkAssistantPage *page_info;
 
1966
  GList *child;
 
1967
 
 
1968
  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
 
1969
  g_return_if_fail (GTK_IS_WIDGET (page));
 
1970
 
 
1971
  priv = assistant->priv;
 
1972
  child = find_page (assistant, page);
 
1973
 
 
1974
  g_return_if_fail (child != NULL);
 
1975
 
 
1976
  page_info = (GtkAssistantPage*) child->data;
 
1977
 
 
1978
  if (type != page_info->type)
 
1979
    {
 
1980
      page_info->type = type;
 
1981
 
 
1982
      /* backwards compatibility to the era before fixing bug 604289 */
 
1983
      if (type == GTK_ASSISTANT_PAGE_SUMMARY && !page_info->complete_set)
 
1984
        {
 
1985
          gtk_assistant_set_page_complete (assistant, page, TRUE);
 
1986
          page_info->complete_set = FALSE;
 
1987
        }
 
1988
 
 
1989
      /* Always set buttons state, a change in a future page
 
1990
         might change current page buttons */
 
1991
      set_assistant_buttons_state (assistant);
 
1992
 
 
1993
      gtk_widget_child_notify (page, "page-type");
 
1994
    }
 
1995
}
 
1996
 
 
1997
/**
 
1998
 * gtk_assistant_get_page_type:
 
1999
 * @assistant: a #GtkAssistant
 
2000
 * @page: a page of @assistant
 
2001
 *
 
2002
 * Gets the page type of @page.
 
2003
 *
 
2004
 * Return value: the page type of @page.
 
2005
 *
 
2006
 * Since: 2.10
 
2007
 **/
 
2008
GtkAssistantPageType
 
2009
gtk_assistant_get_page_type (GtkAssistant *assistant,
 
2010
                             GtkWidget    *page)
 
2011
{
 
2012
  GtkAssistantPage *page_info;
 
2013
  GList *child;
 
2014
 
 
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);
 
2017
 
 
2018
  child = find_page (assistant, page);
 
2019
 
 
2020
  g_return_val_if_fail (child != NULL, GTK_ASSISTANT_PAGE_CONTENT);
 
2021
 
 
2022
  page_info = (GtkAssistantPage*) child->data;
 
2023
 
 
2024
  return page_info->type;
 
2025
}
 
2026
 
 
2027
/**
 
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
 
2032
 *
 
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.
 
2035
 *
 
2036
 * Since: 2.10
 
2037
 **/
 
2038
void
 
2039
gtk_assistant_set_page_header_image (GtkAssistant *assistant,
 
2040
                                     GtkWidget    *page,
 
2041
                                     GdkPixbuf    *pixbuf)
 
2042
{
 
2043
  GtkAssistantPrivate *priv;
 
2044
  GtkAssistantPage *page_info;
 
2045
  GList *child;
 
2046
 
 
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));
 
2050
 
 
2051
  priv = assistant->priv;
 
2052
  child = find_page (assistant, page);
 
2053
 
 
2054
  g_return_if_fail (child != NULL);
 
2055
 
 
2056
  page_info = (GtkAssistantPage*) child->data;
 
2057
 
 
2058
  if (pixbuf != page_info->header_image)
 
2059
    {
 
2060
      if (page_info->header_image)
 
2061
        {
 
2062
          g_object_unref (page_info->header_image);
 
2063
          page_info->header_image = NULL;
 
2064
        }
 
2065
 
 
2066
      if (pixbuf)
 
2067
        page_info->header_image = g_object_ref (pixbuf);
 
2068
 
 
2069
      if (page_info == priv->current_page)
 
2070
        set_assistant_header_image (assistant);
 
2071
 
 
2072
      gtk_widget_child_notify (page, "header-image");
 
2073
    }
 
2074
}
 
2075
 
 
2076
/**
 
2077
 * gtk_assistant_get_page_header_image:
 
2078
 * @assistant: a #GtkAssistant
 
2079
 * @page: a page of @assistant
 
2080
 *
 
2081
 * Gets the header image for @page.
 
2082
 *
 
2083
 * Return value: (transfer none): the header image for @page, or %NULL
 
2084
 *     if there's no header image for the page.
 
2085
 *
 
2086
 * Since: 2.10
 
2087
 **/
 
2088
GdkPixbuf*
 
2089
gtk_assistant_get_page_header_image (GtkAssistant *assistant,
 
2090
                                     GtkWidget    *page)
 
2091
{
 
2092
  GtkAssistantPage *page_info;
 
2093
  GList *child;
 
2094
 
 
2095
  g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
 
2096
  g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
 
2097
 
 
2098
  child = find_page (assistant, page);
 
2099
 
 
2100
  g_return_val_if_fail (child != NULL, NULL);
 
2101
 
 
2102
  page_info = (GtkAssistantPage*) child->data;
 
2103
 
 
2104
  return page_info->header_image;
 
2105
}
 
2106
 
 
2107
/**
 
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
 
2112
 *
 
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.
 
2115
 *
 
2116
 * Since: 2.10
 
2117
 **/
 
2118
void
 
2119
gtk_assistant_set_page_side_image (GtkAssistant *assistant,
 
2120
                                   GtkWidget    *page,
 
2121
                                   GdkPixbuf    *pixbuf)
 
2122
{
 
2123
  GtkAssistantPrivate *priv;
 
2124
  GtkAssistantPage *page_info;
 
2125
  GList *child;
 
2126
 
 
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));
 
2130
 
 
2131
  priv = assistant->priv;
 
2132
  child = find_page (assistant, page);
 
2133
 
 
2134
  g_return_if_fail (child != NULL);
 
2135
 
 
2136
  page_info = (GtkAssistantPage*) child->data;
 
2137
 
 
2138
  if (pixbuf != page_info->sidebar_image)
 
2139
    {
 
2140
      if (page_info->sidebar_image)
 
2141
        {
 
2142
          g_object_unref (page_info->sidebar_image);
 
2143
          page_info->sidebar_image = NULL;
 
2144
        }
 
2145
 
 
2146
      if (pixbuf)
 
2147
        page_info->sidebar_image = g_object_ref (pixbuf);
 
2148
 
 
2149
      if (page_info == priv->current_page)
 
2150
        set_assistant_sidebar_image (assistant);
 
2151
 
 
2152
      gtk_widget_child_notify (page, "sidebar-image");
 
2153
    }
 
2154
}
 
2155
 
 
2156
/**
 
2157
 * gtk_assistant_get_page_side_image:
 
2158
 * @assistant: a #GtkAssistant
 
2159
 * @page: a page of @assistant
 
2160
 *
 
2161
 * Gets the header image for @page.
 
2162
 *
 
2163
 * Return value: (transfer none): the side image for @page, or %NULL
 
2164
 *     if there's no side image for the page.
 
2165
 *
 
2166
 * Since: 2.10
 
2167
 **/
 
2168
GdkPixbuf*
 
2169
gtk_assistant_get_page_side_image (GtkAssistant *assistant,
 
2170
                                   GtkWidget    *page)
 
2171
{
 
2172
  GtkAssistantPage *page_info;
 
2173
  GList *child;
 
2174
 
 
2175
  g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
 
2176
  g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
 
2177
 
 
2178
  child = find_page (assistant, page);
 
2179
 
 
2180
  g_return_val_if_fail (child != NULL, NULL);
 
2181
 
 
2182
  page_info = (GtkAssistantPage*) child->data;
 
2183
 
 
2184
  return page_info->sidebar_image;
 
2185
}
 
2186
 
 
2187
/**
 
2188
 * gtk_assistant_set_page_complete:
 
2189
 * @assistant: a #GtkAssistant
 
2190
 * @page: a page of @assistant
 
2191
 * @complete: the completeness status of the page
 
2192
 * 
 
2193
 * Sets whether @page contents are complete. This will make
 
2194
 * @assistant update the buttons state to be able to continue the task.
 
2195
 *
 
2196
 * Since: 2.10
 
2197
 **/
 
2198
void
 
2199
gtk_assistant_set_page_complete (GtkAssistant *assistant,
 
2200
                                 GtkWidget    *page,
 
2201
                                 gboolean      complete)
 
2202
{
 
2203
  GtkAssistantPrivate *priv;
 
2204
  GtkAssistantPage *page_info;
 
2205
  GList *child;
 
2206
 
 
2207
  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
 
2208
  g_return_if_fail (GTK_IS_WIDGET (page));
 
2209
 
 
2210
  priv = assistant->priv;
 
2211
  child = find_page (assistant, page);
 
2212
 
 
2213
  g_return_if_fail (child != NULL);
 
2214
 
 
2215
  page_info = (GtkAssistantPage*) child->data;
 
2216
 
 
2217
  if (complete != page_info->complete)
 
2218
    {
 
2219
      page_info->complete = complete;
 
2220
      page_info->complete_set = TRUE;
 
2221
 
 
2222
      /* Always set buttons state, a change in a future page
 
2223
         might change current page buttons */
 
2224
      set_assistant_buttons_state (assistant);
 
2225
 
 
2226
      gtk_widget_child_notify (page, "complete");
 
2227
    }
 
2228
}
 
2229
 
 
2230
/**
 
2231
 * gtk_assistant_get_page_complete:
 
2232
 * @assistant: a #GtkAssistant
 
2233
 * @page: a page of @assistant
 
2234
 * 
 
2235
 * Gets whether @page is complete.
 
2236
 * 
 
2237
 * Return value: %TRUE if @page is complete.
 
2238
 *
 
2239
 * Since: 2.10
 
2240
 **/
 
2241
gboolean
 
2242
gtk_assistant_get_page_complete (GtkAssistant *assistant,
 
2243
                                 GtkWidget    *page)
 
2244
{
 
2245
  GtkAssistantPage *page_info;
 
2246
  GList *child;
 
2247
 
 
2248
  g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), FALSE);
 
2249
  g_return_val_if_fail (GTK_IS_WIDGET (page), FALSE);
 
2250
 
 
2251
  child = find_page (assistant, page);
 
2252
 
 
2253
  g_return_val_if_fail (child != NULL, FALSE);
 
2254
 
 
2255
  page_info = (GtkAssistantPage*) child->data;
 
2256
 
 
2257
  return page_info->complete;
 
2258
}
 
2259
 
 
2260
/**
 
2261
 * gtk_assistant_update_buttons_state:
 
2262
 * @assistant: a #GtkAssistant
 
2263
 * 
 
2264
 * Forces @assistant to recompute the buttons state.
 
2265
 * 
 
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.
 
2269
 *
 
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.
 
2273
 *
 
2274
 * Since: 2.10
 
2275
 **/
 
2276
void
 
2277
gtk_assistant_update_buttons_state (GtkAssistant *assistant)
 
2278
{
 
2279
  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
 
2280
 
 
2281
  set_assistant_buttons_state (assistant);
 
2282
}
 
2283
 
 
2284
/**
 
2285
 * gtk_assistant_commit:
 
2286
 * @assistant: a #GtkAssistant
 
2287
 *
 
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.
 
2291
 *
 
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.
 
2297
 *
 
2298
 * Since: 2.22
 
2299
 **/
 
2300
void
 
2301
gtk_assistant_commit (GtkAssistant *assistant)
 
2302
{
 
2303
  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
 
2304
 
 
2305
  g_slist_free (assistant->priv->visited_pages);
 
2306
  assistant->priv->visited_pages = NULL;
 
2307
 
 
2308
  assistant->priv->committed = TRUE;
 
2309
 
 
2310
  set_assistant_buttons_state (assistant);
 
2311
}
 
2312
 
 
2313
 
 
2314
 
 
2315
/* accessible implementation */
 
2316
 
 
2317
static gint
 
2318
gtk_assistant_accessible_get_n_children (AtkObject *accessible)
 
2319
{
 
2320
  GtkAssistant *assistant;
 
2321
  GtkWidget *widget;
 
2322
 
 
2323
  widget = GTK_ACCESSIBLE (accessible)->widget;
 
2324
 
 
2325
  if (!widget)
 
2326
    return 0;
 
2327
 
 
2328
  assistant = GTK_ASSISTANT (widget);
 
2329
   
 
2330
  return g_list_length (assistant->priv->pages) + 1;
 
2331
}
 
2332
 
 
2333
 
 
2334
static AtkObject *
 
2335
gtk_assistant_accessible_ref_child (AtkObject *accessible,
 
2336
                                    gint       index)
 
2337
{
 
2338
  GtkAssistant *assistant;
 
2339
  GtkAssistantPrivate *priv;
 
2340
  GtkWidget *widget, *child;
 
2341
  gint n_pages;
 
2342
  AtkObject *obj;
 
2343
  const gchar *title;
 
2344
 
 
2345
  widget = GTK_ACCESSIBLE (accessible)->widget;
 
2346
  if (!widget)
 
2347
    return NULL;
 
2348
 
 
2349
  assistant = GTK_ASSISTANT (widget);
 
2350
  priv = assistant->priv;
 
2351
  n_pages = g_list_length (priv->pages);
 
2352
 
 
2353
  if (index < 0)
 
2354
    return NULL;
 
2355
  else if (index < n_pages)
 
2356
    {
 
2357
      GtkAssistantPage *page = g_list_nth_data (priv->pages, index);
 
2358
 
 
2359
      child = page->page;
 
2360
      title = gtk_assistant_get_page_title (assistant, child);
 
2361
    }
 
2362
  else if (index == n_pages)
 
2363
    {
 
2364
      child = priv->action_area;
 
2365
      title = NULL;
 
2366
    }
 
2367
  else
 
2368
    return NULL;
 
2369
  
 
2370
  obj = gtk_widget_get_accessible (child);
 
2371
 
 
2372
  if (title)
 
2373
    atk_object_set_name (obj, title);
 
2374
 
 
2375
  return g_object_ref (obj);
 
2376
}
 
2377
 
 
2378
static void
 
2379
gtk_assistant_accessible_class_init (AtkObjectClass *class)
 
2380
{
 
2381
  class->get_n_children = gtk_assistant_accessible_get_n_children;
 
2382
  class->ref_child = gtk_assistant_accessible_ref_child;
 
2383
}
 
2384
 
 
2385
static GType
 
2386
gtk_assistant_accessible_get_type (void)
 
2387
{
 
2388
  static GType type = 0;
 
2389
  
 
2390
  if (!type)
 
2391
    {
 
2392
      /*
 
2393
       * Figure out the size of the class and instance
 
2394
       * we are deriving from
 
2395
       */
 
2396
      AtkObjectFactory *factory;
 
2397
      GType derived_type;
 
2398
      GTypeQuery query;
 
2399
      GType derived_atk_type;
 
2400
 
 
2401
      derived_type = g_type_parent (GTK_TYPE_ASSISTANT);
 
2402
      factory = atk_registry_get_factory (atk_get_default_registry (),
 
2403
                                          derived_type);
 
2404
      derived_atk_type = atk_object_factory_get_accessible_type (factory);
 
2405
      g_type_query (derived_atk_type, &query);
 
2406
 
 
2407
      type = g_type_register_static_simple (derived_atk_type,
 
2408
                                            I_("GtkAssistantAccessible"),
 
2409
                                            query.class_size,
 
2410
                                            (GClassInitFunc) gtk_assistant_accessible_class_init,
 
2411
                                            query.instance_size,
 
2412
                                            NULL, 0);
 
2413
    }
 
2414
 
 
2415
  return type;
 
2416
}
 
2417
 
 
2418
static AtkObject *
 
2419
gtk_assistant_accessible_new (GObject *obj)
 
2420
{
 
2421
  AtkObject *accessible;
 
2422
 
 
2423
  g_return_val_if_fail (GTK_IS_ASSISTANT (obj), NULL);
 
2424
 
 
2425
  accessible = g_object_new (gtk_assistant_accessible_get_type (), NULL);
 
2426
  atk_object_initialize (accessible, obj);
 
2427
 
 
2428
  return accessible;
 
2429
}
 
2430
 
 
2431
static GType
 
2432
gtk_assistant_accessible_factory_get_accessible_type (void)
 
2433
{
 
2434
  return gtk_assistant_accessible_get_type ();
 
2435
}
 
2436
 
 
2437
static AtkObject*
 
2438
gtk_assistant_accessible_factory_create_accessible (GObject *obj)
 
2439
{
 
2440
  return gtk_assistant_accessible_new (obj);
 
2441
}
 
2442
 
 
2443
static void
 
2444
gtk_assistant_accessible_factory_class_init (AtkObjectFactoryClass *class)
 
2445
{
 
2446
  class->create_accessible = gtk_assistant_accessible_factory_create_accessible;
 
2447
  class->get_accessible_type = gtk_assistant_accessible_factory_get_accessible_type;
 
2448
}
 
2449
 
 
2450
static GType
 
2451
gtk_assistant_accessible_factory_get_type (void)
 
2452
{
 
2453
  static GType type = 0;
 
2454
 
 
2455
  if (!type)
 
2456
    {
 
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),
 
2462
                                            NULL, 0);
 
2463
    }
 
2464
 
 
2465
  return type;
 
2466
}
 
2467
 
 
2468
static AtkObject *
 
2469
gtk_assistant_get_accessible (GtkWidget *widget)
 
2470
{
 
2471
  static gboolean first_time = TRUE;
 
2472
 
 
2473
  if (first_time)
 
2474
    {
 
2475
      AtkObjectFactory *factory;
 
2476
      AtkRegistry *registry;
 
2477
      GType derived_type;
 
2478
      GType derived_atk_type;
 
2479
 
 
2480
      /*
 
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.
 
2484
       */
 
2485
      derived_type = g_type_parent (GTK_TYPE_ASSISTANT);
 
2486
 
 
2487
      registry = atk_get_default_registry ();
 
2488
      factory = atk_registry_get_factory (registry,
 
2489
                                          derived_type);
 
2490
      derived_atk_type = atk_object_factory_get_accessible_type (factory);
 
2491
      if (g_type_is_a (derived_atk_type, GTK_TYPE_ACCESSIBLE))
 
2492
        {
 
2493
          atk_registry_set_factory_type (registry,
 
2494
                                         GTK_TYPE_ASSISTANT,
 
2495
                                         gtk_assistant_accessible_factory_get_type ());
 
2496
        }
 
2497
      first_time = FALSE;
 
2498
    }
 
2499
 
 
2500
  return GTK_WIDGET_CLASS (gtk_assistant_parent_class)->get_accessible (widget);
 
2501
}
 
2502
 
 
2503
 
 
2504
static GtkBuildableIface *parent_buildable_iface;
 
2505
 
 
2506
static void
 
2507
gtk_assistant_buildable_interface_init (GtkBuildableIface *iface)
 
2508
{
 
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;
 
2513
}
 
2514
 
 
2515
static GObject *
 
2516
gtk_assistant_buildable_get_internal_child (GtkBuildable *buildable,
 
2517
                                            GtkBuilder   *builder,
 
2518
                                            const gchar  *childname)
 
2519
{
 
2520
    if (strcmp (childname, "action_area") == 0)
 
2521
      return G_OBJECT (GTK_ASSISTANT (buildable)->priv->action_area);
 
2522
 
 
2523
    return parent_buildable_iface->get_internal_child (buildable,
 
2524
                                                       builder,
 
2525
                                                       childname);
 
2526
}
 
2527
 
 
2528
gboolean
 
2529
gtk_assistant_buildable_custom_tag_start (GtkBuildable  *buildable,
 
2530
                                          GtkBuilder    *builder,
 
2531
                                          GObject       *child,
 
2532
                                          const gchar   *tagname,
 
2533
                                          GMarkupParser *parser,
 
2534
                                          gpointer      *data)
 
2535
{
 
2536
  return parent_buildable_iface->custom_tag_start (buildable, builder, child,
 
2537
                                                   tagname, parser, data);
 
2538
}
 
2539
 
 
2540
static void
 
2541
gtk_assistant_buildable_custom_finished (GtkBuildable *buildable,
 
2542
                                         GtkBuilder   *builder,
 
2543
                                         GObject      *child,
 
2544
                                         const gchar  *tagname,
 
2545
                                         gpointer      user_data)
 
2546
{
 
2547
  parent_buildable_iface->custom_finished (buildable, builder, child,
 
2548
                                           tagname, user_data);
 
2549
}
 
2550
 
 
2551
 
 
2552
#define __GTK_ASSISTANT_C__
 
2553
#include "gtkaliasdef.c"