]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkassistant.c
Small documentation tweak
[~andy/gtk] / gtk / gtkassistant.c
index 69fc67e1d01a650d792fbbc2d3049cb23e8220d5..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 "gtkaccessibleprivate.h"
 #include "gtkbutton.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"
@@ -76,6 +74,7 @@
 #include "gtkintl.h"
 #include "gtkprivate.h"
 #include "gtkbuildable.h"
+#include "a11y/gtkwindowaccessible.h"
 
 
 #define HEADER_SPACING 12
@@ -149,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,
@@ -170,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
 {
@@ -213,7 +217,8 @@ gtk_assistant_class_init (GtkAssistantClass *class)
   widget_class->map = gtk_assistant_map;
   widget_class->unmap = gtk_assistant_unmap;
   widget_class->delete_event = gtk_assistant_delete_event;
-  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;
@@ -714,6 +719,10 @@ set_current_page (GtkAssistant *assistant,
   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);
 
@@ -863,6 +872,83 @@ assistant_sidebar_draw_cb (GtkWidget *widget,
   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)
 {
@@ -902,6 +988,9 @@ gtk_assistant_init (GtkAssistant *assistant)
   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);
+
   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);
@@ -916,10 +1005,16 @@ gtk_assistant_init (GtkAssistant *assistant)
 
   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);
@@ -932,6 +1027,13 @@ gtk_assistant_init (GtkAssistant *assistant)
   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))
     {
       gtk_box_pack_end (GTK_BOX (priv->action_area), priv->apply, FALSE, FALSE, 0);
@@ -1000,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,
@@ -1024,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);
@@ -1052,78 +1156,6 @@ gtk_assistant_get_child_property (GtkContainer *container,
     }
 }
 
-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
-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;
-        }
-    }
-
-  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);
-
-  gtk_notebook_remove_page (GTK_NOTEBOOK (priv->content), gtk_notebook_page_num (GTK_NOTEBOOK (priv->content), page_info->page));
-  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_destroy (GtkWidget *widget)
 {
@@ -1135,15 +1167,25 @@ gtk_assistant_destroy (GtkWidget *widget)
    */
   priv->current_page = NULL;
 
-  while (priv->pages)
-    remove_page (assistant, priv->pages);
+  if (priv->content)
+    {
+      GtkNotebook *notebook;
+      GtkWidget *page;
+
+      /* 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);
+
+      /* Our GtkAssistantPage list should be empty now. */
+      g_warn_if_fail (priv->pages == NULL);
+
+      priv->content = NULL;
+    }
 
   if (priv->sidebar)
     priv->sidebar = NULL;
 
-  if (priv->content)
-    priv->content = NULL;
-
   if (priv->action_area)
     priv->action_area = NULL;
 
@@ -1275,14 +1317,12 @@ gtk_assistant_remove (GtkContainer *container,
                       GtkWidget    *page)
 {
   GtkAssistant *assistant = (GtkAssistant*) container;
-  GList *element;
 
-  element = find_page (assistant, page);
-
-  if (element)
+  /* Forward this removal to the content notebook */
+  if (gtk_widget_get_parent (page) == assistant->priv->content)
     {
-      remove_page (assistant, element);
-      gtk_widget_queue_resize ((GtkWidget *) container);
+      container = (GtkContainer *) assistant->priv->content;
+      gtk_container_remove (container, page);
     }
 }
 
@@ -1586,12 +1626,19 @@ gtk_assistant_insert_page (GtkAssistant *assistant,
   page_info = g_slice_new0 (GtkAssistantPage);
   page_info->page  = page;
   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);
 
-  gtk_misc_set_alignment (GTK_MISC (page_info->regular_title), 0.,0.5);
+  /* 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->current_title), 0.,0.5);
+  gtk_misc_set_alignment (GTK_MISC (page_info->current_title), 00.5);
   gtk_widget_hide (page_info->current_title);
 
   context = gtk_widget_get_style_context (page_info->current_title);
@@ -1626,6 +1673,30 @@ gtk_assistant_insert_page (GtkAssistant *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
@@ -1909,13 +1980,21 @@ gtk_assistant_set_page_header_image (GtkAssistant *assistant,
                                      GtkWidget    *page,
                                      GdkPixbuf    *pixbuf)
 {
-  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));
 
+  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);
@@ -1992,13 +2071,21 @@ gtk_assistant_set_page_side_image (GtkAssistant *assistant,
                                    GtkWidget    *page,
                                    GdkPixbuf    *pixbuf)
 {
-  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));
 
+  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);
@@ -2181,29 +2268,13 @@ gtk_assistant_commit (GtkAssistant *assistant)
   update_buttons_state (assistant);
 }
 
-static AtkObject *
-gtk_assistant_get_accessible (GtkWidget *widget)
-{
-  static gboolean first_time = TRUE;
-
-  if (first_time)
-    {
-      _gtk_accessible_set_factory_type (GTK_TYPE_ASSISTANT,
-                                        gtk_assistant_accessible_factory_get_type ());
-
-      first_time = FALSE;
-    }
-
-  return GTK_WIDGET_CLASS (gtk_assistant_parent_class)->get_accessible (widget);
-}
-
 /* 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)
@@ -2275,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;