]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkassistant.c
gtk: remove "gboolean homogeneous" from gtk_box_new()
[~andy/gtk] / gtk / gtkassistant.c
index 4999fa7be84c9d2a2013a06882bf66f78a106804..4374f1f5bc087f2414f5658c45e61727b5c1d709 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
-#include <config.h>
+/**
+ * SECTION:gtkassistant
+ * @Short_description: A widget used to guide users through multi-step operations
+ * @Title: GtkAssistant
+ *
+ * A #GtkAssistant is a widget used to represent a generally complex
+ * operation splitted in several steps, guiding the user through its pages
+ * and controlling the page flow to collect the necessary data.
+ *
+ * The design of GtkAssistant is that it controls what buttons to show and
+ * to make sensitive, based on what it knows about the page sequence and
+ * the <link linkend="GtkAssistantPageType">type</link> of each page, in
+ * addition to state information like the page
+ * <link linkend="gtk-assistant-set-page-complete">completion</link> and
+ * <link linkend="gtk-assistant-commit">committed</link> status.
+ *
+ * <refsect2 id="GtkAssistant-BUILDER-UI">
+ * <title>GtkAssistant as GtkBuildable</title>
+ * <para>
+ * The GtkAssistant implementation of the GtkBuildable interface exposes the
+ * @action_area as internal children with the name "action_area".
+ *
+ * To add pages to an assistant in GtkBuilder, simply add it as a
+ * &lt;child&gt; to the GtkAssistant object, and set its child properties
+ * as necessary.
+ * </para>
+ * </refsect2>
+ */
+
+#include "config.h"
+
+#include <atk/atk.h>
 
 #include "gtkassistant.h"
 
+#include "gtkaccessible.h"
 #include "gtkbutton.h"
 #include "gtkhbox.h"
 #include "gtkhbbox.h"
 #include "gtkimage.h"
 #include "gtklabel.h"
 #include "gtksizegroup.h"
+#include "gtksizerequest.h"
 #include "gtkstock.h"
 
 #include "gtkintl.h"
 #include "gtkprivate.h"
+#include "gtkbuildable.h"
 
-#include "gtkalias.h"
-
-#define GTK_ASSISTANT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_ASSISTANT, GtkAssistantPrivate))
 
 #define HEADER_SPACING 12
 #define ACTION_AREA_SPACING 12
