]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkassistant.c
GtkEntry: Sanity check the end_pos value in _get_display_text()
[~andy/gtk] / gtk / gtkassistant.c
index e4ef82ca6633da7fc943d9683777c76d29b90956..3ba9f227be5abc7934d793a7877a92be13638a2d 100644 (file)
@@ -18,9 +18,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 /**
 
 #include "gtkassistant.h"
 
-#include "gtkaccessible.h"
 #include "gtkbutton.h"
-#include "gtkhbox.h"
-#include "gtkhbbox.h"
+#include "gtkbox.h"
+#include "gtkframe.h"
+#include "gtknotebook.h"
 #include "gtkimage.h"
 #include "gtklabel.h"
+#include "gtksettings.h"
 #include "gtksizegroup.h"
 #include "gtksizerequest.h"
 #include "gtkstock.h"
@@ -75,6 +74,7 @@
 #include "gtkintl.h"
 #include "gtkprivate.h"
 #include "gtkbuildable.h"
+#include "a11y/gtkwindowaccessible.h"
 
 
 #define HEADER_SPACING 12
@@ -84,12 +84,15 @@ typedef struct _GtkAssistantPage GtkAssistantPage;
 
 struct _GtkAssistantPage
 {
-  GtkWidget *page;
   GtkAssistantPageType type;
-  guint      complete : 1;
+  guint      complete     : 1;
   guint      complete_set : 1;
 
-  GtkWidget *title;
+  gchar *title;
+
+  GtkWidget *page;
+  GtkWidget *regular_title;
+  GtkWidget *current_title;
   GdkPixbuf *header_image;
   GdkPixbuf *sidebar_image;
 };
@@ -103,54 +106,37 @@ struct _GtkAssistantPrivate
   GtkWidget *close;
   GtkWidget *last;
 
-  GtkWidget *header_image;
-  GtkWidget *sidebar_image;
-
+  GtkWidget *sidebar;
+  GtkWidget *content;
   GtkWidget *action_area;
 
   GList     *pages;
-
-  GtkAssistantPage *current_page;
-
   GSList    *visited_pages;
+  GtkAssistantPage *current_page;
 
-  GtkSizeGroup *size_group;
+  GtkSizeGroup *button_size_group;
+  GtkSizeGroup *title_size_group;
 
   GtkAssistantPageFunc forward_function;
   gpointer forward_function_data;
   GDestroyNotify forward_data_destroy;
 
+  gint extra_buttons;
+
   guint committed : 1;
 };
 
 static void     gtk_assistant_class_init         (GtkAssistantClass *class);
 static void     gtk_assistant_init               (GtkAssistant      *assistant);
 static void     gtk_assistant_destroy            (GtkWidget         *widget);
-static void     gtk_assistant_style_updated      (GtkWidget         *widget);
-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_draw               (GtkWidget         *widget,
-                                                  cairo_t           *cr);
-static gboolean gtk_assistant_focus              (GtkWidget         *widget,
-                                                  GtkDirectionType   direction);
 static void     gtk_assistant_add                (GtkContainer      *container,
                                                   GtkWidget         *page);
 static void     gtk_assistant_remove             (GtkContainer      *container,
                                                   GtkWidget         *page);
-static void     gtk_assistant_forall             (GtkContainer      *container,
-                                                  gboolean           include_internals,
-                                                  GtkCallback        callback,
-                                                  gpointer           callback_data);
 static void     gtk_assistant_set_child_property (GtkContainer      *container,
                                                   GtkWidget         *child,
                                                   guint              property_id,
@@ -162,9 +148,6 @@ static void     gtk_assistant_get_child_property (GtkContainer      *container,
                                                   GValue            *value,
                                                   GParamSpec        *pspec);
 
-static AtkObject *gtk_assistant_get_accessible   (GtkWidget         *widget);
-static GType      gtk_assistant_accessible_factory_get_type  (void);
-
 static void       gtk_assistant_buildable_interface_init     (GtkBuildableIface *iface);
 static GObject   *gtk_assistant_buildable_get_internal_child (GtkBuildable  *buildable,
                                                               GtkBuilder    *builder,
@@ -183,6 +166,14 @@ static void       gtk_assistant_buildable_custom_finished    (GtkBuildable  *bui
 
 static GList*     find_page                                  (GtkAssistant  *assistant,
                                                               GtkWidget     *page);
+static void       gtk_assistant_do_set_page_header_image     (GtkAssistant  *assistant,
+                                                              GtkWidget     *page,
+                                                              GdkPixbuf     *pixbuf);
+static void       gtk_assistant_do_set_page_side_image       (GtkAssistant  *assistant,
+                                                              GtkWidget     *page,
+                                                              GdkPixbuf     *pixbuf);
+
+GType             _gtk_assistant_accessible_get_type         (void);
 
 enum
 {
@@ -223,20 +214,14 @@ gtk_assistant_class_init (GtkAssistantClass *class)
   container_class = (GtkContainerClass *) class;
 
   widget_class->destroy = gtk_assistant_destroy;
-  widget_class->style_updated = gtk_assistant_style_updated;
-  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->draw = gtk_assistant_draw;
-  widget_class->focus = gtk_assistant_focus;
-  widget_class->get_accessible = gtk_assistant_get_accessible;
+
+  gtk_widget_class_set_accessible_type (widget_class, _gtk_assistant_accessible_get_type ());
 
   container_class->add = gtk_assistant_add;
   container_class->remove = gtk_assistant_remove;
-  container_class->forall = gtk_assistant_forall;
   container_class->set_child_property = gtk_assistant_set_child_property;
   container_class->get_child_property = gtk_assistant_get_child_property;
 
@@ -262,9 +247,11 @@ gtk_assistant_class_init (GtkAssistantClass *class)
    * @assistant: the #GtkAssistant
    * @page: the current page
    *
-   * 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.
+   * 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 preparations which are
+   * necessary before showing @page.
    *
    * Since: 2.10
    */
@@ -281,15 +268,17 @@ gtk_assistant_class_init (GtkAssistantClass *class)
    * GtkAssistant::apply:
    * @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.
+   * 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.
    *
-   * 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.
+   * 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
    */
@@ -357,9 +346,7 @@ gtk_assistant_class_init (GtkAssistantClass *class)
   /**
    * GtkAssistant:title:
    *
-   * The title that is displayed in the page header.
-   *
-   * If title and header-image are both %NULL, no header is displayed.
+   * The title of the page.
    *
    * Since: 2.10
    */
@@ -374,11 +361,12 @@ gtk_assistant_class_init (GtkAssistantClass *class)
   /**
    * GtkAssistant:header-image:
    *
-   * The image that is displayed next to the title in the page header.
-   *
-   * If title and header-image are both %NULL, no header is displayed.
+   * This image used to be displayed in the page header.
    *
    * Since: 2.10
+   *
+   * Deprecated: 3.2: Since GTK+ 3.2, a header is no longer shown;
+   *     add your header decoration to the page content instead.
    */
   gtk_container_class_install_child_property (container_class,
                                               CHILD_PROP_PAGE_HEADER_IMAGE,
@@ -389,13 +377,13 @@ gtk_assistant_class_init (GtkAssistantClass *class)
                                                                    GTK_PARAM_READWRITE));
 
   /**
-   * GtkAssistant:header-image:
-   *
-   * The image that is displayed next to the page.
+   * GtkAssistant:sidebar-image:
    *
-   * Set this to %NULL to make the sidebar disappear.
+   * This image used to be displayed in the 'sidebar'.
    *
    * Since: 2.10
+   *
+   * Deprecated: 3.2: Since GTK+ 3.2, the sidebar image is no longer shown.
    */
   gtk_container_class_install_child_property (container_class,
                                               CHILD_PROP_PAGE_SIDEBAR_IMAGE,
@@ -404,12 +392,13 @@ gtk_assistant_class_init (GtkAssistantClass *class)
                                                                    P_("Sidebar image for the assistant page"),
                                                                    GDK_TYPE_PIXBUF,
                                                                    GTK_PARAM_READWRITE));
