[gtk+] a11y: Redo notebook page management



commit 790d8e324b7e7af6e81b6a98af004c4cc0797109
Author: Benjamin Otte <otte redhat com>
Date:   Wed Jun 29 15:23:06 2011 +0200

    a11y: Redo notebook page management
    
    Previously, the code tried to track the indexes of the pages and keep
    them up to date in a list and tracking the index in the
    GtkNotebookPage. Now, we store the widget we are tracking in the
    GailNotebookPage and keep a hash table of widget=>GailNotebookPage in the
    GailNotebook. This frees us from the burden of tracking page changes.

 gtk/a11y/gailnotebook.c     |  161 ++++++-------------------------------------
 gtk/a11y/gailnotebook.h     |    5 +-
 gtk/a11y/gailnotebookpage.c |   39 ++++-------
 gtk/a11y/gailnotebookpage.h |    9 +--
 4 files changed, 37 insertions(+), 177 deletions(-)
---
diff --git a/gtk/a11y/gailnotebook.c b/gtk/a11y/gailnotebook.c
index 9997547..f00283a 100644
--- a/gtk/a11y/gailnotebook.c
+++ b/gtk/a11y/gailnotebook.c
@@ -43,20 +43,9 @@ static AtkObject*   gail_notebook_ref_selection       (AtkSelection   *selection
 static gint         gail_notebook_get_selection_count (AtkSelection   *selection);
 static gboolean     gail_notebook_is_child_selected   (AtkSelection   *selection,
                                                        gint           i);
-static AtkObject*   find_child_in_list                (GList          *list,
-                                                       gint           index);
-static void         check_cache                       (GailNotebook   *gail_notebook,
-                                                       GtkNotebook    *notebook);
-static void         reset_cache                       (GailNotebook   *gail_notebook,
-                                                       gint           index);
 static void         create_notebook_page_accessible   (GailNotebook   *gail_notebook,
                                                        GtkNotebook    *notebook,
-                                                       gint           index,
-                                                       gboolean       insert_before,
-                                                       GList          *list);
-static void         gail_notebook_child_parent_set    (GtkWidget      *widget,
-                                                       GtkWidget      *old_parent,
-                                                       gpointer       data);
+                                                       GtkWidget      *child);
 static gboolean     gail_notebook_focus_cb            (GtkWidget      *widget,
                                                        GtkDirectionType type);
 static gboolean     gail_notebook_check_focus_tab     (gpointer       data);
@@ -91,10 +80,12 @@ gail_notebook_class_init (GailNotebookClass *klass)
 static void
 gail_notebook_init (GailNotebook      *notebook)
 {
-  notebook->page_cache = NULL;
+  notebook->pages = g_hash_table_new_full (g_direct_hash,
+                                           g_direct_equal,
+                                           NULL,
+                                           g_object_unref);
   notebook->selected_page = -1;
   notebook->focus_tab_page = -1;
-  notebook->remove_index = -1;
   notebook->idle_focus_id = 0;
 }
 