@@ -51,7 +82,8 @@ struct _GtkAssistantPage
 {
   GtkWidget *page;
   GtkAssistantPageType type;
-  gboolean   complete;
+  guint      complete : 1;
+  guint      complete_set : 1;
 
   GtkWidget *title;
   GdkPixbuf *header_image;
@@ -60,6 +92,13 @@ struct _GtkAssistantPage
 
 struct _GtkAssistantPrivate
 {
+  GtkWidget *cancel;
+  GtkWidget *forward;
+  GtkWidget *back;
+  GtkWidget *apply;
+  GtkWidget *close;
+  GtkWidget *last;
+
   GtkWidget *header_image;
   GtkWidget *sidebar_image;
 
@@ -76,23 +115,29 @@ struct _GtkAssistantPrivate
   GtkAssistantPageFunc forward_function;
   gpointer forward_function_data;
   GDestroyNotify forward_data_destroy;
+
+  guint committed : 1;
 };
 
 static void     gtk_assistant_class_init         (GtkAssistantClass *class);
 static void     gtk_assistant_init               (GtkAssistant      *assistant);
-static void     gtk_assistant_destroy            (GtkObject         *object);
+static void     gtk_assistant_destroy            (GtkWidget         *widget);
 static void     gtk_assistant_style_set          (GtkWidget         *widget,
                                                  GtkStyle          *old_style);
-static void     gtk_assistant_size_request       (GtkWidget         *widget,
-                                                 GtkRequisition    *requisition);
+static void     gtk_assistant_get_preferred_width  (GtkWidget        *widget,
+                                                    gint             *minimum,
+                                                    gint             *natural);
+static void     gtk_assistant_get_preferred_height (GtkWidget        *widget,
+                                                    gint             *minimum,
+                                                    gint             *natural);
 static void     gtk_assistant_size_allocate      (GtkWidget         *widget,
                                                  GtkAllocation     *allocation);
 static void     gtk_assistant_map                (GtkWidget         *widget);
 static void     gtk_assistant_unmap              (GtkWidget         *widget);
 static gboolean gtk_assistant_delete_event       (GtkWidget         *widget,
                                                  GdkEventAny       *event);
-static gboolean gtk_assistant_expose             (GtkWidget         *widget,
-                                                 GdkEventExpose    *event);
+static gboolean gtk_assistant_draw               (GtkWidget         *widget,
+                                                 cairo_t           *cr);
 static gboolean gtk_assistant_focus              (GtkWidget         *widget,
                                                  GtkDirectionType   direction);
 static void     gtk_assistant_add                (GtkContainer      *container,
@@ -114,6 +159,27 @@ static void     gtk_assistant_get_child_property (GtkContainer      *container,
                                                  GValue            *value,
                                                  GParamSpec        *pspec);
 
+static AtkObject *gtk_assistant_get_accessible   (GtkWidget         *widget);
+
+static void       gtk_assistant_buildable_interface_init     (GtkBuildableIface *iface);
+static GObject   *gtk_assistant_buildable_get_internal_child (GtkBuildable  *buildable,
+                                                              GtkBuilder    *builder,
+                                                              const gchar   *childname);
+static gboolean   gtk_assistant_buildable_custom_tag_start   (GtkBuildable  *buildable,
+                                                              GtkBuilder    *builder,
+                                                              GObject       *child,
+                                                              const gchar   *tagname,
+                                                              GMarkupParser *parser,
+                                                              gpointer      *data);
+static void       gtk_assistant_buildable_custom_finished    (GtkBuildable  *buildable,
+                                                              GtkBuilder    *builder,
+                                                              GObject       *child,
+                                                              const gchar   *tagname,
+                                                              gpointer       user_data);
+
+static GList*     find_page                                  (GtkAssistant  *assistant,
+                                                              GtkWidget     *page);
+
 enum
 {
   CHILD_PROP_0,
@@ -136,32 +202,33 @@ enum
 static guint signals [LAST_SIGNAL] = { 0 };
 
 
-G_DEFINE_TYPE (GtkAssistant, gtk_assistant, GTK_TYPE_WINDOW);
+G_DEFINE_TYPE_WITH_CODE (GtkAssistant, gtk_assistant, GTK_TYPE_WINDOW,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                                gtk_assistant_buildable_interface_init))
 
 
 static void
 gtk_assistant_class_init (GtkAssistantClass *class)
 {
   GObjectClass *gobject_class;
-  GtkObjectClass *object_class;
   GtkWidgetClass *widget_class;
   GtkContainerClass *container_class;
 
   gobject_class   = (GObjectClass *) class;
-  object_class    = (GtkObjectClass *) class;
   widget_class    = (GtkWidgetClass *) class;
   container_class = (GtkContainerClass *) class;
 
-  object_class->destroy = gtk_assistant_destroy;
-
+  widget_class->destroy = gtk_assistant_destroy;
   widget_class->style_set = gtk_assistant_style_set;
-  widget_class->size_request = gtk_assistant_size_request;
+  widget_class->get_preferred_width = gtk_assistant_get_preferred_width;
+  widget_class->get_preferred_height = gtk_assistant_get_preferred_height;
   widget_class->size_allocate = gtk_assistant_size_allocate;
   widget_class->map = gtk_assistant_map;
   widget_class->unmap = gtk_assistant_unmap;
   widget_class->delete_event = gtk_assistant_delete_event;
-  widget_class->expose_event = gtk_assistant_expose;
+  widget_class->draw = gtk_assistant_draw;
   widget_class->focus = gtk_assistant_focus;
+  widget_class->get_accessible = gtk_assistant_get_accessible;
 
   container_class->add = gtk_assistant_add;
   container_class->remove = gtk_assistant_remove;
@@ -191,8 +258,8 @@ gtk_assistant_class_init (GtkAssistantClass *class)
    * @assistant: the #GtkAssistant
    * @page: the current page
    *
-   * The ::prepared signal is emitted when a new page is set as the assistant's 
-   * current page, before making the new page visible. A handler for this signal 
+   * The ::prepare signal is emitted when a new page is set as the assistant's
+   * current page, before making the new page visible. A handler for this signal
    * can do any preparation which are necessary before showing @page.
    *
    * Since: 2.10
@@ -208,17 +275,17 @@ gtk_assistant_class_init (GtkAssistantClass *class)
 
   /**
    * GtkAssistant::apply:
-   * @assistant: the @GtkAssistant
+   * @assistant: the #GtkAssistant
    *
    * The ::apply signal is emitted when the apply button is clicked. The default
-   * behavior of the #GtkAssistant is to switch to the page after the current page,
-   * unless the current page is the last one.
+   * behavior of the #GtkAssistant is to switch to the page after the current
+   * page, unless the current page is the last one.
    *
-   * A handler for the ::apply signal should carry out the actions for which the
-   * wizard has collected data. If the action takes a long time to complete, you
-   * might consider to put a page of type GTK_ASSISTANT_PAGE_PROGRESS after the
-   * confirmation page and handle this operation within the "prepare" signal of
-   * the progress page.
+   * A handler for the ::apply signal should carry out the actions for which
+   * the wizard has collected data. If the action takes a long time to complete,
+   * you might consider putting a page of type %GTK_ASSISTANT_PAGE_PROGRESS
+   * after the confirmation page and handle this operation within the
+   * #GtkAssistant::prepare signal of the progress page.
    *
    * Since: 2.10
    */
@@ -237,7 +304,7 @@ gtk_assistant_class_init (GtkAssistantClass *class)
    *
    * The ::close signal is emitted either when the close button of
    * a summary page is clicked, or when the apply button in the last
-   * page in the flow (of type GTK_ASSISTANT_PAGE_CONFIRM) is clicked.
+   * page in the flow (of type %GTK_ASSISTANT_PAGE_CONFIRM) is clicked.
    *
    * Since: 2.10
    */
@@ -270,7 +337,7 @@ gtk_assistant_class_init (GtkAssistantClass *class)
   /**
    * GtkAssistant:page-type:
    *
-   * The type of the assistant page. 
+   * The type of the assistant page.
    *
    * Since: 2.10
    */
@@ -286,7 +353,7 @@ gtk_assistant_class_init (GtkAssistantClass *class)
   /**
    * GtkAssistant:title:
    *
-   * The title that is displayed in the page header. 
+   * The title that is displayed in the page header.
    *
    * If title and header-image are both %NULL, no header is displayed.
    *
@@ -320,7 +387,7 @@ gtk_assistant_class_init (GtkAssistantClass *class)
   /**
    * GtkAssistant:header-image:
    *
-   * The image that is displayed next to the page. 
+   * The image that is displayed next to the page.
    *
    * Set this to %NULL to make the sidebar disappear.
    *
@@ -371,7 +438,7 @@ default_forward_function (gint current_page, gpointer data)
 
   page_info = (GtkAssistantPage *) page_node->data;
 
-  while (page_node && !GTK_WIDGET_VISIBLE (page_info->page))
+  while (page_node && !gtk_widget_get_visible (page_info->page))
     {
       page_node = page_node->next;
       current_page++;
@@ -404,23 +471,38 @@ compute_last_button_state (GtkAssistant *assistant)
       page_info = g_list_nth_data (priv->pages, page_num);
 
       count++;
-
-      g_assert (page_info);
     }
 
   /* make the last button visible if we can skip multiple
-   * pages and end on a confirmation or summary page 
+   * pages and end on a confirmation or summary page
    */
-  if (count > 1 && 
+  if (count > 1 && page_info &&
       (page_info->type == GTK_ASSISTANT_PAGE_CONFIRM ||
        page_info->type == GTK_ASSISTANT_PAGE_SUMMARY))
     {
-      gtk_widget_show (assistant->last);
-      gtk_widget_set_sensitive (assistant->last,
+      gtk_widget_show (priv->last);
+      gtk_widget_set_sensitive (priv->last,
                                current_page_info->complete);
     }
   else
-    gtk_widget_hide (assistant->last);
+    gtk_widget_hide (priv->last);
+}
+
+static void
+compute_progress_state (GtkAssistant *assistant)
+{
+  GtkAssistantPrivate *priv = assistant->priv;
+  gint page_num, n_pages;
+
+  n_pages = gtk_assistant_get_n_pages (assistant);
+  page_num = gtk_assistant_get_current_page (assistant);
+
+  page_num = (priv->forward_function) (page_num, priv->forward_function_data);
+
+  if (page_num >= 0 && page_num < n_pages)
+    gtk_widget_show (priv->forward);
+  else
+    gtk_widget_hide (priv->forward);
 }
 
 static void
@@ -451,68 +533,87 @@ set_assistant_buttons_state (GtkAssistant *assistant)
 {
   GtkAssistantPrivate *priv = assistant->priv;
 
+  if (!priv->current_page)
+    return;
+  
   switch (priv->current_page->type)
     {
     case GTK_ASSISTANT_PAGE_INTRO:
-      gtk_widget_set_sensitive (assistant->cancel, TRUE);
-      gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
-      gtk_widget_show (assistant->cancel);
-      gtk_widget_show (assistant->forward);
-      gtk_widget_hide (assistant->back);
-      gtk_widget_hide (assistant->apply);
-      gtk_widget_hide (assistant->close);
+      gtk_widget_set_sensitive (priv->cancel, TRUE);
+      gtk_widget_set_sensitive (priv->forward, priv->current_page->complete);
+      gtk_widget_grab_default (priv->forward);
+      gtk_widget_show (priv->forward);
+      gtk_widget_hide (priv->back);
+      gtk_widget_hide (priv->apply);
+      gtk_widget_hide (priv->close);
       compute_last_button_state (assistant);
       break;
     case GTK_ASSISTANT_PAGE_CONFIRM:
-      gtk_widget_set_sensitive (assistant->cancel, TRUE);
-      gtk_widget_set_sensitive (assistant->back, TRUE);
-      gtk_widget_set_sensitive (assistant->apply, priv->current_page->complete);
-      gtk_widget_show (assistant->cancel);
-      gtk_widget_show (assistant->back);
-      gtk_widget_show (assistant->apply);
-      gtk_widget_hide (assistant->forward);
-      gtk_widget_hide (assistant->close);
-      gtk_widget_hide (assistant->last);
+      gtk_widget_set_sensitive (priv->cancel, TRUE);
+      gtk_widget_set_sensitive (priv->back, TRUE);
+      gtk_widget_set_sensitive (priv->apply, priv->current_page->complete);
+      gtk_widget_grab_default (priv->apply);
+      gtk_widget_show (priv->back);
+      gtk_widget_show (priv->apply);
+      gtk_widget_hide (priv->forward);
+      gtk_widget_hide (priv->close);
+      gtk_widget_hide (priv->last);
       break;
     case GTK_ASSISTANT_PAGE_CONTENT:
-      gtk_widget_set_sensitive (assistant->cancel, TRUE);
-      gtk_widget_set_sensitive (assistant->back, TRUE);
-      gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
-      gtk_widget_show (assistant->cancel);
-      gtk_widget_show (assistant->back);
-      gtk_widget_show (assistant->forward);
-      gtk_widget_hide (assistant->apply);
-      gtk_widget_hide (assistant->close);
+      gtk_widget_set_sensitive (priv->cancel, TRUE);
+      gtk_widget_set_sensitive (priv->back, TRUE);
+      gtk_widget_set_sensitive (priv->forward, priv->current_page->complete);
+      gtk_widget_grab_default (priv->forward);
+      gtk_widget_show (priv->back);
+      gtk_widget_show (priv->forward);
+      gtk_widget_hide (priv->apply);
+      gtk_widget_hide (priv->close);
       compute_last_button_state (assistant);
       break;
     case GTK_ASSISTANT_PAGE_SUMMARY:
-      gtk_widget_set_sensitive (assistant->close, TRUE);
-      gtk_widget_show (assistant->close);
-      gtk_widget_hide (assistant->cancel);
-      gtk_widget_hide (assistant->back);
-      gtk_widget_hide (assistant->forward);
-      gtk_widget_hide (assistant->apply);
-      gtk_widget_hide (assistant->last);
+      gtk_widget_set_sensitive (priv->close, priv->current_page->complete);
+      gtk_widget_grab_default (priv->close);
+      gtk_widget_show (priv->close);
+      gtk_widget_hide (priv->back);
+      gtk_widget_hide (priv->forward);
+      gtk_widget_hide (priv->apply);
+      gtk_widget_hide (priv->last);
       break;
     case GTK_ASSISTANT_PAGE_PROGRESS:
-      gtk_widget_set_sensitive (assistant->cancel, priv->current_page->complete);
-      gtk_widget_set_sensitive (assistant->back, priv->current_page->complete);
-      gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
-      gtk_widget_show (assistant->cancel);
-      gtk_widget_show (assistant->back);
-      gtk_widget_show (assistant->forward);
-      gtk_widget_hide (assistant->apply);
-      gtk_widget_hide (assistant->close);
-      gtk_widget_hide (assistant->last);
+      gtk_widget_set_sensitive (priv->cancel, priv->current_page->complete);
+      gtk_widget_set_sensitive (priv->back, priv->current_page->complete);
+      gtk_widget_set_sensitive (priv->forward, priv->current_page->complete);
+      gtk_widget_grab_default (priv->forward);
+      gtk_widget_show (priv->back);
+      gtk_widget_hide (priv->apply);
+      gtk_widget_hide (priv->close);
+      gtk_widget_hide (priv->last);
+      compute_progress_state (assistant);
+      break;
+    case GTK_ASSISTANT_PAGE_CUSTOM:
+      gtk_widget_hide (priv->cancel);
+      gtk_widget_hide (priv->back);
+      gtk_widget_hide (priv->forward);
+      gtk_widget_hide (priv->apply);
+      gtk_widget_hide (priv->last);
+      gtk_widget_hide (priv->close);
       break;
     default:
       g_assert_not_reached ();
     }
 
+  if (priv->committed)
+    gtk_widget_hide (priv->cancel);
+  else if (priv->current_page->type == GTK_ASSISTANT_PAGE_SUMMARY ||
+           priv->current_page->type == GTK_ASSISTANT_PAGE_CUSTOM)
+    gtk_widget_hide (priv->cancel);
+  else
+    gtk_widget_show (priv->cancel);
+
   /* this is quite general, we don't want to
    * go back if it's the first page */
   if (!priv->visited_pages)
-    gtk_widget_hide (assistant->back);
+    gtk_widget_hide (priv->back);
 }
 
 static void
@@ -523,7 +624,7 @@ set_current_page (GtkAssistant     *assistant,
   GtkAssistantPage *old_page;
 
   if (priv->current_page &&
-      GTK_WIDGET_DRAWABLE (priv->current_page->page))
+      gtk_widget_is_drawable (priv->current_page->page))
     old_page = priv->current_page;
   else
     old_page = NULL;
@@ -536,20 +637,42 @@ set_current_page (GtkAssistant     *assistant,
 
   g_signal_emit (assistant, signals [PREPARE], 0, priv->current_page->page);
 
-  if (GTK_WIDGET_VISIBLE (priv->current_page->page) && GTK_WIDGET_MAPPED (assistant))
+  if (gtk_widget_get_visible (priv->current_page->page) && gtk_widget_get_mapped (GTK_WIDGET (assistant)))
     {
       gtk_widget_set_child_visible (priv->current_page->page, TRUE);
       gtk_widget_map (priv->current_page->page);
       gtk_widget_map (priv->current_page->title);
     }
   
-  if (old_page && GTK_WIDGET_MAPPED (old_page->page))
+  if (old_page && gtk_widget_get_mapped (old_page->page))
     {
       gtk_widget_set_child_visible (old_page->page, FALSE);
       gtk_widget_unmap (old_page->page);
       gtk_widget_unmap (old_page->title);
     }
 
+  if (!gtk_widget_child_focus (priv->current_page->page, GTK_DIR_TAB_FORWARD))
+    {
+      GtkWidget *button[6];
+      gint i;
+
+      /* find the best button to focus */
+      button[0] = priv->apply;
+      button[1] = priv->close;
+      button[2] = priv->forward;
+      button[3] = priv->back;
+      button[4] = priv->cancel;
+      button[5] = priv->last;
+      for (i = 0; i < 6; i++)
+        {
+          if (gtk_widget_get_visible (button[i]) && gtk_widget_get_sensitive (button[i]))
+            {
+              gtk_widget_grab_focus (button[i]);
+              break;
+            }
+        }
+    }
+
   gtk_widget_queue_resize (GTK_WIDGET (assistant));
 }
 
@@ -579,68 +702,53 @@ compute_next_step (GtkAssistant *assistant)
 }
 
 static void
-on_assistant_close (GtkWidget *widget, GtkAssistant *assistant)
+on_assistant_close (GtkWidget    *widget,
+                    GtkAssistant *assistant)
 {
   g_signal_emit (assistant, signals [CLOSE], 0, NULL);
 }
 
 static void
-on_assistant_apply (GtkWidget *widget, GtkAssistant *assistant)
+on_assistant_apply (GtkWidget    *widget,
+                    GtkAssistant *assistant)
 {
-  GtkAssistantPrivate *priv = assistant->priv;
   gboolean success;
 
-  success = compute_next_step (assistant);
+  g_signal_emit (assistant, signals [APPLY], 0);
 
-  g_signal_emit (assistant, signals [APPLY], 0, priv->current_page->page);
+  success = compute_next_step (assistant);
 
   /* if the assistant hasn't switched to another page, just emit
    * the CLOSE signal, it't the last page in the assistant flow
    */
   if (!success)
-    g_signal_emit (assistant, signals [CLOSE], 0, priv->current_page->page);
+    g_signal_emit (assistant, signals [CLOSE], 0);
 }
 
 static void
-on_assistant_forward (GtkWidget *widget, GtkAssistant *assistant)
+on_assistant_forward (GtkWidget    *widget,
+                      GtkAssistant *assistant)
 {
-  if (!compute_next_step (assistant))
-    g_critical ("Page flow is broken, you may want to end it with a page of "
-               "type GTK_ASSISTANT_PAGE_CONFIRM or GTK_ASSISTANT_PAGE_SUMMARY");
+  gtk_assistant_next_page (assistant);
 }
 
 static void
-on_assistant_back (GtkWidget *widget, GtkAssistant *assistant)
+on_assistant_back (GtkWidget    *widget,
+                   GtkAssistant *assistant)
 {
-  GtkAssistantPrivate *priv = assistant->priv;
-  GtkAssistantPage *page_info;
-  GSList *page_node;
-
-  /* skip the progress pages when going back */
-  do
-    {
-      page_node = priv->visited_pages;
-
-      g_return_if_fail (page_node != NULL);
-
-      priv->visited_pages = priv->visited_pages->next;
-      page_info = (GtkAssistantPage *) page_node->data;
-      g_slist_free_1 (page_node);
-    }
-  while (page_info->type == GTK_ASSISTANT_PAGE_PROGRESS ||
-        !GTK_WIDGET_VISIBLE (page_info->page));
-
-  set_current_page (assistant, page_info);
+  gtk_assistant_previous_page (assistant);
 }
 
 static void
-on_assistant_cancel (GtkWidget *widget, GtkAssistant *assistant)
+on_assistant_cancel (GtkWidget    *widget,
+                     GtkAssistant *assistant)
 {
   g_signal_emit (assistant, signals [CANCEL], 0, NULL);
 }
 
 static void
-on_assistant_last (GtkWidget *widget, GtkAssistant *assistant)
+on_assistant_last (GtkWidget    *widget,
+                   GtkAssistant *assistant)
 {
   GtkAssistantPrivate *priv = assistant->priv;
 
@@ -670,7 +778,13 @@ gtk_assistant_init (GtkAssistant *assistant)
 {
   GtkAssistantPrivate *priv;
 
-  priv = assistant->priv = GTK_ASSISTANT_GET_PRIVATE (assistant);
+  assistant->priv = G_TYPE_INSTANCE_GET_PRIVATE (assistant,
+                                                 GTK_TYPE_ASSISTANT,
+                                                 GtkAssistantPrivate);
+  priv = assistant->priv;
+
+  gtk_container_set_reallocate_redraws (GTK_CONTAINER (assistant), TRUE);
+  gtk_container_set_border_width (GTK_CONTAINER (assistant), 12);
 
   gtk_widget_push_composite_child ();
 
@@ -687,46 +801,49 @@ gtk_assistant_init (GtkAssistant *assistant)
   gtk_widget_show (priv->sidebar_image);
 
   /* Action area  */
-  priv->action_area  = gtk_hbox_new (FALSE, 6);
-  
-  assistant->close   = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
-  assistant->apply   = gtk_button_new_from_stock (GTK_STOCK_APPLY);
-  assistant->forward = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
-  assistant->back    = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
-  assistant->cancel  = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
-  assistant->last    = gtk_button_new_from_stock (GTK_STOCK_GOTO_LAST);
+  priv->action_area  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+  priv->close   = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
+  priv->apply   = gtk_button_new_from_stock (GTK_STOCK_APPLY);
+  priv->forward = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
+  priv->back    = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
+  priv->cancel  = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
+  priv->last    = gtk_button_new_from_stock (GTK_STOCK_GOTO_LAST);
+  gtk_widget_set_can_default (priv->close, TRUE);
+  gtk_widget_set_can_default (priv->apply, TRUE);
+  gtk_widget_set_can_default (priv->forward, TRUE);
 
   priv->size_group   = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
-  gtk_size_group_add_widget (priv->size_group, assistant->close);
-  gtk_size_group_add_widget (priv->size_group, assistant->apply);
-  gtk_size_group_add_widget (priv->size_group, assistant->forward);
-  gtk_size_group_add_widget (priv->size_group, assistant->back);
-  gtk_size_group_add_widget (priv->size_group, assistant->cancel);
-  gtk_size_group_add_widget (priv->size_group, assistant->last);
+  gtk_size_group_add_widget (priv->size_group, priv->close);
+  gtk_size_group_add_widget (priv->size_group, priv->apply);
+  gtk_size_group_add_widget (priv->size_group, priv->forward);
+  gtk_size_group_add_widget (priv->size_group, priv->back);
+  gtk_size_group_add_widget (priv->size_group, priv->cancel);
+  gtk_size_group_add_widget (priv->size_group, priv->last);
 
   if (!alternative_button_order (assistant))
     {
-      gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->apply, FALSE, FALSE, 0);
-      gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->forward, FALSE, FALSE, 0);
-      gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->back, FALSE, FALSE, 0);
-      gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->last, FALSE, FALSE, 0);
-      gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->cancel, FALSE, FALSE, 0);
-      gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->close, FALSE, FALSE, 0);
+      gtk_box_pack_end (GTK_BOX (priv->action_area), priv->apply, FALSE, FALSE, 0);
+      gtk_box_pack_end (GTK_BOX (priv->action_area), priv->forward, FALSE, FALSE, 0);
+      gtk_box_pack_end (GTK_BOX (priv->action_area), priv->back, FALSE, FALSE, 0);
+      gtk_box_pack_end (GTK_BOX (priv->action_area), priv->last, FALSE, FALSE, 0);
+      gtk_box_pack_end (GTK_BOX (priv->action_area), priv->cancel, FALSE, FALSE, 0);
+      gtk_box_pack_end (GTK_BOX (priv->action_area), priv->close, FALSE, FALSE, 0);
     }
   else
     {
-      gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->close, FALSE, FALSE, 0);
-      gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->cancel, FALSE, FALSE, 0);
-      gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->last, FALSE, FALSE, 0);
-      gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->back, FALSE, FALSE, 0);
-      gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->forward, FALSE, FALSE, 0);
-      gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->apply, FALSE, FALSE, 0);
+      gtk_box_pack_end (GTK_BOX (priv->action_area), priv->close, FALSE, FALSE, 0);
+      gtk_box_pack_end (GTK_BOX (priv->action_area), priv->cancel, FALSE, FALSE, 0);
+      gtk_box_pack_end (GTK_BOX (priv->action_area), priv->apply, FALSE, FALSE, 0);
+      gtk_box_pack_end (GTK_BOX (priv->action_area), priv->forward, FALSE, FALSE, 0);
+      gtk_box_pack_end (GTK_BOX (priv->action_area), priv->back, FALSE, FALSE, 0);
+      gtk_box_pack_end (GTK_BOX (priv->action_area), priv->last, FALSE, FALSE, 0);
     }
 
   gtk_widget_set_parent (priv->action_area, GTK_WIDGET (assistant));
