Index: gailnotebook.c
===================================================================
RCS file: /cvs/gnome/gail/gail/gailnotebook.c,v
retrieving revision 1.25
diff -u -p -r1.25 gailnotebook.c
--- gailnotebook.c	24 Sep 2003 18:00:16 -0000	1.25
+++ gailnotebook.c	12 Mar 2004 11:56:07 -0000
@@ -43,6 +43,16 @@ static gboolean     gail_notebook_is_chi
                                                        gint           i);
 static AtkObject*   find_child_in_list                (GList          *list,
                                                        gint           index);
+static void         add_to_cache                      (GailNotebook   *gail_notebook,
+                                                       GtkNotebook    *notebook);
+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);
 static gboolean     gail_notebook_focus_cb            (GtkWidget      *widget,
                                                        GtkDirectionType type);
 static gboolean     gail_notebook_check_focus_tab     (gpointer       data);
@@ -157,27 +167,7 @@ gail_notebook_ref_child (AtkObject      
   
   accessible = find_child_in_list (gail_notebook->page_cache, i);
 
-  if (accessible == NULL)
-    { 
-    /*
-     * We attempt to create the cache of pages when the GailNotebook
-     * is created but we do not get notifications of pages being added or
-     * removed subsequently.
-     *
-     * So this code should be reached only for a page which was added 
-     * subsequently.
-     *
-     * We have a problem if pages are removed in that we cannot remove
-     * the corresponding accessible from the cache.
-     * See bug 58674
-     */
-      accessible = gail_notebook_page_new (gtk_notebook, i);
-      if (!accessible)
-        return NULL;
-      gail_notebook->page_cache = g_list_append (gail_notebook->page_cache, 
-                                                 accessible);
-      g_return_val_if_fail (accessible, NULL);
-    }
+  g_assert (accessible);
   g_object_ref (accessible);
   return accessible;
 }