+
   /**
    * GtkAssistant:complete:
    *
-   * Setting the "complete" child property to %TRUE marks a page as complete
-   * (i.e.: all the required fields are filled out). GTK+ uses this information
-   * to control the sensitivity of the navigation buttons.
+   * Setting the "complete" child property to %TRUE marks a page as
+   * complete (i.e.: all the required fields are filled out). GTK+ uses
+   * this information to control the sensitivity of the navigation buttons.
    *
    * Since: 2.10
    */
@@ -454,17 +443,23 @@ default_forward_function (gint current_page, gpointer data)
   return current_page;
 }
 
-static void
-compute_last_button_state (GtkAssistant *assistant)
+static gboolean
+last_button_visible (GtkAssistant *assistant, GtkAssistantPage *page)
 {
   GtkAssistantPrivate *priv = assistant->priv;
-  GtkAssistantPage *page_info, *current_page_info;
+  GtkAssistantPage *page_info;
   gint count, page_num, n_pages;
 
+  if (page == NULL)
+    return FALSE;
+
+  if (page->type != GTK_ASSISTANT_PAGE_CONTENT)
+    return FALSE;
+
   count = 0;
-  page_num = gtk_assistant_get_current_page (assistant);
-  n_pages  = gtk_assistant_get_n_pages (assistant);
-  current_page_info = page_info = g_list_nth_data (priv->pages, page_num);
+  page_num = g_list_index (priv->pages, page);
+  n_pages  = g_list_length (priv->pages);
+  page_info = page;
 
   while (page_num >= 0 && page_num < n_pages &&
          page_info->type == GTK_ASSISTANT_PAGE_CONTENT &&
@@ -477,63 +472,87 @@ compute_last_button_state (GtkAssistant *assistant)
       count++;
     }
 
-  /* make the last button visible if we can skip multiple
+  /* Make the last button visible if we can skip multiple
    * pages and end on a confirmation or summary page
    */
   if (count > 1 && page_info &&
       (page_info->type == GTK_ASSISTANT_PAGE_CONFIRM ||
        page_info->type == GTK_ASSISTANT_PAGE_SUMMARY))
-    {
-      gtk_widget_show (priv->last);
-      gtk_widget_set_sensitive (priv->last,
-                                current_page_info->complete);
-    }
+    return TRUE;
   else
-    gtk_widget_hide (priv->last);
+    return FALSE;
 }
 
 static void
-compute_progress_state (GtkAssistant *assistant)
+update_actions_size (GtkAssistant *assistant)
 {
   GtkAssistantPrivate *priv = assistant->priv;
-  gint page_num, n_pages;
+  GList *l;
+  GtkAssistantPage *page;
+  gint buttons, page_buttons;
 
-  n_pages = gtk_assistant_get_n_pages (assistant);
-  page_num = gtk_assistant_get_current_page (assistant);
+  if (!priv->current_page)
+    return;
 
-  page_num = (priv->forward_function) (page_num, priv->forward_function_data);
+  /* Some heuristics to find out how many buttons we should
+   * reserve space for. It is possible to trick this code
+   * with page forward functions and invisible pages, etc.
+   */
+  buttons = 0;
+  for (l = priv->pages; l; l = l->next)
+    {
+      page = l->data;
 
-  if (page_num >= 0 && page_num < n_pages)
-    gtk_widget_show (priv->forward);
-  else
-    gtk_widget_hide (priv->forward);
+      if (!gtk_widget_get_visible (page->page))
+        continue;
+
+      page_buttons = 2; /* cancel, forward/apply/close */
+      if (l != priv->pages)
+        page_buttons += 1; /* back */
+      if (last_button_visible (assistant, page))
+        page_buttons += 1; /* last */
+
+      buttons = MAX (buttons, page_buttons);
+    }
+
+  buttons += priv->extra_buttons;
+
+  gtk_widget_set_size_request (priv->action_area,
+                               buttons * gtk_widget_get_allocated_width (priv->cancel) + (buttons - 1) * 6,
+                               -1);
 }
 
 static void
-set_assistant_header_image (GtkAssistant *assistant)
+compute_last_button_state (GtkAssistant *assistant)
 {
   GtkAssistantPrivate *priv = assistant->priv;
 
-  gtk_image_set_from_pixbuf (GTK_IMAGE (priv->header_image),
-                             priv->current_page->header_image);
+  gtk_widget_set_sensitive (priv->last, priv->current_page->complete);
+  if (last_button_visible (assistant, priv->current_page))
+    gtk_widget_show (priv->last);
+  else
+    gtk_widget_hide (priv->last);
 }
 
 static void
-set_assistant_sidebar_image (GtkAssistant *assistant)
+compute_progress_state (GtkAssistant *assistant)
 {
   GtkAssistantPrivate *priv = assistant->priv;
+  gint page_num, n_pages;
 
-  gtk_image_set_from_pixbuf (GTK_IMAGE (priv->sidebar_image),
-                             priv->current_page->sidebar_image);
+  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 (priv->current_page->sidebar_image)
-    gtk_widget_show (priv->sidebar_image);
+  if (page_num >= 0 && page_num < n_pages)
+    gtk_widget_show (priv->forward);
   else
-    gtk_widget_hide (priv->sidebar_image);
+    gtk_widget_hide (priv->forward);
 }
 
 static void
-set_assistant_buttons_state (GtkAssistant *assistant)
+update_buttons_state (GtkAssistant *assistant)
 {
   GtkAssistantPrivate *priv = assistant->priv;
 
@@ -621,44 +640,98 @@ set_assistant_buttons_state (GtkAssistant *assistant)
     gtk_widget_hide (priv->back);
 }
 