-  gtk_widget_show (assistant->forward);
-  gtk_widget_show (assistant->back);
-  gtk_widget_show (assistant->cancel);
+  gtk_widget_show (priv->forward);
+  gtk_widget_show (priv->back);
+  gtk_widget_show (priv->cancel);
   gtk_widget_show (priv->action_area);
 
   gtk_widget_pop_composite_child ();
@@ -739,17 +856,17 @@ gtk_assistant_init (GtkAssistant *assistant)
   priv->forward_function_data = assistant;
   priv->forward_data_destroy = NULL;
 
-  g_signal_connect (G_OBJECT (assistant->close), "clicked",
+  g_signal_connect (G_OBJECT (priv->close), "clicked",
                    G_CALLBACK (on_assistant_close), assistant);
-  g_signal_connect (G_OBJECT (assistant->apply), "clicked",
+  g_signal_connect (G_OBJECT (priv->apply), "clicked",
                    G_CALLBACK (on_assistant_apply), assistant);
-  g_signal_connect (G_OBJECT (assistant->forward), "clicked",
+  g_signal_connect (G_OBJECT (priv->forward), "clicked",
                    G_CALLBACK (on_assistant_forward), assistant);
-  g_signal_connect (G_OBJECT (assistant->back), "clicked",
+  g_signal_connect (G_OBJECT (priv->back), "clicked",
                    G_CALLBACK (on_assistant_back), assistant);
-  g_signal_connect (G_OBJECT (assistant->cancel), "clicked",
+  g_signal_connect (G_OBJECT (priv->cancel), "clicked",
                    G_CALLBACK (on_assistant_cancel), assistant);
-  g_signal_connect (G_OBJECT (assistant->last), "clicked",
+  g_signal_connect (G_OBJECT (priv->last), "clicked",
                    G_CALLBACK (on_assistant_last), assistant);
 }
 
@@ -831,7 +948,7 @@ on_page_notify_visibility (GtkWidget  *widget,
   GtkAssistant *assistant = GTK_ASSISTANT (data);
 
   /* update buttons state, flow may have changed */
-  if (GTK_WIDGET_MAPPED (assistant))
+  if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
     set_assistant_buttons_state (assistant);
 }
 
@@ -841,12 +958,32 @@ remove_page (GtkAssistant *assistant,
 {
   GtkAssistantPrivate *priv = assistant->priv;
   GtkAssistantPage *page_info;
+  GList *page_node;
 
   page_info = element->data;
 
-  /* If we are mapped and visible, we want to deal with changing the page. */
-  if ((GTK_WIDGET_MAPPED (page_info->page)) && (page_info == priv->current_page))
-    compute_next_step (assistant);
+  /* If this is the current page, we need to switch away. */
+  if (page_info == priv->current_page)
+    {
+      if (!compute_next_step (assistant))
+        {
+         /* The best we can do at this point is probably to pick the first
+          * visible page.
+          */
+         page_node = priv->pages;
+
+         while (page_node && !gtk_widget_get_visible (((GtkAssistantPage *) page_node->data)->page))
+           page_node = page_node->next;
+
+          if (page_node == element)
+            page_node = page_node->next;
+
+         if (page_node)
+           priv->current_page = page_node->data;
+         else
+           priv->current_page = NULL;
+        }
+    }
 
   priv->pages = g_list_remove_link (priv->pages, element);
   priv->visited_pages = g_slist_remove_all (priv->visited_pages, page_info);
@@ -861,14 +998,14 @@ remove_page (GtkAssistant *assistant,
     g_object_unref (page_info->sidebar_image);
 
   gtk_widget_destroy (page_info->title);
-  g_free (page_info);
+  g_slice_free (GtkAssistantPage, page_info);
   g_list_free_1 (element);
 }
 
 static void
-gtk_assistant_destroy (GtkObject *object)
+gtk_assistant_destroy (GtkWidget *widget)
 {
-  GtkAssistant *assistant = GTK_ASSISTANT (object);
+  GtkAssistant *assistant = GTK_ASSISTANT (widget);
   GtkAssistantPrivate *priv = assistant->priv;
 
   if (priv->header_image)
@@ -917,9 +1054,9 @@ gtk_assistant_destroy (GtkObject *object)
   priv->current_page = NULL;
 
   while (priv->pages)
-    remove_page (GTK_ASSISTANT (object), priv->pages);
-      
-  GTK_OBJECT_CLASS (gtk_assistant_parent_class)->destroy (object);
+    remove_page (assistant, priv->pages);
+
+  GTK_WIDGET_CLASS (gtk_assistant_parent_class)->destroy (widget);
 }
 
 static GList*
@@ -963,7 +1100,7 @@ set_title_font (GtkWidget *assistant,
   gint size;
 
   desc = pango_font_description_new ();
-  size = pango_font_description_get_size (assistant->style->font_desc);
+  size = pango_font_description_get_size (gtk_widget_get_style (assistant)->font_desc);
 
   pango_font_description_set_weight (desc, PANGO_WEIGHT_ULTRABOLD);
   pango_font_description_set_size   (desc, size * PANGO_SCALE_XX_LARGE);
@@ -1002,6 +1139,7 @@ gtk_assistant_size_request (GtkWidget      *widget,
   GtkRequisition child_requisition;
   gint header_padding, content_padding;
   gint width, height, header_width, header_height;
+  guint border_width;
   GList *list;
 
   gtk_widget_style_get (widget,
@@ -1017,11 +1155,13 @@ gtk_assistant_size_request (GtkWidget      *widget,
       GtkAssistantPage *page = list->data;
       gint w, h;
 
-      gtk_widget_size_request (page->page, &child_requisition);
+      gtk_widget_get_preferred_size (page->page,
+                                     &child_requisition, NULL);
       width  = MAX (width,  child_requisition.width);
       height = MAX (height, child_requisition.height);
 
-      gtk_widget_size_request (page->title, &child_requisition);
+      gtk_widget_get_preferred_size (page->title,
+                                     &child_requisition, NULL);
       w = child_requisition.width;
       h = child_requisition.height;
 
@@ -1037,35 +1177,65 @@ gtk_assistant_size_request (GtkWidget      *widget,
       list = list->next;
     }
 
-  gtk_widget_size_request (priv->sidebar_image, &child_requisition);
+  gtk_widget_get_preferred_size (priv->sidebar_image,
+                                 &child_requisition, NULL);
   width  += child_requisition.width;
   height  = MAX (height, child_requisition.height);
 
   gtk_widget_set_size_request (priv->header_image, header_width, header_height);
-  gtk_widget_size_request (priv->header_image, &child_requisition);
+  gtk_widget_get_preferred_size (priv->header_image,
+                                 &child_requisition, NULL);
   width   = MAX (width, header_width) + 2 * header_padding;
   height += header_height + 2 * header_padding;
 
-  gtk_widget_size_request (priv->action_area, &child_requisition);
+  gtk_widget_get_preferred_size (priv->action_area,
+                                 &child_requisition, NULL);
   width   = MAX (width, child_requisition.width);
   height += child_requisition.height + ACTION_AREA_SPACING;
 
-  width += GTK_CONTAINER (widget)->border_width * 2 + content_padding * 2;
-  height += GTK_CONTAINER (widget)->border_width * 2 + content_padding * 2;
+  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+  width += border_width * 2 + content_padding * 2;
+  height += border_width * 2 + content_padding * 2;
 
   requisition->width = width;
   requisition->height = height;
 }
 
+static void
+gtk_assistant_get_preferred_width (GtkWidget *widget,
+                                   gint      *minimum,
+                                   gint      *natural)
+{
+  GtkRequisition requisition;
+
+  gtk_assistant_size_request (widget, &requisition);
+
+  *minimum = *natural = requisition.width;
+}
+
+static void
+gtk_assistant_get_preferred_height (GtkWidget *widget,
+                                    gint      *minimum,
+                                    gint      *natural)
+{
+  GtkRequisition requisition;
+
+  gtk_assistant_size_request (widget, &requisition);
+
+  *minimum = *natural = requisition.height;
+}
+
 static void
 gtk_assistant_size_allocate (GtkWidget      *widget,
                             GtkAllocation  *allocation)
 {
   GtkAssistant *assistant = GTK_ASSISTANT (widget);
   GtkAssistantPrivate *priv = assistant->priv;
-  GtkRequisition header_requisition;
+  GtkRequisition header_requisition, action_requisition, sidebar_requisition;
   GtkAllocation child_allocation, header_allocation;
+  GtkAllocation action_area_allocation, header_image_allocation;
   gint header_padding, content_padding;
+  guint border_width;
   gboolean rtl;
   GList *pages;
 
@@ -1077,56 +1247,68 @@ gtk_assistant_size_allocate (GtkWidget      *widget,
                        "content-padding", &content_padding,
                        NULL);
 
-  widget->allocation = *allocation;
+  gtk_widget_set_allocation (widget, allocation);
+  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
 
   /* Header */
-  gtk_widget_get_child_requisition (priv->header_image, &header_requisition);
+  gtk_widget_get_preferred_size (priv->header_image,
+                                 &header_requisition, NULL);
 
-  header_allocation.x = allocation->x + GTK_CONTAINER (widget)->border_width + header_padding;
-  header_allocation.y = allocation->y + GTK_CONTAINER (widget)->border_width + header_padding;
-  header_allocation.width  = allocation->width - 2 * GTK_CONTAINER (widget)->border_width - 2 * header_padding;
+  header_allocation.x = border_width + header_padding;
+  header_allocation.y = border_width + header_padding;
+  header_allocation.width  = allocation->width - 2 * border_width - 2 * header_padding;
   header_allocation.height = header_requisition.height;
 
   gtk_widget_size_allocate (priv->header_image, &header_allocation);
 
   /* Action area */
-  child_allocation.x = allocation->x + GTK_CONTAINER (widget)->border_width;
-  child_allocation.y = allocation->y + allocation->height -
-    GTK_CONTAINER (widget)->border_width - priv->action_area->requisition.height;
-  child_allocation.width  = allocation->width - 2 * GTK_CONTAINER (widget)->border_width;
-  child_allocation.height = priv->action_area->requisition.height;
+  gtk_widget_get_preferred_size (priv->action_area,
+                                 &action_requisition, NULL);
+
+  child_allocation.x = border_width;
+  child_allocation.y = allocation->height - border_width - action_requisition.height;
+  child_allocation.width  = allocation->width - 2 * border_width;
+  child_allocation.height = action_requisition.height;
 
   gtk_widget_size_allocate (priv->action_area, &child_allocation);
 
+  gtk_widget_get_allocation (priv->header_image, &header_image_allocation);
+  gtk_widget_get_allocation (priv->action_area, &action_area_allocation);
+
   /* Sidebar */
+  gtk_widget_get_preferred_size (priv->sidebar_image,
+                                 &sidebar_requisition, NULL);
+
   if (rtl)
-    child_allocation.x = allocation->x + allocation->width -
-      GTK_CONTAINER (widget)->border_width - priv->sidebar_image->requisition.width;
+    child_allocation.x = allocation->width - border_width - sidebar_requisition.width;
   else
-    child_allocation.x = allocation->x + GTK_CONTAINER (widget)->border_width;
+    child_allocation.x = border_width;
 
-  child_allocation.y = allocation->y + GTK_CONTAINER (widget)->border_width +
-    priv->header_image->allocation.height + 2 * header_padding;
-  child_allocation.width = priv->sidebar_image->requisition.width;
-  child_allocation.height = allocation->height - 2 * GTK_CONTAINER (widget)->border_width -
-    priv->header_image->allocation.height - 2 * header_padding - priv->action_area->allocation.height;
+  child_allocation.y = border_width + header_image_allocation.height + 2 * header_padding;
+  child_allocation.width = sidebar_requisition.width;
+  child_allocation.height = allocation->height - 2 * border_width -
+    header_image_allocation.height - 2 * header_padding - action_area_allocation.height;
 
   gtk_widget_size_allocate (priv->sidebar_image, &child_allocation);
 
   /* Pages */
-  child_allocation.x = allocation->x + GTK_CONTAINER (widget)->border_width + content_padding;
-  child_allocation.y = allocation->y + GTK_CONTAINER (widget)->border_width +
-    priv->header_image->allocation.height + 2 * header_padding + content_padding;
-  child_allocation.width  = allocation->width - 2 * GTK_CONTAINER (widget)->border_width - 2 * content_padding;
-  child_allocation.height = allocation->height - 2 * GTK_CONTAINER (widget)->border_width -
-    priv->header_image->allocation.height - 2 * header_padding - ACTION_AREA_SPACING - priv->action_area->allocation.height - 2 * content_padding;
-
-  if (GTK_WIDGET_VISIBLE (priv->sidebar_image))
+  child_allocation.x = border_width + content_padding;
+  child_allocation.y = border_width +
+    header_image_allocation.height + 2 * header_padding + content_padding;
+  child_allocation.width  = allocation->width - 2 * border_width - 2 * content_padding;
+  child_allocation.height = allocation->height - 2 * border_width -
+    header_image_allocation.height - 2 * header_padding - ACTION_AREA_SPACING - action_area_allocation.height - 2 * content_padding;
+
+  if (gtk_widget_get_visible (priv->sidebar_image))
     {
+      GtkAllocation sidebar_image_allocation;
+
+      gtk_widget_get_allocation (priv->sidebar_image, &sidebar_image_allocation);
+
       if (!rtl)
-       child_allocation.x += priv->sidebar_image->allocation.width;
+       child_allocation.x += sidebar_image_allocation.width;
 
-      child_allocation.width -= priv->sidebar_image->allocation.width;
+      child_allocation.width -= sidebar_image_allocation.width;
     }
 
   while (pages)
@@ -1145,41 +1327,34 @@ gtk_assistant_map (GtkWidget *widget)
   GtkAssistant *assistant = GTK_ASSISTANT (widget);
   GtkAssistantPrivate *priv = assistant->priv;
   GList *page_node;
+  GtkAssistantPage *page;
 
-  GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+  gtk_widget_set_mapped (widget, TRUE);
 
   gtk_widget_map (priv->header_image);
   gtk_widget_map (priv->action_area);
 
-  if (GTK_WIDGET_VISIBLE (priv->sidebar_image) &&
-      !GTK_WIDGET_MAPPED (priv->sidebar_image))
+  if (gtk_widget_get_visible (priv->sidebar_image) &&
+      !gtk_widget_get_mapped (priv->sidebar_image))
     gtk_widget_map (priv->sidebar_image);
 
   /* if there's no default page, pick the first one */
-  if (!priv->current_page && priv->pages)
+  page = NULL;
+  if (!priv->current_page)
     {
       page_node = priv->pages;
 
-      while (page_node && !GTK_WIDGET_VISIBLE (((GtkAssistantPage *) page_node->data)->page))
+      while (page_node && !gtk_widget_get_visible (((GtkAssistantPage *) page_node->data)->page))
        page_node = page_node->next;
 
       if (page_node)
-       priv->current_page = page_node->data;
+       page = page_node->data;
     }
 
-  if (priv->current_page &&
-      GTK_WIDGET_VISIBLE (priv->current_page->page) &&
-      !GTK_WIDGET_MAPPED (priv->current_page->page))
-    {
-      set_assistant_buttons_state ((GtkAssistant *) widget);
-      set_assistant_header_image ((GtkAssistant*) widget);
-      set_assistant_sidebar_image ((GtkAssistant*) widget);
-
-      g_signal_emit (widget, signals [PREPARE], 0, priv->current_page->page);
-      gtk_widget_set_child_visible (priv->current_page->page, TRUE);
-      gtk_widget_map (priv->current_page->page);
-      gtk_widget_map (priv->current_page->title);
-    }
+  if (page &&
+      gtk_widget_get_visible (page->page) &&
+      !gtk_widget_get_mapped (page->page))
+    set_current_page (assistant, page);
 
   GTK_WIDGET_CLASS (gtk_assistant_parent_class)->map (widget);
 }
@@ -1190,16 +1365,16 @@ gtk_assistant_unmap (GtkWidget *widget)
   GtkAssistant *assistant = GTK_ASSISTANT (widget);
   GtkAssistantPrivate *priv = assistant->priv;
 
-  GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+  gtk_widget_set_mapped (widget, FALSE);
 
   gtk_widget_unmap (priv->header_image);
   gtk_widget_unmap (priv->action_area);
 
-  if (GTK_WIDGET_DRAWABLE (priv->sidebar_image))
+  if (gtk_widget_is_drawable (priv->sidebar_image))
     gtk_widget_unmap (priv->sidebar_image);
 
   if (priv->current_page &&
-      GTK_WIDGET_DRAWABLE (priv->current_page->page))
+      gtk_widget_is_drawable (priv->current_page->page))
     gtk_widget_unmap (priv->current_page->page);
 
   g_slist_free (priv->visited_pages);
@@ -1226,16 +1401,17 @@ gtk_assistant_delete_event (GtkWidget   *widget,
 }
 
 static void
-assistant_paint_colored_box (GtkWidget *widget)
+assistant_paint_colored_box (GtkWidget *widget,
+                             cairo_t   *cr)
 {
   GtkAssistant *assistant = GTK_ASSISTANT (widget);
   GtkAssistantPrivate *priv = assistant->priv;
+  GtkAllocation allocation, action_area_allocation, header_image_allocation;
+  GtkStyle *style;
   gint border_width, header_padding, content_padding;
-  cairo_t *cr;
   gint content_x, content_width;
   gboolean rtl;
 
-  cr   = gdk_cairo_create (widget->window);
   rtl  = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
   border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
 
@@ -1244,62 +1420,67 @@ assistant_paint_colored_box (GtkWidget *widget)
                        "content-padding", &content_padding,
                        NULL);
 
+  style = gtk_widget_get_style (widget);
+  gtk_widget_get_allocation (widget, &allocation);
+  gtk_widget_get_allocation (priv->action_area, &action_area_allocation);
+  gtk_widget_get_allocation (priv->header_image, &header_image_allocation);
+
   /* colored box */
-  gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_SELECTED]);
+  gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_SELECTED]);
   cairo_rectangle (cr,
                   border_width,
                   border_width,
-                  widget->allocation.width - 2 * border_width,
-                  widget->allocation.height - priv->action_area->allocation.height - 2 * border_width - ACTION_AREA_SPACING);
+                   allocation.width - 2 * border_width,
+                   allocation.height - action_area_allocation.height - 2 * border_width - ACTION_AREA_SPACING);
   cairo_fill (cr);
 
   /* content box */
   content_x = content_padding + border_width;
-  content_width = widget->allocation.width - 2 * content_padding - 2 * border_width;
+  content_width = allocation.width - 2 * content_padding - 2 * border_width;
 
-  if (GTK_WIDGET_VISIBLE (priv->sidebar_image))
+  if (gtk_widget_get_visible (priv->sidebar_image))
     {
+      GtkAllocation sidebar_image_allocation;
+
+      gtk_widget_get_allocation (priv->sidebar_image, &sidebar_image_allocation);
+
       if (!rtl)
-       content_x += priv->sidebar_image->allocation.width;
-      content_width -= priv->sidebar_image->allocation.width;
+       content_x += sidebar_image_allocation.width;
+      content_width -= sidebar_image_allocation.width;
     }
-  
-  gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_NORMAL]);
+
+  gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]);
 
   cairo_rectangle (cr,
                   content_x,
-                  priv->header_image->allocation.height + content_padding + 2 * header_padding + border_width,
+                  header_image_allocation.height + content_padding + 2 * header_padding + border_width,
                   content_width,
-                  widget->allocation.height - 2 * border_width - priv->action_area->allocation.height -
-                  priv->header_image->allocation.height - 2 * content_padding - 2 * header_padding - ACTION_AREA_SPACING);
+                  allocation.height - 2 * border_width - action_area_allocation.height -
+                  header_image_allocation.height - 2 * content_padding - 2 * header_padding - ACTION_AREA_SPACING);
   cairo_fill (cr);
