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