@@ -115,15 +106,13 @@ gail_notebook_ref_child (AtkObject      *obj,
     return NULL;
 
   gail_notebook = GAIL_NOTEBOOK (obj);
-  
   gtk_notebook = GTK_NOTEBOOK (widget);
 
-  if (gail_notebook->page_count < gtk_notebook_get_n_pages (gtk_notebook))
-    check_cache (gail_notebook, gtk_notebook);
-
-  accessible = find_child_in_list (gail_notebook->page_cache, i);
+  accessible = g_hash_table_lookup (gail_notebook->pages, 
+                                    gtk_notebook_get_nth_page (gtk_notebook, i));
+  /* can return NULL when i >= n_children */
 
-  if (accessible != NULL)
+  if (accessible)
     g_object_ref (accessible);
 
   return accessible;
@@ -140,8 +129,7 @@ gail_notebook_page_added (GtkNotebook *gtk_notebook,
 
   atk_obj = gtk_widget_get_accessible (GTK_WIDGET (gtk_notebook));
   notebook = GAIL_NOTEBOOK (atk_obj);
-  create_notebook_page_accessible (notebook, gtk_notebook, page_num, FALSE, NULL);
-  notebook->page_count++;
+  create_notebook_page_accessible (notebook, gtk_notebook, child);
 }
 
 static void
@@ -152,24 +140,18 @@ gail_notebook_page_removed (GtkNotebook *notebook,
 {
   GailNotebook *gail_notebook;
   AtkObject *obj;
-  gint index;
 
   gail_notebook = GAIL_NOTEBOOK (gtk_widget_get_accessible (GTK_WIDGET (notebook)));
-  index = gail_notebook->remove_index;
-  gail_notebook->remove_index = -1;
 
-  obj = find_child_in_list (gail_notebook->page_cache, index);
+  obj = g_hash_table_lookup (gail_notebook->pages, widget);
   g_return_if_fail (obj);
-  gail_notebook->page_cache = g_list_remove (gail_notebook->page_cache, obj);
-  gail_notebook->page_count -= 1;
-  reset_cache (gail_notebook, index);
   g_signal_emit_by_name (gail_notebook,
                          "children_changed::remove",
                          page_num,
                          obj,
                          NULL);
   gail_notebook_page_invalidate (GAIL_NOTEBOOK_PAGE (obj));
-  g_object_unref (obj);
+  g_hash_table_remove (gail_notebook->pages, widget);
 }
 
 static void
@@ -186,9 +168,10 @@ gail_notebook_real_initialize (AtkObject *obj,
   gtk_notebook = GTK_NOTEBOOK (data);
   for (i = 0; i < gtk_notebook_get_n_pages (gtk_notebook); i++)
     {
-      create_notebook_page_accessible (notebook, gtk_notebook, i, FALSE, NULL);
+      create_notebook_page_accessible (notebook,
+                                       gtk_notebook,
+                                       gtk_notebook_get_nth_page (gtk_notebook, i));
     }
-  notebook->page_count = i;
   notebook->selected_page = gtk_notebook_get_current_page (gtk_notebook);
 
   g_signal_connect (gtk_notebook,
@@ -231,8 +214,6 @@ gail_notebook_real_notify_gtk (GObject           *obj,
       gail_notebook = GAIL_NOTEBOOK (atk_obj);
       gtk_notebook = GTK_NOTEBOOK (widget);
      
-      if (gail_notebook->page_count < gtk_notebook_get_n_pages (gtk_notebook))
-       check_cache (gail_notebook, gtk_notebook);
       /*
        * Notify SELECTED state change for old and new page
        */
@@ -290,22 +271,8 @@ static void
 gail_notebook_finalize (GObject            *object)
 {
   GailNotebook *notebook = GAIL_NOTEBOOK (object);
-  GList *list;
-
-  /*
-   * Get rid of the GailNotebookPage objects which we have cached.
-   */
-  list = notebook->page_cache;
-  if (list != NULL)
-    {
-      while (list)
-        {
-          g_object_unref (list->data);
-          list = list->next;
-        }
-    }
 
-  g_list_free (notebook->page_cache);
+  g_hash_table_destroy (notebook->pages);
 
   if (notebook->idle_focus_id)
     g_source_remove (notebook->idle_focus_id);
@@ -428,103 +395,17 @@ gail_notebook_is_child_selected (AtkSelection *selection,
     return FALSE; 
 }
 
-static AtkObject*
-find_child_in_list (GList *list,
-                    gint  index)
-{
-  AtkObject *obj = NULL;
-
-  while (list)
-    {
-      if (GAIL_NOTEBOOK_PAGE (list->data)->index == index)
-        {
-          obj = ATK_OBJECT (list->data);
-          break;
-        }
-      list = list->next;
-    }
-  return obj;
-}
-
-static void
-check_cache (GailNotebook *gail_notebook,
-             GtkNotebook  *notebook)
-{
-  GList *gtk_list;
-  GList *gail_list;
-  gint i;
-
-  gtk_list = gtk_container_get_children (GTK_CONTAINER (notebook));
-  gail_list = gail_notebook->page_cache;
-
-  i = 0;
-  while (gtk_list)
-    {
-      if (!gail_list)
-        {
-          create_notebook_page_accessible (gail_notebook, notebook, i, FALSE, NULL);
-        }
-      else if (GAIL_NOTEBOOK_PAGE (gail_list->data)->page != gtk_list->data)
-        {
-          create_notebook_page_accessible (gail_notebook, notebook, i, TRUE, gail_list);
-        }
-      else
-        {
-          gail_list = gail_list->next;
-        }
-      i++;
-      gtk_list = gtk_list->next;
-    }
-  g_list_free (gtk_list);
-
-  gail_notebook->page_count = i;
-}
-
-static void
-reset_cache (GailNotebook *gail_notebook,
-             gint         index)
-{
-  GList *l;
-
-  for (l = gail_notebook->page_cache; l; l = l->next)
-    {
-      if (GAIL_NOTEBOOK_PAGE (l->data)->index > index)
-        GAIL_NOTEBOOK_PAGE (l->data)->index -= 1;
-    }
-}
-
 static void
 create_notebook_page_accessible (GailNotebook *gail_notebook,
                                  GtkNotebook  *notebook,
-                                 gint         index,
-                                 gboolean     insert_before,
-                                 GList        *list)
+                                 GtkWidget    *child)
 {
   AtkObject *obj;
 
-  obj = gail_notebook_page_new (notebook, index);
-  g_object_ref (obj);
-  if (insert_before)
-    gail_notebook->page_cache = g_list_insert_before (gail_notebook->page_cache, list, obj);
-  else
-    gail_notebook->page_cache = g_list_append (gail_notebook->page_cache, obj);
-  g_signal_connect (gtk_notebook_get_nth_page (notebook, index), 
-                    "parent_set",
-                    G_CALLBACK (gail_notebook_child_parent_set),
-                    obj);
-}
-
-static void
-gail_notebook_child_parent_set (GtkWidget *widget,
-                                GtkWidget *old_parent,
-                                gpointer   data)
-{
-  GailNotebook *gail_notebook;
-
-  if (!old_parent)
-    return;
-  gail_notebook = GAIL_NOTEBOOK (gtk_widget_get_accessible (old_parent));
-  gail_notebook->remove_index = GAIL_NOTEBOOK_PAGE (data)->index;
+  obj = gail_notebook_page_new (notebook, child);
+  g_hash_table_insert (gail_notebook->pages,
+                       child,
+                       obj);
 }
 
 static gboolean
diff --git a/gtk/a11y/gailnotebook.h b/gtk/a11y/gailnotebook.h
index fd16a3b..a22c5f4 100644
--- a/gtk/a11y/gailnotebook.h
+++ b/gtk/a11y/gailnotebook.h
@@ -44,13 +44,10 @@ struct _GailNotebook
    * If the page is found in the list then a new page does not
    * need to be created
    */
-  GList*       page_cache;
+  GHashTable * pages;
   gint         selected_page;
   gint         focus_tab_page;
-  gint         page_count;
   guint        idle_focus_id;
-
-  gint         remove_index;
 };
 
 GType gail_notebook_get_type (void);
diff --git a/gtk/a11y/gailnotebookpage.c b/gtk/a11y/gailnotebookpage.c
index 13b3e56..6b31280 100644
--- a/gtk/a11y/gailnotebookpage.c
+++ b/gtk/a11y/gailnotebookpage.c
@@ -156,7 +156,11 @@ notify_child_added (gpointer data)
     {
       atk_parent = gtk_widget_get_accessible (GTK_WIDGET (page->notebook));
       atk_object_set_parent (atk_object, atk_parent);
-      g_signal_emit_by_name (atk_parent, "children_changed::add", page->index, atk_object, NULL);
+      g_signal_emit_by_name (atk_parent,
+                             "children_changed::add",
+                             gtk_notebook_page_num (page->notebook, page->child),
+                             atk_object,
+                             NULL);
     }
   
   return FALSE;
@@ -164,30 +168,20 @@ notify_child_added (gpointer data)
 
 AtkObject*
 gail_notebook_page_new (GtkNotebook *notebook, 
-                        gint        pagenum)
+                        GtkWidget   *child)
 {
   GObject *object;
   AtkObject *atk_object;
   GailNotebookPage *page;
-  GtkWidget *child;
   GtkWidget *label;
-  GtkWidget *widget_page;
 
   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
 
-  child = gtk_notebook_get_nth_page (notebook, pagenum);
-
-  if (!child)
-    return NULL;
-
   object = g_object_new (GAIL_TYPE_NOTEBOOK_PAGE, NULL);
-  g_return_val_if_fail (object != NULL, NULL);
 
   page = GAIL_NOTEBOOK_PAGE (object);
   page->notebook = notebook;
-  page->index = pagenum;
-  widget_page = gtk_notebook_get_nth_page (notebook, pagenum);
-  page->page = widget_page;
+  page->child = child;
   page->textutil = NULL;
   
   atk_object = ATK_OBJECT (page);
@@ -223,6 +217,7 @@ gail_notebook_page_invalidate (GailNotebookPage *page)
                                   TRUE);
   atk_object_set_parent (ATK_OBJECT (page), NULL);
   page->notebook = NULL;
+  page->child = NULL;
 }
 
 static void
@@ -349,7 +344,6 @@ static AtkObject*
 gail_notebook_page_ref_child (AtkObject *accessible,
                               gint i)
 {
-  GtkWidget *child;
   AtkObject *child_obj;
   GailNotebookPage *page = NULL;
    
@@ -361,11 +355,7 @@ gail_notebook_page_ref_child (AtkObject *accessible,
   if (!page->notebook)
     return NULL;
 
-  child = gtk_notebook_get_nth_page (page->notebook, page->index);
-  if (!GTK_IS_WIDGET (child))
-    return NULL;
-   
-  child_obj = gtk_widget_get_accessible (child);
+  child_obj = gtk_widget_get_accessible (page->child);
   g_object_ref (child_obj);
   return child_obj;
 }
@@ -375,10 +365,11 @@ gail_notebook_page_get_index_in_parent (AtkObject *accessible)
 {
   GailNotebookPage *page;
 
-  g_return_val_if_fail (GAIL_IS_NOTEBOOK_PAGE (accessible), -1);
   page = GAIL_NOTEBOOK_PAGE (accessible);
+  if (!page->notebook || !page->child)
+    return -1;
 
-  return page->index;
+  return gtk_notebook_page_num (page->notebook, page->child);
 }
 
 static AtkStateSet*
@@ -794,11 +785,7 @@ get_label_from_notebook_page (GailNotebookPage *page)
   if (!gtk_notebook_get_show_tabs (notebook))
     return NULL;
 
-  child = gtk_notebook_get_nth_page (notebook, page->index);
-  if (child == NULL) return NULL;
-  g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
-
-  child = gtk_notebook_get_tab_label (notebook, child);
+  child = gtk_notebook_get_tab_label (notebook, page->child);
 
   if (GTK_IS_LABEL (child))
     return child;
diff --git a/gtk/a11y/gailnotebookpage.h b/gtk/a11y/gailnotebookpage.h
index 78aaca4..5f68b5f 100644
--- a/gtk/a11y/gailnotebookpage.h
+++ b/gtk/a11y/gailnotebookpage.h
@@ -40,13 +40,8 @@ struct _GailNotebookPage
   AtkObject parent;
 
   GtkNotebook *notebook;
-#ifndef GTK_DISABLE_DEPRECATED
-  GtkNotebookPage *page;
-#else
-  gpointer page;
-#endif
   
-  gint index;
+  GtkWidget *child;
   guint notify_child_added_id;
 
   GailTextUtil *textutil;
@@ -59,7 +54,7 @@ struct _GailNotebookPageClass
   AtkObjectClass parent_class;
 };
 
-AtkObject *gail_notebook_page_new(GtkNotebook *notebook, gint pagenum);
+AtkObject *gail_notebook_page_new(GtkNotebook *notebook, GtkWidget *child);
 
 void       gail_notebook_page_invalidate (GailNotebookPage *page);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]