-
-  cairo_destroy (cr);
 }
 
 static gboolean
-gtk_assistant_expose (GtkWidget      *widget,
-                     GdkEventExpose *event)
+gtk_assistant_draw (GtkWidget *widget,
+                   cairo_t   *cr)
 {
   GtkAssistant *assistant = GTK_ASSISTANT (widget);
   GtkAssistantPrivate *priv = assistant->priv;
-  GtkContainer *container;
+  GtkContainer *container = GTK_CONTAINER (widget);
 
-  if (GTK_WIDGET_DRAWABLE (widget))
-    {
-      container = GTK_CONTAINER (widget);
+  if (GTK_WIDGET_CLASS (gtk_assistant_parent_class)->draw)
+    GTK_WIDGET_CLASS (gtk_assistant_parent_class)->draw (widget, cr);
 
-      assistant_paint_colored_box (widget);
+  assistant_paint_colored_box (widget, cr);
 
-      gtk_container_propagate_expose (container, priv->header_image, event);
-      gtk_container_propagate_expose (container, priv->sidebar_image, event);
-      gtk_container_propagate_expose (container, priv->action_area, event);
+  gtk_container_propagate_draw (container, priv->header_image, cr);
+  gtk_container_propagate_draw (container, priv->sidebar_image, cr);
+  gtk_container_propagate_draw (container, priv->action_area, cr);
 
-      if (priv->current_page)
-       {
-         gtk_container_propagate_expose (container, priv->current_page->page, event);
-         gtk_container_propagate_expose (container, priv->current_page->title, event);
-       }
+  if (priv->current_page)
+    {
+      gtk_container_propagate_draw (container, priv->current_page->page, cr);
+      gtk_container_propagate_draw (container, priv->current_page->title, cr);
     }
 
   return FALSE;
@@ -1316,10 +1497,11 @@ gtk_assistant_focus (GtkWidget        *widget,
   priv = GTK_ASSISTANT (widget)->priv;
 
   /* we only have to care about 2 widgets, action area and the current page */
-  if (container->focus_child == priv->action_area)
+  if (gtk_container_get_focus_child (container) == priv->action_area)
     {
       if (!gtk_widget_child_focus (priv->action_area, direction) &&
-         !gtk_widget_child_focus (priv->current_page->page, direction))
+         (priv->current_page == NULL ||
+          !gtk_widget_child_focus (priv->current_page->page, direction)))
        {
          /* if we're leaving the action area and the current page hasn't
             any focusable widget, clear focus and go back to the action area */
@@ -1329,13 +1511,15 @@ gtk_assistant_focus (GtkWidget        *widget,
     }
   else
     {
-      if (!gtk_widget_child_focus (priv->current_page->page, direction) &&
+      if ((priv->current_page ==  NULL ||
+          !gtk_widget_child_focus (priv->current_page->page, direction)) &&
          !gtk_widget_child_focus (priv->action_area, direction))
        {
          /* if we're leaving the current page and there isn't nothing focusable
             in the action area, try to clear focus and go back to the page */
          gtk_window_set_focus (GTK_WINDOW (widget), NULL);
-         gtk_widget_child_focus (priv->current_page->page, direction);
+         if (priv->current_page != NULL)
+           gtk_widget_child_focus (priv->current_page->page, direction);
        }
     }
 
@@ -1346,8 +1530,6 @@ static void
 gtk_assistant_add (GtkContainer *container,
                   GtkWidget    *page)
 {
-  g_return_if_fail (GTK_IS_WIDGET (page));
-
   gtk_assistant_append_page (GTK_ASSISTANT (container), page);
 }
 
@@ -1355,11 +1537,9 @@ static void
 gtk_assistant_remove (GtkContainer *container,
                      GtkWidget    *page)
 {
-  GtkAssistant *assistant;
+  GtkAssistant *assistant = (GtkAssistant*) container;
   GList *element;
 
-  assistant = (GtkAssistant*) container;
-
   element = find_page (assistant, page);
 
   if (element)
@@ -1415,9 +1595,8 @@ gtk_assistant_new (void)
 {
   GtkWidget *assistant;
 
-  assistant = g_object_new (GTK_TYPE_ASSISTANT,
-                           "border-width", 12,
-                           NULL);
+  assistant = g_object_new (GTK_TYPE_ASSISTANT, NULL);
+
   return assistant;
 }
 
@@ -1475,7 +1654,7 @@ gtk_assistant_set_current_page (GtkAssistant *assistant,
   if (page_num >= 0)
     page = (GtkAssistantPage *) g_list_nth_data (priv->pages, page_num);
   else
-    page = (GtkAssistantPage *) g_list_last (priv->pages);
+    page = (GtkAssistantPage *) g_list_last (priv->pages)->data;
 
   g_return_if_fail (page != NULL);
 
@@ -1487,12 +1666,80 @@ gtk_assistant_set_current_page (GtkAssistant *assistant,
    * initial page setting, for the cases where the
    * initial page is != to 0
    */
-  if (GTK_WIDGET_MAPPED (assistant))
-    priv->visited_pages = g_slist_prepend (priv->visited_pages, page);
+  if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
+    priv->visited_pages = g_slist_prepend (priv->visited_pages,
+                                          priv->current_page);
 
   set_current_page (assistant, page);
 }
 
+/**
+ * gtk_assistant_next_page:
+ * @assistant: a #GtkAssistant
+ *
+ * Navigate to the next page. It is a programming
+ *  error to call this function if there is no next page.
+ *
+ * This function is for use when creating pages of the
+ *  #GTK_ASSISTANT_PAGE_CUSTOM type.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_assistant_next_page (GtkAssistant *assistant)
+{
+  GtkAssistantPrivate *priv;
+
+  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
+
+  priv = assistant->priv;
+
+  if (!compute_next_step (assistant))
+    g_critical ("Page flow is broken, you may want to end it with a page of "
+               "type GTK_ASSISTANT_PAGE_CONFIRM or GTK_ASSISTANT_PAGE_SUMMARY");
+}
+
+/**
+ * gtk_assistant_previous_page:
+ * @assistant: a #GtkAssistant
+ *
+ * Navigate to the previous visited page. It is a programming
+ *  error to call this function if no previous page is
+ *  available.
+ *
+ * This function is for use when creating pages of the
+ *  #GTK_ASSISTANT_PAGE_CUSTOM type.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_assistant_previous_page (GtkAssistant *assistant)
+{
+  GtkAssistantPrivate *priv;
+  GtkAssistantPage *page_info;
+  GSList *page_node;
+
+  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
+
+  priv = assistant->priv;
+
+  /* skip the progress pages when going back */
+  do
+    {
+      page_node = priv->visited_pages;
+
+      g_return_if_fail (page_node != NULL);
+
+      priv->visited_pages = priv->visited_pages->next;
+      page_info = (GtkAssistantPage *) page_node->data;
+      g_slist_free_1 (page_node);
+    }
+  while (page_info->type == GTK_ASSISTANT_PAGE_PROGRESS ||
+        !gtk_widget_get_visible (page_info->page));
+
+  set_current_page (assistant, page_info);
+}
+
 /**
  * gtk_assistant_get_n_pages:
  * @assistant: a #GtkAssistant
@@ -1522,7 +1769,8 @@ gtk_assistant_get_n_pages (GtkAssistant *assistant)
  *
  * Returns the child widget contained in page number @page_num.
  *
- * Return value: The child widget, or %NULL if @page_num is out of bounds.
+ * Return value: (transfer none): The child widget, or %NULL
+ *     if @page_num is out of bounds.
  *
  * Since: 2.10
  **/
@@ -1535,10 +1783,14 @@ gtk_assistant_get_nth_page (GtkAssistant *assistant,
   GList *elem;
 
   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
+  g_return_val_if_fail (page_num >= -1, NULL);
 
   priv = assistant->priv;
 
-  elem = g_list_nth (priv->pages, page_num);
+  if (page_num == -1)
+    elem = g_list_last (priv->pages);
+  else
+    elem = g_list_nth (priv->pages, page_num);
 
   if (!elem)
     return NULL;
@@ -1614,12 +1866,12 @@ gtk_assistant_insert_page (GtkAssistant *assistant,
 
   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
   g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
-  g_return_val_if_fail (page->parent == NULL, 0);
-  g_return_val_if_fail (!GTK_WIDGET_TOPLEVEL (page), 0);
+  g_return_val_if_fail (gtk_widget_get_parent (page) == NULL, 0);
+  g_return_val_if_fail (!gtk_widget_is_toplevel (page), 0);
 
   priv = assistant->priv;
 
-  page_info = g_new0 (GtkAssistantPage, 1);
+  page_info = g_slice_new0 (GtkAssistantPage);
   page_info->page  = page;
   page_info->title = gtk_label_new (NULL);
 
@@ -1642,7 +1894,7 @@ gtk_assistant_insert_page (GtkAssistant *assistant,
   gtk_widget_set_parent (page_info->page,  GTK_WIDGET (assistant));
   gtk_widget_set_parent (page_info->title, GTK_WIDGET (assistant));
 
-  if (GTK_WIDGET_REALIZED (GTK_WIDGET (assistant)))
+  if (gtk_widget_get_realized (GTK_WIDGET (assistant)))
     {
       gtk_widget_realize (page_info->page);
       gtk_widget_realize (page_info->title);
@@ -1656,7 +1908,7 @@ gtk_assistant_insert_page (GtkAssistant *assistant,
 /**
  * gtk_assistant_set_forward_page_func:
  * @assistant: a #GtkAssistant
- * @page_func: the #GtkAssistantPageFunc, or %NULL to use the default one
+ * @page_func: (allow-none): the #GtkAssistantPageFunc, or %NULL to use the default one
  * @data: user data for @page_func
  * @destroy: destroy notifier for @data
  *
@@ -1699,8 +1951,7 @@ gtk_assistant_set_forward_page_func (GtkAssistant         *assistant,
 
   /* Page flow has possibly changed, so the
      buttons state might need to change too */
-  if (priv->current_page)
-    set_assistant_buttons_state (assistant);
+  set_assistant_buttons_state (assistant);
 }
 
 /**
@@ -1758,7 +2009,7 @@ gtk_assistant_remove_action_widget (GtkAssistant *assistant,
 /**
  * gtk_assistant_set_page_title:
  * @assistant: a #GtkAssistant
- * @page: a page of @assitant
+ * @page: a page of @assistant
  * @title: the new title for @page
  * 
  * Sets a title for @page. The title is displayed in the header
@@ -1771,14 +2022,12 @@ gtk_assistant_set_page_title (GtkAssistant *assistant,
                              GtkWidget    *page,
                              const gchar  *title)
 {
-  GtkAssistantPrivate *priv;
   GtkAssistantPage *page_info;
   GList *child;
 
   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
   g_return_if_fail (GTK_IS_WIDGET (page));
 
-  priv = assistant->priv;
   child = find_page (assistant, page);
 
   g_return_if_fail (child != NULL);
@@ -1805,14 +2054,12 @@ G_CONST_RETURN gchar*
 gtk_assistant_get_page_title (GtkAssistant *assistant,
                              GtkWidget    *page)
 {
-  GtkAssistantPrivate *priv;
   GtkAssistantPage *page_info;
   GList *child;
 
   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
   g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
 
-  priv = assistant->priv;
   child = find_page (assistant, page);
 
   g_return_val_if_fail (child != NULL, NULL);
@@ -1825,7 +2072,7 @@ gtk_assistant_get_page_title (GtkAssistant *assistant,
 /**
  * gtk_assistant_set_page_type:
  * @assistant: a #GtkAssistant
- * @page: a page of @assitant
+ * @page: a page of @assistant
  * @type: the new type for @page
  * 
  * Sets the page type for @page. The page type determines the page
@@ -1856,10 +2103,16 @@ gtk_assistant_set_page_type (GtkAssistant         *assistant,
     {
       page_info->type = type;
 
+      /* backwards compatibility to the era before fixing bug 604289 */
+      if (type == GTK_ASSISTANT_PAGE_SUMMARY && !page_info->complete_set)
+        {
+          gtk_assistant_set_page_complete (assistant, page, TRUE);
+          page_info->complete_set = FALSE;
+        }
+
       /* Always set buttons state, a change in a future page
         might change current page buttons */
-      if (priv->current_page)
-       set_assistant_buttons_state (assistant);
+      set_assistant_buttons_state (assistant);
 
       gtk_widget_child_notify (page, "page-type");
     }
@@ -1880,14 +2133,12 @@ GtkAssistantPageType
 gtk_assistant_get_page_type (GtkAssistant *assistant,
                             GtkWidget    *page)
 {
-  GtkAssistantPrivate *priv;
   GtkAssistantPage *page_info;
   GList *child;
 
   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), GTK_ASSISTANT_PAGE_CONTENT);
   g_return_val_if_fail (GTK_IS_WIDGET (page), GTK_ASSISTANT_PAGE_CONTENT);
 
-  priv = assistant->priv;
   child = find_page (assistant, page);
 
   g_return_val_if_fail (child != NULL, GTK_ASSISTANT_PAGE_CONTENT);
@@ -1900,9 +2151,9 @@ gtk_assistant_get_page_type (GtkAssistant *assistant,
 /**
  * gtk_assistant_set_page_header_image:
  * @assistant: a #GtkAssistant
- * @page: a page of @assitant
- * @pixbuf: the new header image @page
- * 
+ * @page: a page of @assistant
+ * @pixbuf: (allow-none): the new header image @page
+ *
  * Sets a header image for @page. This image is displayed in the header
  * area of the assistant when @page is the current page.
  *
@@ -1950,11 +2201,11 @@ gtk_assistant_set_page_header_image (GtkAssistant *assistant,
  * gtk_assistant_get_page_header_image:
  * @assistant: a #GtkAssistant
  * @page: a page of @assistant
- * 
- * Gets the header image for @page. 
- * 
- * Return value: the header image for @page, or %NULL
- * if there's no header image for the page.
+ *
+ * Gets the header image for @page.
+ *
+ * Return value: (transfer none): the header image for @page, or %NULL
+ *     if there's no header image for the page.
  *
  * Since: 2.10
  **/
@@ -1962,14 +2213,12 @@ GdkPixbuf*
 gtk_assistant_get_page_header_image (GtkAssistant *assistant,
                                     GtkWidget    *page)
 {
-  GtkAssistantPrivate *priv;
   GtkAssistantPage *page_info;
   GList *child;
 
   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
   g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
 
-  priv = assistant->priv;
   child = find_page (assistant, page);
 
   g_return_val_if_fail (child != NULL, NULL);
@@ -1982,9 +2231,9 @@ gtk_assistant_get_page_header_image (GtkAssistant *assistant,
 /**
  * gtk_assistant_set_page_side_image:
  * @assistant: a #GtkAssistant
- * @page: a page of @assitant
- * @pixbuf: the new header image @page
- * 
+ * @page: a page of @assistant
+ * @pixbuf: (allow-none): the new header image @page
+ *
  * Sets a header image for @page. This image is displayed in the side
  * area of the assistant when @page is the current page.
  *
@@ -2032,11 +2281,11 @@ gtk_assistant_set_page_side_image (GtkAssistant *assistant,
  * gtk_assistant_get_page_side_image:
  * @assistant: a #GtkAssistant
  * @page: a page of @assistant
- * 
- * Gets the header image for @page. 
- * 
- * Return value: the side image for @page, or %NULL
- * if there's no side image for the page.
+ *
+ * Gets the header image for @page.
+ *
+ * Return value: (transfer none): the side image for @page, or %NULL
+ *     if there's no side image for the page.
  *
  * Since: 2.10
  **/
@@ -2044,14 +2293,12 @@ GdkPixbuf*
 gtk_assistant_get_page_side_image (GtkAssistant *assistant,
                                   GtkWidget    *page)
 {
-  GtkAssistantPrivate *priv;
   GtkAssistantPage *page_info;
   GList *child;
 
   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
   g_return_val_if_fail (GTK_IS_WIDGET (page), NULL);
 
-  priv = assistant->priv;
   child = find_page (assistant, page);
 
   g_return_val_if_fail (child != NULL, NULL);
@@ -2064,7 +2311,7 @@ gtk_assistant_get_page_side_image (GtkAssistant *assistant,
 /**
  * gtk_assistant_set_page_complete:
  * @assistant: a #GtkAssistant
- * @page: a page of @assitant
+ * @page: a page of @assistant
  * @complete: the completeness status of the page
  * 
  * Sets whether @page contents are complete. This will make
@@ -2094,11 +2341,11 @@ gtk_assistant_set_page_complete (GtkAssistant *assistant,
   if (complete != page_info->complete)
     {
       page_info->complete = complete;
+      page_info->complete_set = TRUE;
 
       /* Always set buttons state, a change in a future page
         might change current page buttons */
-      if (priv->current_page)
-       set_assistant_buttons_state (assistant);
+      set_assistant_buttons_state (assistant);
 
       gtk_widget_child_notify (page, "complete");
     }
@@ -2109,7 +2356,7 @@ gtk_assistant_set_page_complete (GtkAssistant *assistant,
  * @assistant: a #GtkAssistant
  * @page: a page of @assistant
  * 
- * Gets whether @page is complete..
+ * Gets whether @page is complete.
  * 
  * Return value: %TRUE if @page is complete.
  *
@@ -2119,14 +2366,12 @@ gboolean
 gtk_assistant_get_page_complete (GtkAssistant *assistant,
                                 GtkWidget    *page)
 {
-  GtkAssistantPrivate *priv;
   GtkAssistantPage *page_info;
   GList *child;
 
   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), FALSE);
   g_return_val_if_fail (GTK_IS_WIDGET (page), FALSE);
 
-  priv = assistant->priv;
   child = find_page (assistant, page);
 
   g_return_val_if_fail (child != NULL, FALSE);
@@ -2160,6 +2405,269 @@ gtk_assistant_update_buttons_state (GtkAssistant *assistant)
   set_assistant_buttons_state (assistant);
 }
 
+/**
+ * gtk_assistant_commit:
+ * @assistant: a #GtkAssistant
+ *
+ * Erases the visited page history so the back button is not
+ * shown on the current page, and removes the cancel button
+ * from subsequent pages.
+ *
+ * Use this when the information provided up to the current
+ * page is hereafter deemed permanent and cannot be modified
+ * or undone.  For example, showing a progress page to track
+ * a long-running, unreversible operation after the user has
+ * clicked apply on a confirmation page.
+ *
+ * Since: 2.22
+ **/
+void
+gtk_assistant_commit (GtkAssistant *assistant)
+{
+  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
+
+  g_slist_free (assistant->priv->visited_pages);
+  assistant->priv->visited_pages = NULL;
+
+  assistant->priv->committed = TRUE;
+
+  set_assistant_buttons_state (assistant);
+}
+
+
+
+/* accessible implementation */
+
+static gint
+gtk_assistant_accessible_get_n_children (AtkObject *accessible)
+{
+  GtkAssistant *assistant;
+  GtkWidget *widget;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
+
+  if (!widget)
+    return 0;
+
+  assistant = GTK_ASSISTANT (widget);
+   
+  return g_list_length (assistant->priv->pages) + 1;
+}
+
+
+static AtkObject *
+gtk_assistant_accessible_ref_child (AtkObject *accessible,
+                                   gint       index)
+{
+  GtkAssistant *assistant;
+  GtkAssistantPrivate *priv;
+  GtkWidget *widget, *child;
+  gint n_pages;
+  AtkObject *obj;
+  const gchar *title;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
+  if (!widget)
+    return NULL;
 
-#define __GTK_ASSISTANT_C__
-#include "gtkaliasdef.c"
+  assistant = GTK_ASSISTANT (widget);
+  priv = assistant->priv;
+  n_pages = g_list_length (priv->pages);
+
+  if (index < 0)
+    return NULL;
+  else if (index < n_pages)
+    {
+      GtkAssistantPage *page = g_list_nth_data (priv->pages, index);
+
+      child = page->page;
+      title = gtk_assistant_get_page_title (assistant, child);
+    }
+  else if (index == n_pages)
+    {
+      child = priv->action_area;
+      title = NULL;
+    }
+  else
+    return NULL;
+  
+  obj = gtk_widget_get_accessible (child);
+
+  if (title)
+    atk_object_set_name (obj, title);
+
+  return g_object_ref (obj);
+}
+
+static void
+gtk_assistant_accessible_class_init (AtkObjectClass *class)
+{
+  class->get_n_children = gtk_assistant_accessible_get_n_children;
+  class->ref_child = gtk_assistant_accessible_ref_child;
+}
+
+static GType
+gtk_assistant_accessible_get_type (void)
+{
+  static GType type = 0;
+  
+  if (!type)
+    {
+      /*
+       * Figure out the size of the class and instance
+       * we are deriving from
+       */
+      AtkObjectFactory *factory;
+      GType derived_type;
+      GTypeQuery query;
+      GType derived_atk_type;
+
+      derived_type = g_type_parent (GTK_TYPE_ASSISTANT);
+      factory = atk_registry_get_factory (atk_get_default_registry (),
+                                         derived_type);
+      derived_atk_type = atk_object_factory_get_accessible_type (factory);
+      g_type_query (derived_atk_type, &query);
+
+      type = g_type_register_static_simple (derived_atk_type,
+                                           I_("GtkAssistantAccessible"),
+                                           query.class_size,
+                                           (GClassInitFunc) gtk_assistant_accessible_class_init,
+                                           query.instance_size,
+                                           NULL, 0);
+    }
+
+  return type;
+}
+
+static AtkObject *
+gtk_assistant_accessible_new (GObject *obj)
+{
+  AtkObject *accessible;
+
+  g_return_val_if_fail (GTK_IS_ASSISTANT (obj), NULL);
+
+  accessible = g_object_new (gtk_assistant_accessible_get_type (), NULL);
+  atk_object_initialize (accessible, obj);
+
+  return accessible;
+}
+
+static GType
+gtk_assistant_accessible_factory_get_accessible_type (void)
+{
+  return gtk_assistant_accessible_get_type ();
+}
+
+static AtkObject*
+gtk_assistant_accessible_factory_create_accessible (GObject *obj)
+{
+  return gtk_assistant_accessible_new (obj);
+}
+
+static void
+gtk_assistant_accessible_factory_class_init (AtkObjectFactoryClass *class)
+{
+  class->create_accessible = gtk_assistant_accessible_factory_create_accessible;
+  class->get_accessible_type = gtk_assistant_accessible_factory_get_accessible_type;
+}
+
+static GType
+gtk_assistant_accessible_factory_get_type (void)
+{
+  static GType type = 0;
+
+  if (!type)
+    {
+      type = g_type_register_static_simple (ATK_TYPE_OBJECT_FACTORY,
+                                           I_("GtkAssistantAccessibleFactory"),
+                                           sizeof (AtkObjectFactoryClass),
+                                           (GClassInitFunc) gtk_assistant_accessible_factory_class_init,
+                                           sizeof (AtkObjectFactory),
+                                           NULL, 0);
+    }
+
+  return type;
+}
+
+static AtkObject *
+gtk_assistant_get_accessible (GtkWidget *widget)
+{
+  static gboolean first_time = TRUE;
+
+  if (first_time)
+    {
+      AtkObjectFactory *factory;
+      AtkRegistry *registry;
+      GType derived_type;
+      GType derived_atk_type;
+
+      /*
+       * Figure out whether accessibility is enabled by looking at the
+       * type of the accessible object which would be created for
+       * the parent type of GtkAssistant.
+       */
+      derived_type = g_type_parent (GTK_TYPE_ASSISTANT);
+
+      registry = atk_get_default_registry ();
+      factory = atk_registry_get_factory (registry,
+                                         derived_type);
+      derived_atk_type = atk_object_factory_get_accessible_type (factory);
+      if (g_type_is_a (derived_atk_type, GTK_TYPE_ACCESSIBLE))
+       {
+         atk_registry_set_factory_type (registry,
+                                        GTK_TYPE_ASSISTANT,
+                                        gtk_assistant_accessible_factory_get_type ());
+       }
+      first_time = FALSE;
+    }
+
+  return GTK_WIDGET_CLASS (gtk_assistant_parent_class)->get_accessible (widget);
+}
+
+
+static GtkBuildableIface *parent_buildable_iface;
+
+static void
+gtk_assistant_buildable_interface_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->get_internal_child = gtk_assistant_buildable_get_internal_child;
+  iface->custom_tag_start = gtk_assistant_buildable_custom_tag_start;
+  iface->custom_finished = gtk_assistant_buildable_custom_finished;
+}
+
+static GObject *
+gtk_assistant_buildable_get_internal_child (GtkBuildable *buildable,
+                                            GtkBuilder   *builder,
+                                            const gchar  *childname)
+{
+    if (strcmp (childname, "action_area") == 0)
+      return G_OBJECT (GTK_ASSISTANT (buildable)->priv->action_area);
+
+    return parent_buildable_iface->get_internal_child (buildable,
+                                                       builder,
+                                                       childname);
+}
+
+gboolean
+gtk_assistant_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                          GtkBuilder    *builder,
+                                          GObject       *child,
+                                          const gchar   *tagname,
+                                          GMarkupParser *parser,
+                                          gpointer      *data)
+{
+  return parent_buildable_iface->custom_tag_start (buildable, builder, child,
+                                                   tagname, parser, data);
+}
+
+static void
+gtk_assistant_buildable_custom_finished (GtkBuildable *buildable,
+                                         GtkBuilder   *builder,
+                                         GObject      *child,
+                                         const gchar  *tagname,
+                                         gpointer      user_data)
+{
+  parent_buildable_iface->custom_finished (buildable, builder, child,
+                                           tagname, user_data);
+}