-static void
-set_current_page (GtkAssistant     *assistant,
-                  GtkAssistantPage *page)
+static gboolean
+update_page_title_state (GtkAssistant *assistant, GList *list)
 {
+  GtkAssistantPage *page, *other;
   GtkAssistantPrivate *priv = assistant->priv;
-  GtkAssistantPage *old_page;
+  gboolean visible;
+  GList *l;
 
-  if (priv->current_page &&
-      gtk_widget_is_drawable (priv->current_page->page))
-    old_page = priv->current_page;
-  else
-    old_page = NULL;
+  page = list->data;
 
-  priv->current_page = page;
+  if (page->title == NULL || page->title[0] == 0)
+    visible = FALSE;
+  else
+    visible = gtk_widget_get_visible (page->page);
 
-  set_assistant_buttons_state (assistant);
-  set_assistant_header_image (assistant);
-  set_assistant_sidebar_image (assistant);
+  if (page == priv->current_page)
+    {
+      gtk_widget_set_visible (page->regular_title, FALSE);
+      gtk_widget_set_visible (page->current_title, visible);
+    }
+  else
+    {
+      /* If multiple consecutive pages have the same title,
+       * we only show it once, since it would otherwise look
+       * silly. We have to be a little careful, since we
+       * _always_ show the title of the current page.
+       */
+      if (list->prev)
+        {
+          other = list->prev->data;
+          if (g_strcmp0 (page->title, other->title) == 0)
+            visible = FALSE;
+        }
+      for (l = list->next; l; l = l->next)
+        {
+          other = l->data;
+          if (g_strcmp0 (page->title, other->title) != 0)
+            break;
 
-  g_signal_emit (assistant, signals [PREPARE], 0, priv->current_page->page);
+          if (other == priv->current_page)
+            {
+              visible = FALSE;
+              break;
+            }
+        }
 
-  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_set_child_visible (priv->current_page->title, TRUE);
-      gtk_widget_map (priv->current_page->page);
-      gtk_widget_map (priv->current_page->title);
+      gtk_widget_set_visible (page->regular_title, visible);
+      gtk_widget_set_visible (page->current_title, FALSE);
     }
 
-  if (old_page && gtk_widget_get_mapped (old_page->page))
+  return visible;
+}
+
+static void
+update_title_state (GtkAssistant *assistant)
+{
+  GtkAssistantPrivate *priv = assistant->priv;
+  GList *l;
+  gboolean show_titles;
+
+  show_titles = FALSE;
+  for (l = priv->pages; l != NULL; l = l->next)
     {
-      gtk_widget_set_child_visible (old_page->page, FALSE);
-      gtk_widget_set_child_visible (old_page->title, FALSE);
-      gtk_widget_unmap (old_page->page);
-      gtk_widget_unmap (old_page->title);
+      if (update_page_title_state (assistant, l))
+        show_titles = TRUE;
     }
 
+  gtk_widget_set_visible (priv->sidebar, show_titles);
+}
+
+static void
+set_current_page (GtkAssistant *assistant,
+                  gint          page_num)
+{
+  GtkAssistantPrivate *priv = assistant->priv;
+
+  priv->current_page = (GtkAssistantPage *)g_list_nth_data (priv->pages, page_num);
+
+  g_signal_emit (assistant, signals [PREPARE], 0, priv->current_page->page);
+  /* do not continue if the prepare signal handler has already changed the
+   * current page */
+  if (priv->current_page != (GtkAssistantPage *)g_list_nth_data (priv->pages, page_num))
+    return;
+
+  update_title_state (assistant);
+
+  gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->content), page_num);
+
+  /* update buttons state, flow may have changed */
+  if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
+    update_buttons_state (assistant);
+
   if (!gtk_widget_child_focus (priv->current_page->page, GTK_DIR_TAB_FORWARD))
     {
       GtkWidget *button[6];
@@ -702,7 +775,7 @@ compute_next_step (GtkAssistant *assistant)
   if (next_page >= 0 && next_page < n_pages)
     {
       priv->visited_pages = g_slist_prepend (priv->visited_pages, page_info);
-      set_current_page (assistant, g_list_nth_data (priv->pages, next_page));
+      set_current_page (assistant, next_page);
 
       return TRUE;
     }
@@ -782,60 +855,184 @@ alternative_button_order (GtkAssistant *assistant)
   return result;
 }
 
+static gboolean
+assistant_sidebar_draw_cb (GtkWidget *widget,
+                           cairo_t *cr,
+                           gpointer user_data)
+{
+  gint width, height;
+  GtkStyleContext *context;
+
+  width = gtk_widget_get_allocated_width (widget);
+  height = gtk_widget_get_allocated_height (widget);
+  context = gtk_widget_get_style_context (widget);
+
+  gtk_render_background (context, cr, 0, 0, width, height);
+
+  return FALSE;
+}
+
+static void
+on_page_notify_visibility (GtkWidget  *widget,
+                           GParamSpec *arg,
+                           gpointer    data)
+{
+  GtkAssistant *assistant = GTK_ASSISTANT (data);
+
+  if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
+    {
+      update_buttons_state (assistant);
+      update_title_state (assistant);
+    }
+}
+
+static void
+assistant_remove_page_cb (GtkNotebook *notebook,
+                          GtkWidget *page,
+                          GtkAssistant *assistant)
+{
+  GtkAssistantPrivate *priv = assistant->priv;
+  GtkAssistantPage *page_info;
+  GList *page_node;
+  GList *element;
+
+  element = find_page (assistant, page);
+  if (!element)
+    return;
+
+  page_info = element->data;
+
+  /* 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;
+        }
+    }
+
+  g_signal_handlers_disconnect_by_func (page_info->page, on_page_notify_visibility, assistant);
+
+  gtk_size_group_remove_widget (priv->title_size_group, page_info->regular_title);
+  gtk_size_group_remove_widget (priv->title_size_group, page_info->current_title);
+
+  gtk_container_remove (GTK_CONTAINER (priv->sidebar), page_info->regular_title);
+  gtk_container_remove (GTK_CONTAINER (priv->sidebar), page_info->current_title);
+
+  priv->pages = g_list_remove_link (priv->pages, element);
+  priv->visited_pages = g_slist_remove_all (priv->visited_pages, page_info);
+
+  g_free (page_info->title);
+
+  g_slice_free (GtkAssistantPage, page_info);
+  g_list_free_1 (element);
+
+  if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
+    {
+      update_buttons_state (assistant);
+      update_actions_size (assistant);
+    }
+}
+
 static void
 gtk_assistant_init (GtkAssistant *assistant)
 {
   GtkAssistantPrivate *priv;
   GtkStyleContext *context;
+  GtkWidget *main_box;
+  GtkWidget *content_box;
+  GtkWidget *sidebar_frame;
 
   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);
+  /* use border on inner panes instead */
+  gtk_container_set_border_width (GTK_CONTAINER (assistant), 0);
 
   gtk_widget_push_composite_child ();
 
-  /* Header */
-  priv->header_image = gtk_image_new ();
-  gtk_misc_set_alignment (GTK_MISC (priv->header_image), 1., 0.5);
-  gtk_widget_set_parent (priv->header_image, GTK_WIDGET (assistant));
-  gtk_widget_show (priv->header_image);
+  main_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+  priv->sidebar = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
 
-  context = gtk_widget_get_style_context (priv->header_image);
-  gtk_style_context_add_class (context, GTK_STYLE_CLASS_HIGHLIGHT);
+  /* use a frame for the sidebar, and manually render a background
+   * in it. GtkFrame also gives us padding support for free.
+   */
+  sidebar_frame = gtk_frame_new (NULL);
+  context = gtk_widget_get_style_context (sidebar_frame);
+  gtk_style_context_add_class (context, GTK_STYLE_CLASS_SIDEBAR);
 
-  /* Sidebar */
-  priv->sidebar_image = gtk_image_new ();
-  gtk_misc_set_alignment (GTK_MISC (priv->sidebar_image), 0., 0.);
-  gtk_widget_set_parent (priv->sidebar_image, GTK_WIDGET (assistant));
-  gtk_widget_show (priv->sidebar_image);
+  g_signal_connect (sidebar_frame, "draw",
+                    G_CALLBACK (assistant_sidebar_draw_cb), assistant);
 
-  context = gtk_widget_get_style_context (priv->sidebar_image);
-  gtk_style_context_add_class (context, GTK_STYLE_CLASS_HIGHLIGHT);
+  content_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+  gtk_container_set_border_width (GTK_CONTAINER (content_box), 12);
+  priv->content = gtk_notebook_new ();
+  gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->content), FALSE);
+  gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->content), FALSE);
+  priv->action_area = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+  g_signal_connect (priv->content, "remove",
+                    G_CALLBACK (assistant_remove_page_cb), assistant);
 
-  /* Action area  */
-  priv->action_area  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+  gtk_container_add (GTK_CONTAINER (sidebar_frame), priv->sidebar);
+  gtk_box_pack_start (GTK_BOX (main_box), sidebar_frame, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (main_box), content_box, TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (content_box), priv->content, TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (content_box), priv->action_area, FALSE, TRUE, 0);
+  gtk_widget_set_halign (priv->action_area, GTK_ALIGN_END);
+
+  gtk_widget_show_all (main_box);
+
+  gtk_widget_set_parent (main_box, GTK_WIDGET (assistant));
+  _gtk_bin_set_child (GTK_BIN (assistant), main_box);
 
   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->forward = gtk_button_new_with_mnemonic (_("C_ontinue"));
+  gtk_button_set_image (GTK_BUTTON (priv->forward),
+      gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_BUTTON));
+  priv->back    = gtk_button_new_with_mnemonic (_("Go _Back"));
+  gtk_button_set_image (GTK_BUTTON (priv->back),
+      gtk_image_new_from_stock (GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON));
   priv->cancel  = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
