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