]> Pileus Git - ~andy/gtk/blob - gtk/a11y/gtktreeviewaccessible.c
a11y: Use the accessible type
[~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 void     cursor_changed       (GtkTreeView      *tree_view,
51                                       GtkTreeViewAccessible *accessible);
52 static gboolean focus_in             (GtkWidget        *widget);
53 static gboolean focus_out            (GtkWidget        *widget);
54
55 /* Misc */
56
57 static int              cell_info_get_index             (GtkTreeView                     *tree_view,
58                                                          GtkTreeViewAccessibleCellInfo   *info);
59 static gboolean         update_cell_value               (GtkRendererCellAccessible       *renderer_cell,
60                                                          GtkTreeViewAccessible           *accessible,
61                                                          gboolean               emit_change_signal);
62 static gboolean         is_cell_showing                 (GtkTreeView            *tree_view,
63                                                          GdkRectangle           *cell_rect);
64
65 static void             cell_destroyed                  (gpointer               data);
66 static void             cell_info_new                   (GtkTreeViewAccessible           *accessible,
67                                                          GtkTreeModel           *tree_model,
68                                                          GtkRBTree              *tree,
69                                                          GtkRBNode              *node,
70                                                          GtkTreeViewColumn      *tv_col,
71                                                          GtkCellAccessible      *cell);
72 static GtkCellAccessible *find_cell                       (GtkTreeViewAccessible           *accessible,
73                                                          gint                   index);
74 static gint             get_column_number               (GtkTreeView            *tree_view,
75                                                          GtkTreeViewColumn      *column);
76 static gint             get_focus_index                 (GtkTreeView            *tree_view);
77 static gint             get_index                       (GtkTreeView            *tree_view,
78                                                          GtkTreePath            *path,
79                                                          gint                   actual_column);
80 static void             count_rows                      (GtkTreeModel           *model,
81                                                          GtkTreeIter            *iter,
82                                                          GtkTreePath            *end_path,
83                                                          gint                   *count,
84                                                          gint                   level,
85                                                          gint                   depth);
86
87 static gboolean         get_rbtree_column_from_index    (GtkTreeView            *tree_view,
88                                                          gint                   index,
89                                                          GtkRBTree              **tree,
90                                                          GtkRBNode              **node,
91                                                          GtkTreeViewColumn      **column);
92
93 static GtkTreeViewAccessibleCellInfo* find_cell_info    (GtkTreeViewAccessible           *view,
94                                                          GtkCellAccessible               *cell);
95 static AtkObject *       get_header_from_column         (GtkTreeViewColumn      *tv_col);
96
97
98 static void atk_table_interface_init                  (AtkTableIface                *iface);
99 static void atk_selection_interface_init              (AtkSelectionIface            *iface);
100 static void atk_component_interface_init              (AtkComponentIface            *iface);
101 static void gtk_cell_accessible_parent_interface_init (GtkCellAccessibleParentIface *iface);
102
103 G_DEFINE_TYPE_WITH_CODE (GtkTreeViewAccessible, _gtk_tree_view_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE,
104                          G_IMPLEMENT_INTERFACE (ATK_TYPE_TABLE, atk_table_interface_init)
105                          G_IMPLEMENT_INTERFACE (ATK_TYPE_SELECTION, atk_selection_interface_init)
106                          G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init)
107                          G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_ACCESSIBLE_PARENT, gtk_cell_accessible_parent_interface_init))
108
109
110 static GQuark
111 gtk_tree_view_accessible_get_data_quark (void)
112 {
113   static GQuark quark = 0;
114
115   if (G_UNLIKELY (quark == 0))
116     quark = g_quark_from_static_string ("gtk-tree-view-accessible-data");
117
118   return quark;
119 }
120
121 static void
122 cell_info_free (GtkTreeViewAccessibleCellInfo *cell_info)
123 {
124   if (cell_info->cell)
125     {
126       g_object_steal_qdata (G_OBJECT (cell_info->cell),
127                             gtk_tree_view_accessible_get_data_quark ());
128       _gtk_cell_accessible_add_state (cell_info->cell, ATK_STATE_DEFUNCT, FALSE);
129     }
130
131   g_free (cell_info);
132 }
133
134 static GtkTreePath *
135 cell_info_get_path (GtkTreeViewAccessibleCellInfo *cell_info)
136 {
137   return _gtk_tree_path_new_from_rbtree (cell_info->tree, cell_info->node);
138 }
139
140 static guint
141 cell_info_hash (gconstpointer info)
142 {
143   const GtkTreeViewAccessibleCellInfo *cell_info = info;
144   guint node, col;
145
146   node = GPOINTER_TO_UINT (cell_info->node);
147   col = GPOINTER_TO_UINT (cell_info->cell_col_ref);
148
149   return ((node << sizeof (guint) / 2) | (node >> sizeof (guint) / 2)) ^ col;
150 }
151
152 static gboolean
153 cell_info_equal (gconstpointer a, gconstpointer b)
154 {
155   const GtkTreeViewAccessibleCellInfo *cell_info_a = a;
156   const GtkTreeViewAccessibleCellInfo *cell_info_b = b;
157
158   return cell_info_a->node == cell_info_b->node &&
159          cell_info_a->cell_col_ref == cell_info_b->cell_col_ref;
160 }
161
162 static void
163 gtk_tree_view_accessible_initialize (AtkObject *obj,
164                                      gpointer   data)
165 {
166   GtkTreeViewAccessible *accessible;
167   GtkTreeView *tree_view;
168   GtkTreeModel *tree_model;
169   GtkWidget *widget;
170
171   ATK_OBJECT_CLASS (_gtk_tree_view_accessible_parent_class)->initialize (obj, data);
172
173   accessible = GTK_TREE_VIEW_ACCESSIBLE (obj);
174   accessible->focus_cell = NULL;
175
176   accessible->cell_infos = g_hash_table_new_full (cell_info_hash,
177       cell_info_equal, NULL, (GDestroyNotify) cell_info_free);
178
179   widget = GTK_WIDGET (data);
180   tree_view = GTK_TREE_VIEW (widget);
181   tree_model = gtk_tree_view_get_model (tree_view);
182
183   g_signal_connect (tree_view, "cursor-changed",
184                     G_CALLBACK (cursor_changed), accessible);
185   g_signal_connect (tree_view, "focus-in-event",
186                     G_CALLBACK (focus_in), NULL);
187   g_signal_connect (tree_view, "focus-out-event",
188                     G_CALLBACK (focus_out), NULL);
189
190   if (tree_model)
191     {
192       if (gtk_tree_model_get_flags (tree_model) & GTK_TREE_MODEL_LIST_ONLY)
193         obj->role = ATK_ROLE_TABLE;
194       else
195         obj->role = ATK_ROLE_TREE_TABLE;
196     }
197 }
198
199 static void
200 gtk_tree_view_accessible_finalize (GObject *object)
201 {
202   GtkTreeViewAccessible *accessible = GTK_TREE_VIEW_ACCESSIBLE (object);
203
204   if (accessible->cell_infos)
205     g_hash_table_destroy (accessible->cell_infos);
206
207   G_OBJECT_CLASS (_gtk_tree_view_accessible_parent_class)->finalize (object);
208 }
209
210 static void
211 gtk_tree_view_accessible_notify_gtk (GObject    *obj,
212                                      GParamSpec *pspec)
213 {
214   GtkWidget *widget;
215   GtkTreeView *tree_view;
216   GtkTreeViewAccessible *accessible;
217
218   widget = GTK_WIDGET (obj);
219   accessible = GTK_TREE_VIEW_ACCESSIBLE (gtk_widget_get_accessible (widget));
220   tree_view = GTK_TREE_VIEW (widget);
221
222   if (g_strcmp0 (pspec->name, "model") == 0)
223     {
224       GtkTreeModel *tree_model;
225       AtkRole role;
226
227       tree_model = gtk_tree_view_get_model (tree_view);
228       g_hash_table_remove_all (accessible->cell_infos);
229
230       if (tree_model)
231         {
232           if (gtk_tree_model_get_flags (tree_model) & GTK_TREE_MODEL_LIST_ONLY)
233             role = ATK_ROLE_TABLE;
234           else
235             role = ATK_ROLE_TREE_TABLE;
236         }
237       else
238         {
239           role = ATK_ROLE_UNKNOWN;
240         }
241       atk_object_set_role (ATK_OBJECT (accessible), role);
242       g_object_freeze_notify (G_OBJECT (accessible));
243       g_signal_emit_by_name (accessible, "model-changed");
244       g_signal_emit_by_name (accessible, "visible-data-changed");
245       g_object_thaw_notify (G_OBJECT (accessible));
246     }
247   else
248     GTK_WIDGET_ACCESSIBLE_CLASS (_gtk_tree_view_accessible_parent_class)->notify_gtk (obj, pspec);
249 }
250
251 static void
252 gtk_tree_view_accessible_destroyed (GtkWidget     *widget,
253                                     GtkAccessible *gtk_accessible)
254 {
255   GtkTreeViewAccessible *accessible;
256
257   if (!GTK_IS_TREE_VIEW (widget))
258     return;
259
260   accessible = GTK_TREE_VIEW_ACCESSIBLE (gtk_accessible);
261
262   if (accessible->focus_cell)
263     {
264       g_object_unref (accessible->focus_cell);
265       accessible->focus_cell = NULL;
266     }
267 }
268
269 static void
270 gtk_tree_view_accessible_connect_widget_destroyed (GtkAccessible *accessible)
271 {
272   GtkWidget *widget;
273
274   widget = gtk_accessible_get_widget (accessible);
275   if (widget)
276     g_signal_connect_after (widget, "destroy",
277                             G_CALLBACK (gtk_tree_view_accessible_destroyed), accessible);
278
279   GTK_ACCESSIBLE_CLASS (_gtk_tree_view_accessible_parent_class)->connect_widget_destroyed (accessible);
280 }
281
282 static gint
283 get_n_rows (GtkTreeView *tree_view)
284 {
285   GtkRBTree *tree;
286
287   tree = _gtk_tree_view_get_rbtree (tree_view);
288
289   if (tree == NULL)
290     return 0;
291
292   return tree->root->total_count;
293 }
294
295 static gint
296 get_n_columns (GtkTreeView *tree_view)
297 {
298   guint i, visible_columns;
299
300   visible_columns = 0;
301
302   for (i = 0; i < gtk_tree_view_get_n_columns (tree_view); i++)
303     {
304       GtkTreeViewColumn *column = gtk_tree_view_get_column (tree_view, i);
305
306       if (gtk_tree_view_column_get_visible (column))
307         visible_columns++;
308     }
309
310   return visible_columns;
311 }
312 static gint
313 gtk_tree_view_accessible_get_n_children (AtkObject *obj)
314 {
315   GtkWidget *widget;
316   GtkTreeView *tree_view;
317
318   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
319   if (widget == NULL)
320     return 0;
321
322   tree_view = GTK_TREE_VIEW (widget);
323   return (get_n_rows (tree_view) + 1) * get_n_columns (tree_view);
324 }
325
326 static GtkTreeViewColumn *
327 get_visible_column (GtkTreeView *tree_view,
328                     guint        id)
329 {
330   guint i;
331
332   for (i = 0; i < gtk_tree_view_get_n_columns (tree_view); i++)
333     {
334       GtkTreeViewColumn *column = gtk_tree_view_get_column (tree_view, i);
335
336       if (!gtk_tree_view_column_get_visible (column))
337         continue;
338
339       if (id == 0)
340         return column;
341
342       id--;
343     }
344
345   g_return_val_if_reached (NULL);
346 }
347
348 static AtkObject *
349 gtk_tree_view_accessible_ref_child (AtkObject *obj,
350                                     gint       i)
351 {
352   GtkWidget *widget;
353   GtkTreeViewAccessible *accessible;
354   GtkCellAccessible *cell;
355   GtkTreeView *tree_view;
356   GtkTreeModel *tree_model;
357   GtkCellRenderer *renderer;
358   GtkTreeIter iter;
359   GtkTreeViewColumn *tv_col;
360   GtkTreePath *path;
361   GtkRBTree *tree;
362   GtkRBNode *node;
363   AtkObject *child;
364   AtkObject *parent;
365   GtkTreeViewColumn *expander_tv;
366   GList *renderer_list;
367   GList *l;
368   GtkContainerCellAccessible *container = NULL;
369   GtkRendererCellAccessible *renderer_cell;
370   gboolean is_expander, is_expanded, retval;
371   gint focus_index;
372
373   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
374   if (widget == NULL)
375     return NULL;
376
377   if (i >= gtk_tree_view_accessible_get_n_children (obj))
378     return NULL;
379
380   accessible = GTK_TREE_VIEW_ACCESSIBLE (obj);
381   tree_view = GTK_TREE_VIEW (widget);
382   if (i < get_n_columns (tree_view))
383     {
384       tv_col = get_visible_column (tree_view, i);
385       child = get_header_from_column (tv_col);
386       if (child)
387         g_object_ref (child);
388       return child;
389     }
390
391   /* Check whether the child is cached */
392   cell = find_cell (accessible, i);
393   if (cell)
394     {
395       g_object_ref (cell);
396       return ATK_OBJECT (cell);
397     }
398
399   if (accessible->focus_cell == NULL)
400       focus_index = get_focus_index (tree_view);
401   else
402       focus_index = -1;
403
404   /* Find the RBTree and GtkTreeViewColumn for the index */
405   if (!get_rbtree_column_from_index (tree_view, i, &tree, &node, &tv_col))
406     return NULL;
407
408   path = _gtk_tree_path_new_from_rbtree (tree, node);
409   tree_model = gtk_tree_view_get_model (tree_view);
410   retval = gtk_tree_model_get_iter (tree_model, &iter, path);
411   if (!retval)
412     return NULL;
413
414   expander_tv = gtk_tree_view_get_expander_column (tree_view);
415   is_expander = FALSE;
416   is_expanded = FALSE;
417   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
418     {
419       if (expander_tv == tv_col)
420         {
421           is_expander = TRUE;
422           is_expanded = node->children != NULL;
423         }
424     }
425   gtk_tree_view_column_cell_set_cell_data (tv_col, tree_model, &iter,
426                                            is_expander, is_expanded);
427
428   renderer_list = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (tv_col));
429
430   /* If there is not exactly one renderer in the list,
431    * make a container
432    */
433   if (renderer_list == NULL || renderer_list->next)
434     {
435       GtkCellAccessible *container_cell;
436
437       container = _gtk_container_cell_accessible_new ();
438
439       container_cell = GTK_CELL_ACCESSIBLE (container);
440       _gtk_cell_accessible_initialise (container_cell, widget, ATK_OBJECT (accessible));
441
442       /* The GtkTreeViewAccessibleCellInfo structure for the container will
443        * be before the ones for the cells so that the first one we find for
444        * a position will be for the container
445        */
446       cell_info_new (accessible, tree_model, tree, node, tv_col, container_cell);
447       parent = ATK_OBJECT (container);
448     }
449   else
450     parent = ATK_OBJECT (accessible);
451
452   child = NULL;
453
454   for (l = renderer_list; l; l = l->next)
455     {
456       renderer = GTK_CELL_RENDERER (l->data);
457
458       if (GTK_IS_CELL_RENDERER_TEXT (renderer))
459         child = _gtk_text_cell_accessible_new ();
460       else if (GTK_IS_CELL_RENDERER_TOGGLE (renderer))
461         child = _gtk_boolean_cell_accessible_new ();
462       else if (GTK_IS_CELL_RENDERER_PIXBUF (renderer))
463         child = _gtk_image_cell_accessible_new ();
464       else
465         child = _gtk_renderer_cell_accessible_new (renderer);
466
467       cell = GTK_CELL_ACCESSIBLE (child);
468       renderer_cell = GTK_RENDERER_CELL_ACCESSIBLE (child);
469
470       /* Create the GtkTreeViewAccessibleCellInfo for this cell */
471       if (parent == ATK_OBJECT (accessible))
472         cell_info_new (accessible, tree_model, tree, node, tv_col, cell);
473
474       _gtk_cell_accessible_initialise (cell, widget, parent);
475
476       if (container)
477         _gtk_container_cell_accessible_add_child (container, cell);
478
479       update_cell_value (renderer_cell, accessible, FALSE);
480
481       _gtk_cell_accessible_add_state (cell, ATK_STATE_FOCUSABLE, FALSE);
482       if (focus_index == i)
483         {
484           accessible->focus_cell = g_object_ref (cell);
485           _gtk_cell_accessible_add_state (cell, ATK_STATE_FOCUSED, FALSE);
486           g_signal_emit_by_name (accessible, "active-descendant-changed", cell);
487         }
488     }
489   g_list_free (renderer_list);
490   if (container)
491     child = ATK_OBJECT (container);
492
493   if (expander_tv == tv_col)
494     {
495       AtkRelationSet *relation_set;
496       AtkObject *accessible_array[1];
497       AtkRelation* relation;
498       AtkObject *parent_node;
499
500       relation_set = atk_object_ref_relation_set (ATK_OBJECT (child));
501
502       gtk_tree_path_up (path);
503       if (gtk_tree_path_get_depth (path) == 0)
504         parent_node = obj;
505       else
506         {
507           gint parent_index;
508
509           parent_index = get_index (tree_view, path, i % get_n_columns (tree_view));
510           parent_node = atk_object_ref_accessible_child (obj, parent_index);
511         }
512       accessible_array[0] = parent_node;
513       relation = atk_relation_new (accessible_array, 1,
514                                    ATK_RELATION_NODE_CHILD_OF);
515       atk_relation_set_add (relation_set, relation);
516       atk_object_add_relationship (parent_node, ATK_RELATION_NODE_PARENT_OF, child);
517       g_object_unref (relation);
518       g_object_unref (relation_set);
519     }
520   gtk_tree_path_free (path);
521
522   /* We do not increase the reference count here; when g_object_unref()
523    * is called for the cell then cell_destroyed() is called and this
524    * removes the cell from the cache.
525    */
526   return child;
527 }
528
529 static AtkStateSet*
530 gtk_tree_view_accessible_ref_state_set (AtkObject *obj)
531 {
532   AtkStateSet *state_set;
533   GtkWidget *widget;
534
535   state_set = ATK_OBJECT_CLASS (_gtk_tree_view_accessible_parent_class)->ref_state_set (obj);
536   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
537
538   if (widget != NULL)
539     atk_state_set_add_state (state_set, ATK_STATE_MANAGES_DESCENDANTS);
540
541   return state_set;
542 }
543
544 static void
545 _gtk_tree_view_accessible_class_init (GtkTreeViewAccessibleClass *klass)
546 {
547   AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
548   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
549   GtkAccessibleClass *accessible_class = (GtkAccessibleClass*)klass;
550   GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
551   GtkContainerAccessibleClass *container_class = (GtkContainerAccessibleClass*)klass;
552
553   class->get_n_children = gtk_tree_view_accessible_get_n_children;
554   class->ref_child = gtk_tree_view_accessible_ref_child;
555   class->ref_state_set = gtk_tree_view_accessible_ref_state_set;
556   class->initialize = gtk_tree_view_accessible_initialize;
557
558   widget_class->notify_gtk = gtk_tree_view_accessible_notify_gtk;
559
560   accessible_class->connect_widget_destroyed = gtk_tree_view_accessible_connect_widget_destroyed;
561
562   /* The children of a GtkTreeView are the buttons at the top of the columns
563    * we do not represent these as children so we do not want to report
564    * children added or deleted when these changed.
565    */
566   container_class->add_gtk = NULL;
567   container_class->remove_gtk = NULL;
568
569   gobject_class->finalize = gtk_tree_view_accessible_finalize;
570 }
571
572 static void
573 _gtk_tree_view_accessible_init (GtkTreeViewAccessible *view)
574 {
575 }
576
577 gint
578 get_focus_index (GtkTreeView *tree_view)
579 {
580   GtkTreePath *focus_path;
581   GtkTreeViewColumn *focus_column;
582   gint index;
583
584   gtk_tree_view_get_cursor (tree_view, &focus_path, &focus_column);
585   if (focus_path && focus_column)
586     index = get_index (tree_view, focus_path,
587                        get_column_number (tree_view, focus_column));
588   else
589     index = -1;
590
591   if (focus_path)
592     gtk_tree_path_free (focus_path);
593
594   return index;
595 }
596
597 /* This function returns a reference to the accessible object
598  * for the cell in the treeview which has focus, if any
599  */
600 static AtkObject *
601 gtk_tree_view_accessible_ref_focus_cell (GtkTreeView *tree_view)
602 {
603   AtkObject *focus_cell = NULL;
604   AtkObject *atk_obj;
605   gint focus_index;
606
607   focus_index = get_focus_index (tree_view);
608   if (focus_index >= 0)
609     {
610       atk_obj = gtk_widget_get_accessible (GTK_WIDGET (tree_view));
611       focus_cell = atk_object_ref_accessible_child (atk_obj, focus_index);
612     }
613
614   return focus_cell;
615 }
616
617 /* atkcomponent.h */
618
619 static AtkObject *
620 gtk_tree_view_accessible_ref_accessible_at_point (AtkComponent *component,
621                                                   gint          x,
622                                                   gint          y,
623                                                   AtkCoordType  coord_type)
624 {
625   GtkWidget *widget;
626   GtkTreeView *tree_view;
627   GtkTreePath *path;
628   GtkTreeViewColumn *tv_column;
629   gint x_pos, y_pos;
630   gint bx, by;
631   gboolean ret_val;
632
633   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
634   if (widget == NULL)
635     return NULL;
636
637   tree_view = GTK_TREE_VIEW (widget);
638
639   atk_component_get_extents (component, &x_pos, &y_pos, NULL, NULL, coord_type);
640   gtk_tree_view_convert_widget_to_bin_window_coords (tree_view, x, y, &bx, &by);
641   ret_val = gtk_tree_view_get_path_at_pos (tree_view,
642                                            bx - x_pos, by - y_pos,
643                                            &path, &tv_column, NULL, NULL);
644   if (ret_val)
645     {
646       gint index, column;
647
648       column = get_column_number (tree_view, tv_column);
649       index = get_index (tree_view, path, column);
650       gtk_tree_path_free (path);
651
652       return gtk_tree_view_accessible_ref_child (ATK_OBJECT (component), index);
653     }
654
655   return NULL;
656 }
657
658 static void
659 atk_component_interface_init (AtkComponentIface *iface)
660 {
661   iface->ref_accessible_at_point = gtk_tree_view_accessible_ref_accessible_at_point;
662 }
663
664 /* atktable.h */
665
666 static gint
667 gtk_tree_view_accessible_get_index_at (AtkTable *table,
668                                        gint      row,
669                                        gint      column)
670 {
671   GtkWidget *widget;
672   gint n_cols, n_rows;
673
674   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
675   if (widget == NULL)
676     return -1;
677
678   n_cols = atk_table_get_n_columns (table);
679   n_rows = atk_table_get_n_rows (table);
680
681   if (row >= n_rows || column >= n_cols)
682     return -1;
683
684   return (row + 1) * n_cols + column;
685 }
686
687 static gint
688 gtk_tree_view_accessible_get_column_at_index (AtkTable *table,
689                                               gint      index)
690 {
691   GtkWidget *widget;
692   gint n_columns;
693
694   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
695   if (widget == NULL)
696     return -1;
697
698   if (index >= gtk_tree_view_accessible_get_n_children (ATK_OBJECT (table)))
699     return -1;
700
701   n_columns = get_n_columns (GTK_TREE_VIEW (widget));
702
703   /* checked by the n_children() check above */
704   g_assert (n_columns > 0);
705
706   return index % n_columns;
707 }
708
709 static gint
710 gtk_tree_view_accessible_get_row_at_index (AtkTable *table,
711                                            gint      index)
712 {
713   GtkWidget *widget;
714   GtkTreeView *tree_view;
715
716   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
717   if (widget == NULL)
718     return -1;
719
720   tree_view = GTK_TREE_VIEW (widget);
721
722   index /= get_n_columns (tree_view);
723   index--;
724   if (index >= get_n_rows (tree_view))
725     return -1;
726
727   return index;
728 }
729
730 static AtkObject *
731 gtk_tree_view_accessible_table_ref_at (AtkTable *table,
732                                        gint      row,
733                                        gint      column)
734 {
735   gint index;
736
737   index = gtk_tree_view_accessible_get_index_at (table, row, column);
738   if (index == -1)
739     return NULL;
740
741   return gtk_tree_view_accessible_ref_child (ATK_OBJECT (table), index);
742 }
743
744 static gint
745 gtk_tree_view_accessible_get_n_rows (AtkTable *table)
746 {
747   GtkWidget *widget;
748
749   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
750   if (widget == NULL)
751     return 0;
752
753   return get_n_rows (GTK_TREE_VIEW (widget));
754 }
755
756 static gint
757 gtk_tree_view_accessible_get_n_columns (AtkTable *table)
758 {
759   GtkWidget *widget;
760
761   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
762   if (widget == NULL)
763     return 0;
764
765   return get_n_columns (GTK_TREE_VIEW (widget));
766 }
767
768 static gboolean
769 gtk_tree_view_accessible_is_row_selected (AtkTable *table,
770                                           gint      row)
771 {
772   GtkWidget *widget;
773   GtkRBTree *tree;
774   GtkRBNode *node;
775
776   if (row < 0)
777     return FALSE;
778
779   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
780   if (widget == NULL)
781     return FALSE;
782
783   if (!_gtk_rbtree_find_index (_gtk_tree_view_get_rbtree (GTK_TREE_VIEW (widget)),
784                                row,
785                                &tree,
786                                &node))
787     return FALSE;
788
789   return GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED);
790 }
791
792 static gboolean
793 gtk_tree_view_accessible_is_selected (AtkTable *table,
794                                       gint      row,
795                                       gint      column)
796 {
797   return gtk_tree_view_accessible_is_row_selected (table, row);
798 }
799
800 typedef struct {
801   GArray *array;
802   GtkTreeView *treeview;
803 } SelectedRowsData;
804
805 static void
806 get_selected_rows (GtkTreeModel *model,
807                    GtkTreePath  *path,
808                    GtkTreeIter  *iter,
809                    gpointer      datap)
810 {
811   SelectedRowsData *data = datap;
812   GtkRBTree *tree;
813   GtkRBNode *node;
814   int id;
815
816   if (_gtk_tree_view_find_node (data->treeview,
817                                 path,
818                                 &tree, &node))
819     {
820       g_assert_not_reached ();
821     }
822
823   id = _gtk_rbtree_node_get_index (tree, node);
824
825   g_array_append_val (data->array, id);
826 }
827
828 static gint
829 gtk_tree_view_accessible_get_selected_rows (AtkTable  *table,
830                                             gint     **rows_selected)
831 {
832   SelectedRowsData data;
833   GtkWidget *widget;
834   gint n_rows;
835
836   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
837   if (widget == NULL)
838     return 0;
839
840   data.treeview = GTK_TREE_VIEW (widget);
841   data.array = g_array_new (FALSE, FALSE, sizeof (gint));
842
843   gtk_tree_selection_selected_foreach (gtk_tree_view_get_selection (data.treeview),
844                                        get_selected_rows,
845                                        &data);
846
847   n_rows = data.array->len;
848   if (rows_selected)
849     *rows_selected = (gint *) g_array_free (data.array, FALSE);
850   else
851     g_array_free (data.array, TRUE);
852   
853   return n_rows;
854 }
855
856 static gboolean
857 gtk_tree_view_accessible_add_row_selection (AtkTable *table,
858                                             gint      row)
859 {
860   GtkTreeView *treeview;
861   GtkTreePath *path;
862   GtkRBTree *tree;
863   GtkRBNode *node;
864
865   if (row < 0)
866     return FALSE;
867
868   treeview = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (table)));
869   if (treeview == NULL)
870     return FALSE;
871
872   if (!_gtk_rbtree_find_index (_gtk_tree_view_get_rbtree (treeview),
873                                row,
874                                &tree,
875                                &node))
876     return FALSE;
877
878   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
879     return FALSE;
880
881   path = _gtk_tree_path_new_from_rbtree (tree, node);
882   gtk_tree_selection_select_path (gtk_tree_view_get_selection (treeview), path);
883   gtk_tree_path_free (path);
884
885   return TRUE;
886 }
887
888 static gboolean
889 gtk_tree_view_accessible_remove_row_selection (AtkTable *table,
890                                                gint      row)
891 {
892   GtkTreeView *treeview;
893   GtkTreePath *path;
894   GtkRBTree *tree;
895   GtkRBNode *node;
896
897   if (row < 0)
898     return FALSE;
899
900   treeview = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (table)));
901   if (treeview == NULL)
902     return FALSE;
903
904   if (!_gtk_rbtree_find_index (_gtk_tree_view_get_rbtree (treeview),
905                                row,
906                                &tree,
907                                &node))
908     return FALSE;
909
910   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
911     return FALSE;
912
913   path = _gtk_tree_path_new_from_rbtree (tree, node);
914   gtk_tree_selection_unselect_path (gtk_tree_view_get_selection (treeview), path);
915   gtk_tree_path_free (path);
916
917   return TRUE;
918 }
919
920 static AtkObject *
921 gtk_tree_view_accessible_get_column_header (AtkTable *table,
922                                             gint      in_col)
923 {
924   GtkWidget *widget;
925   GtkTreeView *tree_view;
926   GtkTreeViewColumn *tv_col;
927
928   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
929   if (widget == NULL)
930     return NULL;
931
932   tree_view = GTK_TREE_VIEW (widget);
933   if (in_col < 0 || in_col >= get_n_columns (tree_view))
934     return NULL;
935
936   tv_col = get_visible_column (tree_view, in_col);
937   return get_header_from_column (tv_col);
938 }
939
940 static const gchar *
941 gtk_tree_view_accessible_get_column_description (AtkTable *table,
942                                                  gint      in_col)
943 {
944   GtkWidget *widget;
945   GtkTreeView *tree_view;
946   GtkTreeViewColumn *tv_col;
947
948   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
949   if (widget == NULL)
950     return NULL;
951
952   tree_view = GTK_TREE_VIEW (widget);
953   if (in_col < 0 || in_col >= get_n_columns (tree_view))
954     return NULL;
955
956   tv_col = get_visible_column (tree_view, in_col);
957   return gtk_tree_view_column_get_title (tv_col);
958 }
959
960 static void
961 atk_table_interface_init (AtkTableIface *iface)
962 {
963   iface->ref_at = gtk_tree_view_accessible_table_ref_at;
964   iface->get_n_rows = gtk_tree_view_accessible_get_n_rows;
965   iface->get_n_columns = gtk_tree_view_accessible_get_n_columns;
966   iface->get_index_at = gtk_tree_view_accessible_get_index_at;
967   iface->get_column_at_index = gtk_tree_view_accessible_get_column_at_index;
968   iface->get_row_at_index = gtk_tree_view_accessible_get_row_at_index;
969   iface->is_row_selected = gtk_tree_view_accessible_is_row_selected;
970   iface->is_selected = gtk_tree_view_accessible_is_selected;
971   iface->get_selected_rows = gtk_tree_view_accessible_get_selected_rows;
972   iface->add_row_selection = gtk_tree_view_accessible_add_row_selection;
973   iface->remove_row_selection = gtk_tree_view_accessible_remove_row_selection;
974   iface->get_column_extent_at = NULL;
975   iface->get_row_extent_at = NULL;
976   iface->get_column_header = gtk_tree_view_accessible_get_column_header;
977   iface->get_column_description = gtk_tree_view_accessible_get_column_description;
978 }
979
980 /* atkselection.h */
981
982 static gboolean
983 gtk_tree_view_accessible_add_selection (AtkSelection *selection,
984                                         gint          i)
985 {
986   AtkTable *table;
987   gint n_columns;
988   gint row;
989
990   table = ATK_TABLE (selection);
991   n_columns = gtk_tree_view_accessible_get_n_columns (table);
992   if (n_columns != 1)
993     return FALSE;
994
995   row = gtk_tree_view_accessible_get_row_at_index (table, i);
996   return gtk_tree_view_accessible_add_row_selection (table, row);
997 }
998
999 static gboolean
1000 gtk_tree_view_accessible_clear_selection (AtkSelection *selection)
1001 {
1002   GtkWidget *widget;
1003   GtkTreeView *tree_view;
1004   GtkTreeSelection *tree_selection;
1005
1006   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
1007   if (widget == NULL)
1008     return FALSE;
1009
1010   tree_view = GTK_TREE_VIEW (widget);
1011   tree_selection = gtk_tree_view_get_selection (tree_view);
1012
1013   gtk_tree_selection_unselect_all (tree_selection);
1014   return TRUE;
1015 }
1016
1017 static AtkObject *
1018 gtk_tree_view_accessible_ref_selection (AtkSelection *selection,
1019                                         gint          i)
1020 {
1021   AtkTable *table;
1022   gint row;
1023   gint n_selected;
1024   gint n_columns;
1025   gint *selected;
1026
1027   table = ATK_TABLE (selection);
1028   n_columns = gtk_tree_view_accessible_get_n_columns (table);
1029   n_selected = gtk_tree_view_accessible_get_selected_rows (table, &selected);
1030   if (i >= n_columns * n_selected)
1031     return NULL;
1032
1033   row = selected[i / n_columns];
1034   g_free (selected);
1035
1036   return gtk_tree_view_accessible_table_ref_at (table, row, i % n_columns);
1037 }
1038
1039 static gint
1040 gtk_tree_view_accessible_get_selection_count (AtkSelection *selection)
1041 {
1042   AtkTable *table;
1043   gint n_selected;
1044
1045   table = ATK_TABLE (selection);
1046   n_selected = gtk_tree_view_accessible_get_selected_rows (table, NULL);
1047   if (n_selected > 0)
1048     n_selected *= gtk_tree_view_accessible_get_n_columns (table);
1049   return n_selected;
1050 }
1051
1052 static gboolean
1053 gtk_tree_view_accessible_is_child_selected (AtkSelection *selection,
1054                                             gint          i)
1055 {
1056   GtkWidget *widget;
1057   gint row;
1058
1059   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
1060   if (widget == NULL)
1061     return FALSE;
1062
1063   row = atk_table_get_row_at_index (ATK_TABLE (selection), i);
1064
1065   return gtk_tree_view_accessible_is_row_selected (ATK_TABLE (selection), row);
1066 }
1067
1068 static void atk_selection_interface_init (AtkSelectionIface *iface)
1069 {
1070   iface->add_selection = gtk_tree_view_accessible_add_selection;
1071   iface->clear_selection = gtk_tree_view_accessible_clear_selection;
1072   iface->ref_selection = gtk_tree_view_accessible_ref_selection;
1073   iface->get_selection_count = gtk_tree_view_accessible_get_selection_count;
1074   iface->is_child_selected = gtk_tree_view_accessible_is_child_selected;
1075 }
1076
1077 #define EXTRA_EXPANDER_PADDING 4
1078
1079 static void
1080 gtk_tree_view_accessible_get_cell_area (GtkCellAccessibleParent *parent,
1081                                         GtkCellAccessible       *cell,
1082                                         GdkRectangle            *cell_rect)
1083 {
1084   GtkWidget *widget;
1085   GtkTreeView *tree_view;
1086   GtkTreeViewColumn *tv_col;
1087   GtkTreePath *path;
1088   AtkObject *parent_cell;
1089   GtkTreeViewAccessibleCellInfo *cell_info;
1090   GtkCellAccessible *top_cell;
1091
1092   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
1093   if (widget == NULL)
1094     return;
1095
1096   tree_view = GTK_TREE_VIEW (widget);
1097   parent_cell = atk_object_get_parent (ATK_OBJECT (cell));
1098   if (parent_cell != ATK_OBJECT (parent))
1099     top_cell = GTK_CELL_ACCESSIBLE (parent_cell);
1100   else
1101     top_cell = cell;
1102   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), top_cell);
1103   if (!cell_info)
1104     return;
1105   path = cell_info_get_path (cell_info);
1106   tv_col = cell_info->cell_col_ref;
1107   if (path)
1108     {
1109       GtkTreeViewColumn *expander_column;
1110       gint focus_line_width;
1111
1112       gtk_tree_view_get_cell_area (tree_view, path, tv_col, cell_rect);
1113       expander_column = gtk_tree_view_get_expander_column (tree_view);
1114       if (expander_column == tv_col)
1115         {
1116           gint expander_size;
1117           gtk_widget_style_get (widget,
1118                                 "expander-size", &expander_size,
1119                                 NULL);
1120           cell_rect->x += expander_size + EXTRA_EXPANDER_PADDING;
1121           cell_rect->width -= expander_size + EXTRA_EXPANDER_PADDING;
1122         }
1123       gtk_widget_style_get (widget,
1124                             "focus-line-width", &focus_line_width,
1125                             NULL);
1126
1127       cell_rect->x += focus_line_width;
1128       cell_rect->width -= 2 * focus_line_width;
1129
1130       gtk_tree_path_free (path);
1131
1132       /* A column has more than one renderer so we find the position
1133        * and width of each
1134        */
1135       if (top_cell != cell)
1136         {
1137           gint cell_index;
1138           gboolean found;
1139           gint cell_start;
1140           gint cell_width;
1141           GList *renderers;
1142           GtkCellRenderer *renderer;
1143
1144           cell_index = atk_object_get_index_in_parent (ATK_OBJECT (cell));
1145           renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (tv_col));
1146           renderer = g_list_nth_data (renderers, cell_index);
1147
1148           found = gtk_tree_view_column_cell_get_position (tv_col, renderer, &cell_start, &cell_width);
1149           if (found)
1150             {
1151               cell_rect->x += cell_start;
1152               cell_rect->width = cell_width;
1153             }
1154           g_list_free (renderers);
1155         }
1156
1157     }
1158 }
1159
1160 static void
1161 gtk_tree_view_accessible_get_cell_extents (GtkCellAccessibleParent *parent,
1162                                            GtkCellAccessible       *cell,
1163                                            gint                    *x,
1164                                            gint                    *y,
1165                                            gint                    *width,
1166                                            gint                    *height,
1167                                            AtkCoordType             coord_type)
1168 {
1169   GtkWidget *widget;
1170   GtkTreeView *tree_view;
1171   GdkWindow *bin_window;
1172   GdkRectangle cell_rect;
1173   gint w_x, w_y;
1174
1175   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
1176   if (widget == NULL)
1177     return;
1178
1179   tree_view = GTK_TREE_VIEW (widget);
1180   gtk_tree_view_accessible_get_cell_area (parent, cell, &cell_rect);
1181   bin_window = gtk_tree_view_get_bin_window (tree_view);
1182   gdk_window_get_origin (bin_window, &w_x, &w_y);
1183
1184   if (coord_type == ATK_XY_WINDOW)
1185     {
1186       GdkWindow *window;
1187       gint x_toplevel, y_toplevel;
1188
1189       window = gdk_window_get_toplevel (bin_window);
1190       gdk_window_get_origin (window, &x_toplevel, &y_toplevel);
1191
1192       w_x -= x_toplevel;
1193       w_y -= y_toplevel;
1194     }
1195
1196   *width = cell_rect.width;
1197   *height = cell_rect.height;
1198   if (is_cell_showing (tree_view, &cell_rect))
1199     {
1200       *x = cell_rect.x + w_x;
1201       *y = cell_rect.y + w_y;
1202     }
1203   else
1204     {
1205       *x = G_MININT;
1206       *y = G_MININT;
1207     }
1208 }
1209
1210 static gboolean
1211 gtk_tree_view_accessible_grab_cell_focus (GtkCellAccessibleParent *parent,
1212                                           GtkCellAccessible       *cell)
1213 {
1214   GtkWidget *widget;
1215   GtkTreeView *tree_view;
1216   GtkTreeViewColumn *tv_col;
1217   GtkTreePath *path;
1218   AtkObject *parent_cell;
1219   AtkObject *cell_object;
1220   GtkTreeViewAccessibleCellInfo *cell_info;
1221   GtkCellRenderer *renderer = NULL;
1222   GtkWidget *toplevel;
1223   gint index;
1224
1225   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
1226   if (widget == NULL)
1227     return FALSE;
1228
1229   tree_view = GTK_TREE_VIEW (widget);
1230
1231   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), cell);
1232   if (!cell_info)
1233     return FALSE;
1234   cell_object = ATK_OBJECT (cell);
1235   parent_cell = atk_object_get_parent (cell_object);
1236   tv_col = cell_info->cell_col_ref;
1237   if (parent_cell != ATK_OBJECT (parent))
1238     {
1239       /* GtkCellAccessible is in a GtkContainerCellAccessible.
1240        * The GtkTreeViewColumn has multiple renderers;
1241        * find the corresponding one.
1242        */
1243       GList *renderers;
1244
1245       renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (tv_col));
1246       index = atk_object_get_index_in_parent (cell_object);
1247       renderer = g_list_nth_data (renderers, index);
1248       g_list_free (renderers);
1249     }
1250   path = cell_info_get_path (cell_info);
1251   if (path)
1252     {
1253       if (renderer)
1254         gtk_tree_view_set_cursor_on_cell (tree_view, path, tv_col, renderer, FALSE);
1255       else
1256         gtk_tree_view_set_cursor (tree_view, path, tv_col, FALSE);
1257
1258       gtk_tree_path_free (path);
1259       gtk_widget_grab_focus (widget);
1260       toplevel = gtk_widget_get_toplevel (widget);
1261       if (gtk_widget_is_toplevel (toplevel))
1262         {
1263 #ifdef GDK_WINDOWING_X11
1264           gtk_window_present_with_time (GTK_WINDOW (toplevel),
1265                                         gdk_x11_get_server_time (gtk_widget_get_window (widget)));
1266 #else
1267           gtk_window_present (GTK_WINDOW (toplevel));
1268 #endif
1269         }
1270
1271       return TRUE;
1272     }
1273   else
1274       return FALSE;
1275 }
1276
1277 static int
1278 gtk_tree_view_accessible_get_child_index (GtkCellAccessibleParent *parent,
1279                                           GtkCellAccessible       *cell)
1280 {
1281   GtkTreeViewAccessibleCellInfo *cell_info;
1282   GtkTreeView *tree_view;
1283
1284   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), cell);
1285   if (!cell_info)
1286     return -1;
1287
1288   tree_view = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)));
1289
1290   return cell_info_get_index (tree_view, cell_info);
1291 }
1292
1293 static GtkCellRendererState
1294 gtk_tree_view_accessible_get_renderer_state (GtkCellAccessibleParent *parent,
1295                                              GtkCellAccessible       *cell)
1296 {
1297   GtkTreeViewAccessibleCellInfo *cell_info;
1298   GtkTreeView *treeview;
1299   GtkCellRendererState flags;
1300
1301   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), cell);
1302   if (!cell_info)
1303     return 0;
1304
1305   flags = 0;
1306
1307   if (GTK_RBNODE_FLAG_SET (cell_info->node, GTK_RBNODE_IS_SELECTED))
1308     flags |= GTK_CELL_RENDERER_SELECTED;
1309
1310   if (GTK_RBNODE_FLAG_SET (cell_info->node, GTK_RBNODE_IS_PRELIT))
1311     flags |= GTK_CELL_RENDERER_PRELIT;
1312
1313   if (gtk_tree_view_column_get_sort_indicator (cell_info->cell_col_ref))
1314     flags |= GTK_CELL_RENDERER_SORTED;
1315
1316   treeview = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)));
1317
1318   if (cell_info->cell_col_ref == gtk_tree_view_get_expander_column (treeview))
1319     {
1320       if (GTK_RBNODE_FLAG_SET (cell_info->node, GTK_RBNODE_IS_PARENT))
1321         flags |= GTK_CELL_RENDERER_EXPANDABLE;
1322
1323       if (cell_info->node->children)
1324         flags |= GTK_CELL_RENDERER_EXPANDED;
1325     }
1326
1327   if (gtk_widget_has_focus (GTK_WIDGET (treeview)))
1328     {
1329       GtkTreeViewColumn *column;
1330       GtkTreePath *path;
1331       GtkRBTree *tree;
1332       GtkRBNode *node;
1333       
1334       gtk_tree_view_get_cursor (treeview, &path, &column);
1335       if (path)
1336         {
1337           _gtk_tree_view_find_node (treeview, path, &tree, &node);
1338           gtk_tree_path_free (path);
1339         }
1340       else
1341         tree = NULL;
1342
1343       if (cell_info->cell_col_ref == column
1344           && cell_info->tree == tree
1345           && cell_info->node == node)
1346         flags |= GTK_CELL_RENDERER_FOCUSED;
1347     }
1348
1349   return flags;
1350 }
1351
1352 static void
1353 gtk_tree_view_accessible_set_cell_data (GtkCellAccessibleParent *parent,
1354                                         GtkCellAccessible       *cell)
1355 {
1356   GtkTreeViewAccessibleCellInfo *cell_info;
1357   GtkTreeView *treeview;
1358   gboolean is_expander, is_expanded;
1359   GtkTreeModel *model;
1360   GtkTreeIter iter;
1361   GtkTreePath *path;
1362
1363   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), cell);
1364   if (!cell_info)
1365     return;
1366
1367   treeview = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)));
1368   model = gtk_tree_view_get_model (treeview);
1369
1370   if (GTK_RBNODE_FLAG_SET (cell_info->node, GTK_RBNODE_IS_PARENT) &&
1371       cell_info->cell_col_ref == gtk_tree_view_get_expander_column (treeview))
1372     {
1373       is_expander = TRUE;
1374       is_expanded = cell_info->node->children != NULL;
1375     }
1376   else
1377     {
1378       is_expander = FALSE;
1379       is_expanded = FALSE;
1380     }
1381
1382   path = cell_info_get_path (cell_info);
1383   if (path == NULL ||
1384       !gtk_tree_model_get_iter (model, &iter, path))
1385     {
1386       /* We only track valid cells, this should never happen */
1387       g_return_if_reached ();
1388     }
1389
1390   gtk_tree_view_column_cell_set_cell_data (cell_info->cell_col_ref,
1391                                            model,
1392                                            &iter,
1393                                            is_expander,
1394                                            is_expanded);
1395 }
1396
1397 static void
1398 gtk_tree_view_accessible_expand_collapse (GtkCellAccessibleParent *parent,
1399                                           GtkCellAccessible       *cell)
1400 {
1401   GtkTreeViewAccessibleCellInfo *cell_info;
1402   GtkTreeView *treeview;
1403   GtkTreePath *path;
1404
1405   treeview = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)));
1406
1407   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), cell);
1408   if (!cell_info ||
1409       cell_info->cell_col_ref != gtk_tree_view_get_expander_column (treeview))
1410     return;
1411
1412   path = cell_info_get_path (cell_info);
1413
1414   if (cell_info->node->children)
1415     gtk_tree_view_collapse_row (treeview, path);
1416   else
1417     gtk_tree_view_expand_row (treeview, path, FALSE);
1418
1419   gtk_tree_path_free (path);
1420 }
1421
1422 static void
1423 gtk_tree_view_accessible_activate (GtkCellAccessibleParent *parent,
1424                                    GtkCellAccessible       *cell)
1425 {
1426   GtkTreeViewAccessibleCellInfo *cell_info;
1427   GtkTreeView *treeview;
1428   GtkTreePath *path;
1429
1430   treeview = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)));
1431
1432   cell_info = find_cell_info (GTK_TREE_VIEW_ACCESSIBLE (parent), cell);
1433   if (!cell_info)
1434     return;
1435
1436   path = cell_info_get_path (cell_info);
1437
1438   gtk_tree_view_row_activated (treeview, path, cell_info->cell_col_ref);
1439
1440   gtk_tree_path_free (path);
1441 }
1442
1443 static void
1444 gtk_tree_view_accessible_edit (GtkCellAccessibleParent *parent,
1445                                GtkCellAccessible       *cell)
1446 {
1447   GtkTreeView *treeview;
1448
1449   if (!gtk_tree_view_accessible_grab_cell_focus (parent, cell))
1450     return;
1451
1452   treeview = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)));
1453
1454   g_signal_emit_by_name (treeview,
1455                          "real-select-cursor-row",
1456                          TRUE);
1457 }
1458
1459 static void
1460 gtk_cell_accessible_parent_interface_init (GtkCellAccessibleParentIface *iface)
1461 {
1462   iface->get_cell_extents = gtk_tree_view_accessible_get_cell_extents;
1463   iface->get_cell_area = gtk_tree_view_accessible_get_cell_area;
1464   iface->grab_focus = gtk_tree_view_accessible_grab_cell_focus;
1465   iface->get_child_index = gtk_tree_view_accessible_get_child_index;
1466   iface->get_renderer_state = gtk_tree_view_accessible_get_renderer_state;
1467   iface->set_cell_data = gtk_tree_view_accessible_set_cell_data;
1468   iface->expand_collapse = gtk_tree_view_accessible_expand_collapse;
1469   iface->activate = gtk_tree_view_accessible_activate;
1470   iface->edit = gtk_tree_view_accessible_edit;
1471 }
1472
1473 /* signal handling */
1474
1475 static void
1476 cursor_changed (GtkTreeView           *tree_view,
1477                 GtkTreeViewAccessible *accessible)
1478 {
1479   AtkObject *cell;
1480
1481   cell = gtk_tree_view_accessible_ref_focus_cell (tree_view);
1482   if (cell)
1483     {
1484       if (cell != accessible->focus_cell)
1485         {
1486           if (accessible->focus_cell)
1487             {
1488               _gtk_cell_accessible_remove_state (GTK_CELL_ACCESSIBLE (accessible->focus_cell), ATK_STATE_ACTIVE, FALSE);
1489               _gtk_cell_accessible_remove_state (GTK_CELL_ACCESSIBLE (accessible->focus_cell), ATK_STATE_FOCUSED, FALSE);
1490               g_object_unref (accessible->focus_cell);
1491               accessible->focus_cell = cell;
1492             }
1493
1494           if (gtk_widget_has_focus (GTK_WIDGET (tree_view)))
1495             {
1496               _gtk_cell_accessible_add_state (GTK_CELL_ACCESSIBLE (cell), ATK_STATE_ACTIVE, FALSE);
1497               _gtk_cell_accessible_add_state (GTK_CELL_ACCESSIBLE (cell), ATK_STATE_FOCUSED, FALSE);
1498             }
1499
1500           g_signal_emit_by_name (accessible, "active-descendant-changed", cell);
1501         }
1502       else
1503         g_object_unref (cell);
1504     }
1505 }
1506
1507 static gboolean
1508 focus_in (GtkWidget *widget)
1509 {
1510   GtkTreeView *tree_view;
1511   GtkTreeViewAccessible *accessible;
1512   AtkStateSet *state_set;
1513   AtkObject *cell;
1514
1515   tree_view = GTK_TREE_VIEW (widget);
1516   accessible = GTK_TREE_VIEW_ACCESSIBLE (gtk_widget_get_accessible (widget));
1517
1518   if (accessible->focus_cell == NULL)
1519     {
1520       cell = gtk_tree_view_accessible_ref_focus_cell (tree_view);
1521       if (cell)
1522         {
1523           state_set = atk_object_ref_state_set (cell);
1524           if (state_set)
1525             {
1526               if (!atk_state_set_contains_state (state_set, ATK_STATE_FOCUSED))
1527                 {
1528                   _gtk_cell_accessible_add_state (GTK_CELL_ACCESSIBLE (cell), ATK_STATE_ACTIVE, FALSE);
1529                   accessible->focus_cell = cell;
1530                   _gtk_cell_accessible_add_state (GTK_CELL_ACCESSIBLE (cell), ATK_STATE_FOCUSED, FALSE);
1531                   g_signal_emit_by_name (accessible, "active-descendant-changed", cell);
1532                 }
1533               g_object_unref (state_set);
1534             }
1535         }
1536     }
1537   return FALSE;
1538 }
1539
1540 static gboolean
1541 focus_out (GtkWidget *widget)
1542 {
1543   GtkTreeViewAccessible *accessible;
1544
1545   accessible = GTK_TREE_VIEW_ACCESSIBLE (gtk_widget_get_accessible (widget));
1546   if (accessible->focus_cell)
1547     {
1548       _gtk_cell_accessible_remove_state (GTK_CELL_ACCESSIBLE (accessible->focus_cell), ATK_STATE_ACTIVE, FALSE);
1549       _gtk_cell_accessible_remove_state (GTK_CELL_ACCESSIBLE (accessible->focus_cell), ATK_STATE_FOCUSED, FALSE);
1550       g_object_unref (accessible->focus_cell);
1551       accessible->focus_cell = NULL;
1552     }
1553   return FALSE;
1554 }
1555
1556 void
1557 _gtk_tree_view_accessible_reorder (GtkTreeView *treeview)
1558 {
1559   GtkTreeViewAccessible *accessible;
1560
1561   accessible = GTK_TREE_VIEW_ACCESSIBLE (_gtk_widget_peek_accessible (GTK_WIDGET (treeview)));
1562   if (accessible == NULL)
1563     return;
1564
1565   g_signal_emit_by_name (accessible, "row-reordered");
1566 }
1567
1568 static gboolean
1569 is_cell_showing (GtkTreeView  *tree_view,
1570                  GdkRectangle *cell_rect)
1571 {
1572   GdkRectangle rect, *visible_rect;
1573   GdkRectangle rect1, *tree_cell_rect;
1574   gint bx, by;
1575   gboolean is_showing;
1576
1577  /* A cell is considered "SHOWING" if any part of the cell is
1578   * in the visible area. Other ways we could do this is by a
1579   * cell's midpoint or if the cell is fully in the visible range.
1580   * Since we have the cell_rect x, y, width, height of the cell,
1581   * any of these is easy to compute.
1582   *
1583   * It is assumed that cell's rectangle is in widget coordinates
1584   * so we must transform to tree cordinates.
1585   */
1586   visible_rect = &rect;
1587   tree_cell_rect = &rect1;
1588   tree_cell_rect->x = cell_rect->x;
1589   tree_cell_rect->y = cell_rect->y;
1590   tree_cell_rect->width = cell_rect->width;
1591   tree_cell_rect->height = cell_rect->height;
1592
1593   gtk_tree_view_get_visible_rect (tree_view, visible_rect);
1594   gtk_tree_view_convert_tree_to_bin_window_coords (tree_view, visible_rect->x,
1595                                                    visible_rect->y, &bx, &by);
1596
1597   if (((tree_cell_rect->x + tree_cell_rect->width) < bx) ||
1598      ((tree_cell_rect->y + tree_cell_rect->height) < by) ||
1599      (tree_cell_rect->x > (bx + visible_rect->width)) ||
1600      (tree_cell_rect->y > (by + visible_rect->height)))
1601     is_showing =  FALSE;
1602   else
1603     is_showing = TRUE;
1604
1605   return is_showing;
1606 }
1607
1608 /* Misc Public */
1609
1610 /* This function is called when a cell's flyweight is created in
1611  * gtk_tree_view_accessible_table_ref_at with emit_change_signal
1612  * set to FALSE and in model_row_changed() on receipt of "row-changed"
1613  * signal when emit_change_signal is set to TRUE
1614  */
1615 static gboolean
1616 update_cell_value (GtkRendererCellAccessible      *renderer_cell,
1617                    GtkTreeViewAccessible *accessible,
1618                    gboolean               emit_change_signal)
1619 {
1620   GtkTreeViewAccessibleCellInfo *cell_info;
1621   GtkTreeView *tree_view;
1622   GtkTreeModel *tree_model;
1623   GtkTreePath *path;
1624   GtkTreeIter iter;
1625   GList *renderers, *cur_renderer;
1626   GParamSpec *spec;
1627   GtkRendererCellAccessibleClass *renderer_cell_class;
1628   GtkCellRendererClass *gtk_cell_renderer_class;
1629   GtkCellAccessible *cell;
1630   gchar **prop_list;
1631   AtkObject *parent;
1632   gboolean is_expander, is_expanded;
1633
1634   renderer_cell_class = GTK_RENDERER_CELL_ACCESSIBLE_GET_CLASS (renderer_cell);
1635   if (renderer_cell->renderer)
1636     gtk_cell_renderer_class = GTK_CELL_RENDERER_GET_CLASS (renderer_cell->renderer);
1637   else
1638     gtk_cell_renderer_class = NULL;
1639
1640   prop_list = renderer_cell_class->property_list;
1641
1642   cell = GTK_CELL_ACCESSIBLE (renderer_cell);
1643   cell_info = find_cell_info (accessible, cell);
1644   if (!cell_info)
1645     return FALSE;
1646
1647   if (emit_change_signal)
1648     {
1649       tree_view = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)));
1650       tree_model = gtk_tree_view_get_model (tree_view);
1651       path = cell_info_get_path (cell_info);
1652       if (path == NULL)
1653         return FALSE;
1654
1655       gtk_tree_model_get_iter (tree_model, &iter, path);
1656       is_expander = FALSE;
1657       is_expanded = FALSE;
1658       if (gtk_tree_model_iter_has_child (tree_model, &iter))
1659         {
1660           GtkTreeViewColumn *expander_tv;
1661
1662           expander_tv = gtk_tree_view_get_expander_column (tree_view);
1663           if (expander_tv == cell_info->cell_col_ref)
1664             {
1665               is_expander = TRUE;
1666               is_expanded = gtk_tree_view_row_expanded (tree_view, path);
1667             }
1668         }
1669       gtk_tree_path_free (path);
1670       gtk_tree_view_column_cell_set_cell_data (cell_info->cell_col_ref,
1671                                                tree_model, &iter,
1672                                                is_expander, is_expanded);
1673     }
1674   renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (cell_info->cell_col_ref));
1675   if (!renderers)
1676     return FALSE;
1677
1678   /* If the cell is in a container, its index is used to find the renderer
1679    * in the list. Otherwise, we assume that the cell is represented
1680    * by the first renderer in the list
1681    */
1682   parent = atk_object_get_parent (ATK_OBJECT (cell));
1683
1684   if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
1685     cur_renderer = g_list_nth (renderers, atk_object_get_index_in_parent (ATK_OBJECT (cell)));
1686   else
1687     cur_renderer = renderers;
1688
1689   if (cur_renderer == NULL)
1690     return FALSE;
1691
1692   if (gtk_cell_renderer_class)
1693     {
1694       while (*prop_list)
1695         {
1696           spec = g_object_class_find_property
1697                            (G_OBJECT_CLASS (gtk_cell_renderer_class), *prop_list);
1698
1699           if (spec != NULL)
1700             {
1701               GValue value = G_VALUE_INIT;
1702
1703               g_value_init (&value, spec->value_type);
1704               g_object_get_property (cur_renderer->data, *prop_list, &value);
1705               g_object_set_property (G_OBJECT (renderer_cell->renderer),
1706                                      *prop_list, &value);
1707               g_value_unset (&value);
1708             }
1709           else
1710             g_warning ("Invalid property: %s\n", *prop_list);
1711           prop_list++;
1712         }
1713     }
1714   g_list_free (renderers);
1715
1716   return _gtk_renderer_cell_accessible_update_cache (renderer_cell, emit_change_signal);
1717 }
1718
1719 /* Misc Private */
1720
1721 static void
1722 cell_destroyed (gpointer data)
1723 {
1724   GtkTreeViewAccessibleCellInfo *cell_info = data;
1725
1726   cell_info->cell = NULL;
1727
1728   g_hash_table_remove (cell_info->view->cell_infos, cell_info);
1729 }
1730
1731 static int
1732 cell_info_get_index (GtkTreeView                     *tree_view,
1733                      GtkTreeViewAccessibleCellInfo   *info)
1734 {
1735   int index;
1736
1737   index = _gtk_rbtree_node_get_index (info->tree, info->node) + 1;
1738   index *= get_n_columns (tree_view);
1739   index += get_column_number (tree_view, info->cell_col_ref);
1740
1741   return index;
1742 }
1743
1744 static void
1745 cell_info_new (GtkTreeViewAccessible *accessible,
1746                GtkTreeModel          *tree_model,
1747                GtkRBTree             *tree,
1748                GtkRBNode             *node,
1749                GtkTreeViewColumn     *tv_col,
1750                GtkCellAccessible     *cell)
1751 {
1752   GtkTreeViewAccessibleCellInfo *cell_info;
1753
1754   cell_info = g_new (GtkTreeViewAccessibleCellInfo, 1);
1755
1756   cell_info->tree = tree;
1757   cell_info->node = node;
1758   cell_info->cell_col_ref = tv_col;
1759   cell_info->cell = cell;
1760   cell_info->view = accessible;
1761
1762   g_object_set_qdata_full (G_OBJECT (cell), 
1763                            gtk_tree_view_accessible_get_data_quark (),
1764                            cell_info,
1765                            cell_destroyed);
1766
1767   g_hash_table_replace (accessible->cell_infos, cell_info, cell_info);
1768 }
1769
1770 static GtkCellAccessible *
1771 peek_cell (GtkTreeViewAccessible *accessible,
1772            GtkRBTree             *tree,
1773            GtkRBNode             *node,
1774            GtkTreeViewColumn     *column)
1775 {
1776   GtkTreeViewAccessibleCellInfo lookup, *cell_info;
1777
1778   lookup.tree = tree;
1779   lookup.node = node;
1780   lookup.cell_col_ref = column;
1781
1782   cell_info = g_hash_table_lookup (accessible->cell_infos, &lookup);
1783   if (cell_info == NULL)
1784     return NULL;
1785
1786   return cell_info->cell;
1787 }
1788
1789 static GtkCellAccessible *
1790 find_cell (GtkTreeViewAccessible *accessible,
1791            gint                   index)
1792 {
1793   GtkTreeView *tree_view;
1794   GtkRBTree *tree;
1795   GtkRBNode *node;
1796
1797   tree_view = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)));
1798
1799   if (!_gtk_rbtree_find_index (_gtk_tree_view_get_rbtree (tree_view),
1800                                index / get_n_columns (tree_view) - 1,
1801                                &tree,
1802                                &node))
1803     {
1804       g_assert_not_reached ();
1805     }
1806
1807   return peek_cell (accessible,
1808                     tree, node, 
1809                     get_visible_column (tree_view, index % get_n_columns (tree_view)));
1810 }
1811
1812 /* Returns the column number of the specified GtkTreeViewColumn
1813  * The column must be visible.
1814  */
1815 static gint
1816 get_column_number (GtkTreeView       *treeview,
1817                    GtkTreeViewColumn *column)
1818 {
1819   GtkTreeViewColumn *cur;
1820   guint i, number;
1821
1822   number = 0;
1823
1824   for (i = 0; i < gtk_tree_view_get_n_columns (treeview); i++)
1825     {
1826       cur = gtk_tree_view_get_column (treeview, i);
1827       
1828       if (!gtk_tree_view_column_get_visible (cur))
1829         continue;
1830
1831       if (cur == column)
1832         break;
1833
1834       number++;
1835     }
1836
1837   g_return_val_if_fail (i < gtk_tree_view_get_n_columns (treeview), 0);
1838
1839   return number;
1840 }
1841
1842 static gint
1843 get_index (GtkTreeView *tree_view,
1844            GtkTreePath *path,
1845            gint         actual_column)
1846 {
1847   gint depth = 0;
1848   gint index = 1;
1849   gint *indices = NULL;
1850
1851   if (path)
1852     {
1853       depth = gtk_tree_path_get_depth (path);
1854       indices = gtk_tree_path_get_indices (path);
1855     }
1856
1857   if (depth > 1)
1858     {
1859       GtkTreePath *copy_path;
1860       GtkTreeModel *model;
1861
1862       model = gtk_tree_view_get_model (tree_view);
1863       copy_path = gtk_tree_path_copy (path);
1864       gtk_tree_path_up (copy_path);
1865       count_rows (model, NULL, copy_path, &index, 0, depth);
1866       gtk_tree_path_free (copy_path);
1867     }
1868
1869   if (path)
1870     index += indices[depth - 1];
1871   index *= get_n_columns (tree_view);
1872   index +=  actual_column;
1873   return index;
1874 }
1875
1876 /* The function count_rows counts the number of rows starting at iter
1877  * and ending at end_path. The value of level is the depth of iter and
1878  * the value of depth is the depth of end_path. Rows at depth before
1879  * end_path are counted. This functions counts rows which are not visible
1880  * because an ancestor is collapsed.
1881  */
1882 static void
1883 count_rows (GtkTreeModel *model,
1884             GtkTreeIter  *iter,
1885             GtkTreePath  *end_path,
1886             gint         *count,
1887             gint          level,
1888             gint          depth)
1889 {
1890   GtkTreeIter child_iter;
1891
1892   if (!model)
1893     return;
1894
1895   level++;
1896   *count += gtk_tree_model_iter_n_children (model, iter);
1897
1898   if (gtk_tree_model_get_flags (model) & GTK_TREE_MODEL_LIST_ONLY)
1899     return;
1900
1901   if (level >= depth)
1902     return;
1903
1904   if (gtk_tree_model_iter_children (model, &child_iter, iter))
1905     {
1906       gboolean ret_val = TRUE;
1907
1908       while (ret_val)
1909         {
1910           if (level == depth - 1)
1911             {
1912               GtkTreePath *iter_path;
1913               gboolean finished = FALSE;
1914
1915               iter_path = gtk_tree_model_get_path (model, &child_iter);
1916               if (end_path && gtk_tree_path_compare (iter_path, end_path) >= 0)
1917                 finished = TRUE;
1918               gtk_tree_path_free (iter_path);
1919               if (finished)
1920                 break;
1921             }
1922           if (gtk_tree_model_iter_has_child (model, &child_iter))
1923             count_rows (model, &child_iter, end_path, count, level, depth);
1924           ret_val = gtk_tree_model_iter_next (model, &child_iter);
1925         }
1926     }
1927 }
1928
1929 static gboolean
1930 get_rbtree_column_from_index (GtkTreeView        *tree_view,
1931                               gint                index,
1932                               GtkRBTree         **tree,
1933                               GtkRBNode         **node,
1934                               GtkTreeViewColumn **column)
1935 {
1936   guint n_columns = get_n_columns (tree_view);
1937
1938   if (n_columns == 0)
1939     return FALSE;
1940   /* First row is the column headers */
1941   index -= n_columns;
1942   if (index < 0)
1943     return FALSE;
1944
1945   if (tree)
1946     {
1947       g_return_val_if_fail (node != NULL, FALSE);
1948
1949       if (!_gtk_rbtree_find_index (_gtk_tree_view_get_rbtree (tree_view),
1950                                    index / n_columns,
1951                                    tree,
1952                                    node))
1953         return FALSE;
1954     }
1955
1956   if (column)
1957     {
1958       *column = get_visible_column (tree_view, index % n_columns);
1959       if (*column == NULL)
1960         return FALSE;
1961   }
1962   return TRUE;
1963 }
1964
1965 static GtkTreeViewAccessibleCellInfo *
1966 find_cell_info (GtkTreeViewAccessible *accessible,
1967                 GtkCellAccessible     *cell)
1968 {
1969   AtkObject *parent;
1970   
1971   parent = atk_object_get_parent (ATK_OBJECT (cell));
1972   while (parent != ATK_OBJECT (accessible))
1973     {
1974       cell = GTK_CELL_ACCESSIBLE (parent);
1975       parent = atk_object_get_parent (ATK_OBJECT (cell));
1976     }
1977
1978   return g_object_get_qdata (G_OBJECT (cell),
1979                              gtk_tree_view_accessible_get_data_quark ());
1980 }
1981
1982 static AtkObject *
1983 get_header_from_column (GtkTreeViewColumn *tv_col)
1984 {
1985   AtkObject *rc;
1986   GtkWidget *header_widget;
1987
1988   if (tv_col == NULL)
1989     return NULL;
1990
1991   header_widget = gtk_tree_view_column_get_button (tv_col);
1992
1993   if (header_widget)
1994     rc = gtk_widget_get_accessible (header_widget);
1995   else
1996     rc = NULL;
1997
1998   return rc;
1999 }
2000
2001 void
2002 _gtk_tree_view_accessible_add (GtkTreeView *treeview,
2003                                GtkRBTree   *tree,
2004                                GtkRBNode   *node)
2005 {
2006   GtkTreeViewAccessible *accessible;
2007   guint row, n_rows, n_cols, i;
2008
2009   accessible = GTK_TREE_VIEW_ACCESSIBLE (_gtk_widget_peek_accessible (GTK_WIDGET (treeview)));
2010   if (accessible == NULL)
2011     return;
2012
2013   if (node == NULL)
2014     {
2015       row = tree->parent_tree ? _gtk_rbtree_node_get_index (tree->parent_tree, tree->parent_node) : 0;
2016       n_rows = tree->root->total_count;
2017     }
2018   else
2019     {
2020       row = _gtk_rbtree_node_get_index (tree, node);
2021       n_rows = 1 + (node->children ? node->children->root->total_count : 0);
2022     }
2023
2024   g_signal_emit_by_name (accessible, "row-inserted", row, n_rows);
2025
2026   n_cols = get_n_columns (treeview);
2027   for (i = (row + 1) * n_cols; i < (row + n_rows + 1) * n_cols; i++)
2028     {
2029      /* Pass NULL as the child object, i.e. 4th argument */
2030       g_signal_emit_by_name (accessible, "children-changed::add", i, NULL, NULL);
2031     }
2032 }
2033
2034 void
2035 _gtk_tree_view_accessible_remove (GtkTreeView *treeview,
2036                                   GtkRBTree   *tree,
2037                                   GtkRBNode   *node)
2038 {
2039   GtkTreeViewAccessibleCellInfo *cell_info;
2040   GHashTableIter iter;
2041   GtkTreeViewAccessible *accessible;
2042   guint row, n_rows, n_cols, i;
2043
2044   accessible = GTK_TREE_VIEW_ACCESSIBLE (_gtk_widget_peek_accessible (GTK_WIDGET (treeview)));
2045   if (accessible == NULL)
2046     return;
2047
2048   /* if this shows up in profiles, special-case node->children == NULL */
2049
2050   if (node == NULL)
2051     {
2052       row = tree->parent_tree ? _gtk_rbtree_node_get_index (tree->parent_tree, tree->parent_node) : 0;
2053       n_rows = tree->root->total_count + 1;
2054     }
2055   else
2056     {
2057       row = _gtk_rbtree_node_get_index (tree, node);
2058       n_rows = 1 + (node->children ? node->children->root->total_count : 0);
2059
2060       tree = node->children;
2061     }
2062
2063   g_signal_emit_by_name (accessible, "row-deleted", row, n_rows);
2064
2065   n_cols = get_n_columns (treeview);
2066   for (i = (n_rows + row + 1) * n_cols - 1; i >= (row + 1) * n_cols; i--)
2067     {
2068      /* Pass NULL as the child object, i.e. 4th argument */
2069       g_signal_emit_by_name (accessible, "children-changed::remove", i, NULL, NULL);
2070     }
2071
2072   g_hash_table_iter_init (&iter, accessible->cell_infos);
2073   while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&cell_info))
2074     {
2075       if (node == cell_info->node ||
2076           tree == cell_info->tree ||
2077           (tree && _gtk_rbtree_contains (tree, cell_info->tree)))
2078         g_hash_table_iter_remove (&iter);
2079     }
2080 }
2081
2082 void
2083 _gtk_tree_view_accessible_changed (GtkTreeView *treeview,
2084                                    GtkRBTree   *tree,
2085                                    GtkRBNode   *node)
2086 {
2087   GtkTreeViewAccessible *accessible;
2088   guint i;
2089
2090   accessible = GTK_TREE_VIEW_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (treeview)));
2091
2092   for (i = 0; i < gtk_tree_view_get_n_columns (treeview); i++)
2093     {
2094       GtkCellAccessible *cell = peek_cell (accessible,
2095                                            tree, node,
2096                                            gtk_tree_view_get_column (treeview, i));
2097
2098       if (!GTK_IS_RENDERER_CELL_ACCESSIBLE (cell))
2099         continue;
2100
2101       update_cell_value (GTK_RENDERER_CELL_ACCESSIBLE (cell),
2102                          accessible, TRUE);
2103     }
2104
2105   g_signal_emit_by_name (accessible, "visible-data-changed");
2106 }
2107
2108 /* NB: id is not checked, only columns < id are.
2109  * This is important so the function works for notification of removal of a column */
2110 static guint
2111 to_visible_column_id (GtkTreeView *treeview,
2112                       guint        id)
2113 {
2114   guint i;
2115   guint invisible;
2116
2117   invisible = 0;
2118
2119   for (i = 0; i < id; i++)
2120     {
2121       GtkTreeViewColumn *column = gtk_tree_view_get_column (treeview, i);
2122
2123       if (!gtk_tree_view_column_get_visible (column))
2124         invisible++;
2125     }
2126
2127   return id - invisible;
2128 }
2129
2130 void
2131 _gtk_tree_view_accessible_do_add_column (GtkTreeViewAccessible *accessible,
2132                                          GtkTreeView           *treeview,
2133                                          GtkTreeViewColumn     *column,
2134                                          guint                  id)
2135 {
2136   guint row, n_rows, n_cols;
2137
2138   /* Generate column-inserted signal */
2139   g_signal_emit_by_name (accessible, "column-inserted", id, 1);
2140
2141   n_rows = get_n_rows (treeview);
2142   n_cols = get_n_columns (treeview);
2143
2144   /* Generate children-changed signals */
2145   for (row = 0; row <= n_rows; row++)
2146     {
2147      /* Pass NULL as the child object, i.e. 4th argument */
2148       g_signal_emit_by_name (accessible, "children-changed::add",
2149                              (row * n_cols) + id, NULL, NULL);
2150     }
2151 }
2152
2153 void
2154 _gtk_tree_view_accessible_add_column (GtkTreeView       *treeview,
2155                                       GtkTreeViewColumn *column,
2156                                       guint              id)
2157 {
2158   AtkObject *obj;
2159
2160   if (!gtk_tree_view_column_get_visible (column))
2161     return;
2162
2163   obj = _gtk_widget_peek_accessible (GTK_WIDGET (treeview));
2164   if (obj == NULL)
2165     return;
2166
2167   _gtk_tree_view_accessible_do_add_column (GTK_TREE_VIEW_ACCESSIBLE (obj),
2168                                            treeview,
2169                                            column,
2170                                            to_visible_column_id (treeview, id));
2171 }
2172
2173 void
2174 _gtk_tree_view_accessible_do_remove_column (GtkTreeViewAccessible *accessible,
2175                                             GtkTreeView           *treeview,
2176                                             GtkTreeViewColumn     *column,
2177                                             guint                  id)
2178 {
2179   GtkTreeViewAccessibleCellInfo *cell_info;
2180   GHashTableIter iter;
2181   gpointer value;
2182   guint row, n_rows, n_cols;
2183
2184   /* Clean column from cache */
2185   g_hash_table_iter_init (&iter, accessible->cell_infos);
2186   while (g_hash_table_iter_next (&iter, NULL, &value))
2187     {
2188       cell_info = value;
2189       if (cell_info->cell_col_ref == column)
2190         g_hash_table_iter_remove (&iter);
2191     }
2192
2193   /* Generate column-deleted signal */
2194   g_signal_emit_by_name (accessible, "column-deleted", id, 1);
2195
2196   n_rows = get_n_rows (treeview);
2197   n_cols = get_n_columns (treeview);
2198
2199   /* Generate children-changed signals */
2200   for (row = 0; row <= n_rows; row++)
2201     {
2202       /* Pass NULL as the child object, 4th argument */
2203       g_signal_emit_by_name (accessible, "children-changed::remove",
2204                              (row * n_cols) + id, NULL, NULL);
2205     }
2206 }
2207
2208 void
2209 _gtk_tree_view_accessible_remove_column (GtkTreeView       *treeview,
2210                                          GtkTreeViewColumn *column,
2211                                          guint              id)
2212 {
2213   AtkObject *obj;
2214
2215   if (!gtk_tree_view_column_get_visible (column))
2216     return;
2217
2218   obj = _gtk_widget_peek_accessible (GTK_WIDGET (treeview));
2219   if (obj == NULL)
2220     return;
2221
2222   _gtk_tree_view_accessible_do_remove_column (GTK_TREE_VIEW_ACCESSIBLE (obj),
2223                                               treeview,
2224                                               column,
2225                                               to_visible_column_id (treeview, id));
2226 }
2227
2228 void
2229 _gtk_tree_view_accessible_reorder_column (GtkTreeView       *treeview,
2230                                           GtkTreeViewColumn *column)
2231 {
2232   AtkObject *obj;
2233
2234   obj = _gtk_widget_peek_accessible (GTK_WIDGET (treeview));
2235   if (obj == NULL)
2236     return;
2237
2238   g_signal_emit_by_name (obj, "column-reordered");
2239 }
2240
2241 void
2242 _gtk_tree_view_accessible_toggle_visibility (GtkTreeView       *treeview,
2243                                              GtkTreeViewColumn *column)
2244 {
2245   AtkObject *obj;
2246   guint id;
2247
2248   obj = _gtk_widget_peek_accessible (GTK_WIDGET (treeview));
2249   if (obj == NULL)
2250     return;
2251
2252   id = get_column_number (treeview, column);
2253
2254   if (gtk_tree_view_column_get_visible (column))
2255     _gtk_tree_view_accessible_do_add_column (GTK_TREE_VIEW_ACCESSIBLE (obj),
2256                                              treeview,
2257                                              column,
2258                                              id);
2259   else
2260     _gtk_tree_view_accessible_do_remove_column (GTK_TREE_VIEW_ACCESSIBLE (obj),
2261                                                 treeview,
2262                                                 column,
2263                                                 id);
2264 }
2265
2266 void
2267 _gtk_tree_view_accessible_add_state (GtkTreeView          *treeview,
2268                                      GtkRBTree            *tree,
2269                                      GtkRBNode            *node,
2270                                      GtkCellRendererState  state)
2271 {
2272   GtkTreeViewAccessible *accessible;
2273   AtkObject *obj;
2274   guint i;
2275
2276   obj = _gtk_widget_peek_accessible (GTK_WIDGET (treeview));
2277   if (obj == NULL)
2278     return;
2279
2280   accessible = GTK_TREE_VIEW_ACCESSIBLE (obj);
2281
2282   for (i = 0; i < gtk_tree_view_get_n_columns (treeview); i++)
2283     {
2284       GtkCellAccessible *cell = peek_cell (accessible,
2285                                            tree, node,
2286                                            gtk_tree_view_get_column (treeview, i));
2287
2288       if (cell == NULL)
2289         continue;
2290
2291       _gtk_cell_accessible_state_changed (cell, state, 0);
2292     }
2293
2294   if (state == GTK_CELL_RENDERER_SELECTED)
2295     g_signal_emit_by_name (accessible, "selection-changed");
2296 }
2297
2298 void
2299 _gtk_tree_view_accessible_remove_state (GtkTreeView          *treeview,
2300                                         GtkRBTree            *tree,
2301                                         GtkRBNode            *node,
2302                                         GtkCellRendererState  state)
2303 {
2304   GtkTreeViewAccessible *accessible;
2305   AtkObject *obj;
2306   guint i;
2307
2308   obj = _gtk_widget_peek_accessible (GTK_WIDGET (treeview));
2309   if (obj == NULL)
2310     return;
2311
2312   accessible = GTK_TREE_VIEW_ACCESSIBLE (obj);
2313
2314   for (i = 0; i < gtk_tree_view_get_n_columns (treeview); i++)
2315     {
2316       GtkCellAccessible *cell = peek_cell (accessible,
2317                                            tree, node,
2318                                            gtk_tree_view_get_column (treeview, i));
2319
2320       if (cell == NULL)
2321         continue;
2322
2323       _gtk_cell_accessible_state_changed (cell, 0, state);
2324     }
2325
2326   if (state == GTK_CELL_RENDERER_SELECTED)
2327     g_signal_emit_by_name (accessible, "selection-changed");
2328 }