-  priv->last    = gtk_button_new_from_stock (GTK_STOCK_GOTO_LAST);
+  priv->last    = gtk_button_new_with_mnemonic (_("_Finish"));
+  gtk_button_set_image (GTK_BUTTON (priv->last),
+      gtk_image_new_from_stock (GTK_STOCK_GOTO_LAST, GTK_ICON_SIZE_BUTTON));
   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, 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);
+  priv->button_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+  gtk_size_group_add_widget (priv->button_size_group, priv->close);
+  gtk_size_group_add_widget (priv->button_size_group, priv->apply);
+  gtk_size_group_add_widget (priv->button_size_group, priv->forward);
+  gtk_size_group_add_widget (priv->button_size_group, priv->back);
+  gtk_size_group_add_widget (priv->button_size_group, priv->cancel);
+  gtk_size_group_add_widget (priv->button_size_group, priv->last);
+
+  gtk_widget_set_no_show_all (priv->close, TRUE);
+  gtk_widget_set_no_show_all (priv->apply, TRUE);
+  gtk_widget_set_no_show_all (priv->forward, TRUE);
+  gtk_widget_set_no_show_all (priv->back, TRUE);
+  gtk_widget_set_no_show_all (priv->cancel, TRUE);
+  gtk_widget_set_no_show_all (priv->last, TRUE);
 
   if (!alternative_button_order (assistant))
     {
@@ -856,7 +1053,6 @@ gtk_assistant_init (GtkAssistant *assistant)
       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 (priv->forward);
   gtk_widget_show (priv->back);
   gtk_widget_show (priv->cancel);
@@ -864,6 +1060,8 @@ gtk_assistant_init (GtkAssistant *assistant)
 
   gtk_widget_pop_composite_child ();
 
+  priv->title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
   priv->pages = NULL;
   priv->current_page = NULL;
   priv->visited_pages = NULL;
@@ -887,11 +1085,11 @@ gtk_assistant_init (GtkAssistant *assistant)
 }
 
 static void