@@ -186,23 +176,20 @@ static void
 gail_notebook_real_initialize (AtkObject *obj,
                                gpointer  data)
 {
-  GailNotebook *notebook = GAIL_NOTEBOOK (obj);
-  GtkNotebook *gtk_notebook = GTK_NOTEBOOK (data);
+  GailNotebook *notebook;
+  GtkNotebook *gtk_notebook;
   GtkWidget *page;
   gint i;
 
   ATK_OBJECT_CLASS (parent_class)->initialize (obj, data);
 
-  i = 0;
-  page = gtk_notebook_get_nth_page (gtk_notebook, i);
-  while (page)
+  notebook = GAIL_NOTEBOOK (obj);
+  gtk_notebook = GTK_NOTEBOOK (data);
+  for (i = 0; i < g_list_length (gtk_notebook->children); i++)
     {
-      AtkObject *obj;
-
-      obj = gail_notebook_page_new (gtk_notebook, i);
-      notebook->page_cache = g_list_append (notebook->page_cache, obj);
-      page = gtk_notebook_get_nth_page (gtk_notebook, ++i);
+      create_notebook_page_accessible (notebook, gtk_notebook, i, FALSE, NULL);
     }
+  notebook->page_count = i;
   notebook->selected_page = gtk_notebook_get_current_page (gtk_notebook);
   if (gtk_notebook->focus_tab && gtk_notebook->focus_tab->data)
     {
@@ -223,17 +210,25 @@ static void
 gail_notebook_real_notify_gtk (GObject           *obj,
                                GParamSpec        *pspec)
 {
-  GtkWidget *widget = GTK_WIDGET (obj);
-  AtkObject* atk_obj = gtk_widget_get_accessible (widget);
+  GtkWidget *widget;
+  AtkObject* atk_obj;
+
+  widget = GTK_WIDGET (obj);
+  atk_obj = gtk_widget_get_accessible (widget);
 
   if (strcmp (pspec->name, "page") == 0)
     {
       gint page_num, old_page_num;
       gint focus_page_num = 0;
       gint old_focus_page_num;
-      GailNotebook *gail_notebook = GAIL_NOTEBOOK (atk_obj);
-      GtkNotebook *gtk_notebook = GTK_NOTEBOOK (widget);
+      GailNotebook *gail_notebook;
+      GtkNotebook *gtk_notebook;
      
+      gail_notebook = GAIL_NOTEBOOK (atk_obj);
+      gtk_notebook = GTK_NOTEBOOK (widget);
+     
+      if (gail_notebook->page_count < g_list_length (gtk_notebook->children))
+        add_to_cache (gail_notebook, gtk_notebook);
       /*
        * Notify SELECTED state change for old and new page
        */
@@ -251,20 +246,22 @@ gail_notebook_real_notify_gtk (GObject  
         {
           AtkObject *obj;
 
-          g_signal_emit_by_name (atk_obj, "selection_changed");
-          g_signal_emit_by_name (atk_obj, "visible_data_changed");
 
-          obj = find_child_in_list (gail_notebook->page_cache, old_page_num);
+          obj = gail_notebook_ref_child (atk_obj, old_page_num);
           if (obj)
-            atk_object_notify_state_change (obj,
-                                            ATK_STATE_SELECTED,
-                                            FALSE);
-          obj = find_child_in_list (gail_notebook->page_cache, page_num);
+            {
+              atk_object_notify_state_change (obj,
+                                              ATK_STATE_SELECTED,
+                                              FALSE);
+              g_object_unref (obj);
+            }
+          obj = gail_notebook_ref_child (atk_obj, page_num);
           if (obj)
             {
               atk_object_notify_state_change (obj,
                                               ATK_STATE_SELECTED,
                                               TRUE);
+              g_object_unref (obj);
               /*
                * The page which is being displayed has changed but there is
                * no need to tell the focus tracker as the focus page will also 
@@ -272,6 +269,8 @@ gail_notebook_real_notify_gtk (GObject  
                * Notebook does not have tabs.
                */
             }
+          g_signal_emit_by_name (atk_obj, "selection_changed");
+          g_signal_emit_by_name (atk_obj, "visible_data_changed");
         }
       if (gtk_notebook_get_show_tabs (gtk_notebook) &&
          (focus_page_num != old_focus_page_num))
@@ -445,6 +444,84 @@ find_child_in_list (GList *list,
   return obj;
 }
 
+static void
+add_to_cache (GailNotebook *gail_notebook,
+              GtkNotebook  *notebook)
+{
+  GList *gtk_list;
+  GList *gail_list;
+  AtkObject *obj;
+  gint i;
+
+  gtk_list = notebook->children;
+  gail_list = gail_notebook->page_cache;
+
+  i = 0;
+  gail_list = gail_notebook->page_cache;
+  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;
+    }
+  gail_notebook->page_count = i;
+}
+
+static void
+create_notebook_page_accessible (GailNotebook *gail_notebook,
+                                 GtkNotebook  *notebook,
+                                 gint         index,
+                                 gboolean     insert_before,
+                                 GList        *list)
+{
+  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),
+                    GINT_TO_POINTER (index));
+}
+
+static void
+gail_notebook_child_parent_set (GtkWidget *widget,
+                                GtkWidget *old_parent,
+                                gpointer  data)
+{
+  GailNotebook *gail_notebook;
+  AtkObject *obj;
+  gint index;
+
+  g_return_if_fail (old_parent != NULL);
+  gail_notebook = GAIL_NOTEBOOK (gtk_widget_get_accessible (old_parent));
+  index = GPOINTER_TO_INT (data);
+
+  obj = find_child_in_list (gail_notebook->page_cache, index);
+  g_return_if_fail (obj);
+  gail_notebook->page_cache = g_list_remove (gail_notebook->page_cache, obj);
+  g_signal_emit_by_name (ATK_OBJECT (gail_notebook),
+                         "children_changed::remove",
+                          GAIL_NOTEBOOK_PAGE (obj)->index, 
+                          obj, NULL);
+  g_object_unref (obj);
+}
+
 static gboolean
 gail_notebook_focus_cb (GtkWidget      *widget,
                         GtkDirectionType type)
Index: gailnotebook.h
===================================================================
RCS file: /cvs/gnome/gail/gail/gailnotebook.h,v
retrieving revision 1.8
diff -u -p -r1.8 gailnotebook.h
--- gailnotebook.h	22 Apr 2002 15:13:45 -0000	1.8
+++ gailnotebook.h	12 Mar 2004 11:56:07 -0000
@@ -50,6 +50,7 @@ struct _GailNotebook
   GList*       page_cache;
   gint         selected_page;
   gint         focus_tab_page;
+  gint         page_count;
   guint        idle_focus_id;
 };
 
Index: gailnotebookpage.c
===================================================================
RCS file: /cvs/gnome/gail/gail/gailnotebookpage.c,v
retrieving revision 1.23
diff -u -p -r1.23 gailnotebookpage.c
--- gailnotebookpage.c	14 Nov 2003 14:55:17 -0000	1.23
+++ gailnotebookpage.c	12 Mar 2004 11:56:08 -0000
@@ -185,6 +185,7 @@ gail_notebook_page_new (GtkNotebook *not
   GailNotebookPage *page;
   GtkWidget *child;
   GtkWidget *label;
+  GList *list;
   
   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
 
@@ -200,6 +201,8 @@ gail_notebook_page_new (GtkNotebook *not
   page->notebook = notebook;
   g_object_add_weak_pointer (G_OBJECT (page->notebook), (gpointer *)&page->notebook);
   page->index = pagenum;
+  list = g_list_nth (notebook->children, pagenum);
+  page->page = list->data;
   page->textutil = NULL;
   
   atk_object = ATK_OBJECT (page);
@@ -208,6 +211,7 @@ gail_notebook_page_new (GtkNotebook *not
 
   atk_child = gtk_widget_get_accessible (child);
   atk_object_set_parent (atk_child, atk_object);
+  g_signal_emit_by_name (atk_object, "children_changed::add", pagenum, atk_child, NULL);
   
   /*
    * We get notified of changes to the label
Index: gailnotebookpage.h
===================================================================
RCS file: /cvs/gnome/gail/gail/gailnotebookpage.h,v
retrieving revision 1.5
diff -u -p -r1.5 gailnotebookpage.h
--- gailnotebookpage.h	4 Feb 2003 08:50:59 -0000	1.5
+++ gailnotebookpage.h	12 Mar 2004 11:56:08 -0000
@@ -44,6 +44,7 @@ struct _GailNotebookPage
   AtkObject parent;
 
   GtkNotebook *notebook;
+  GtkNotebookPage *page;
   
   gint index;
 
