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