-gtk_assistant_set_child_property (GtkContainer    *container,
-                                  GtkWidget       *child,
-                                  guint            property_id,
-                                  const GValue    *value,
-                                  GParamSpec      *pspec)
+gtk_assistant_set_child_property (GtkContainer *container,
+                                  GtkWidget    *child,
+                                  guint         property_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
 {
   switch (property_id)
     {
@@ -904,12 +1102,12 @@ gtk_assistant_set_child_property (GtkContainer    *container,
                                     g_value_get_string (value));
       break;
     case CHILD_PROP_PAGE_HEADER_IMAGE:
-      gtk_assistant_set_page_header_image (GTK_ASSISTANT (container), child,
-                                           g_value_get_object (value));
+      gtk_assistant_do_set_page_header_image (GTK_ASSISTANT (container), child,
+                                              g_value_get_object (value));
       break;
     case CHILD_PROP_PAGE_SIDEBAR_IMAGE:
-      gtk_assistant_set_page_side_image (GTK_ASSISTANT (container), child,
-                                         g_value_get_object (value));
+      gtk_assistant_do_set_page_side_image (GTK_ASSISTANT (container), child,
+                                            g_value_get_object (value));
       break;
     case CHILD_PROP_PAGE_COMPLETE:
       gtk_assistant_set_page_complete (GTK_ASSISTANT (container), child,
@@ -928,27 +1126,29 @@ gtk_assistant_get_child_property (GtkContainer *container,
                                   GValue       *value,
                                   GParamSpec   *pspec)
 {
+  GtkAssistant *assistant = GTK_ASSISTANT (container);
+
   switch (property_id)
     {
     case CHILD_PROP_PAGE_TYPE:
       g_value_set_enum (value,
-                        gtk_assistant_get_page_type (GTK_ASSISTANT (container), child));
+                        gtk_assistant_get_page_type (assistant, child));
       break;
     case CHILD_PROP_PAGE_TITLE:
       g_value_set_string (value,
-                          gtk_assistant_get_page_title (GTK_ASSISTANT (container), child));
+                          gtk_assistant_get_page_title (assistant, child));
       break;
     case CHILD_PROP_PAGE_HEADER_IMAGE:
       g_value_set_object (value,
-                          gtk_assistant_get_page_header_image (GTK_ASSISTANT (container), child));
+                          ((GtkAssistantPage*) find_page (assistant, child))->header_image);
       break;
     case CHILD_PROP_PAGE_SIDEBAR_IMAGE:
       g_value_set_object (value,
-                          gtk_assistant_get_page_side_image (GTK_ASSISTANT (container), child));
+                          ((GtkAssistantPage*) find_page (assistant, child))->sidebar_image);
       break;
     case CHILD_PROP_PAGE_COMPLETE:
       g_value_set_boolean (value,
-                           gtk_assistant_get_page_complete (GTK_ASSISTANT (container), child));
+                           gtk_assistant_get_page_complete (assistant, child));
       break;
     default:
       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
@@ -957,370 +1157,87 @@ gtk_assistant_get_child_property (GtkContainer *container,
 }
 
 static void
-on_page_notify_visibility (GtkWidget  *widget,
-                           GParamSpec *arg,
-                           gpointer    data)
-{
-  GtkAssistant *assistant = GTK_ASSISTANT (data);
-
-  /* update buttons state, flow may have changed */
-  if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
-    set_assistant_buttons_state (assistant);
-}
-
-static void
-remove_page (GtkAssistant *assistant,
-             GList        *element)
-{
-  GtkAssistantPrivate *priv = assistant->priv;
-  GtkAssistantPage *page_info;
-  GList *page_node;
-
-  page_info = element->data;
-
-  /* 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);
-
-  g_signal_handlers_disconnect_by_func (page_info->page, on_page_notify_visibility, assistant);
-  gtk_widget_unparent (page_info->page);
-
-  if (page_info->header_image)
-    g_object_unref (page_info->header_image);
-
-  if (page_info->sidebar_image)
-    g_object_unref (page_info->sidebar_image);
-
-  gtk_widget_destroy (page_info->title);
-  g_slice_free (GtkAssistantPage, page_info);
-  g_list_free_1 (element);
-}
-
-static void
-gtk_assistant_destroy (GtkWidget *widget)
-{
-  GtkAssistant *assistant = GTK_ASSISTANT (widget);
-  GtkAssistantPrivate *priv = assistant->priv;
-
-  if (priv->header_image)
-    {
-      gtk_widget_destroy (priv->header_image);
-      priv->header_image = NULL;
-    }
-
-  if (priv->sidebar_image)
-    {
-      gtk_widget_destroy (priv->sidebar_image);
-      priv->sidebar_image = NULL;
-    }
-
-  if (priv->action_area)
-    {
-      gtk_widget_destroy (priv->action_area);
-      priv->action_area = NULL;
-    }
-
-  if (priv->size_group)
-    {
-      g_object_unref (priv->size_group);
-      priv->size_group = NULL;
-    }
-
-  if (priv->forward_function)
-    {
-      if (priv->forward_function_data &&
-          priv->forward_data_destroy)
-        priv->forward_data_destroy (priv->forward_function_data);
-
-      priv->forward_function = NULL;
-      priv->forward_function_data = NULL;
-      priv->forward_data_destroy = NULL;
-    }
-
-  if (priv->visited_pages)
-    {
-      g_slist_free (priv->visited_pages);
-      priv->visited_pages = NULL;
-    }
-
-  /* We set current to NULL so that the remove code doesn't try
-   * to do anything funny */
-  priv->current_page = NULL;
-
-  while (priv->pages)
-    remove_page (assistant, priv->pages);
-
-  GTK_WIDGET_CLASS (gtk_assistant_parent_class)->destroy (widget);
-}
-
-static GList*
-find_page (GtkAssistant  *assistant,
-           GtkWidget     *page)
-{
-  GtkAssistantPrivate *priv = assistant->priv;
-  GList *child = priv->pages;
-
-  while (child)
-    {
-      GtkAssistantPage *page_info = child->data;
-      if (page_info->page == page)
-        return child;
-
-      child = child->next;
-    }
-
-  return NULL;
-}
-
-static void
-set_title_font (GtkWidget *assistant,
-                GtkWidget *title_label)
-{
-  PangoFontDescription *desc;
-  GtkStyleContext *context;
-  gint size;
-
-  desc = pango_font_description_new ();
-  context = gtk_widget_get_style_context (title_label);
-  size = pango_font_description_get_size (gtk_style_context_get_font (context, 0));
-
-  pango_font_description_set_weight (desc, PANGO_WEIGHT_ULTRABOLD);
-  pango_font_description_set_size   (desc, size * PANGO_SCALE_XX_LARGE);
-
-  gtk_widget_modify_font (title_label, desc);
-  pango_font_description_free (desc);
-}
-
-static void
-gtk_assistant_style_updated (GtkWidget *widget)
-{
-  GtkAssistant *assistant = GTK_ASSISTANT (widget);
-  GtkAssistantPrivate *priv = assistant->priv;
-  GList *list;
-
-  list = priv->pages;
-
-  while (list)
-    {
-      GtkAssistantPage *page = list->data;
-
-      set_title_font (widget, page->title);
-      list = list->next;
-    }
-}
-
-static void
-gtk_assistant_size_request (GtkWidget      *widget,
-                            GtkRequisition *requisition)
-{
-  GtkAssistant *assistant = GTK_ASSISTANT (widget);
-  GtkAssistantPrivate *priv = assistant->priv;
-  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,
-                        "header-padding", &header_padding,
-                        "content-padding", &content_padding,
-                        NULL);
-  width = height = 0;
-  header_width = header_height = 0;
-  list  = priv->pages;
-
-  while (list)
-    {
-      GtkAssistantPage *page = list->data;
-      gint w, h;
-
-      gtk_widget_get_preferred_size (page->page,
-                                     &child_requisition, NULL);
-      width  = MAX (width,  child_requisition.width);
-      height = MAX (height, child_requisition.height);
-
-      gtk_widget_get_preferred_size (page->title,
-                                     &child_requisition, NULL);
-      w = child_requisition.width;
-      h = child_requisition.height;
-
-      if (page->header_image)
-        {
-          w += gdk_pixbuf_get_width (page->header_image) + HEADER_SPACING;
-          h  = MAX (h, gdk_pixbuf_get_height (page->header_image));
-        }
-
-      header_width  = MAX (header_width, w);
-      header_height = MAX (header_height, h);
-
-      list = list->next;
-    }
-
-  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_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_get_preferred_size (priv->action_area,
-                                 &child_requisition, NULL);
-  width   = MAX (width, child_requisition.width);
-  height += child_requisition.height + ACTION_AREA_SPACING;
-
-  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)
+gtk_assistant_destroy (GtkWidget *widget)
 {
   GtkAssistant *assistant = GTK_ASSISTANT (widget);
   GtkAssistantPrivate *priv = assistant->priv;
-  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;
-
-  rtl   = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
-  pages = priv->pages;
-
-  gtk_widget_style_get (widget,
-                        "header-padding", &header_padding,
-                        "content-padding", &content_padding,
-                        NULL);
 
-  gtk_widget_set_allocation (widget, allocation);
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
-
-  /* Header */
-  gtk_widget_get_preferred_size (priv->header_image,
-                                 &header_requisition, NULL);
-
-  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;
+  /* We set current to NULL so that the remove code doesn't try
+   * to do anything funny
+   */
+  priv->current_page = NULL;
 
-  gtk_widget_size_allocate (priv->header_image, &header_allocation);
+  if (priv->content)
+    {
+      GtkNotebook *notebook;
+      GtkWidget *page;
 
-  /* Action area */
-  gtk_widget_get_preferred_size (priv->action_area,
-                                 &action_requisition, NULL);
+      /* Remove all pages from the content notebook. */
+      notebook = (GtkNotebook *) priv->content;
+      while ((page = gtk_notebook_get_nth_page (notebook, 0)) != NULL)
+        gtk_container_remove ((GtkContainer *) notebook, page);
 
-  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;
+      /* Our GtkAssistantPage list should be empty now. */
+      g_warn_if_fail (priv->pages == NULL);
 
-  gtk_widget_size_allocate (priv->action_area, &child_allocation);
+      priv->content = NULL;
+    }
 
-  gtk_widget_get_allocation (priv->header_image, &header_image_allocation);
-  gtk_widget_get_allocation (priv->action_area, &action_area_allocation);
+  if (priv->sidebar)
+    priv->sidebar = NULL;
 
-  /* Sidebar */
-  gtk_widget_get_preferred_size (priv->sidebar_image,
-                                 &sidebar_requisition, NULL);
+  if (priv->action_area)
+    priv->action_area = NULL;
 
-  if (rtl)
-    child_allocation.x = allocation->width - border_width - sidebar_requisition.width;
-  else
-    child_allocation.x = border_width;
+  if (priv->button_size_group)
+    {
+      g_object_unref (priv->button_size_group);
+      priv->button_size_group = NULL;
+    }
 
-  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;
+  if (priv->title_size_group)
+    {
+      g_object_unref (priv->title_size_group);
+      priv->title_size_group = NULL;
+    }
 
-  gtk_widget_size_allocate (priv->sidebar_image, &child_allocation);
+  if (priv->forward_function)
+    {
+      if (priv->forward_function_data &&
+          priv->forward_data_destroy)
+        priv->forward_data_destroy (priv->forward_function_data);
 
-  /* Pages */
-  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;
+      priv->forward_function = NULL;
+      priv->forward_function_data = NULL;
+      priv->forward_data_destroy = NULL;
+    }
 
-  if (gtk_widget_get_visible (priv->sidebar_image))
+  if (priv->visited_pages)
     {
-      GtkAllocation sidebar_image_allocation;
-
-      gtk_widget_get_allocation (priv->sidebar_image, &sidebar_image_allocation);
+      g_slist_free (priv->visited_pages);
+      priv->visited_pages = NULL;
+    }
 
-      if (!rtl)
-        child_allocation.x += sidebar_image_allocation.width;
+  GTK_WIDGET_CLASS (gtk_assistant_parent_class)->destroy (widget);
+}
 
-      child_allocation.width -= sidebar_image_allocation.width;
-    }
+static GList*
+find_page (GtkAssistant  *assistant,
+           GtkWidget     *page)
+{
+  GtkAssistantPrivate *priv = assistant->priv;
+  GList *child = priv->pages;
 
-  while (pages)
+  while (child)
     {
-      GtkAssistantPage *page = pages->data;
+      GtkAssistantPage *page_info = child->data;
+      if (page_info->page == page)
+        return child;
 
-      gtk_widget_size_allocate (page->page, &child_allocation);
-      gtk_widget_size_allocate (page->title, &header_allocation);
-      pages = pages->next;
+      child = child->next;
     }
+
+  return NULL;
 }
 
 static void
@@ -1330,33 +1247,31 @@ gtk_assistant_map (GtkWidget *widget)
   GtkAssistantPrivate *priv = assistant->priv;
   GList *page_node;
   GtkAssistantPage *page;
-
-  gtk_widget_set_mapped (widget, TRUE);
-
-  gtk_widget_map (priv->header_image);
-  gtk_widget_map (priv->action_area);
-
-  if (gtk_widget_get_visible (priv->sidebar_image) &&
-      !gtk_widget_get_mapped (priv->sidebar_image))
-    gtk_widget_map (priv->sidebar_image);
+  gint page_num;
 
   /* if there's no default page, pick the first one */
   page = NULL;
