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