]> Pileus Git - ~andy/gtk/blob - gtk/a11y/gtktreeviewaccessible.c
a11y: Add _gtk_cell_accessible_set_cell_data()
[~andy/gtk] / gtk / a11y / gtktreeviewaccessible.c
1 /* GAIL - The GNOME Accessibility Implementation Library
2  * Copyright 2001, 2002, 2003 Sun Microsystems Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include <gtk/gtk.h>
23 #ifdef GDK_WINDOWING_X11
24 #include <gdk/x11/gdkx.h>
25 #endif
26
27 #include "gtktreeprivate.h"
28 #include "gtkwidgetprivate.h"
29
30 #include "gtktreeviewaccessible.h"
31 #include "gtkrenderercellaccessible.h"
32 #include "gtkbooleancellaccessible.h"
33 #include "gtkimagecellaccessible.h"
34 #include "gtkcontainercellaccessible.h"
35 #include "gtktextcellaccessible.h"
36 #include "gtkcellaccessibleparent.h"
37
38 typedef struct _GtkTreeViewAccessibleCellInfo  GtkTreeViewAccessibleCellInfo;
39 struct _GtkTreeViewAccessibleCellInfo
40 {
41   GtkCellAccessible *cell;
42   GtkRBTree *tree;
43   GtkRBNode *node;
44   GtkTreeViewColumn *cell_col_ref;
45   GtkTreeViewAccessible *view;
46 };
47
48 /* signal handling */
49
50 static gboolean row_expanded_cb      (GtkTreeView      *tree_view,
51                                       GtkTreeIter      *iter,
52                                       GtkTreePath      *path);
53 static gboolean row_collapsed_cb     (GtkTreeView      *tree_view,
54                                       GtkTreeIter      *iter,
55                                       GtkTreePath      *path);
56 static void     size_allocate_cb     (GtkWidget        *widget,
57                                       GtkAllocation    *allocation);
58 static void     selection_changed_cb (GtkTreeSelection *selection,
59                                       gpointer          data);
60
61 static void     cursor_changed       (GtkTreeView      *tree_view,
62                                       GtkTreeViewAccessible *accessible);
63 static gboolean focus_in             (GtkWidget        *widget);
64 static gboolean focus_out            (GtkWidget        *widget);
65
66 static void     destroy_count_func   (GtkTreeView      *tree_view,
67                                       GtkTreePath      *path,
68                                       gint              count,
69                                       gpointer          user_data);
70
71 /* Misc */
72
73 static void             set_iter_nth_row                (GtkTreeView            *tree_view,
74                                                          GtkTreeIter            *iter,
75                                                          gint                   row);
76 static gint             get_row_from_tree_path          (GtkTreeView            *tree_view,
77                                                          GtkTreePath            *path);
78 static void             iterate_thru_children           (GtkTreeView            *tree_view,
79                                                          GtkTreeModel           *tree_model,
80                                                          GtkTreePath            *tree_path,
81                                                          GtkTreePath            *orig,
82                                                          gint                   *count,
83                                                          gint                   depth);
84 static int              cell_info_get_index             (GtkTreeView                     *tree_view,
85                                                          GtkTreeViewAccessibleCellInfo   *info);
86 static void             traverse_cells                  (GtkTreeViewAccessible           *tree_view,
87                                                          GtkTreePath            *tree_path,
88                                                          gboolean               inc_row);
89 static gboolean         update_cell_value               (GtkRendererCellAccessible       *renderer_cell,
90                                                          GtkTreeViewAccessible           *accessible,
91                                                          gboolean               emit_change_signal);
92 static void             set_cell_visibility             (GtkTreeView            *tree_view,
93                                                          GtkCellAccessible      *cell,
94                                                          GtkTreeViewColumn      *tv_col,
95                                                          GtkTreePath            *tree_path,
96                                                          gboolean               emit_signal);
97 static gboolean         is_cell_showing                 (GtkTreeView            *tree_view,
98                                                          GdkRectangle           *cell_rect);
99 static void             set_expand_state                (GtkTreeView            *tree_view,
100                                                          GtkTreeModel           *tree_model,
101                                                          GtkTreeViewAccessible           *accessible,
102                                                          GtkTreePath            *tree_path,
103                                                          gboolean               set_on_ancestor);
104 static void             set_cell_expandable             (GtkCellAccessible     *cell);
105 static void             add_cell_actions                (GtkCellAccessible     *cell,
106                                                          gboolean               editable);
107
108 static void             toggle_cell_toggled             (GtkCellAccessible     *cell);
109 static void             edit_cell                       (GtkCellAccessible     *cell);
110 static void             activate_cell                   (GtkCellAccessible     *cell);
111 static void             cell_destroyed                  (gpointer               data);
112 static void             cell_info_new                   (GtkTreeViewAccessible           *accessible,
113                                                          GtkTreeModel           *tree_model,
114                                                          GtkRBTree              *tree,
115                                                          GtkRBNode              *node,
116                                                          GtkTreeViewColumn      *tv_col,
117                                                          GtkCellAccessible      *cell);
118 static GtkCellAccessible *find_cell                       (GtkTreeViewAccessible           *accessible,
119                                                          gint                   index);
120 static void             connect_model_signals           (GtkTreeView            *view,
121                                                          GtkTreeViewAccessible           *accessible);
122 static void             disconnect_model_signals        (GtkTreeViewAccessible           *accessible);
123 static gint             get_column_number               (GtkTreeView            *tree_view,
124                                                          GtkTreeViewColumn      *column);
125 static gint             get_focus_index                 (GtkTreeView            *tree_view);
126 static gint             get_index                       (GtkTreeView            *tree_view,
127                                                          GtkTreePath            *path,
128                                                          gint                   actual_column);
129 static void             count_rows                      (GtkTreeModel           *model,
130                                                          GtkTreeIter            *iter,
131                                                          GtkTreePath            *end_path,
132                                                          gint                   *count,
133                                                          gint                   level,
134                                                          gint                   depth);
135
136 static gboolean         get_rbtree_column_from_index    (GtkTreeView            *tree_view,
137                                                          gint                   index,
138                                                          GtkRBTree              **tree,
139                                                          GtkRBNode              **node,
140                                                          GtkTreeViewColumn      **column);
141
142 static GtkTreeViewAccessibleCellInfo* find_cell_info    (GtkTreeViewAccessible           *view,
143                                                          GtkCellAccessible               *cell);
144 static AtkObject *       get_header_from_column         (GtkTreeViewColumn      *tv_col);
145
146
147 static void atk_table_interface_init                  (AtkTableIface                *iface);
148 static void atk_selection_interface_init              (AtkSelectionIface            *iface);
149 static void atk_component_interface_init              (AtkComponentIface            *iface);
150 static void gtk_cell_accessible_parent_interface_init (GtkCellAccessibleParentIface *iface);
151
152 G_DEFINE_TYPE_WITH_CODE (GtkTreeViewAccessible, _gtk_tree_view_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE,
153                          G_IMPLEMENT_INTERFACE (ATK_TYPE_TABLE, atk_table_interface_init)
154                          G_IMPLEMENT_INTERFACE (ATK_TYPE_SELECTION, atk_selection_interface_init)
155                          G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init)
156                          G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_ACCESSIBLE_PARENT, gtk_cell_accessible_parent_interface_init))
157
158
159 static void
160 adjustment_changed (GtkAdjustment *adjustment,
161                     GtkWidget     *widget)
162 {
163   GtkTreeViewAccessible *accessible;
164
165   accessible = GTK_TREE_VIEW_ACCESSIBLE (gtk_widget_get_accessible (widget));
166   traverse_cells (accessible, NULL, FALSE);
167 }
168
169 static void
170 hadjustment_set_cb (GObject    *widget,
171                     GParamSpec *pspec,
172                     gpointer    data)
173 {
174   GtkTreeViewAccessible *accessible = data;
175   GtkAdjustment *adj;
176
177   g_object_get (widget, "hadjustment", &adj, NULL);
178   accessible->old_hadj = adj;
179   g_object_add_weak_pointer (G_OBJECT (accessible->old_hadj), (gpointer *)&accessible->old_hadj);
180   g_signal_connect (adj, "value-changed", G_CALLBACK (adjustment_changed), widget);
181 }
182
183 static void
184 vadjustment_set_cb (GObject    *widget,
185                     GParamSpec *pspec,
186                     gpointer    data)
187 {
188   GtkTreeViewAccessible *accessible = data;
189   GtkAdjustment *adj;
190
191   g_object_get (widget, "vadjustment", &adj, NULL);
192   accessible->old_vadj = adj;
193   g_object_add_weak_pointer (G_OBJECT (accessible->old_vadj), (gpointer *)&accessible->old_vadj);
194   g_signal_connect (adj, "value-changed",
195                     G_CALLBACK (adjustment_changed), widget);
196 }
197
198 static GQuark
199 gtk_tree_view_accessible_get_data_quark (void)
200 {
201   static GQuark quark = 0;
202
203   if (G_UNLIKELY (quark == 0))
204     quark = g_quark_from_static_string ("gtk-tree-view-accessible-data");
205
206   return quark;
207 }
208
209 static void
210 cell_info_free (GtkTreeViewAccessibleCellInfo *cell_info)
211 {
212   if (cell_info->cell)
213     {
214       g_object_steal_qdata (G_OBJECT (cell_info->cell),
215                             gtk_tree_view_accessible_get_data_quark ());
216       _gtk_cell_accessible_add_state (cell_info->cell, ATK_STATE_DEFUNCT, FALSE);
217     }
218
219   g_free (cell_info);
220 }
221
222 static GtkTreePath *
223 cell_info_get_path (GtkTreeViewAccessibleCellInfo *cell_info)
224 {
225   return _gtk_tree_view_find_path (NULL,
226                                    cell_info->tree,
227                                    cell_info->node);
228 }
229
230 static guint
231 cell_info_hash (gconstpointer info)
232 {
233   const GtkTreeViewAccessibleCellInfo *cell_info = info;
234   guint node, col;
235
236   node = GPOINTER_TO_UINT (cell_info->node);
237   col = GPOINTER_TO_UINT (cell_info->cell_col_ref);
238
239   return ((node << sizeof (guint) / 2) | (node >> sizeof (guint) / 2)) ^ col;
240 }
241
242 static gboolean
243 cell_info_equal (gconstpointer a, gconstpointer b)
244 {
245   const GtkTreeViewAccessibleCellInfo *cell_info_a = a;
246   const GtkTreeViewAccessibleCellInfo *cell_info_b = b;
247
248   return cell_info_a->node == cell_info_b->node &&
249          cell_info_a->cell_col_ref == cell_info_b->cell_col_ref;
250 }
251
252 static void
253 gtk_tree_view_accessible_initialize (AtkObject *obj,
254                                      gpointer   data)
255 {
256   GtkTreeViewAccessible *accessible;
257   GtkTreeView *tree_view;
258   GtkTreeModel *tree_model;
259   GtkWidget *widget;
260   GtkTreeSelection *selection;
261
262   ATK_OBJECT_CLASS (_gtk_tree_view_accessible_parent_class)->initialize (obj, data);
263
264   accessible = GTK_TREE_VIEW_ACCESSIBLE (obj);
265   accessible->focus_cell = NULL;
266   accessible->old_hadj = NULL;
267   accessible->old_vadj = NULL;
268   accessible->idle_expand_id = 0;
269   accessible->idle_expand_path = NULL;
270   accessible->n_children_deleted = 0;
271
272   accessible->cell_infos = g_hash_table_new_full (cell_info_hash,
273       cell_info_equal, NULL, (GDestroyNotify) cell_info_free);
274
275   widget = GTK_WIDGET (data);
276   tree_view = GTK_TREE_VIEW (widget);
277   tree_model = gtk_tree_view_get_model (tree_view);
278   selection = gtk_tree_view_get_selection (tree_view);
279
280   g_signal_connect_after (widget, "row-collapsed",
281                           G_CALLBACK (row_collapsed_cb), NULL);
282   g_signal_connect (widget, "row-expanded",
283                     G_CALLBACK (row_expanded_cb), NULL);
284   g_signal_connect (widget, "size-allocate",
285                     G_CALLBACK (size_allocate_cb), NULL);
286   g_signal_connect (selection, "changed",
287                     G_CALLBACK (selection_changed_cb), obj);
288
289   g_signal_connect (tree_view, "cursor-changed",
290                     G_CALLBACK (cursor_changed), accessible);
291   g_signal_connect (tree_view, "focus-in-event",
292                     G_CALLBACK (focus_in), NULL);
293   g_signal_connect (tree_view, "focus-out-event",
294                     G_CALLBACK (focus_out), NULL);
295
296   accessible->tree_model = tree_model;
297   if (tree_model)
298     {
299       g_object_add_weak_pointer (G_OBJECT (accessible->tree_model), (gpointer *)&accessible->tree_model);
300       connect_model_signals (tree_view, accessible);
301
302       if (gtk_tree_model_get_flags (tree_model) & GTK_TREE_MODEL_LIST_ONLY)
303         obj->role = ATK_ROLE_TABLE;
304       else
305         obj->role = ATK_ROLE_TREE_TABLE;
306     }
307
308   hadjustment_set_cb (G_OBJECT (widget), NULL, accessible);
309   vadjustment_set_cb (G_OBJECT (widget), NULL, accessible);
310   g_signal_connect (widget, "notify::hadjustment",
311                     G_CALLBACK (hadjustment_set_cb), accessible);
312   g_signal_connect (widget, "notify::vadjustment",
313                     G_CALLBACK (vadjustment_set_cb), accessible);
314
315   gtk_tree_view_set_destroy_count_func (tree_view,
316                                         destroy_count_func,
317                                         NULL, NULL);
318 }
319
320 static void
321 gtk_tree_view_accessible_finalize (GObject *object)
322 {
323   GtkTreeViewAccessible *accessible = GTK_TREE_VIEW_ACCESSIBLE (object);
324
325   /* remove any idle handlers still pending */
326   if (accessible->idle_expand_id)
327     g_source_remove (accessible->idle_expand_id);
328
329   if (accessible->tree_model)
330     disconnect_model_signals (accessible);
331
332   if (accessible->cell_infos)
333     g_hash_table_destroy (accessible->cell_infos);
334
335   G_OBJECT_CLASS (_gtk_tree_view_accessible_parent_class)->finalize (object);
336 }
337
338 static void
339 gtk_tree_view_accessible_notify_gtk (GObject    *obj,
340                                      GParamSpec *pspec)
341 {
342   GtkWidget *widget;
343   GtkTreeView *tree_view;
344   GtkTreeViewAccessible *accessible;
345   GtkAdjustment *adj;
346
347   widget = GTK_WIDGET (obj);
348   accessible = GTK_TREE_VIEW_ACCESSIBLE (gtk_widget_get_accessible (widget));
349   tree_view = GTK_TREE_VIEW (widget);
350
351   if (g_strcmp0 (pspec->name, "model") == 0)
352     {
353       GtkTreeModel *tree_model;
354       AtkRole role;
355
356       tree_model = gtk_tree_view_get_model (tree_view);
357       if (accessible->tree_model)
358         disconnect_model_signals (accessible);
359       g_hash_table_remove_all (accessible->cell_infos);
360       accessible->tree_model = tree_model;
361
362       if (tree_model)
363         {
364           g_object_add_weak_pointer (G_OBJECT (accessible->tree_model), (gpointer *)&accessible->tree_model);
365           connect_model_signals (tree_view, accessible);
366
367           if (gtk_tree_model_get_flags (tree_model) & GTK_TREE_MODEL_LIST_ONLY)
368             role = ATK_ROLE_TABLE;
369           else
370             role = ATK_ROLE_TREE_TABLE;
371         }
372       else
373         {
374           role = ATK_ROLE_UNKNOWN;
375         }
376       atk_object_set_role (ATK_OBJECT (accessible), role);
377       g_object_freeze_notify (G_OBJECT (accessible));
378       g_signal_emit_by_name (accessible, "model-changed");
379       g_signal_emit_by_name (accessible, "visible-data-changed");
380       g_object_thaw_notify (G_OBJECT (accessible));
381     }
382   else if (g_strcmp0 (pspec->name, "hadjustment") == 0)
383     {
384       g_object_get (tree_view, "hadjustment", &adj, NULL);
385       g_signal_handlers_disconnect_by_func (accessible->old_hadj,
386                                             (gpointer) adjustment_changed,
387                                             widget);
388       accessible->old_hadj = adj;
389       g_object_add_weak_pointer (G_OBJECT (accessible->old_hadj), (gpointer *)&accessible->old_hadj);
390       g_signal_connect (adj, "value-changed", G_CALLBACK (adjustment_changed), tree_view);
391     }
392   else if (g_strcmp0 (pspec->name, "vadjustment") == 0)
393     {
394       g_object_get (tree_view, "vadjustment", &adj, NULL);
395       g_signal_handlers_disconnect_by_func (accessible->old_vadj,
396                                             (gpointer) adjustment_changed,
397                                             widget);
398       accessible->old_vadj = adj;
399       g_object_add_weak_pointer (G_OBJECT (accessible->old_hadj), (gpointer *)&accessible->old_vadj);
400       g_signal_connect (adj, "value-changed", G_CALLBACK (adjustment_changed), tree_view);
401     }
402   else
403     GTK_WIDGET_ACCESSIBLE_CLASS (_gtk_tree_view_accessible_parent_class)->notify_gtk (obj, pspec);
404 }
405
406 static void
407 gtk_tree_view_accessible_destroyed (GtkWidget     *widget,
408                                     GtkAccessible *gtk_accessible)
409 {
410   GtkAdjustment *adj;
411   GtkTreeViewAccessible *accessible;
412
413   if (!GTK_IS_TREE_VIEW (widget))
414     return;
415
416   accessible = GTK_TREE_VIEW_ACCESSIBLE (gtk_accessible);
417   adj = accessible->old_hadj;
418   if (adj)
419     g_signal_handlers_disconnect_by_func (adj,
420                                           (gpointer) adjustment_changed,
421                                           widget);
422   adj = accessible->old_vadj;
423   if (adj)
424     g_signal_handlers_disconnect_by_func (adj,
425                                           (gpointer) adjustment_changed,
426                                           widget);
427   if (accessible->tree_model)
428     {
429       disconnect_model_signals (accessible);
430       accessible->tree_model = NULL;
431     }
432   if (accessible->focus_cell)
433     {
434       g_object_unref (accessible->focus_cell);
435       accessible->focus_cell = NULL;
436     }
437   if (accessible->idle_expand_id)
438     {
439       g_source_remove (accessible->idle_expand_id);
440       accessible->idle_expand_id = 0;
441     }
442 }
443
444 static void
445 gtk_tree_view_accessible_connect_widget_destroyed (GtkAccessible *accessible)
446 {
447   GtkWidget *widget;
448
449   widget = gtk_accessible_get_widget (accessible);
450   if (widget)
451     g_signal_connect_after (widget, "destroy",
452                             G_CALLBACK (gtk_tree_view_accessible_destroyed), accessible);
453
454   GTK_ACCESSIBLE_CLASS (_gtk_tree_view_accessible_parent_class)->connect_widget_destroyed (accessible);
455 }
456
457 static gint
458 get_n_rows (GtkTreeView *tree_view)
459 {
460   GtkRBTree *tree;
461
462   tree = _gtk_tree_view_get_rbtree (tree_view);
463
464   if (tree == NULL)
465     return 0;
466
467   return tree->root->total_count;
468 }
469
470 static gint
471 get_n_columns (GtkTreeView *tree_view)
472 {
473   guint i, visible_columns;
474
475   visible_columns = 0;
476
477   for (i = 0; i < gtk_tree_view_get_n_columns (tree_view); i++)
478     {
479       GtkTreeViewColumn *column = gtk_tree_view_get_column (tree_view, i);
480
481       if (gtk_tree_view_column_get_visible (column))
482         visible_columns++;
483     }
484
485   return visible_columns;
486 }
487 static gint
488 gtk_tree_view_accessible_get_n_children (AtkObject *obj)
489 {
490   GtkWidget *widget;
491   GtkTreeView *tree_view;
492
493   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
494   if (widget == NULL)
495     return 0;
496
497   tree_view = GTK_TREE_VIEW (widget);
498   return (get_n_rows (tree_view) + 1) * get_n_columns (tree_view);
499 }
500
501 static GtkTreeViewColumn *
502 get_visible_column (GtkTreeView *tree_view,
503                     guint        id)
504 {
505   guint i;
506
507   for (i = 0; i < gtk_tree_view_get_n_columns (tree_view); i++)
508     {
509       GtkTreeViewColumn *column = gtk_tree_view_get_column (tree_view, i);
510
511       if (!gtk_tree_view_column_get_visible (column))
512         continue;
513
514       if (id == 0)
515         return column;
516
517       id--;
518     }
519
520   g_return_val_if_reached (NULL);
521 }
522
523 static AtkObject *
524 gtk_tree_view_accessible_ref_child (AtkObject *obj,
525                                     gint       i)
526 {
527   GtkWidget *widget;
528   GtkTreeViewAccessible *accessible;
529   GtkCellAccessible *cell;
530   GtkTreeView *tree_view;
531   GtkTreeModel *tree_model;
532   GtkCellRenderer *renderer;
533   GtkTreeIter iter;
534   GtkTreeViewColumn *tv_col;
535   GtkTreeSelection *selection;
536   GtkTreePath *path;
537   GtkRBTree *tree;
538   GtkRBNode *node;
539   AtkObject *child;
540   AtkObject *parent;
541   GtkTreeViewColumn *expander_tv;
542   GList *renderer_list;
543   GList *l;
544   GtkContainerCellAccessible *container = NULL;
545   GtkRendererCellAccessible *renderer_cell;
546   gboolean is_expander, is_expanded, retval;
547   gboolean editable = FALSE;
548   gint focus_index;
549
550   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
551   if (widget == NULL)
552     return NULL;
553
554   if (i >= gtk_tree_view_accessible_get_n_children (obj))
555     return NULL;
556
557   accessible = GTK_TREE_VIEW_ACCESSIBLE (obj);
558   tree_view = GTK_TREE_VIEW (widget);
559   if (i < get_n_columns (tree_view))
560     {
561       tv_col = get_visible_column (tree_view, i);
562       child = get_header_from_column (tv_col);
563       if (child)
564         g_object_ref (child);
565       return child;
566     }
567
568   /* Check whether the child is cached */
569   cell = find_cell (accessible, i);
570   if (cell)
571     {
572       g_object_ref (cell);
573       return ATK_OBJECT (cell);
574     }
575
576   if (accessible->focus_cell == NULL)
577       focus_index = get_focus_index (tree_view);
578   else
579       focus_index = -1;
580
581   /* Find the RBTree and GtkTreeViewColumn for the index */
582   if (!get_rbtree_column_from_index (tree_view, i, &tree, &node, &tv_col))
583     return NULL;
584
585   path = _gtk_tree_view_find_path (tree_view, tree, node);
586   tree_model = gtk_tree_view_get_model (tree_view);
587   retval = gtk_tree_model_get_iter (tree_model, &iter, path);
588   if (!retval)
589     return NULL;
590
591   expander_tv = gtk_tree_view_get_expander_column (tree_view);
592   is_expander = FALSE;
593   is_expanded = FALSE;
594   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
595     {
596       if (expander_tv == tv_col)
597         {
598           is_expander = TRUE;
599           is_expanded = node->children != NULL;
600         }
601     }
602   gtk_tree_view_column_cell_set_cell_data (tv_col, tree_model, &iter,
603                                            is_expander, is_expanded);
604
605   renderer_list = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (tv_col));
606
607   /* If there is not exactly one renderer in the list,
608    * make a container
609    */
610   if (renderer_list == NULL || renderer_list->next)
611     {
612       GtkCellAccessible *container_cell;
613
614       container = _gtk_container_cell_accessible_new ();
615
616       container_cell = GTK_CELL_ACCESSIBLE (container);
617       _gtk_cell_accessible_initialise (container_cell, widget, ATK_OBJECT (accessible));
618
619       /* The GtkTreeViewAccessibleCellInfo structure for the container will
620        * be before the ones for the cells so that the first one we find for
621        * a position will be for the container
622        */
623       cell_info_new (accessible, tree_model, tree, node, tv_col, container_cell);
624       parent = ATK_OBJECT (container);
625     }
626   else
627     parent = ATK_OBJECT (accessible);
628
629   child = NULL;
630
631   for (l = renderer_list; l; l = l->next)
632     {
633       renderer = GTK_CELL_RENDERER (l->data);
634
635       if (GTK_IS_CELL_RENDERER_TEXT (renderer))
636         {
637           g_object_get (G_OBJECT (renderer), "editable", &editable, NULL);
638           child = _gtk_text_cell_accessible_new ();
639         }
640       else if (GTK_IS_CELL_RENDERER_TOGGLE (renderer))
641         child = _gtk_boolean_cell_accessible_new ();
642       else if (GTK_IS_CELL_RENDERER_PIXBUF (renderer))
643         child = _gtk_image_cell_accessible_new ();
644       else
645         child = _gtk_renderer_cell_accessible_new ();
646
647       cell = GTK_CELL_ACCESSIBLE (child);
648       renderer_cell = GTK_RENDERER_CELL_ACCESSIBLE (child);
649
650       /* Create the GtkTreeViewAccessibleCellInfo for this cell */
651       if (parent == ATK_OBJECT (accessible))
652         cell_info_new (accessible, tree_model, tree, node, tv_col, cell);
653
654       _gtk_cell_accessible_initialise (cell, widget, parent);
655
656       if (container)
657         _gtk_container_cell_accessible_add_child (container, cell);
658
659       update_cell_value (renderer_cell, accessible, FALSE);
660
661       /* Add the actions appropriate for this cell */
662       add_cell_actions (cell, editable);
663
664       /* Set state if it is expandable */
665       if (is_expander)
666         {
667           set_cell_expandable (cell);
668           if (is_expanded)
669             _gtk_cell_accessible_add_state (cell, ATK_STATE_EXPANDED, FALSE);
670         }
671
672       /* If the column is visible, sets the cell's state */
673       if (gtk_tree_view_column_get_visible (tv_col))
674         set_cell_visibility (tree_view, cell, tv_col, path, FALSE);
675
676       /* If the row is selected, all cells on the row are selected */
677       selection = gtk_tree_view_get_selection (tree_view);
678
679       if (gtk_tree_selection_path_is_selected (selection, path))
680         _gtk_cell_accessible_add_state (cell, ATK_STATE_SELECTED, FALSE);
681
682       _gtk_cell_accessible_add_state (cell, ATK_STATE_FOCUSABLE, FALSE);
683       if (focus_index == i)
684         {
685           accessible->focus_cell = g_object_ref (cell);
686           _gtk_cell_accessible_add_state (cell, ATK_STATE_FOCUSED, FALSE);
687           g_signal_emit_by_name (accessible, "active-descendant-changed", cell);
688         }
689     }
690   g_list_free (renderer_list);
691   if (container)
692     child = ATK_OBJECT (container);
693
694   if (expander_tv == tv_col)
695     {
696       AtkRelationSet *relation_set;
697       AtkObject *accessible_array[1];
698       AtkRelation* relation;
699       AtkObject *parent_node;
700
701       relation_set = atk_object_ref_relation_set (ATK_OBJECT (child));
702
703       gtk_tree_path_up (path);
704       if (gtk_tree_path_get_depth (path) == 0)
705         parent_node = obj;
706       else
707         {
708           gint parent_index;
709
710           parent_index = get_index (tree_view, path, i % get_n_columns (tree_view));
711           parent_node = atk_object_ref_accessible_child (obj, parent_index);
712         }
713       accessible_array[0] = parent_node;
714       relation = atk_relation_new (accessible_array, 1,
715                                    ATK_RELATION_NODE_CHILD_OF);
716       atk_relation_set_add (relation_set, relation);
717       atk_object_add_relationship (parent_node, ATK_RELATION_NODE_PARENT_OF, child);
718       g_object_unref (relation);
719       g_object_unref (relation_set);
720     }
721   gtk_tree_path_free (path);
722
723   /* We do not increase the reference count here; when g_object_unref()
724    * is called for the cell then cell_destroyed() is called and this
725    * removes the cell from the cache.
726    */
727   return child;
728 }
729
730 static AtkStateSet*
731 gtk_tree_view_accessible_ref_state_set (AtkObject *obj)
732 {
733   AtkStateSet *state_set;
734   GtkWidget *widget;
735
736   state_set = ATK_OBJECT_CLASS (_gtk_tree_view_accessible_parent_class)->ref_state_set (obj);
737   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
738
739   if (widget != NULL)
740     atk_state_set_add_state (state_set, ATK_STATE_MANAGES_DESCENDANTS);
741
742   return state_set;
743 }
744
745 static void
746 _gtk_tree_view_accessible_class_init (GtkTreeViewAccessibleClass *klass)
747 {
748   AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
749   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
750   GtkAccessibleClass *accessible_class = (GtkAccessibleClass*)klass;
751   GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
752   GtkContainerAccessibleClass *container_class = (GtkContainerAccessibleClass*)klass;
753
754   class->get_n_children = gtk_tree_view_accessible_get_n_children;
755   class->ref_child = gtk_tree_view_accessible_ref_child;
756   class->ref_state_set = gtk_tree_view_accessible_ref_state_set;
757   class->initialize = gtk_tree_view_accessible_initialize;
758
759   widget_class->notify_gtk = gtk_tree_view_accessible_notify_gtk;
760
761   accessible_class->connect_widget_destroyed = gtk_tree_view_accessible_connect_widget_destroyed;
762
763   /* The children of a GtkTreeView are the buttons at the top of the columns
764    * we do not represent these as children so we do not want to report
765    * children added or deleted when these changed.
766    */
767   container_class->add_gtk = NULL;
768   container_class->remove_gtk = NULL;
769
770   gobject_class->finalize = gtk_tree_view_accessible_finalize;
771 }
772
773 static void
774 _gtk_tree_view_accessible_init (GtkTreeViewAccessible *view)
775 {
776 }
777
778 gint
779 get_focus_index (GtkTreeView *tree_view)
780 {
781   GtkTreePath *focus_path;
782   GtkTreeViewColumn *focus_column;
783   gint index;
784
785   gtk_tree_view_get_cursor (tree_view, &focus_path, &focus_column);
786   if (focus_path && focus_column)
787     index = get_index (tree_view, focus_path,
788                        get_column_number (tree_view, focus_column));
789   else
790     index = -1;
791
792   if (focus_path)
793     gtk_tree_path_free (focus_path);
794
795   return index;
796 }
797
798 /* This function returns a reference to the accessible object
799  * for the cell in the treeview which has focus, if any
800  */
801 static AtkObject *
802 gtk_tree_view_accessible_ref_focus_cell (GtkTreeView *tree_view)
803 {
804   AtkObject *focus_cell = NULL;
805   AtkObject *atk_obj;
806   gint focus_index;
807
808   focus_index = get_focus_index (tree_view);
809   if (focus_index >= 0)
810     {
811       atk_obj = gtk_widget_get_accessible (GTK_WIDGET (tree_view));
812       focus_cell = atk_object_ref_accessible_child (atk_obj, focus_index);
813     }
814
815   return focus_cell;
816 }
817
818 /* atkcomponent.h */
819
820 static AtkObject *
821 gtk_tree_view_accessible_ref_accessible_at_point (AtkComponent *component,
822                                                   gint          x,
823                                                   gint          y,
824                                                   AtkCoordType  coord_type)
825 {
826   GtkWidget *widget;
827   GtkTreeView *tree_view;
828   GtkTreePath *path;
829   GtkTreeViewColumn *tv_column;
830   gint x_pos, y_pos;
831   gint bx, by;
832   gboolean ret_val;
833
834   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
835   if (widget == NULL)
836     return NULL;
837
838   tree_view = GTK_TREE_VIEW (widget);
839
840   atk_component_get_extents (component, &x_pos, &y_pos, NULL, NULL, coord_type);
841   gtk_tree_view_convert_widget_to_bin_window_coords (tree_view, x, y, &bx, &by);
842   ret_val = gtk_tree_view_get_path_at_pos (tree_view,
843                                            bx - x_pos, by - y_pos,
844                                            &path, &tv_column, NULL, NULL);
845   if (ret_val)
846     {
847       gint index, column;
848
849       column = get_column_number (tree_view, tv_column);
850       index = get_index (tree_view, path, column);
851       gtk_tree_path_free (path);
852
853       return gtk_tree_view_accessible_ref_child (ATK_OBJECT (component), index);
854     }
855
856   return NULL;
857 }
858
859 static void
860 atk_component_interface_init (AtkComponentIface *iface)
861 {
862   iface->ref_accessible_at_point = gtk_tree_view_accessible_ref_accessible_at_point;
863 }
864
865 /* atktable.h */
866
867 static gint
868 gtk_tree_view_accessible_get_index_at (AtkTable *table,
869                                        gint      row,
870                                        gint      column)
871 {
872   GtkWidget *widget;
873   gint n_cols, n_rows;
874
875   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
876   if (widget == NULL)
877     return -1;
878
879   n_cols = atk_table_get_n_columns (table);
880   n_rows = atk_table_get_n_rows (table);
881
882   if (row >= n_rows || column >= n_cols)
883     return -1;
884
885   return (row + 1) * n_cols + column;
886 }
887
888 static gint
889 gtk_tree_view_accessible_get_column_at_index (AtkTable *table,
890                                               gint      index)
891 {
892   GtkWidget *widget;
893   gint n_columns;
894
895   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
896   if (widget == NULL)
897     return -1;
898
899   if (index >= gtk_tree_view_accessible_get_n_children (ATK_OBJECT (table)))
900     return -1;
901
902   n_columns = get_n_columns (GTK_TREE_VIEW (widget));
903
904   /* checked by the n_children() check above */
905   g_assert (n_columns > 0);
906
907   return index % n_columns;
908 }
909
910 static gint
911 gtk_tree_view_accessible_get_row_at_index (AtkTable *table,
912                                            gint      index)
913 {
914   GtkWidget *widget;
915   GtkTreeView *tree_view;
916
917   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
918   if (widget == NULL)
919     return -1;
920
921   tree_view = GTK_TREE_VIEW (widget);
922
923   index /= get_n_columns (tree_view);
924   index--;
925   if (index >= get_n_rows (tree_view))
926     return -1;
927
928   return index;
929 }
930
931 static AtkObject *
932 gtk_tree_view_accessible_table_ref_at (AtkTable *table,
933                                        gint      row,
934                                        gint      column)
935 {
936   gint index;
937
938   index = gtk_tree_view_accessible_get_index_at (table, row, column);
939   if (index == -1)
940     return NULL;
941
942   return gtk_tree_view_accessible_ref_child (ATK_OBJECT (table), index);
943 }
944
945 static gint
946 gtk_tree_view_accessible_get_n_rows (AtkTable *table)
947 {
948   GtkWidget *widget;
949
950   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
951   if (widget == NULL)
952     return 0;
953
954   return get_n_rows (GTK_TREE_VIEW (widget));
955 }
956
957 static gint
958 gtk_tree_view_accessible_get_n_columns (AtkTable *table)
959 {
960   GtkWidget *widget;
961
962   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
963   if (widget == NULL)
964     return 0;
965
966   return get_n_columns (GTK_TREE_VIEW (widget));
967 }
968
969 static gboolean
970 gtk_tree_view_accessible_is_row_selected (AtkTable *table,
971                                           gint      row)
972 {
973   GtkWidget *widget;
974   GtkTreeView *tree_view;
975   GtkTreeSelection *selection;
976   GtkTreeIter iter;
977
978   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
979   if (widget == NULL)
980     return FALSE;
981
982   if (row < 0)
983     return FALSE;
984
985   tree_view = GTK_TREE_VIEW (widget);
986   selection = gtk_tree_view_get_selection (tree_view);
987
988   set_iter_nth_row (tree_view, &iter, row);
989   return gtk_tree_selection_iter_is_selected (selection, &iter);
990 }
991
992 static gboolean
993 gtk_tree_view_accessible_is_selected (AtkTable *table,
994                                       gint      row,
995                                       gint      column)
996 {
997   return gtk_tree_view_accessible_is_row_selected (table, row);
998 }
999
1000 static void
1001 get_selected_rows (GtkTreeModel *model,
1002                    GtkTreePath  *path,
1003                    GtkTreeIter  *iter,
1004                    gpointer      data)
1005 {
1006   GPtrArray *array = (GPtrArray *)data;
1007
1008   g_ptr_array_add (array, gtk_tree_path_copy (path));
1009 }
1010
1011 static gint
1012 gtk_tree_view_accessible_get_selected_rows (AtkTable  *table,
1013                                             gint     **rows_selected)
1014 {
1015   GtkWidget *widget;
1016   GtkTreeView *tree_view;
1017   GtkTreeModel *tree_model;
1018   GtkTreeIter iter;
1019   GtkTreeSelection *selection;
1020   GtkTreePath *tree_path;
1021   gint ret_val = 0;
1022
1023   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
1024   if (widget == NULL)
1025     return 0;
1026
1027   tree_view = GTK_TREE_VIEW (widget);
1028   selection = gtk_tree_view_get_selection (tree_view);
1029
1030   switch (gtk_tree_selection_get_mode (selection))
1031     {
1032     case GTK_SELECTION_SINGLE:
1033     case GTK_SELECTION_BROWSE:
1034       if (gtk_tree_selection_get_selected (selection, &tree_model, &iter))
1035         {
1036           gint row;
1037
1038           if (rows_selected)
1039             {
1040               *rows_selected = g_new (gint, 1);
1041               tree_path = gtk_tree_model_get_path (tree_model, &iter);
1042               row = get_row_from_tree_path (tree_view, tree_path);
1043               gtk_tree_path_free (tree_path);
1044
1045               /* shouldn't ever happen */
1046               g_return_val_if_fail (row != -1, 0);
1047
1048               *rows_selected[0] = row;
1049             }
1050           ret_val = 1;
1051         }
1052       break;
1053     case GTK_SELECTION_MULTIPLE:
1054       {
1055         GPtrArray *array = g_ptr_array_new();
1056
1057         gtk_tree_selection_selected_foreach (selection, get_selected_rows, array);
1058         ret_val = array->len;
1059
1060         if (rows_selected && ret_val)
1061           {
1062             gint i;
1063
1064             *rows_selected = g_new (gint, ret_val);
1065             for (i = 0; i < ret_val; i++)
1066               {
1067                 gint row;
1068
1069                 tree_path = (GtkTreePath *) g_ptr_array_index (array, i);
1070                 row = get_row_from_tree_path (tree_view, tree_path);
1071                 gtk_tree_path_free (tree_path);
1072                 (*rows_selected)[i] = row;
1073               }
1074           }
1075         g_ptr_array_free (array, FALSE);
1076       }
1077       break;
1078     case GTK_SELECTION_NONE:
1079       break;
1080     }
1081   return ret_val;
1082 }
1083
1084 static gboolean
1085 gtk_tree_view_accessible_add_row_selection (AtkTable *table,
1086                                             gint      row)
1087 {
1088   GtkWidget *widget;
1089   GtkTreeView *tree_view;
1090   GtkTreeModel *tree_model;
1091   GtkTreeSelection *selection;
1092   GtkTreePath *tree_path;
1093   GtkTreeIter iter_to_row;
1094
1095   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
1096   if (widget == NULL)
1097     return FALSE;
1098
1099   if (!gtk_tree_view_accessible_is_row_selected (table, row))
1100     {
1101       tree_view = GTK_TREE_VIEW (widget);
1102       tree_model = gtk_tree_view_get_model (tree_view);
1103       selection = gtk_tree_view_get_selection (tree_view);
1104
1105       if (gtk_tree_model_get_flags (tree_model) & GTK_TREE_MODEL_LIST_ONLY)
1106         {
1107           tree_path = gtk_tree_path_new ();
1108           gtk_tree_path_append_index (tree_path, row);
1109           gtk_tree_selection_select_path (selection,tree_path);
1110           gtk_tree_path_free (tree_path);
1111         }
1112       else
1113         {
1114           set_iter_nth_row (tree_view, &iter_to_row, row);
1115           gtk_tree_selection_select_iter (selection, &iter_to_row);
1116         }
1117     }
1118
1119   return gtk_tree_view_accessible_is_row_selected (table, row);
1120 }
1121
1122 static gboolean
1123 gtk_tree_view_accessible_remove_row_selection (AtkTable *table,
1124                                                gint      row)
1125 {
1126   GtkWidget *widget;
1127   GtkTreeView *tree_view;
1128   GtkTreeSelection *selection;
1129
1130   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
1131   if (widget == NULL)
1132     return FALSE;
1133
1134   tree_view = GTK_TREE_VIEW (widget);
1135   selection = gtk_tree_view_get_selection (tree_view);
1136
1137   if (gtk_tree_view_accessible_is_row_selected (table, row))
1138     {
1139       gtk_tree_selection_unselect_all (selection);
1140       return TRUE;
1141     }
1142
1143   return FALSE;
1144 }
1145
1146 static AtkObject *
1147 gtk_tree_view_accessible_get_column_header (AtkTable *table,
1148                                             gint      in_col)
1149 {
1150   GtkWidget *widget;
1151   GtkTreeView *tree_view;
1152   GtkTreeViewColumn *tv_col;
1153
1154   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
1155   if (widget == NULL)
1156     return NULL;
1157
1158   tree_view = GTK_TREE_VIEW (widget);
1159   if (in_col < 0 || in_col >= get_n_columns (tree_view))
1160     return NULL;
1161
1162   tv_col = get_visible_column (tree_view, in_col);
1163   return get_header_from_column (tv_col);
1164 }
1165
1166 static const gchar *
1167 gtk_tree_view_accessible_get_column_description (AtkTable *table,
1168                                                  gint      in_col)
1169 {
1170   GtkWidget *widget;
1171   GtkTreeView *tree_view;
1172   GtkTreeViewColumn *tv_col;
1173
1174   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
1175   if (widget == NULL)
1176     return NULL;
1177
1178   tree_view = GTK_TREE_VIEW (widget);
1179   if (in_col < 0 || in_col >= get_n_columns (tree_view))
1180     return NULL;
1181
1182   tv_col = get_visible_column (tree_view, in_col);
1183   return gtk_tree_view_column_get_title (tv_col);
1184 }
1185
1186 static void
1187 atk_table_interface_init (AtkTableIface *iface)
1188 {
1189   iface->ref_at = gtk_tree_view_accessible_table_ref_at;
1190   iface->get_n_rows = gtk_tree_view_accessible_get_n_rows;
1191   iface->get_n_columns = gtk_tree_view_accessible_get_n_columns;
1192   iface->get_index_at = gtk_tree_view_accessible_get_index_at;
1193   iface->get_column_at_index = gtk_tree_view_accessible_get_column_at_index;
1194   iface->get_row_at_index = gtk_tree_view_accessible_get_row_at_index;
1195   iface->is_row_selected = gtk_tree_view_accessible_is_row_selected;
1196   iface->is_selected = gtk_tree_view_accessible_is_selected;
1197   iface->get_selected_rows = gtk_tree_view_accessible_get_selected_rows;
1198   iface->add_row_selection = gtk_tree_view_accessible_add_row_selection;
1199   iface->remove_row_selection = gtk_tree_view_accessible_remove_row_selection;
1200   iface->get_column_extent_at = NULL;
1201   iface->get_row_extent_at = NULL;
1202   iface->get_column_header = gtk_tree_view_accessible_get_column_header;
1203   iface->get_column_description = gtk_tree_view_accessible_get_column_description;
1204 }
1205
1206 /* atkselection.h */
1207
1208 static gboolean
1209 gtk_tree_view_accessible_add_selection (AtkSelection *selection,
1210                                         gint          i)
1211 {
1212   AtkTable *table;
1213   gint n_columns;
1214   gint row;
1215
1216   table = ATK_TABLE (selection);
1217   n_columns = gtk_tree_view_accessible_get_n_columns (table);
1218   if (n_columns != 1)
1219     return FALSE;
1220
1221   row = gtk_tree_view_accessible_get_row_at_index (table, i);
1222   return gtk_tree_view_accessible_add_row_selection (table, row);
1223 }
1224
1225 static gboolean
1226 gtk_tree_view_accessible_clear_selection (AtkSelection *selection)
1227 {
1228   GtkWidget *widget;
1229   GtkTreeView *tree_view;
1230   GtkTreeSelection *tree_selection;
1231
1232   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
1233   if (widget == NULL)
1234     return FALSE;
1235
1236   tree_view = GTK_TREE_VIEW (widget);
1237   tree_selection = gtk_tree_view_get_selection (tree_view);
1238
1239   gtk_tree_selection_unselect_all (tree_selection);
1240   return TRUE;
1241 }
1242
1243 static AtkObject *
1244 gtk_tree_view_accessible_ref_selection (AtkSelection *selection,
1245                                         gint          i)
1246 {
1247   AtkTable *table;
1248   gint row;
1249   gint n_selected;
1250   gint n_columns;
1251   gint *selected;
1252
1253   table = ATK_TABLE (selection);
1254   n_columns = gtk_tree_view_accessible_get_n_columns (table);
1255   n_selected = gtk_tree_view_accessible_get_selected_rows (table, &selected);
1256   if (i >= n_columns * n_selected)
1257     return NULL;
1258
1259   row = selected[i / n_columns];
1260   g_free (selected);
1261
1262   return gtk_tree_view_accessible_table_ref_at (table, row, i % n_columns);
1263 }
1264
1265 static gint
1266 gtk_tree_view_accessible_get_selection_count (AtkSelection *selection)
1267 {
1268   AtkTable *table;
1269   gint n_selected;
1270
1271   table = ATK_TABLE (selection);
1272   n_selected = gtk_tree_view_accessible_get_selected_rows (table, NULL);
1273   if (n_selected > 0)
1274     n_selected *= gtk_tree_view_accessible_get_n_columns (table);
1275   return n_selected;
1276 }
1277
1278 static gboolean
1279 gtk_tree_view_accessible_is_child_selected (AtkSelection *selection,
1280                                             gint          i)
1281 {
1282   GtkWidget *widget;
1283   gint row;
1284
1285   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
1286   if (widget == NULL)
1287     return FALSE;
1288
1289   row = atk_table_get_row_at_index (ATK_TABLE (selection), i);
1290
1291   return gtk_tree_view_accessible_is_row_selected (ATK_TABLE (selection), row);
1292 }
1293
1294 static void atk_selection_interface_init (AtkSelectionIface *iface)
1295 {
1296   iface->add_selection = gtk_tree_view_accessible_add_selection;
1297   iface->clear_selection = gtk_tree_view_accessible_clear_selection;
1298   iface->ref_selection = gtk_tree_view_accessible_ref_selection;
1299   iface->get_selection_count = gtk_tree_view_accessible_get_selection_count;
1300   iface->is_child_selected = gtk_tree_view_accessible_is_child_selected;
1301 }
1302
1303 #define EXTRA_EXPANDER_PADDING 4
1304
1305 static void
1306 gtk_tree_view_accessible_get_cell_area (GtkCellAccessibleParent *parent,
1307                                         GtkCellAccessible       *cell,
1308                                         GdkRectangle            *cell_rect)
1309 {
1310   GtkWidget *widget;
1311   GtkTreeView *tree_view;
1312   GtkTreeViewColumn *tv_col;
1313   GtkTreePath *path;
1314   AtkObject *parent_cell;
1315   GtkTreeViewAccessibleCellInfo *cell_info;
1316   GtkCellAccessible *top_cell;
1317
1318   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
1319   if (widget == NULL)
1320     return;
1321
1322   tree_view = GTK_TREE_VIEW (widget);
1323   parent_cell = atk_object_get_parent (ATK_OBJECT (cell));
1324   if (parent_cell != ATK_OBJECT (parent))
1325     top_cell = GTK_CELL_ACCESSIBLE (parent_cell);
1326   else
1327     top_cell = cell;
1328   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), top_cell);
1329   if (!cell_info)
1330     return;
1331   path = cell_info_get_path (cell_info);
1332   tv_col = cell_info->cell_col_ref;
1333   if (path)
1334     {
1335       GtkTreeViewColumn *expander_column;
1336       gint focus_line_width;
1337
1338       gtk_tree_view_get_cell_area (tree_view, path, tv_col, cell_rect);
1339       expander_column = gtk_tree_view_get_expander_column (tree_view);
1340       if (expander_column == tv_col)
1341         {
1342           gint expander_size;
1343           gtk_widget_style_get (widget,
1344                                 "expander-size", &expander_size,
1345                                 NULL);
1346           cell_rect->x += expander_size + EXTRA_EXPANDER_PADDING;
1347           cell_rect->width -= expander_size + EXTRA_EXPANDER_PADDING;
1348         }
1349       gtk_widget_style_get (widget,
1350                             "focus-line-width", &focus_line_width,
1351                             NULL);
1352
1353       cell_rect->x += focus_line_width;
1354       cell_rect->width -= 2 * focus_line_width;
1355
1356       gtk_tree_path_free (path);
1357
1358       /* A column has more than one renderer so we find the position
1359        * and width of each
1360        */
1361       if (top_cell != cell)
1362         {
1363           gint cell_index;
1364           gboolean found;
1365           gint cell_start;
1366           gint cell_width;
1367           GList *renderers;
1368           GtkCellRenderer *renderer;
1369
1370           cell_index = atk_object_get_index_in_parent (ATK_OBJECT (cell));
1371           renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (tv_col));
1372           renderer = g_list_nth_data (renderers, cell_index);
1373
1374           found = gtk_tree_view_column_cell_get_position (tv_col, renderer, &cell_start, &cell_width);
1375           if (found)
1376             {
1377               cell_rect->x += cell_start;
1378               cell_rect->width = cell_width;
1379             }
1380           g_list_free (renderers);
1381         }
1382
1383     }
1384 }
1385
1386 static void
1387 gtk_tree_view_accessible_get_cell_extents (GtkCellAccessibleParent *parent,
1388                                            GtkCellAccessible       *cell,
1389                                            gint                    *x,
1390                                            gint                    *y,
1391                                            gint                    *width,
1392                                            gint                    *height,
1393                                            AtkCoordType             coord_type)
1394 {
1395   GtkWidget *widget;
1396   GtkTreeView *tree_view;
1397   GdkWindow *bin_window;
1398   GdkRectangle cell_rect;
1399   gint w_x, w_y;
1400
1401   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
1402   if (widget == NULL)
1403     return;
1404
1405   tree_view = GTK_TREE_VIEW (widget);
1406   gtk_tree_view_accessible_get_cell_area (parent, cell, &cell_rect);
1407   bin_window = gtk_tree_view_get_bin_window (tree_view);
1408   gdk_window_get_origin (bin_window, &w_x, &w_y);
1409
1410   if (coord_type == ATK_XY_WINDOW)
1411     {
1412       GdkWindow *window;
1413       gint x_toplevel, y_toplevel;
1414
1415       window = gdk_window_get_toplevel (bin_window);
1416       gdk_window_get_origin (window, &x_toplevel, &y_toplevel);
1417
1418       w_x -= x_toplevel;
1419       w_y -= y_toplevel;
1420     }
1421
1422   *width = cell_rect.width;
1423   *height = cell_rect.height;
1424   if (is_cell_showing (tree_view, &cell_rect))
1425     {
1426       *x = cell_rect.x + w_x;
1427       *y = cell_rect.y + w_y;
1428     }
1429   else
1430     {
1431       *x = G_MININT;
1432       *y = G_MININT;
1433     }
1434 }
1435
1436 static gboolean
1437 gtk_tree_view_accessible_grab_cell_focus (GtkCellAccessibleParent *parent,
1438                                           GtkCellAccessible       *cell)
1439 {
1440   GtkWidget *widget;
1441   GtkTreeView *tree_view;
1442   GtkTreeViewColumn *tv_col;
1443   GtkTreePath *path;
1444   AtkObject *parent_cell;
1445   AtkObject *cell_object;
1446   GtkTreeViewAccessibleCellInfo *cell_info;
1447   GtkCellRenderer *renderer = NULL;
1448   GtkWidget *toplevel;
1449   gint index;
1450
1451   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
1452   if (widget == NULL)
1453     return FALSE;
1454
1455   tree_view = GTK_TREE_VIEW (widget);
1456
1457   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), cell);
1458   if (!cell_info)
1459     return FALSE;
1460   cell_object = ATK_OBJECT (cell);
1461   parent_cell = atk_object_get_parent (cell_object);
1462   tv_col = cell_info->cell_col_ref;
1463   if (parent_cell != ATK_OBJECT (parent))
1464     {
1465       /* GtkCellAccessible is in a GtkContainerCellAccessible.
1466        * The GtkTreeViewColumn has multiple renderers;
1467        * find the corresponding one.
1468        */
1469       GList *renderers;
1470
1471       renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (tv_col));
1472       index = atk_object_get_index_in_parent (cell_object);
1473       renderer = g_list_nth_data (renderers, index);
1474       g_list_free (renderers);
1475     }
1476   path = cell_info_get_path (cell_info);
1477   if (path)
1478     {
1479       if (renderer)
1480         gtk_tree_view_set_cursor_on_cell (tree_view, path, tv_col, renderer, FALSE);
1481       else
1482         gtk_tree_view_set_cursor (tree_view, path, tv_col, FALSE);
1483
1484       gtk_tree_path_free (path);
1485       gtk_widget_grab_focus (widget);
1486       toplevel = gtk_widget_get_toplevel (widget);
1487       if (gtk_widget_is_toplevel (toplevel))
1488         {
1489 #ifdef GDK_WINDOWING_X11
1490           gtk_window_present_with_time (GTK_WINDOW (toplevel),
1491                                         gdk_x11_get_server_time (gtk_widget_get_window (widget)));
1492 #else
1493           gtk_window_present (GTK_WINDOW (toplevel));
1494 #endif
1495         }
1496
1497       return TRUE;
1498     }
1499   else
1500       return FALSE;
1501 }
1502
1503 static int
1504 gtk_tree_view_accessible_get_child_index (GtkCellAccessibleParent *parent,
1505                                           GtkCellAccessible       *cell)
1506 {
1507   GtkTreeViewAccessibleCellInfo *cell_info;
1508   GtkTreeView *tree_view;
1509
1510   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), cell);
1511   if (!cell_info)
1512     return -1;
1513
1514   tree_view = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)));
1515
1516   return cell_info_get_index (tree_view, cell_info);
1517 }
1518
1519 static void
1520 gtk_tree_view_accessible_set_cell_data (GtkCellAccessibleParent *parent,
1521                                         GtkCellAccessible       *cell)
1522 {
1523   GtkTreeViewAccessibleCellInfo *cell_info;
1524   GtkTreeView *treeview;
1525   gboolean is_expander, is_expanded;
1526   GtkTreeModel *model;
1527   GtkTreeIter iter;
1528   GtkTreePath *path;
1529
1530   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), cell);
1531   if (!cell_info)
1532     return;
1533
1534   treeview = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)));
1535   model = gtk_tree_view_get_model (treeview);
1536
1537   if (GTK_RBNODE_FLAG_SET (cell_info->node, GTK_RBNODE_IS_PARENT) &&
1538       cell_info->cell_col_ref == gtk_tree_view_get_expander_column (treeview))
1539     {
1540       is_expander = TRUE;
1541       is_expanded = cell_info->node->children != NULL;
1542     }
1543   else
1544     {
1545       is_expander = FALSE;
1546       is_expanded = FALSE;
1547     }
1548
1549   path = cell_info_get_path (cell_info);
1550   if (path == NULL ||
1551       !gtk_tree_model_get_iter (model, &iter, path))
1552     {
1553       /* We only track valid cells, this should never happen */
1554       g_return_if_reached ();
1555     }
1556
1557   gtk_tree_view_column_cell_set_cell_data (cell_info->cell_col_ref,
1558                                            model,
1559                                            &iter,
1560                                            is_expander,
1561                                            is_expanded);
1562 }
1563
1564 static void
1565 gtk_cell_accessible_parent_interface_init (GtkCellAccessibleParentIface *iface)
1566 {
1567   iface->get_cell_extents = gtk_tree_view_accessible_get_cell_extents;
1568   iface->get_cell_area = gtk_tree_view_accessible_get_cell_area;
1569   iface->grab_focus = gtk_tree_view_accessible_grab_cell_focus;
1570   iface->get_child_index = gtk_tree_view_accessible_get_child_index;
1571   iface->set_cell_data = gtk_tree_view_accessible_set_cell_data;
1572 }
1573
1574 /* signal handling */
1575
1576 static gboolean
1577 idle_expand_row (gpointer data)
1578 {
1579   GtkTreeViewAccessible *accessible = data;
1580   GtkTreePath *path;
1581   GtkTreeView *tree_view;
1582   GtkTreeIter iter;
1583   GtkTreeModel *tree_model;
1584   gint n_inserted, row;
1585
1586   accessible->idle_expand_id = 0;
1587
1588   path = accessible->idle_expand_path;
1589   tree_view = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)));
1590
1591   tree_model = gtk_tree_view_get_model (tree_view);
1592   if (!tree_model)
1593     return FALSE;
1594
1595   if (!path || !gtk_tree_model_get_iter (tree_model, &iter, path))
1596     return FALSE;
1597
1598   /* Update visibility of cells below expansion row */
1599   traverse_cells (accessible, path, FALSE);
1600
1601   /* Figure out number of visible children, the following test
1602    * should not fail
1603    */
1604   if (gtk_tree_model_iter_has_child (tree_model, &iter))
1605     {
1606       GtkTreePath *path_copy;
1607
1608       /* By passing path into this function, we find the number of
1609        * visible children of path.
1610        */
1611       path_copy = gtk_tree_path_copy (path);
1612       gtk_tree_path_append_index (path_copy, 0);
1613
1614       n_inserted = 0;
1615       iterate_thru_children (tree_view, tree_model,
1616                              path_copy, NULL, &n_inserted, 0);
1617       gtk_tree_path_free (path_copy);
1618     }
1619   else
1620     {
1621       /* We can get here if the row expanded callback deleted the row */
1622       return FALSE;
1623     }
1624
1625   /* Set expand state */
1626   set_expand_state (tree_view, tree_model, accessible, path, TRUE);
1627
1628   row = get_row_from_tree_path (tree_view, path);
1629
1630   /* shouldn't ever happen */
1631   if (row == -1)
1632     g_assert_not_reached ();
1633
1634   /* Must add 1 because the "added rows" are below the row being expanded */
1635   row += 1;
1636
1637   g_signal_emit_by_name (accessible, "row-inserted", row, n_inserted);
1638
1639   accessible->idle_expand_path = NULL;
1640
1641   gtk_tree_path_free (path);
1642
1643   return FALSE;
1644 }
1645
1646 static gboolean
1647 row_expanded_cb (GtkTreeView *tree_view,
1648                  GtkTreeIter *iter,
1649                  GtkTreePath *path)
1650 {
1651   AtkObject *atk_obj;
1652   GtkTreeViewAccessible *accessible;
1653
1654   atk_obj = gtk_widget_get_accessible (GTK_WIDGET (tree_view));
1655   accessible = GTK_TREE_VIEW_ACCESSIBLE (atk_obj);
1656
1657   /*
1658    * The visible rectangle has not been updated when this signal is emitted
1659    * so we process the signal when the GTK processing is completed
1660    */
1661   /* this seems wrong since it overwrites any other pending expand handlers... */
1662   accessible->idle_expand_path = gtk_tree_path_copy (path);
1663   if (accessible->idle_expand_id)
1664     g_source_remove (accessible->idle_expand_id);
1665   accessible->idle_expand_id = gdk_threads_add_idle (idle_expand_row, accessible);
1666
1667   return FALSE;
1668 }
1669
1670 static gboolean
1671 row_collapsed_cb (GtkTreeView *tree_view,
1672                   GtkTreeIter *iter,
1673                   GtkTreePath *path)
1674 {
1675   GtkTreeModel *tree_model;
1676   AtkObject *atk_obj;
1677   GtkTreeViewAccessible *accessible;
1678   gint row;
1679
1680   atk_obj = gtk_widget_get_accessible (GTK_WIDGET (tree_view));
1681   accessible = GTK_TREE_VIEW_ACCESSIBLE (atk_obj);
1682   tree_model = gtk_tree_view_get_model (tree_view);
1683
1684   /* Update visibility of cells below collapsed row */
1685   traverse_cells (accessible, path, FALSE);
1686
1687   /* Set collapse state */
1688   set_expand_state (tree_view, tree_model, accessible, path, FALSE);
1689   if (accessible->n_children_deleted == 0)
1690     return FALSE;
1691   row = get_row_from_tree_path (tree_view, path);
1692   if (row == -1)
1693     return FALSE;
1694   g_signal_emit_by_name (atk_obj, "row-deleted", row,
1695                          accessible->n_children_deleted);
1696   accessible->n_children_deleted = 0;
1697   return FALSE;
1698 }
1699
1700 static void
1701 size_allocate_cb (GtkWidget     *widget,
1702                   GtkAllocation *allocation)
1703 {
1704   AtkObject *atk_obj;
1705   GtkTreeViewAccessible *accessible;
1706
1707   atk_obj = gtk_widget_get_accessible (widget);
1708   accessible = GTK_TREE_VIEW_ACCESSIBLE (atk_obj);
1709
1710   /* If the size allocation changes, the visibility of cells
1711    * may change so update the cells visibility.
1712    */
1713   traverse_cells (accessible, NULL, FALSE);
1714 }
1715
1716 static void
1717 selection_changed_cb (GtkTreeSelection *selection,
1718                       gpointer          data)
1719 {
1720   GtkTreeViewAccessible *accessible;
1721   GtkTreeView *tree_view;
1722   GtkWidget *widget;
1723   GtkTreeViewAccessibleCellInfo *info;
1724   GtkTreeSelection *tree_selection;
1725   GtkTreePath *path;
1726   GHashTableIter iter;
1727
1728   accessible = GTK_TREE_VIEW_ACCESSIBLE (data);
1729   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
1730   if (widget == NULL)
1731     return;
1732
1733   tree_view = GTK_TREE_VIEW (widget);
1734   tree_selection = gtk_tree_view_get_selection (tree_view);
1735
1736   /* FIXME: clean rows iterates through all cells too */
1737   g_hash_table_iter_init (&iter, accessible->cell_infos);
1738   while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&info))
1739     {
1740       _gtk_cell_accessible_remove_state (info->cell, ATK_STATE_SELECTED, TRUE);
1741
1742       path = cell_info_get_path (info);
1743       if (path && gtk_tree_selection_path_is_selected (tree_selection, path))
1744         _gtk_cell_accessible_add_state (info->cell, ATK_STATE_SELECTED, TRUE);
1745       gtk_tree_path_free (path);
1746     }
1747   if (gtk_widget_get_realized (widget))
1748     g_signal_emit_by_name (accessible, "selection-changed");
1749 }
1750
1751 static void
1752 cursor_changed (GtkTreeView           *tree_view,
1753                 GtkTreeViewAccessible *accessible)
1754 {
1755   AtkObject *cell;
1756
1757   cell = gtk_tree_view_accessible_ref_focus_cell (tree_view);
1758   if (cell)
1759     {
1760       if (cell != accessible->focus_cell)
1761         {
1762           if (accessible->focus_cell)
1763             {
1764               _gtk_cell_accessible_remove_state (GTK_CELL_ACCESSIBLE (accessible->focus_cell), ATK_STATE_ACTIVE, FALSE);
1765               _gtk_cell_accessible_remove_state (GTK_CELL_ACCESSIBLE (accessible->focus_cell), ATK_STATE_FOCUSED, FALSE);
1766               g_object_unref (accessible->focus_cell);
1767               accessible->focus_cell = cell;
1768             }
1769
1770           if (gtk_widget_has_focus (GTK_WIDGET (tree_view)))
1771             {
1772               _gtk_cell_accessible_add_state (GTK_CELL_ACCESSIBLE (cell), ATK_STATE_ACTIVE, FALSE);
1773               _gtk_cell_accessible_add_state (GTK_CELL_ACCESSIBLE (cell), ATK_STATE_FOCUSED, FALSE);
1774             }
1775
1776           g_signal_emit_by_name (accessible, "active-descendant-changed", cell);
1777         }
1778       else
1779         g_object_unref (cell);
1780     }
1781 }
1782
1783 static gboolean
1784 focus_in (GtkWidget *widget)
1785 {
1786   GtkTreeView *tree_view;
1787   GtkTreeViewAccessible *accessible;
1788   AtkStateSet *state_set;
1789   AtkObject *cell;
1790
1791   tree_view = GTK_TREE_VIEW (widget);
1792   accessible = GTK_TREE_VIEW_ACCESSIBLE (gtk_widget_get_accessible (widget));
1793
1794   if (accessible->focus_cell == NULL)
1795     {
1796       cell = gtk_tree_view_accessible_ref_focus_cell (tree_view);
1797       if (cell)
1798         {
1799           state_set = atk_object_ref_state_set (cell);
1800           if (state_set)
1801             {
1802               if (!atk_state_set_contains_state (state_set, ATK_STATE_FOCUSED))
1803                 {
1804                   _gtk_cell_accessible_add_state (GTK_CELL_ACCESSIBLE (cell), ATK_STATE_ACTIVE, FALSE);
1805                   accessible->focus_cell = cell;
1806                   _gtk_cell_accessible_add_state (GTK_CELL_ACCESSIBLE (cell), ATK_STATE_FOCUSED, FALSE);
1807                   g_signal_emit_by_name (accessible, "active-descendant-changed", cell);
1808                 }
1809               g_object_unref (state_set);
1810             }
1811         }
1812     }
1813   return FALSE;
1814 }
1815
1816 static gboolean
1817 focus_out (GtkWidget *widget)
1818 {
1819   GtkTreeViewAccessible *accessible;
1820
1821   accessible = GTK_TREE_VIEW_ACCESSIBLE (gtk_widget_get_accessible (widget));
1822   if (accessible->focus_cell)
1823     {
1824       _gtk_cell_accessible_remove_state (GTK_CELL_ACCESSIBLE (accessible->focus_cell), ATK_STATE_ACTIVE, FALSE);
1825       _gtk_cell_accessible_remove_state (GTK_CELL_ACCESSIBLE (accessible->focus_cell), ATK_STATE_FOCUSED, FALSE);
1826       g_object_unref (accessible->focus_cell);
1827       accessible->focus_cell = NULL;
1828     }
1829   return FALSE;
1830 }
1831
1832 static void
1833 model_row_changed (GtkTreeModel *tree_model,
1834                    GtkTreePath  *path,
1835                    GtkTreeIter  *iter,
1836                    gpointer      user_data)
1837 {
1838   GtkTreeView *tree_view = GTK_TREE_VIEW (user_data);
1839   GtkTreeViewAccessible *accessible;
1840   GtkTreePath *cell_path;
1841   GtkTreeViewAccessibleCellInfo *cell_info;
1842   GHashTableIter hash_iter;
1843
1844   accessible = GTK_TREE_VIEW_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (tree_view)));
1845
1846   /* Loop through our cached cells */
1847   /* Must loop through them all */
1848   g_hash_table_iter_init (&hash_iter, accessible->cell_infos);
1849   while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer *)&cell_info))
1850     {
1851       cell_path = cell_info_get_path (cell_info);
1852
1853       if (cell_path != NULL)
1854         {
1855           if (path && gtk_tree_path_compare (cell_path, path) == 0)
1856             {
1857               if (GTK_IS_RENDERER_CELL_ACCESSIBLE (cell_info->cell))
1858                 update_cell_value (GTK_RENDERER_CELL_ACCESSIBLE (cell_info->cell),
1859                                    accessible, TRUE);
1860             }
1861           gtk_tree_path_free (cell_path);
1862         }
1863     }
1864   g_signal_emit_by_name (accessible, "visible-data-changed");
1865 }
1866
1867 static void
1868 model_row_inserted (GtkTreeModel *tree_model,
1869                     GtkTreePath  *path,
1870                     GtkTreeIter  *iter,
1871                     gpointer      user_data)
1872 {
1873   GtkTreeView *tree_view = (GtkTreeView *)user_data;
1874   AtkObject *atk_obj;
1875   GtkTreeViewAccessible *accessible;
1876   GtkTreePath *path_copy;
1877   gint row, n_inserted, child_row;
1878
1879   atk_obj = gtk_widget_get_accessible (GTK_WIDGET (tree_view));
1880   accessible = GTK_TREE_VIEW_ACCESSIBLE (atk_obj);
1881
1882   if (accessible->idle_expand_id)
1883     {
1884       g_source_remove (accessible->idle_expand_id);
1885       accessible->idle_expand_id = 0;
1886
1887       /* don't do this if the insertion precedes the idle path,
1888        * since it will now be invalid
1889        */
1890       if (path && accessible->idle_expand_path &&
1891           (gtk_tree_path_compare (path, accessible->idle_expand_path) > 0))
1892           set_expand_state (tree_view, tree_model, accessible, accessible->idle_expand_path, FALSE);
1893       if (accessible->idle_expand_path)
1894           gtk_tree_path_free (accessible->idle_expand_path);
1895     }
1896   /* Check to see if row is visible */
1897   row = get_row_from_tree_path (tree_view, path);
1898
1899  /* A row insert is not necessarily visible.  For example,
1900   * a row can be draged & dropped into another row, which
1901   * causes an insert on the model that isn't visible in the
1902   * view.  Only generate a signal if the inserted row is
1903   * visible.
1904   */
1905   if (row != -1)
1906     {
1907       GtkTreeIter tmp_iter;
1908       gint n_cols, col;
1909
1910       gtk_tree_model_get_iter (tree_model, &tmp_iter, path);
1911
1912       /* Figure out number of visible children. */
1913       if (gtk_tree_model_iter_has_child (tree_model, &tmp_iter))
1914         {
1915           GtkTreePath *path2;
1916          /*
1917           * By passing path into this function, we find the number of
1918           * visible children of path.
1919           */
1920           n_inserted = 0;
1921           /* iterate_thru_children modifies path, we don't want that, so give
1922            * it a copy */
1923           path2 = gtk_tree_path_copy (path);
1924           iterate_thru_children (tree_view, tree_model,
1925                                  path2, NULL, &n_inserted, 0);
1926           gtk_tree_path_free (path2);
1927
1928           /* Must add one to include the row that is being added */
1929           n_inserted++;
1930         }
1931       else
1932         n_inserted = 1;
1933
1934       traverse_cells (accessible, path, TRUE);
1935
1936       /* Generate row-inserted signal */
1937       g_signal_emit_by_name (atk_obj, "row-inserted", row, n_inserted);
1938
1939       /* Generate children-changed signals */
1940       n_cols = get_n_columns (tree_view);
1941       for (child_row = row; child_row < (row + n_inserted); child_row++)
1942         {
1943           for (col = 0; col < n_cols; col++)
1944             {
1945              /* Pass NULL as the child object, i.e. 4th argument */
1946               g_signal_emit_by_name (atk_obj, "children-changed::add",
1947                                     ((row * n_cols) + col), NULL, NULL);
1948             }
1949         }
1950     }
1951   else
1952     {
1953      /* The row has been inserted inside another row.  This can
1954       * cause a row that previously couldn't be expanded to now
1955       * be expandable.
1956       */
1957       path_copy = gtk_tree_path_copy (path);
1958       gtk_tree_path_up (path_copy);
1959       set_expand_state (tree_view, tree_model, accessible, path_copy, TRUE);
1960       gtk_tree_path_free (path_copy);
1961     }
1962 }
1963
1964 static void
1965 model_row_deleted (GtkTreeModel *tree_model,
1966                    GtkTreePath  *path,
1967                    gpointer      user_data)
1968 {
1969   GtkTreeView *tree_view = (GtkTreeView *)user_data;
1970   GtkTreePath *path_copy;
1971   AtkObject *atk_obj;
1972   GtkTreeViewAccessible *accessible;
1973   gint row, col;
1974
1975   atk_obj = gtk_widget_get_accessible (GTK_WIDGET (tree_view));
1976   accessible = GTK_TREE_VIEW_ACCESSIBLE (atk_obj);
1977
1978   if (accessible->idle_expand_id)
1979     {
1980       g_source_remove (accessible->idle_expand_id);
1981       gtk_tree_path_free (accessible->idle_expand_path);
1982       accessible->idle_expand_id = 0;
1983     }
1984
1985   traverse_cells (accessible, path, TRUE);
1986
1987   /* If deleting a row with a depth > 1, then this may affect the
1988    * expansion/contraction of its parent(s). Make sure this is
1989    * handled.
1990    */
1991   if (gtk_tree_path_get_depth (path) > 1)
1992     {
1993       path_copy = gtk_tree_path_copy (path);
1994       gtk_tree_path_up (path_copy);
1995       set_expand_state (tree_view, tree_model, accessible, path_copy, TRUE);
1996       gtk_tree_path_free (path_copy);
1997     }
1998   row = get_row_from_tree_path (tree_view, path);
1999
2000   /* If the row which is deleted is not visible because it is a child of
2001    * a collapsed row then row will be -1
2002    */
2003   if (row > 0)
2004     g_signal_emit_by_name (atk_obj, "row-deleted", row,
2005                            accessible->n_children_deleted + 1);
2006   accessible->n_children_deleted = 0;
2007
2008   /* Generate children-changed signals */
2009   for (col = 0; col < get_n_columns (tree_view); col++)
2010     {
2011       /* Pass NULL as the child object, 4th argument */
2012       g_signal_emit_by_name (atk_obj, "children-changed::remove",
2013                              ((row * get_n_columns (tree_view)) + col), NULL, NULL);
2014     }
2015 }
2016
2017 /* This function gets called when a row is deleted or when rows are
2018  * removed from the view due to a collapse event. Note that the
2019  * count is the number of visible *children* of the deleted row,
2020  * so it does not include the row being deleted.
2021  *
2022  * As this function is called before the rows are removed we just note
2023  * the number of rows and then deal with it when we get a notification
2024  * that rows were deleted or collapsed.
2025  */
2026 static void
2027 destroy_count_func (GtkTreeView *tree_view,
2028                     GtkTreePath *path,
2029                     gint         count,
2030                     gpointer     user_data)
2031 {
2032   AtkObject *atk_obj;
2033   GtkTreeViewAccessible *accessible;
2034
2035   atk_obj = gtk_widget_get_accessible (GTK_WIDGET (tree_view));
2036   accessible = GTK_TREE_VIEW_ACCESSIBLE (atk_obj);
2037
2038   if (accessible->n_children_deleted != 0)
2039     return;
2040
2041   accessible->n_children_deleted = count;
2042 }
2043
2044 void
2045 _gtk_tree_view_accessible_reorder (GtkTreeView *treeview)
2046 {
2047   GtkTreeViewAccessible *accessible;
2048
2049   accessible = GTK_TREE_VIEW_ACCESSIBLE (_gtk_widget_peek_accessible (GTK_WIDGET (treeview)));
2050   if (accessible == NULL)
2051     return;
2052
2053   if (accessible->idle_expand_id)
2054     {
2055       g_source_remove (accessible->idle_expand_id);
2056       gtk_tree_path_free (accessible->idle_expand_path);
2057       accessible->idle_expand_id = 0;
2058     }
2059   traverse_cells (accessible, NULL, FALSE);
2060
2061   g_signal_emit_by_name (accessible, "row-reordered");
2062 }
2063
2064 static void
2065 set_cell_visibility (GtkTreeView       *tree_view,
2066                      GtkCellAccessible *cell,
2067                      GtkTreeViewColumn *tv_col,
2068                      GtkTreePath       *tree_path,
2069                      gboolean           emit_signal)
2070 {
2071   GdkRectangle cell_rect;
2072
2073   /* Get these three values in tree coords */
2074   if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
2075     gtk_tree_view_get_cell_area (tree_view, tree_path, tv_col, &cell_rect);
2076   else
2077     cell_rect.height = 0;
2078
2079   if (cell_rect.height > 0)
2080     {
2081       /* The height will be zero for a cell for which an antecedent
2082        * is not expanded
2083        */
2084       _gtk_cell_accessible_add_state (cell, ATK_STATE_VISIBLE, emit_signal);
2085       if (is_cell_showing (tree_view, &cell_rect))
2086         _gtk_cell_accessible_add_state (cell, ATK_STATE_SHOWING, emit_signal);
2087       else
2088         _gtk_cell_accessible_remove_state (cell, ATK_STATE_SHOWING, emit_signal);
2089     }
2090   else
2091     {
2092       _gtk_cell_accessible_remove_state (cell, ATK_STATE_VISIBLE, emit_signal);
2093       _gtk_cell_accessible_remove_state (cell, ATK_STATE_SHOWING, emit_signal);
2094     }
2095 }
2096
2097 static gboolean
2098 is_cell_showing (GtkTreeView  *tree_view,
2099                  GdkRectangle *cell_rect)
2100 {
2101   GdkRectangle rect, *visible_rect;
2102   GdkRectangle rect1, *tree_cell_rect;
2103   gint bx, by;
2104   gboolean is_showing;
2105
2106  /* A cell is considered "SHOWING" if any part of the cell is
2107   * in the visible area. Other ways we could do this is by a
2108   * cell's midpoint or if the cell is fully in the visible range.
2109   * Since we have the cell_rect x, y, width, height of the cell,
2110   * any of these is easy to compute.
2111   *
2112   * It is assumed that cell's rectangle is in widget coordinates
2113   * so we must transform to tree cordinates.
2114   */
2115   visible_rect = &rect;
2116   tree_cell_rect = &rect1;
2117   tree_cell_rect->x = cell_rect->x;
2118   tree_cell_rect->y = cell_rect->y;
2119   tree_cell_rect->width = cell_rect->width;
2120   tree_cell_rect->height = cell_rect->height;
2121
2122   gtk_tree_view_get_visible_rect (tree_view, visible_rect);
2123   gtk_tree_view_convert_tree_to_bin_window_coords (tree_view, visible_rect->x,
2124                                                    visible_rect->y, &bx, &by);
2125
2126   if (((tree_cell_rect->x + tree_cell_rect->width) < bx) ||
2127      ((tree_cell_rect->y + tree_cell_rect->height) < by) ||
2128      (tree_cell_rect->x > (bx + visible_rect->width)) ||
2129      (tree_cell_rect->y > (by + visible_rect->height)))
2130     is_showing =  FALSE;
2131   else
2132     is_showing = TRUE;
2133
2134   return is_showing;
2135 }
2136
2137 /* Misc Public */
2138
2139 /* This function is called when a cell's flyweight is created in
2140  * gtk_tree_view_accessible_table_ref_at with emit_change_signal
2141  * set to FALSE and in model_row_changed() on receipt of "row-changed"
2142  * signal when emit_change_signal is set to TRUE
2143  */
2144 static gboolean
2145 update_cell_value (GtkRendererCellAccessible      *renderer_cell,
2146                    GtkTreeViewAccessible *accessible,
2147                    gboolean               emit_change_signal)
2148 {
2149   GtkTreeViewAccessibleCellInfo *cell_info;
2150   GtkTreeView *tree_view;
2151   GtkTreeModel *tree_model;
2152   GtkTreePath *path;
2153   GtkTreeIter iter;
2154   GList *renderers, *cur_renderer;
2155   GParamSpec *spec;
2156   GtkRendererCellAccessibleClass *renderer_cell_class;
2157   GtkCellRendererClass *gtk_cell_renderer_class;
2158   GtkCellAccessible *cell;
2159   gchar **prop_list;
2160   AtkObject *parent;
2161   gboolean is_expander, is_expanded;
2162
2163   renderer_cell_class = GTK_RENDERER_CELL_ACCESSIBLE_GET_CLASS (renderer_cell);
2164   if (renderer_cell->renderer)
2165     gtk_cell_renderer_class = GTK_CELL_RENDERER_GET_CLASS (renderer_cell->renderer);
2166   else
2167     gtk_cell_renderer_class = NULL;
2168
2169   prop_list = renderer_cell_class->property_list;
2170
2171   cell = GTK_CELL_ACCESSIBLE (renderer_cell);
2172   cell_info = find_cell_info (accessible, cell);
2173   if (!cell_info)
2174     return FALSE;
2175
2176   if (emit_change_signal)
2177     {
2178       tree_view = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)));
2179       tree_model = gtk_tree_view_get_model (tree_view);
2180       path = cell_info_get_path (cell_info);
2181       if (path == NULL)
2182         return FALSE;
2183
2184       gtk_tree_model_get_iter (tree_model, &iter, path);
2185       is_expander = FALSE;
2186       is_expanded = FALSE;
2187       if (gtk_tree_model_iter_has_child (tree_model, &iter))
2188         {
2189           GtkTreeViewColumn *expander_tv;
2190
2191           expander_tv = gtk_tree_view_get_expander_column (tree_view);
2192           if (expander_tv == cell_info->cell_col_ref)
2193             {
2194               is_expander = TRUE;
2195               is_expanded = gtk_tree_view_row_expanded (tree_view, path);
2196             }
2197         }
2198       gtk_tree_path_free (path);
2199       gtk_tree_view_column_cell_set_cell_data (cell_info->cell_col_ref,
2200                                                tree_model, &iter,
2201                                                is_expander, is_expanded);
2202     }
2203   renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (cell_info->cell_col_ref));
2204   if (!renderers)
2205     return FALSE;
2206
2207   /* If the cell is in a container, its index is used to find the renderer
2208    * in the list. Otherwise, we assume that the cell is represented
2209    * by the first renderer in the list
2210    */
2211   parent = atk_object_get_parent (ATK_OBJECT (cell));
2212
2213   if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
2214     cur_renderer = g_list_nth (renderers, atk_object_get_index_in_parent (ATK_OBJECT (cell)));
2215   else
2216     cur_renderer = renderers;
2217
2218   if (cur_renderer == NULL)
2219     return FALSE;
2220
2221   if (gtk_cell_renderer_class)
2222     {
2223       while (*prop_list)
2224         {
2225           spec = g_object_class_find_property
2226                            (G_OBJECT_CLASS (gtk_cell_renderer_class), *prop_list);
2227
2228           if (spec != NULL)
2229             {
2230               GValue value = G_VALUE_INIT;
2231
2232               g_value_init (&value, spec->value_type);
2233               g_object_get_property (cur_renderer->data, *prop_list, &value);
2234               g_object_set_property (G_OBJECT (renderer_cell->renderer),
2235                                      *prop_list, &value);
2236               g_value_unset (&value);
2237             }
2238           else
2239             g_warning ("Invalid property: %s\n", *prop_list);
2240           prop_list++;
2241         }
2242     }
2243   g_list_free (renderers);
2244
2245   return _gtk_renderer_cell_accessible_update_cache (renderer_cell, emit_change_signal);
2246 }
2247
2248 static gint
2249 get_row_from_tree_path (GtkTreeView *tree_view,
2250                         GtkTreePath *path)
2251 {
2252   GtkTreeModel *tree_model;
2253   GtkTreePath *root_tree;
2254   gint row;
2255
2256   tree_model = gtk_tree_view_get_model (tree_view);
2257
2258   if (gtk_tree_model_get_flags (tree_model) & GTK_TREE_MODEL_LIST_ONLY)
2259     row = gtk_tree_path_get_indices (path)[0];
2260   else
2261     {
2262       root_tree = gtk_tree_path_new_first ();
2263       row = 0;
2264       iterate_thru_children (tree_view, tree_model, root_tree, path, &row, 0);
2265       gtk_tree_path_free (root_tree);
2266     }
2267
2268   return row;
2269 }
2270
2271 /* Misc Private */
2272
2273 /* Helper recursive function that returns an iter to nth row
2274  */
2275 static GtkTreeIter *
2276 return_iter_nth_row (GtkTreeView  *tree_view,
2277                      GtkTreeModel *tree_model,
2278                      GtkTreeIter  *iter,
2279                      gint          increment,
2280                      gint          row)
2281 {
2282   GtkTreePath *current_path;
2283   GtkTreeIter new_iter;
2284   gboolean row_expanded;
2285
2286   current_path = gtk_tree_model_get_path (tree_model, iter);
2287   if (increment == row)
2288     {
2289       gtk_tree_path_free (current_path);
2290       return iter;
2291     }
2292
2293   row_expanded = gtk_tree_view_row_expanded (tree_view, current_path);
2294   gtk_tree_path_free (current_path);
2295
2296   new_iter = *iter;
2297   if ((row_expanded && gtk_tree_model_iter_children (tree_model, iter, &new_iter)) ||
2298       (gtk_tree_model_iter_next (tree_model, iter)) ||
2299       (gtk_tree_model_iter_parent (tree_model, iter, &new_iter) &&
2300           (gtk_tree_model_iter_next (tree_model, iter))))
2301     return return_iter_nth_row (tree_view, tree_model, iter,
2302       ++increment, row);
2303
2304   return NULL;
2305 }
2306
2307 static void
2308 set_iter_nth_row (GtkTreeView *tree_view,
2309                   GtkTreeIter *iter,
2310                   gint         row)
2311 {
2312   GtkTreeModel *tree_model;
2313
2314   tree_model = gtk_tree_view_get_model (tree_view);
2315   gtk_tree_model_get_iter_first (tree_model, iter);
2316   iter = return_iter_nth_row (tree_view, tree_model, iter, 0, row);
2317 }
2318
2319 /* Recursively called until the row specified by orig is found.
2320  *
2321  * *count will be set to the visible row number of the child
2322  * relative to the row that was initially passed in as tree_path.
2323  * tree_path could be modified by this function.
2324  *
2325  * *count will be -1 if orig is not found as a child (a row that is
2326  * not visible will not be found, e.g. if the row is inside a
2327  * collapsed row).  If NULL is passed in as orig, *count will
2328  * be a count of the visible children.
2329  *
2330  * NOTE: the value for depth must be 0 when this recursive function
2331  * is initially called, or it may not function as expected.
2332  */
2333 static void
2334 iterate_thru_children (GtkTreeView  *tree_view,
2335                        GtkTreeModel *tree_model,
2336                        GtkTreePath  *tree_path,
2337                        GtkTreePath  *orig,
2338                        gint         *count,
2339                        gint          depth)
2340 {
2341   GtkTreeIter iter;
2342
2343   if (!gtk_tree_model_get_iter (tree_model, &iter, tree_path))
2344     return;
2345
2346   if (tree_path && orig && !gtk_tree_path_compare (tree_path, orig))
2347     /* Found it! */
2348     return;
2349
2350   if (tree_path && orig && gtk_tree_path_compare (tree_path, orig) > 0)
2351     {
2352       /* Past it, so return -1 */
2353       *count = -1;
2354       return;
2355     }
2356   else if (gtk_tree_view_row_expanded (tree_view, tree_path) &&
2357     gtk_tree_model_iter_has_child (tree_model, &iter))
2358     {
2359       (*count)++;
2360       gtk_tree_path_append_index (tree_path, 0);
2361       iterate_thru_children (tree_view, tree_model, tree_path,
2362                              orig, count, (depth + 1));
2363       return;
2364     }
2365   else if (gtk_tree_model_iter_next (tree_model, &iter))
2366     {
2367       (*count)++;
2368       tree_path = gtk_tree_model_get_path (tree_model, &iter);
2369        if (tree_path)
2370          {
2371            iterate_thru_children (tree_view, tree_model, tree_path,
2372                                  orig, count, depth);
2373            gtk_tree_path_free (tree_path);
2374          }
2375       return;
2376   }
2377   else if (gtk_tree_path_up (tree_path))
2378     {
2379       GtkTreeIter temp_iter;
2380       gboolean exit_loop = FALSE;
2381       gint new_depth = depth - 1;
2382
2383       (*count)++;
2384
2385      /* Make sure that we back up until we find a row
2386       * where gtk_tree_path_next does not return NULL.
2387       */
2388       while (!exit_loop)
2389         {
2390           if (gtk_tree_path_get_depth (tree_path) == 0)
2391               /* depth is now zero so */
2392             return;
2393           gtk_tree_path_next (tree_path);
2394
2395           /* Verify that the next row is a valid row! */
2396           exit_loop = gtk_tree_model_get_iter (tree_model, &temp_iter, tree_path);
2397
2398           if (!exit_loop)
2399             {
2400               /* Keep going up until we find a row that has a valid next */
2401               if (gtk_tree_path_get_depth(tree_path) > 1)
2402                 {
2403                   new_depth--;
2404                   gtk_tree_path_up (tree_path);
2405                 }
2406               else
2407                 {
2408                  /* If depth is 1 and gtk_tree_model_get_iter returns FALSE,
2409                   * then we are at the last row, so just return.
2410                   */
2411                   if (orig != NULL)
2412                     *count = -1;
2413
2414                   return;
2415                 }
2416             }
2417         }
2418
2419      /* This guarantees that we will stop when we hit the end of the
2420       * children.
2421       */
2422       if (new_depth < 0)
2423         return;
2424
2425       iterate_thru_children (tree_view, tree_model, tree_path,
2426                              orig, count, new_depth);
2427       return;
2428     }
2429
2430  /* If it gets here, then the path wasn't found.  Situations
2431   * that would cause this would be if the path passed in is
2432   * invalid or contained within the last row, but not visible
2433   * because the last row is not expanded.  If NULL was passed
2434   * in then a row count is desired, so only set count to -1
2435   * if orig is not NULL.
2436   */
2437   if (orig != NULL)
2438     *count = -1;
2439
2440   return;
2441 }
2442
2443 /* If tree_path is passed in as NULL, then all cells are acted on.
2444  * Otherwise, just act on those cells that are on a row greater than
2445  * the specified tree_path. If inc_row is passed in as TRUE, then rows
2446  * greater and equal to the specified tree_path are acted on.
2447  *
2448  * The function set_cell_visibility() is called on all cells to be
2449  * acted on to update the visibility of the cell.
2450  */
2451 static void
2452 traverse_cells (GtkTreeViewAccessible *accessible,
2453                 GtkTreePath           *tree_path,
2454                 gboolean               inc_row)
2455 {
2456   GtkTreeViewAccessibleCellInfo *cell_info;
2457   GtkWidget *widget;
2458   GHashTableIter iter;
2459
2460   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
2461   if (!widget)
2462     return;
2463
2464   /* Must loop through them all */
2465   g_hash_table_iter_init (&iter, accessible->cell_infos);
2466   while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&cell_info))
2467     {
2468       GtkTreePath *row_path;
2469       gboolean act_on_cell;
2470
2471       row_path = cell_info_get_path (cell_info);
2472       g_return_if_fail (row_path != NULL);
2473       if (tree_path == NULL)
2474         act_on_cell = TRUE;
2475       else
2476         {
2477           gint comparison;
2478
2479           comparison =  gtk_tree_path_compare (row_path, tree_path);
2480           if ((comparison > 0) ||
2481               (comparison == 0 && inc_row))
2482             act_on_cell = TRUE;
2483           else
2484             act_on_cell = FALSE;
2485         }
2486
2487       if (act_on_cell)
2488         {
2489           set_cell_visibility (GTK_TREE_VIEW (widget),
2490                                cell_info->cell,
2491                                cell_info->cell_col_ref,
2492                                row_path, TRUE);
2493         }
2494       gtk_tree_path_free (row_path);
2495     }
2496
2497   g_signal_emit_by_name (accessible, "visible-data-changed");
2498 }
2499
2500 /* If the tree_path passed in has children, then
2501  * ATK_STATE_EXPANDABLE is set.  If the row is expanded
2502  * ATK_STATE_EXPANDED is turned on.  If the row is
2503  * collapsed, then ATK_STATE_EXPANDED is removed.
2504  *
2505  * If the tree_path passed in has no children, then
2506  * ATK_STATE_EXPANDABLE and ATK_STATE_EXPANDED are removed.
2507  *
2508  * If set_on_ancestor is TRUE, then this function will also
2509  * update all cells that are ancestors of the tree_path.
2510  */
2511 static void
2512 set_expand_state (GtkTreeView           *tree_view,
2513                   GtkTreeModel          *tree_model,
2514                   GtkTreeViewAccessible *accessible,
2515                   GtkTreePath           *tree_path,
2516                   gboolean               set_on_ancestor)
2517 {
2518   GtkTreeViewColumn *expander_tv;
2519   GtkTreeViewAccessibleCellInfo *cell_info;
2520   GtkTreePath *cell_path;
2521   GtkTreeIter iter;
2522   gboolean found;
2523   GHashTableIter hash_iter;
2524
2525   g_hash_table_iter_init (&hash_iter, accessible->cell_infos);
2526   while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer *) &cell_info))
2527     {
2528       cell_path = cell_info_get_path (cell_info);
2529       found = FALSE;
2530
2531       if (cell_path != NULL)
2532         {
2533           GtkCellAccessible *cell = GTK_CELL_ACCESSIBLE (cell_info->cell);
2534
2535           expander_tv = gtk_tree_view_get_expander_column (tree_view);
2536
2537           /* Only set state for the cell that is in the column with the
2538            * expander toggle
2539            */
2540           if (expander_tv == cell_info->cell_col_ref)
2541             {
2542               if (tree_path && gtk_tree_path_compare (cell_path, tree_path) == 0)
2543                 found = TRUE;
2544               else if (set_on_ancestor &&
2545                        gtk_tree_path_get_depth (cell_path) <
2546                        gtk_tree_path_get_depth (tree_path) &&
2547                        gtk_tree_path_is_ancestor (cell_path, tree_path) == 1)
2548                 /* Only set if set_on_ancestor was passed in as TRUE */
2549                 found = TRUE;
2550             }
2551
2552           /* Set ATK_STATE_EXPANDABLE and ATK_STATE_EXPANDED
2553            * for ancestors and found cells.
2554            */
2555           if (found)
2556             {
2557               /* Must check against cell_path since cell_path
2558                * can be equal to or an ancestor of tree_path.
2559                */
2560               gtk_tree_model_get_iter (tree_model, &iter, cell_path);
2561
2562               /* Set or unset ATK_STATE_EXPANDABLE as appropriate */
2563               if (gtk_tree_model_iter_has_child (tree_model, &iter))
2564                 {
2565                   set_cell_expandable (cell);
2566
2567                   if (gtk_tree_view_row_expanded (tree_view, cell_path))
2568                     _gtk_cell_accessible_add_state (cell, ATK_STATE_EXPANDED, TRUE);
2569                   else
2570                     _gtk_cell_accessible_remove_state (cell, ATK_STATE_EXPANDED, TRUE);
2571                 }
2572               else
2573                 {
2574                   _gtk_cell_accessible_remove_state (cell, ATK_STATE_EXPANDED, TRUE);
2575                   if (_gtk_cell_accessible_remove_state (cell, ATK_STATE_EXPANDABLE, TRUE))
2576                   /* The state may have been propagated to the container cell */
2577                   if (!GTK_IS_CONTAINER_CELL_ACCESSIBLE (cell))
2578                     _gtk_cell_accessible_remove_action_by_name (cell,
2579                                                                 "expand or contract");
2580                 }
2581
2582               /* We assume that each cell in the cache once and
2583                * a container cell is before its child cells so we are
2584                * finished if set_on_ancestor is not set to TRUE.
2585                */
2586               if (!set_on_ancestor)
2587                 break;
2588             }
2589         }
2590       gtk_tree_path_free (cell_path);
2591     }
2592 }
2593
2594 static void
2595 add_cell_actions (GtkCellAccessible *cell,
2596                   gboolean           editable)
2597 {
2598   if (GTK_IS_BOOLEAN_CELL_ACCESSIBLE (cell))
2599     _gtk_cell_accessible_add_action (cell,
2600                                      "toggle", "toggles the cell",
2601                                      NULL, toggle_cell_toggled);
2602   if (editable)
2603     _gtk_cell_accessible_add_action (cell,
2604                                      "edit", "creates a widget in which the contents of the cell can be edited",
2605                                      NULL, edit_cell);
2606   _gtk_cell_accessible_add_action (cell,
2607                                    "activate", "activate the cell",
2608                                    NULL, activate_cell);
2609 }
2610
2611 static void
2612 toggle_cell_expanded (GtkCellAccessible *cell)
2613 {
2614   GtkTreeViewAccessibleCellInfo *cell_info;
2615   GtkTreeView *tree_view;
2616   GtkTreePath *path;
2617   AtkObject *parent;
2618   AtkStateSet *stateset;
2619
2620   parent = atk_object_get_parent (ATK_OBJECT (cell));
2621   if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
2622     parent = atk_object_get_parent (parent);
2623
2624   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), cell);
2625   if (!cell_info)
2626     return;
2627
2628   tree_view = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)));
2629   path = cell_info_get_path (cell_info);
2630   if (!path)
2631     return;
2632
2633   stateset = atk_object_ref_state_set (ATK_OBJECT (cell));
2634   if (atk_state_set_contains_state (stateset, ATK_STATE_EXPANDED))
2635     gtk_tree_view_collapse_row (tree_view, path);
2636   else
2637     gtk_tree_view_expand_row (tree_view, path, TRUE);
2638   g_object_unref (stateset);
2639   gtk_tree_path_free (path);
2640 }
2641
2642 static void
2643 toggle_cell_toggled (GtkCellAccessible *cell)
2644 {
2645   GtkTreeViewAccessibleCellInfo *cell_info;
2646   GtkTreePath *path;
2647   gchar *pathstring;
2648   GList *renderers, *cur_renderer;
2649   AtkObject *parent;
2650   gboolean is_container_cell = FALSE;
2651
2652   parent = atk_object_get_parent (ATK_OBJECT (cell));
2653   if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
2654     {
2655       is_container_cell = TRUE;
2656       parent = atk_object_get_parent (parent);
2657     }
2658
2659   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), cell);
2660   if (!cell_info)
2661     return;
2662
2663   path = cell_info_get_path (cell_info);
2664   if (!path)
2665     return;
2666
2667   /* If the cell is in a container, its index is used to find the
2668    * renderer in the list. Otherwise, we assume that the cell is
2669    * represented by the first renderer in the list
2670    */
2671   renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (cell_info->cell_col_ref));
2672   if (is_container_cell)
2673     cur_renderer = g_list_nth (renderers, atk_object_get_index_in_parent (ATK_OBJECT (cell)));
2674   else
2675     cur_renderer = renderers;
2676
2677   if (cur_renderer)
2678     {
2679       pathstring = gtk_tree_path_to_string (path);
2680       g_signal_emit_by_name (cur_renderer->data, "toggled", pathstring);
2681       g_free (pathstring);
2682     }
2683
2684   g_list_free (renderers);
2685   gtk_tree_path_free (path);
2686 }
2687
2688 static void
2689 edit_cell (GtkCellAccessible *cell)
2690 {
2691   GtkTreeViewAccessibleCellInfo *cell_info;
2692   GtkTreeView *tree_view;
2693   GtkTreePath *path;
2694   AtkObject *parent;
2695
2696   parent = atk_object_get_parent (ATK_OBJECT (cell));
2697   if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
2698     parent = atk_object_get_parent (parent);
2699
2700   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), cell);
2701   if (!cell_info)
2702     return;
2703
2704   tree_view = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)));
2705   path = cell_info_get_path (cell_info);
2706   if (!path)
2707     return;
2708   gtk_tree_view_set_cursor (tree_view, path, cell_info->cell_col_ref, TRUE);
2709   gtk_tree_path_free (path);
2710 }
2711
2712 static void
2713 activate_cell (GtkCellAccessible *cell)
2714 {
2715   GtkTreeViewAccessibleCellInfo *cell_info;
2716   GtkTreeView *tree_view;
2717   GtkTreePath *path;
2718   AtkObject *parent;
2719
2720   parent = atk_object_get_parent (ATK_OBJECT (cell));
2721   if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
2722     parent = atk_object_get_parent (parent);
2723
2724   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), cell);
2725   if (!cell_info)
2726     return;
2727
2728   tree_view = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)));
2729   path = cell_info_get_path (cell_info);
2730   if (!path)
2731     return;
2732   gtk_tree_view_row_activated (tree_view, path, cell_info->cell_col_ref);
2733   gtk_tree_path_free (path);
2734 }
2735
2736 static void
2737 cell_destroyed (gpointer data)
2738 {
2739   GtkTreeViewAccessibleCellInfo *cell_info = data;
2740
2741   cell_info->cell = NULL;
2742
2743   g_hash_table_remove (cell_info->view->cell_infos, cell_info);
2744 }
2745
2746 static int
2747 cell_info_get_index (GtkTreeView                     *tree_view,
2748                      GtkTreeViewAccessibleCellInfo   *info)
2749 {
2750   int index;
2751
2752   index = _gtk_rbtree_node_get_index (info->tree, info->node) + 1;
2753   index *= get_n_columns (tree_view);
2754   index += get_column_number (tree_view, info->cell_col_ref);
2755
2756   return index;
2757 }
2758
2759 static void
2760 cell_info_new (GtkTreeViewAccessible *accessible,
2761                GtkTreeModel          *tree_model,
2762                GtkRBTree             *tree,
2763                GtkRBNode             *node,
2764                GtkTreeViewColumn     *tv_col,
2765                GtkCellAccessible     *cell)
2766 {
2767   GtkTreeViewAccessibleCellInfo *cell_info;
2768
2769   cell_info = g_new (GtkTreeViewAccessibleCellInfo, 1);
2770
2771   cell_info->tree = tree;
2772   cell_info->node = node;
2773   cell_info->cell_col_ref = tv_col;
2774   cell_info->cell = cell;
2775   cell_info->view = accessible;
2776
2777   g_object_set_qdata_full (G_OBJECT (cell), 
2778                            gtk_tree_view_accessible_get_data_quark (),
2779                            cell_info,
2780                            cell_destroyed);
2781
2782   g_hash_table_replace (accessible->cell_infos, cell_info, cell_info);
2783 }
2784
2785 static GtkCellAccessible *
2786 find_cell (GtkTreeViewAccessible *accessible,
2787            gint                   index)
2788 {
2789   GtkTreeViewAccessibleCellInfo lookup, *cell_info;
2790   GtkTreeView *tree_view;
2791
2792   tree_view = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)));
2793
2794   if (!_gtk_rbtree_find_index (_gtk_tree_view_get_rbtree (tree_view),
2795                                index / get_n_columns (tree_view) - 1,
2796                                &lookup.tree,
2797                                &lookup.node))
2798     {
2799       g_assert_not_reached ();
2800     }
2801   lookup.cell_col_ref = get_visible_column (tree_view, index % get_n_columns (tree_view));
2802
2803   cell_info = g_hash_table_lookup (accessible->cell_infos, &lookup);
2804   if (cell_info == NULL)
2805     return NULL;
2806
2807   return cell_info->cell;
2808 }
2809
2810 static void
2811 connect_model_signals (GtkTreeView           *view,
2812                        GtkTreeViewAccessible *accessible)
2813 {
2814   GObject *obj;
2815
2816   obj = G_OBJECT (accessible->tree_model);
2817   g_signal_connect_data (obj, "row-changed",
2818                          G_CALLBACK (model_row_changed), view, NULL, 0);
2819   g_signal_connect_data (obj, "row-inserted",
2820                          G_CALLBACK (model_row_inserted), view, NULL,
2821                          G_CONNECT_AFTER);
2822   g_signal_connect_data (obj, "row-deleted",
2823                          G_CALLBACK (model_row_deleted), view, NULL,
2824                          G_CONNECT_AFTER);
2825 }
2826
2827 static void
2828 disconnect_model_signals (GtkTreeViewAccessible *accessible)
2829 {
2830   GObject *obj;
2831   GtkWidget *widget;
2832
2833   obj = G_OBJECT (accessible->tree_model);
2834   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
2835   g_signal_handlers_disconnect_by_func (obj, model_row_changed, widget);
2836   g_signal_handlers_disconnect_by_func (obj, model_row_inserted, widget);
2837   g_signal_handlers_disconnect_by_func (obj, model_row_deleted, widget);
2838 }
2839
2840 /* Returns the column number of the specified GtkTreeViewColumn
2841  * The column must be visible.
2842  */
2843 static gint
2844 get_column_number (GtkTreeView       *treeview,
2845                    GtkTreeViewColumn *column)
2846 {
2847   GtkTreeViewColumn *cur;
2848   guint i, number;
2849
2850   number = 0;
2851
2852   for (i = 0; i < gtk_tree_view_get_n_columns (treeview); i++)
2853     {
2854       cur = gtk_tree_view_get_column (treeview, i);
2855       
2856       if (!gtk_tree_view_column_get_visible (cur))
2857         continue;
2858
2859       if (cur == column)
2860         break;
2861
2862       number++;
2863     }
2864
2865   g_return_val_if_fail (i < gtk_tree_view_get_n_columns (treeview), 0);
2866
2867   return number;
2868 }
2869
2870 static gint
2871 get_index (GtkTreeView *tree_view,
2872            GtkTreePath *path,
2873            gint         actual_column)
2874 {
2875   gint depth = 0;
2876   gint index = 1;
2877   gint *indices = NULL;
2878
2879   if (path)
2880     {
2881       depth = gtk_tree_path_get_depth (path);
2882       indices = gtk_tree_path_get_indices (path);
2883     }
2884
2885   if (depth > 1)
2886     {
2887       GtkTreePath *copy_path;
2888       GtkTreeModel *model;
2889
2890       model = gtk_tree_view_get_model (tree_view);
2891       copy_path = gtk_tree_path_copy (path);
2892       gtk_tree_path_up (copy_path);
2893       count_rows (model, NULL, copy_path, &index, 0, depth);
2894       gtk_tree_path_free (copy_path);
2895     }
2896
2897   if (path)
2898     index += indices[depth - 1];
2899   index *= get_n_columns (tree_view);
2900   index +=  actual_column;
2901   return index;
2902 }
2903
2904 /* The function count_rows counts the number of rows starting at iter
2905  * and ending at end_path. The value of level is the depth of iter and
2906  * the value of depth is the depth of end_path. Rows at depth before
2907  * end_path are counted. This functions counts rows which are not visible
2908  * because an ancestor is collapsed.
2909  */
2910 static void
2911 count_rows (GtkTreeModel *model,
2912             GtkTreeIter  *iter,
2913             GtkTreePath  *end_path,
2914             gint         *count,
2915             gint          level,
2916             gint          depth)
2917 {
2918   GtkTreeIter child_iter;
2919
2920   if (!model)
2921     return;
2922
2923   level++;
2924   *count += gtk_tree_model_iter_n_children (model, iter);
2925
2926   if (gtk_tree_model_get_flags (model) & GTK_TREE_MODEL_LIST_ONLY)
2927     return;
2928
2929   if (level >= depth)
2930     return;
2931
2932   if (gtk_tree_model_iter_children (model, &child_iter, iter))
2933     {
2934       gboolean ret_val = TRUE;
2935
2936       while (ret_val)
2937         {
2938           if (level == depth - 1)
2939             {
2940               GtkTreePath *iter_path;
2941               gboolean finished = FALSE;
2942
2943               iter_path = gtk_tree_model_get_path (model, &child_iter);
2944               if (end_path && gtk_tree_path_compare (iter_path, end_path) >= 0)
2945                 finished = TRUE;
2946               gtk_tree_path_free (iter_path);
2947               if (finished)
2948                 break;
2949             }
2950           if (gtk_tree_model_iter_has_child (model, &child_iter))
2951             count_rows (model, &child_iter, end_path, count, level, depth);
2952           ret_val = gtk_tree_model_iter_next (model, &child_iter);
2953         }
2954     }
2955 }
2956
2957 static gboolean
2958 get_rbtree_column_from_index (GtkTreeView        *tree_view,
2959                               gint                index,
2960                               GtkRBTree         **tree,
2961                               GtkRBNode         **node,
2962                               GtkTreeViewColumn **column)
2963 {
2964   guint n_columns = get_n_columns (tree_view);
2965
2966   if (n_columns == 0)
2967     return FALSE;
2968   /* First row is the column headers */
2969   index -= n_columns;
2970   if (index < 0)
2971     return FALSE;
2972
2973   if (tree)
2974     {
2975       g_return_val_if_fail (node != NULL, FALSE);
2976
2977       if (!_gtk_rbtree_find_index (_gtk_tree_view_get_rbtree (tree_view),
2978                                    index / n_columns,
2979                                    tree,
2980                                    node))
2981         return FALSE;
2982     }
2983
2984   if (column)
2985     {
2986       *column = get_visible_column (tree_view, index % n_columns);
2987       if (*column == NULL)
2988         return FALSE;
2989   }
2990   return TRUE;
2991 }
2992
2993 static void
2994 set_cell_expandable (GtkCellAccessible *cell)
2995 {
2996   if (_gtk_cell_accessible_add_state (cell, ATK_STATE_EXPANDABLE, FALSE))
2997     _gtk_cell_accessible_add_action (cell,
2998                                      "expand or contract",
2999                                      "expands or contracts the row in the tree view containing this cell",
3000                                      NULL, toggle_cell_expanded);
3001 }
3002
3003 static GtkTreeViewAccessibleCellInfo *
3004 find_cell_info (GtkTreeViewAccessible *accessible,
3005                 GtkCellAccessible     *cell)
3006 {
3007   AtkObject *parent;
3008   
3009   parent = atk_object_get_parent (ATK_OBJECT (cell));
3010   while (parent != ATK_OBJECT (accessible))
3011     {
3012       cell = GTK_CELL_ACCESSIBLE (parent);
3013       parent = atk_object_get_parent (ATK_OBJECT (cell));
3014     }
3015
3016   return g_object_get_qdata (G_OBJECT (cell),
3017                              gtk_tree_view_accessible_get_data_quark ());
3018 }
3019
3020 static AtkObject *
3021 get_header_from_column (GtkTreeViewColumn *tv_col)
3022 {
3023   AtkObject *rc;
3024   GtkWidget *header_widget;
3025
3026   if (tv_col == NULL)
3027     return NULL;
3028
3029   header_widget = gtk_tree_view_column_get_button (tv_col);
3030
3031   if (header_widget)
3032     rc = gtk_widget_get_accessible (header_widget);
3033   else
3034     rc = NULL;
3035
3036   return rc;
3037 }
3038
3039 /**
3040  * _gtk_rbtree_get_ancestor_node:
3041  * @ancestor: the ancestor tree
3042  * @child_tree: the potential child's tree
3043  * @child_node: the potential child's node
3044  *
3045  * Finds the node that is the ancestor of @child_tree and @child_node
3046  * and belongs to @ancestor. If @ancestor is not an ancestor tree
3047  * of @child_node, %NULL is returned.
3048  *
3049  * Returns: the ancestor node or %NULL if @ancestor is not an ancestor.
3050  **/
3051 static GtkRBNode *
3052 _gtk_rbtree_get_ancestor_node (GtkRBTree *ancestor,
3053                                GtkRBTree *child_tree,
3054                                GtkRBNode *child_node)
3055 {
3056   while (child_tree != NULL)
3057     {
3058       if (child_tree == ancestor)
3059         return child_node;
3060
3061       child_node = child_tree->parent_node;
3062       child_tree = child_tree->parent_tree;
3063     }
3064
3065   return NULL;
3066 }
3067
3068 void
3069 _gtk_tree_view_accessible_remove (GtkTreeView *treeview,
3070                                   GtkRBTree   *tree,
3071                                   GtkRBNode   *node)
3072 {
3073   GtkTreeViewAccessibleCellInfo *cell_info;
3074   GHashTableIter iter;
3075   GtkTreeViewAccessible *accessible;
3076
3077   accessible = GTK_TREE_VIEW_ACCESSIBLE (_gtk_widget_peek_accessible (GTK_WIDGET (treeview)));
3078   if (accessible == NULL)
3079     return;
3080
3081   /* if this shows up in profiles, special-case node->children == NULL */
3082
3083   g_hash_table_iter_init (&iter, accessible->cell_infos);
3084   while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&cell_info))
3085     {
3086       GtkRBNode *child_node = _gtk_rbtree_get_ancestor_node (tree,
3087                                                              cell_info->tree,
3088                                                              cell_info->node);
3089
3090       if (child_node == NULL)
3091         continue;
3092
3093       if (node == NULL || node == child_node)
3094         g_hash_table_iter_remove (&iter);
3095     }
3096 }
3097
3098 /* NB: id is not checked, only columns < id are.
3099  * This is important so the function works for notification of removal of a column */
3100 static guint
3101 to_visible_column_id (GtkTreeView *treeview,
3102                       guint        id)
3103 {
3104   guint i;
3105   guint invisible;
3106
3107   invisible = 0;
3108
3109   for (i = 0; i < id; i++)
3110     {
3111       GtkTreeViewColumn *column = gtk_tree_view_get_column (treeview, i);
3112
3113       if (!gtk_tree_view_column_get_visible (column))
3114         invisible++;
3115     }
3116
3117   return id - invisible;
3118 }
3119
3120 void
3121 _gtk_tree_view_accessible_do_add_column (GtkTreeViewAccessible *accessible,
3122                                          GtkTreeView           *treeview,
3123                                          GtkTreeViewColumn     *column,
3124                                          guint                  id)
3125 {
3126   guint row, n_rows, n_cols;
3127
3128   /* Generate column-inserted signal */
3129   g_signal_emit_by_name (accessible, "column-inserted", id, 1);
3130
3131   n_rows = get_n_rows (treeview);
3132   n_cols = get_n_columns (treeview);
3133
3134   /* Generate children-changed signals */
3135   for (row = 0; row <= n_rows; row++)
3136     {
3137      /* Pass NULL as the child object, i.e. 4th argument */
3138       g_signal_emit_by_name (accessible, "children-changed::add",
3139                              (row * n_cols) + id, NULL, NULL);
3140     }
3141
3142   traverse_cells (accessible, NULL, FALSE);
3143 }
3144
3145 void
3146 _gtk_tree_view_accessible_add_column (GtkTreeView       *treeview,
3147                                       GtkTreeViewColumn *column,
3148                                       guint              id)
3149 {
3150   AtkObject *obj;
3151
3152   if (!gtk_tree_view_column_get_visible (column))
3153     return;
3154
3155   obj = _gtk_widget_peek_accessible (GTK_WIDGET (treeview));
3156   if (obj == NULL)
3157     return;
3158
3159   _gtk_tree_view_accessible_do_add_column (GTK_TREE_VIEW_ACCESSIBLE (obj),
3160                                            treeview,
3161                                            column,
3162                                            to_visible_column_id (treeview, id));
3163 }
3164
3165 void
3166 _gtk_tree_view_accessible_do_remove_column (GtkTreeViewAccessible *accessible,
3167                                             GtkTreeView           *treeview,
3168                                             GtkTreeViewColumn     *column,
3169                                             guint                  id)
3170 {
3171   GtkTreeViewAccessibleCellInfo *cell_info;
3172   GHashTableIter iter;
3173   gpointer value;
3174   guint row, n_rows, n_cols;
3175
3176   /* Clean column from cache */
3177   g_hash_table_iter_init (&iter, accessible->cell_infos);
3178   while (g_hash_table_iter_next (&iter, NULL, &value))
3179     {
3180       cell_info = value;
3181       if (cell_info->cell_col_ref == column)
3182         g_hash_table_iter_remove (&iter);
3183     }
3184
3185   /* Generate column-deleted signal */
3186   g_signal_emit_by_name (accessible, "column-deleted", id, 1);
3187
3188   n_rows = get_n_rows (treeview);
3189   n_cols = get_n_columns (treeview);
3190
3191   /* Generate children-changed signals */
3192   for (row = 0; row <= n_rows; row++)
3193     {
3194       /* Pass NULL as the child object, 4th argument */
3195       g_signal_emit_by_name (accessible, "children-changed::remove",
3196                              (row * n_cols) + id, NULL, NULL);
3197     }
3198
3199   traverse_cells (accessible, NULL, FALSE);
3200 }
3201
3202 void
3203 _gtk_tree_view_accessible_remove_column (GtkTreeView       *treeview,
3204                                          GtkTreeViewColumn *column,
3205                                          guint              id)
3206 {
3207   AtkObject *obj;
3208
3209   if (!gtk_tree_view_column_get_visible (column))
3210     return;
3211
3212   obj = _gtk_widget_peek_accessible (GTK_WIDGET (treeview));
3213   if (obj == NULL)
3214     return;
3215
3216   _gtk_tree_view_accessible_do_remove_column (GTK_TREE_VIEW_ACCESSIBLE (obj),
3217                                               treeview,
3218                                               column,
3219                                               to_visible_column_id (treeview, id));
3220 }
3221
3222 void
3223 _gtk_tree_view_accessible_reorder_column (GtkTreeView       *treeview,
3224                                           GtkTreeViewColumn *column)
3225 {
3226   AtkObject *obj;
3227
3228   obj = _gtk_widget_peek_accessible (GTK_WIDGET (treeview));
3229   if (obj == NULL)
3230     return;
3231
3232   g_signal_emit_by_name (obj, "column-reordered");
3233
3234   traverse_cells (GTK_TREE_VIEW_ACCESSIBLE (obj), NULL, FALSE);
3235 }
3236
3237 void
3238 _gtk_tree_view_accessible_toggle_visibility (GtkTreeView       *treeview,
3239                                              GtkTreeViewColumn *column)
3240 {
3241   AtkObject *obj;
3242   guint id;
3243
3244   obj = _gtk_widget_peek_accessible (GTK_WIDGET (treeview));
3245   if (obj == NULL)
3246     return;
3247
3248   id = get_column_number (treeview, column);
3249
3250   if (gtk_tree_view_column_get_visible (column))
3251     _gtk_tree_view_accessible_do_add_column (GTK_TREE_VIEW_ACCESSIBLE (obj),
3252                                              treeview,
3253                                              column,
3254                                              id);
3255   else
3256     _gtk_tree_view_accessible_do_remove_column (GTK_TREE_VIEW_ACCESSIBLE (obj),
3257                                                 treeview,
3258                                                 column,
3259                                                 id);
3260 }