+  page_num = 0;
   if (!priv->current_page)
     {
       page_node = priv->pages;
 
       while (page_node && !gtk_widget_get_visible (((GtkAssistantPage *) page_node->data)->page))
-        page_node = page_node->next;
+        {
+          page_node = page_node->next;
+          page_num++;
+        }
 
       if (page_node)
         page = page_node->data;
     }
 
-  if (page &&
-      gtk_widget_get_visible (page->page) &&
-      !gtk_widget_get_mapped (page->page))
-    set_current_page (assistant, page);
+  if (page && gtk_widget_get_visible (page->page))
+    set_current_page (assistant, page_num);
+
+  update_buttons_state (assistant);
+  update_actions_size (assistant);
+  update_title_state (assistant);
 
   GTK_WIDGET_CLASS (gtk_assistant_parent_class)->map (widget);
 }
@@ -1367,23 +1282,6 @@ gtk_assistant_unmap (GtkWidget *widget)
   GtkAssistant *assistant = GTK_ASSISTANT (widget);
   GtkAssistantPrivate *priv = assistant->priv;
 
-  gtk_widget_set_mapped (widget, FALSE);
-
-  gtk_widget_unmap (priv->header_image);
-  gtk_widget_unmap (priv->action_area);
-
-  if (gtk_widget_is_drawable (priv->sidebar_image))
-    gtk_widget_unmap (priv->sidebar_image);
-
-  if (priv->current_page &&
-      gtk_widget_is_drawable (priv->current_page->page))
-    {
-      gtk_widget_set_child_visible (priv->current_page->page, FALSE);
-      gtk_widget_set_child_visible (priv->current_page->title, FALSE);
-      gtk_widget_unmap (priv->current_page->title);
-      gtk_widget_unmap (priv->current_page->page);
-    }
-
   g_slist_free (priv->visited_pages);
   priv->visited_pages = NULL;
   priv->current_page  = NULL;
@@ -1407,147 +1305,6 @@ gtk_assistant_delete_event (GtkWidget   *widget,
   return TRUE;
 }
 
-static void
-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;
-  GtkStyleContext *context;
-  GtkStateFlags state;
-  GdkRGBA color;
-  gint border_width, header_padding, content_padding;
-  gint content_x, content_width;
-  gboolean rtl;
-
-  rtl  = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
-
-  gtk_widget_style_get (widget,
-                        "header-padding",  &header_padding,
-                        "content-padding", &content_padding,
-                        NULL);
-
-  context = gtk_widget_get_style_context (widget);
-  state = gtk_widget_get_state_flags (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 */
-  gtk_style_context_save (context);
-  gtk_style_context_add_class (context, GTK_STYLE_CLASS_HIGHLIGHT);
-
-  gtk_style_context_get_background_color (context, state, &color);
-  gdk_cairo_set_source_rgba (cr, &color);
-
-  cairo_rectangle (cr,
-                   border_width,
-                   border_width,
-                   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 = allocation.width - 2 * content_padding - 2 * border_width;
-
-  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 += sidebar_image_allocation.width;
-      content_width -= sidebar_image_allocation.width;
-    }
-
-  gtk_style_context_restore (context);
-
-  gtk_style_context_get_background_color (context, state, &color);
-  gdk_cairo_set_source_rgba (cr, &color);
-
-  cairo_rectangle (cr,
-                   content_x,
-                   header_image_allocation.height + content_padding + 2 * header_padding + border_width,
-                   content_width,
-                   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);
-}
-
-static gboolean
-gtk_assistant_draw (GtkWidget *widget,
-                    cairo_t   *cr)
-{
-  GtkAssistant *assistant = GTK_ASSISTANT (widget);
-  GtkAssistantPrivate *priv = assistant->priv;
-  GtkContainer *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, cr);
-
-  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_draw (container, priv->current_page->page, cr);
-      gtk_container_propagate_draw (container, priv->current_page->title, cr);
-    }
-
-  return FALSE;
-}
-
-static gboolean
-gtk_assistant_focus (GtkWidget        *widget,
-                     GtkDirectionType  direction)
-{
-  GtkAssistantPrivate *priv;
-  GtkContainer *container;
-
-  container = GTK_CONTAINER (widget);
-  priv = GTK_ASSISTANT (widget)->priv;
-
-  /* we only have to care about 2 widgets, action area and the current page */
-  if (gtk_container_get_focus_child (container) == priv->action_area)
-    {
-      if (!gtk_widget_child_focus (priv->action_area, 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 has no
-           * focusable widget, clear focus and go back to the action area
-           */
-          gtk_container_set_focus_child (GTK_CONTAINER (priv->action_area), NULL);
-          gtk_widget_child_focus (priv->action_area, direction);
-        }
-    }
-  else
-    {
-      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);
-          if (priv->current_page != NULL)
-            gtk_widget_child_focus (priv->current_page->page, direction);
-        }
-    }
-
-  return TRUE;
-}
-
 static void
 gtk_assistant_add (GtkContainer *container,
                    GtkWidget    *page)
@@ -1560,46 +1317,12 @@ gtk_assistant_remove (GtkContainer *container,
                       GtkWidget    *page)
 {
   GtkAssistant *assistant = (GtkAssistant*) container;
-  GList *element;
-
-  element = find_page (assistant, page);
-
-  if (element)
-    {
-      remove_page (assistant, element);
-      gtk_widget_queue_resize ((GtkWidget *) container);
-    }
-}
-
-static void
-gtk_assistant_forall (GtkContainer *container,
-                      gboolean      include_internals,
-                      GtkCallback   callback,
-                      gpointer      callback_data)
-{
-  GtkAssistant *assistant = (GtkAssistant*) container;
-  GtkAssistantPrivate *priv = assistant->priv;
-  GList *pages;
-
-  if (include_internals)
-    {
-      (*callback) (priv->header_image, callback_data);
-      (*callback) (priv->sidebar_image, callback_data);
-      (*callback) (priv->action_area, callback_data);
-    }
 
-  pages = priv->pages;
-
-  while (pages)
+  /* Forward this removal to the content notebook */
+  if (gtk_widget_get_parent (page) == assistant->priv->content)
     {
-      GtkAssistantPage *page = (GtkAssistantPage *) pages->data;
-
-      (*callback) (page->page, callback_data);
-
-      if (include_internals)
-        (*callback) (page->title, callback_data);
-
-      pages = pages->next;
+      container = (GtkContainer *) assistant->priv->content;
+      gtk_container_remove (container, page);
     }
 }
 
@@ -1626,11 +1349,11 @@ gtk_assistant_new (void)
  * gtk_assistant_get_current_page:
  * @assistant: a #GtkAssistant
  *
- * Returns the page number of the current page
+ * Returns the page number of the current page.
  *
  * Return value: The index (starting from 0) of the current
- *     page in the @assistant, if the @assistant has no pages,
- *     -1 will be returned
+ *     page in the @assistant, or -1 if the @assistant has no pages,
+ *     or no current page.
  *
  * Since: 2.10
  */
@@ -1679,7 +1402,10 @@ 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)->data;
+    {
+      page = (GtkAssistantPage *) g_list_last (priv->pages)->data;
+      page_num = g_list_length (priv->pages);
+    }
 
   g_return_if_fail (page != NULL);
 
