]> Pileus Git - ~andy/gtk/blob - gtk/a11y/gailcontainer.c
gail: Move from modules/other/gail to gtk/a11y
[~andy/gtk] / gtk / a11y / gailcontainer.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 #include "gailcontainer.h"
24
25 static void         gail_container_class_init          (GailContainerClass *klass);
26 static void         gail_container_init                (GailContainer      *container);
27
28 static gint         gail_container_get_n_children      (AtkObject          *obj);
29 static AtkObject*   gail_container_ref_child           (AtkObject          *obj,
30                                                         gint               i);
31 static gint         gail_container_add_gtk             (GtkContainer       *container,
32                                                         GtkWidget          *widget,
33                                                         gpointer           data);
34 static gint         gail_container_remove_gtk          (GtkContainer       *container,
35                                                         GtkWidget          *widget,
36                                                         gpointer           data);
37 static gint         gail_container_real_add_gtk        (GtkContainer       *container,
38                                                         GtkWidget          *widget,
39                                                         gpointer           data);
40 static gint         gail_container_real_remove_gtk     (GtkContainer       *container,
41                                                         GtkWidget          *widget,
42                                                         gpointer           data);
43
44 static void          gail_container_real_initialize    (AtkObject          *obj,
45                                                         gpointer           data);
46
47 static void          gail_container_finalize           (GObject            *object);
48
49 G_DEFINE_TYPE (GailContainer, gail_container, GAIL_TYPE_WIDGET)
50
51 static void
52 gail_container_class_init (GailContainerClass *klass)
53 {
54   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
55   AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
56
57   gobject_class->finalize = gail_container_finalize;
58
59   class->get_n_children = gail_container_get_n_children;
60   class->ref_child = gail_container_ref_child;
61   class->initialize = gail_container_real_initialize;
62
63   klass->add_gtk = gail_container_real_add_gtk;
64   klass->remove_gtk = gail_container_real_remove_gtk;
65 }
66
67 static void
68 gail_container_init (GailContainer      *container)
69 {
70   container->children = NULL;
71 }
72
73 static gint
74 gail_container_get_n_children (AtkObject* obj)
75 {
76   GtkWidget *widget;
77   GList *children;
78   gint count = 0;
79
80   g_return_val_if_fail (GAIL_IS_CONTAINER (obj), count);
81
82   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
83   if (widget == NULL)
84     return 0;
85
86   children = gtk_container_get_children (GTK_CONTAINER(widget));
87   count = g_list_length (children);
88   g_list_free (children);
89
90   return count; 
91 }
92
93 static AtkObject* 
94 gail_container_ref_child (AtkObject *obj,
95                           gint       i)
96 {
97   GList *children, *tmp_list;
98   AtkObject  *accessible;
99   GtkWidget *widget;
100
101   g_return_val_if_fail (GAIL_IS_CONTAINER (obj), NULL);
102   g_return_val_if_fail ((i >= 0), NULL);
103
104   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
105   if (widget == NULL)
106     return NULL;
107
108   children = gtk_container_get_children (GTK_CONTAINER (widget));
109   tmp_list = g_list_nth (children, i);
110   if (!tmp_list)
111     {
112       g_list_free (children);
113       return NULL;
114     }  
115   accessible = gtk_widget_get_accessible (GTK_WIDGET (tmp_list->data));
116
117   g_list_free (children);
118   g_object_ref (accessible);
119   return accessible; 
120 }
121
122 static gint
123 gail_container_add_gtk (GtkContainer *container,
124                         GtkWidget    *widget,
125                         gpointer     data)
126 {
127   GailContainer *gail_container = GAIL_CONTAINER (data);
128   GailContainerClass *klass;
129
130   klass = GAIL_CONTAINER_GET_CLASS (gail_container);
131
132   if (klass->add_gtk)
133     return klass->add_gtk (container, widget, data);
134   else
135     return 1;
136 }
137  
138 static gint
139 gail_container_remove_gtk (GtkContainer *container,
140                            GtkWidget    *widget,
141                            gpointer     data)
142 {
143   GailContainer *gail_container = GAIL_CONTAINER (data);
144   GailContainerClass *klass;
145
146   klass = GAIL_CONTAINER_GET_CLASS (gail_container);
147
148   if (klass->remove_gtk)
149     return klass->remove_gtk (container, widget, data);
150   else
151     return 1;
152 }
153  
154 static gint
155 gail_container_real_add_gtk (GtkContainer *container,
156                              GtkWidget    *widget,
157                              gpointer     data)
158 {
159   AtkObject* atk_parent = ATK_OBJECT (data);
160   AtkObject* atk_child = gtk_widget_get_accessible (widget);
161   GailContainer *gail_container = GAIL_CONTAINER (atk_parent);
162   gint       index;
163
164   g_object_notify (G_OBJECT (atk_child), "accessible_parent");
165
166   g_list_free (gail_container->children);
167   gail_container->children = gtk_container_get_children (container);
168   index = g_list_index (gail_container->children, widget);
169   g_signal_emit_by_name (atk_parent, "children_changed::add", 
170                          index, atk_child, NULL);
171
172   return 1;
173 }
174
175 static gint
176 gail_container_real_remove_gtk (GtkContainer       *container,
177                                 GtkWidget          *widget,
178                                 gpointer           data)
179 {
180   AtkPropertyValues values = { NULL };
181   AtkObject* atk_parent;
182   AtkObject *atk_child;
183   GailContainer *gail_container;
184   gint       index;
185
186   atk_parent = ATK_OBJECT (data);
187   atk_child = gtk_widget_get_accessible (widget);
188
189   if (atk_child)
190     {
191       g_value_init (&values.old_value, G_TYPE_POINTER);
192       g_value_set_pointer (&values.old_value, atk_parent);
193     
194       values.property_name = "accessible-parent";
195
196       g_object_ref (atk_child);
197       g_signal_emit_by_name (atk_child,
198                              "property_change::accessible-parent", &values, NULL);
199       g_object_unref (atk_child);
200     }
201   gail_container = GAIL_CONTAINER (atk_parent);
202   index = g_list_index (gail_container->children, widget);
203   g_list_free (gail_container->children);
204   gail_container->children = gtk_container_get_children (container);
205   if (index >= 0 && index <= g_list_length (gail_container->children))
206     g_signal_emit_by_name (atk_parent, "children_changed::remove", 
207                            index, atk_child, NULL);
208
209   return 1;
210 }
211
212 static void
213 gail_container_real_initialize (AtkObject *obj,
214                                 gpointer  data)
215 {
216   GailContainer *container = GAIL_CONTAINER (obj);
217
218   ATK_OBJECT_CLASS (gail_container_parent_class)->initialize (obj, data);
219
220   container->children = gtk_container_get_children (GTK_CONTAINER (data));
221
222   g_signal_connect (data, "add",
223                     G_CALLBACK (gail_container_add_gtk),
224                     obj);
225   g_signal_connect (data, "remove",
226                     G_CALLBACK (gail_container_remove_gtk),
227                     obj);
228
229   if (GTK_IS_TOOLBAR (data))
230     obj->role = ATK_ROLE_TOOL_BAR;
231   else if (GTK_IS_VIEWPORT (data))
232     obj->role = ATK_ROLE_VIEWPORT;
233   else
234     obj->role = ATK_ROLE_PANEL;
235 }
236
237 static void
238 gail_container_finalize (GObject *object)
239 {
240   GailContainer *container = GAIL_CONTAINER (object);
241
242   g_list_free (container->children);
243   G_OBJECT_CLASS (gail_container_parent_class)->finalize (object);
244 }