@@ -1694,7 +1420,7 @@ gtk_assistant_set_current_page (GtkAssistant *assistant,
     priv->visited_pages = g_slist_prepend (priv->visited_pages,
                                            priv->current_page);
 
-  set_current_page (assistant, page);
+  set_current_page (assistant, page_num);
 }
 
 /**
@@ -1761,7 +1487,7 @@ gtk_assistant_previous_page (GtkAssistant *assistant)
   while (page_info->type == GTK_ASSISTANT_PAGE_PROGRESS ||
          !gtk_widget_get_visible (page_info->page));
 
-  set_current_page (assistant, page_info);
+  set_current_page (assistant, g_list_index (priv->pages, page_info));
 }
 
 /**
@@ -1887,8 +1613,8 @@ gtk_assistant_insert_page (GtkAssistant *assistant,
 {
   GtkAssistantPrivate *priv;
   GtkAssistantPage *page_info;
-  GtkStyleContext *context;
   gint n_pages;
+  GtkStyleContext *context;
 
   g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
   g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
@@ -1899,18 +1625,31 @@ gtk_assistant_insert_page (GtkAssistant *assistant,
 
   page_info = g_slice_new0 (GtkAssistantPage);
   page_info->page  = page;
-  page_info->title = gtk_label_new (NULL);
-
-  g_signal_connect (G_OBJECT (page), "notify::visible",
-                    G_CALLBACK (on_page_notify_visibility), assistant);
+  page_info->regular_title = gtk_label_new (NULL);
+  gtk_widget_set_no_show_all (page_info->regular_title, TRUE);
+  page_info->current_title = gtk_label_new (NULL);
+  gtk_widget_set_no_show_all (page_info->current_title, TRUE);
+
+  /* Note: we need to use misc alignment here as long as GtkLabel
+   * pays attention to it. GtkWiget::halign is ineffective, since
+   * all the labels are getting the same size anyway, due to the
+   * size group.
+   */
+  gtk_misc_set_alignment (GTK_MISC (page_info->regular_title), 0, 0.5);
+  gtk_widget_show (page_info->regular_title);
 
-  gtk_misc_set_alignment (GTK_MISC (page_info->title), 0.,0.5);
-  set_title_font   (GTK_WIDGET (assistant), page_info->title);
-  gtk_widget_show  (page_info->title);
+  gtk_misc_set_alignment (GTK_MISC (page_info->current_title), 0, 0.5);
+  gtk_widget_hide (page_info->current_title);
 
-  context = gtk_widget_get_style_context (page_info->title);
+  context = gtk_widget_get_style_context (page_info->current_title);
   gtk_style_context_add_class (context, GTK_STYLE_CLASS_HIGHLIGHT);
 
+  gtk_size_group_add_widget (priv->title_size_group, page_info->regular_title);
+  gtk_size_group_add_widget (priv->title_size_group, page_info->current_title);
+
+  g_signal_connect (G_OBJECT (page), "notify::visible",
+                    G_CALLBACK (on_page_notify_visibility), assistant);
+
   n_pages = g_list_length (priv->pages);
 
   if (position < 0 || position > n_pages)
@@ -1918,22 +1657,46 @@ gtk_assistant_insert_page (GtkAssistant *assistant,
 
   priv->pages = g_list_insert (priv->pages, page_info, position);
 
-  gtk_widget_set_child_visible (page_info->page, FALSE);
-  gtk_widget_set_child_visible (page_info->title, FALSE);
-  gtk_widget_set_parent (page_info->page,  GTK_WIDGET (assistant));
-  gtk_widget_set_parent (page_info->title, GTK_WIDGET (assistant));
+  gtk_box_pack_start (GTK_BOX (priv->sidebar), page_info->regular_title, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (priv->sidebar), page_info->current_title, FALSE, FALSE, 0);
+  gtk_box_reorder_child (GTK_BOX (priv->sidebar), page_info->regular_title, 2 * position);
+  gtk_box_reorder_child (GTK_BOX (priv->sidebar), page_info->current_title, 2 * position + 1);
 
-  if (gtk_widget_get_realized (GTK_WIDGET (assistant)))
+  gtk_notebook_insert_page (GTK_NOTEBOOK (priv->content), page, NULL, position);
+
+  if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
     {
-      gtk_widget_realize (page_info->page);
-      gtk_widget_realize (page_info->title);
+      update_buttons_state (assistant);
+      update_actions_size (assistant);
     }
 
-  gtk_widget_queue_resize (GTK_WIDGET (assistant));
-
   return position;
 }
 
+/**
+ * gtk_assistant_remove_page:
+ * @assistant: a #GtkAssistant
+ * @page_num: the index of a page in the @assistant,
+ *     or -1 to remove the last page
+ *
+ * Removes the @page_num's page from @assistant.
+ *
+ * Since: 3.2
+ */
+void
+gtk_assistant_remove_page (GtkAssistant *assistant,
+                           gint          page_num)
+{
+  GtkWidget *page;
+
+  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
+
+  page = gtk_assistant_get_nth_page (assistant, page_num);
+
+  if (page)
+    gtk_container_remove (GTK_CONTAINER (assistant), page);
+}
+
 /**
  * gtk_assistant_set_forward_page_func:
  * @assistant: a #GtkAssistant
@@ -1984,7 +1747,8 @@ gtk_assistant_set_forward_page_func (GtkAssistant         *assistant,
   /* Page flow has possibly changed, so the
    * buttons state might need to change too
    */
-  set_assistant_buttons_state (assistant);
+  if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
+    update_buttons_state (assistant);
 }
 
 /**
@@ -2008,7 +1772,12 @@ gtk_assistant_add_action_widget (GtkAssistant *assistant,
   priv = assistant->priv;
 
   if (GTK_IS_BUTTON (child))
-    gtk_size_group_add_widget (priv->size_group, child);
+    {
+      gtk_size_group_add_widget (priv->button_size_group, child);
+      priv->extra_buttons += 1;
+      if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
+        update_actions_size (assistant);
+    }
 
   gtk_box_pack_end (GTK_BOX (priv->action_area), child, FALSE, FALSE, 0);
 }
@@ -2034,7 +1803,12 @@ gtk_assistant_remove_action_widget (GtkAssistant *assistant,
   priv = assistant->priv;
 
   if (GTK_IS_BUTTON (child))
-    gtk_size_group_remove_widget (priv->size_group, child);
+    {
+      gtk_size_group_remove_widget (priv->button_size_group, child);
+      priv->extra_buttons -= 1;
+      if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
+        update_actions_size (assistant);
+    }
 
   gtk_container_remove (GTK_CONTAINER (priv->action_area), child);
 }
@@ -2069,9 +1843,14 @@ gtk_assistant_set_page_title (GtkAssistant *assistant,
 
   page_info = (GtkAssistantPage*) child->data;
 
-  gtk_label_set_text ((GtkLabel*) page_info->title, title);
+  g_free (page_info->title);
+  page_info->title = g_strdup (title);
+
+  gtk_label_set_text ((GtkLabel*) page_info->regular_title, title);
+  gtk_label_set_text ((GtkLabel*) page_info->current_title, title);
+
   gtk_widget_queue_resize (GTK_WIDGET (assistant));
-  gtk_widget_child_notify (page, "title");
+  gtk_container_child_notify (GTK_CONTAINER (assistant), page, "title");
 }
 
 /**
@@ -2085,7 +1864,7 @@ gtk_assistant_set_page_title (GtkAssistant *assistant,
  *
  * Since: 2.10
  */
-G_CONST_RETURN gchar*
+const gchar*
 gtk_assistant_get_page_title (GtkAssistant *assistant,
                               GtkWidget    *page)
 {
@@ -2101,7 +1880,7 @@ gtk_assistant_get_page_title (GtkAssistant *assistant,
 
   page_info = (GtkAssistantPage*) child->data;
 
-  return gtk_label_get_text ((GtkLabel*) page_info->title);
+  return page_info->title;
 }
 
 /**
@@ -2147,9 +1926,9 @@ gtk_assistant_set_page_type (GtkAssistant         *assistant,
       /* Always set buttons state, a change in a future page
        * might change current page buttons
        */
-      set_assistant_buttons_state (assistant);
+      update_buttons_state (assistant);
 
-      gtk_widget_child_notify (page, "page-type");
+      gtk_container_child_notify (GTK_CONTAINER (assistant), page, "page-type");
     }
 }
 
@@ -2191,25 +1970,31 @@ gtk_assistant_get_page_type (GtkAssistant *assistant,
  *
  * Sets a header image for @page.
  *
- * This image is displayed in the header area of the assistant
- * when @page is the current page.
- *
  * Since: 2.10
+ *
+ * Deprecated: 3.2: Since GTK+ 3.2, a header is no longer shown;
+ *     add your header decoration to the page content instead.
  */
 void
 gtk_assistant_set_page_header_image (GtkAssistant *assistant,
                                      GtkWidget    *page,
                                      GdkPixbuf    *pixbuf)
 {
-  GtkAssistantPrivate *priv;
-  GtkAssistantPage *page_info;
-  GList *child;
-
   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
   g_return_if_fail (GTK_IS_WIDGET (page));
   g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
 
-  priv = assistant->priv;
+  gtk_assistant_do_set_page_header_image (assistant, page, pixbuf);
+}
+
+static void
+gtk_assistant_do_set_page_header_image (GtkAssistant *assistant,
+                                        GtkWidget    *page,
+                                        GdkPixbuf    *pixbuf)
+{
+  GtkAssistantPage *page_info;
+  GList *child;
+
   child = find_page (assistant, page);
 
   g_return_if_fail (child != NULL);
@@ -2227,10 +2012,7 @@ gtk_assistant_set_page_header_image (GtkAssistant *assistant,
       if (pixbuf)
         page_info->header_image = g_object_ref (pixbuf);
 
-      if (page_info == priv->current_page)
-        set_assistant_header_image (assistant);
-
-      gtk_widget_child_notify (page, "header-image");
+      gtk_container_child_notify (GTK_CONTAINER (assistant), page, "header-image");
     }
 }
 
@@ -2245,6 +2027,9 @@ gtk_assistant_set_page_header_image (GtkAssistant *assistant,
  *     or %NULL if there's no header image for the page
  *
  * Since: 2.10
+ *
+ * Deprecated: 3.2: Since GTK+ 3.2, a header is no longer shown;
+ *     add your header decoration to the page content instead.
  */
 GdkPixbuf*
 gtk_assistant_get_page_header_image (GtkAssistant *assistant,
@@ -2269,29 +2054,38 @@ gtk_assistant_get_page_header_image (GtkAssistant *assistant,
  * gtk_assistant_set_page_side_image:
  * @assistant: a #GtkAssistant
  * @page: a page of @assistant
- * @pixbuf: (allow-none): the new header image @page
+ * @pixbuf: (allow-none): the new side image @page
  *
- * Sets a header image for @page.
+ * Sets a side image for @page.
  *
- * This image is displayed in the side area of the assistant
+ * This image used to be displayed in the side area of the assistant
  * when @page is the current page.
  *
  * Since: 2.10
+ *
+ * Deprecated: 3.2: Since GTK+ 3.2, sidebar images are not
+ *     shown anymore.
  */
 void
 gtk_assistant_set_page_side_image (GtkAssistant *assistant,
                                    GtkWidget    *page,
                                    GdkPixbuf    *pixbuf)
 {
-  GtkAssistantPrivate *priv;
-  GtkAssistantPage *page_info;
-  GList *child;
-
   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
   g_return_if_fail (GTK_IS_WIDGET (page));
   g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
 
-  priv = assistant->priv;
+  gtk_assistant_do_set_page_side_image (assistant, page, pixbuf);
+}
+
+static void
+gtk_assistant_do_set_page_side_image (GtkAssistant *assistant,
+                                      GtkWidget    *page,
+                                      GdkPixbuf    *pixbuf)
+{
+  GtkAssistantPage *page_info;
+  GList *child;
+
   child = find_page (assistant, page);
 
   g_return_if_fail (child != NULL);
@@ -2309,10 +2103,7 @@ gtk_assistant_set_page_side_image (GtkAssistant *assistant,
       if (pixbuf)
         page_info->sidebar_image = g_object_ref (pixbuf);
 
-      if (page_info == priv->current_page)
-        set_assistant_sidebar_image (assistant);
-
-      gtk_widget_child_notify (page, "sidebar-image");
+      gtk_container_child_notify (GTK_CONTAINER (assistant), page, "sidebar-image");
     }
 }
 
@@ -2321,12 +2112,15 @@ gtk_assistant_set_page_side_image (GtkAssistant *assistant,
  * @assistant: a #GtkAssistant
  * @page: a page of @assistant
  *
- * Gets the header image for @page.
+ * Gets the side 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
+ *
+ * Deprecated: 3.2: Since GTK+ 3.2, sidebar images are not
+ *     shown anymore.
  */
 GdkPixbuf*
 gtk_assistant_get_page_side_image (GtkAssistant *assistant,
@@ -2385,9 +2179,9 @@ gtk_assistant_set_page_complete (GtkAssistant *assistant,
       /* Always set buttons state, a change in a future page
        * might change current page buttons
        */
-      set_assistant_buttons_state (assistant);
+      update_buttons_state (assistant);
 
-      gtk_widget_child_notify (page, "complete");
+      gtk_container_child_notify (GTK_CONTAINER (assistant), page, "complete");
     }
 }
 
@@ -2442,7 +2236,7 @@ gtk_assistant_update_buttons_state (GtkAssistant *assistant)
 {
   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
 
-  set_assistant_buttons_state (assistant);
+  update_buttons_state (assistant);
 }
 
 /**
@@ -2471,48 +2265,16 @@ gtk_assistant_commit (GtkAssistant *assistant)
 
   assistant->priv->committed = TRUE;
 
-  set_assistant_buttons_state (assistant);
-}
-
-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);
+  update_buttons_state (assistant);
 }
 
 /* accessible implementation */
 
 /* dummy typedefs */
-typedef struct _GtkAssistantAccessible          GtkAssistantAccessible;
-typedef struct _GtkAssistantAccessibleClass     GtkAssistantAccessibleClass;
+typedef GtkWindowAccessible      GtkAssistantAccessible;
+typedef GtkWindowAccessibleClass GtkAssistantAccessibleClass;
 
-ATK_DEFINE_TYPE (GtkAssistantAccessible, _gtk_assistant_accessible, GTK_TYPE_ASSISTANT);
+G_DEFINE_TYPE (GtkAssistantAccessible, _gtk_assistant_accessible, GTK_TYPE_WINDOW_ACCESSIBLE);
 
 static gint
 gtk_assistant_accessible_get_n_children (AtkObject *accessible)
@@ -2523,7 +2285,7 @@ gtk_assistant_accessible_get_n_children (AtkObject *accessible)
   if (widget == NULL)
     return 0;
 
-  return g_list_length (GTK_ASSISTANT (accessible)->priv->pages) + 1;
+  return g_list_length (GTK_ASSISTANT (widget)->priv->pages) + 1;
 }
 
 static AtkObject *
@@ -2584,43 +2346,6 @@ _gtk_assistant_accessible_init (GtkAssistantAccessible *self)
 {
 }
 
-/* factory */
-typedef AtkObjectFactory        GtkAssistantAccessibleFactory;
-typedef AtkObjectFactoryClass   GtkAssistantAccessibleFactoryClass;
-
-G_DEFINE_TYPE (GtkAssistantAccessibleFactory,
-               gtk_assistant_accessible_factory,
-               ATK_TYPE_OBJECT_FACTORY);
-
-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)
-{
-  AtkObject *accessible;
-
-  accessible = g_object_new (_gtk_assistant_accessible_get_type (), NULL);
-  atk_object_initialize (accessible, obj);
-
-  return accessible;
-}
-
-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 void
-gtk_assistant_accessible_factory_init (AtkObjectFactory *factory)
-{
-}
-
 /* buildable implementation */
 
 static GtkBuildableIface *parent_buildable_iface;