]> Pileus Git - ~andy/gtk/blob - modules/other/gail/gailcontainer.c
Include "config.h" instead of <config.h> Command used: find -name
[~andy/gtk] / modules / other / gail / 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 (obj)->widget;
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   widget = GTK_ACCESSIBLE (obj)->widget;
104   if (widget == NULL)
105     return NULL;
106
107   children = gtk_container_get_children (GTK_CONTAINER (widget));
108   tmp_list = g_list_nth (children, i);
109   if (!tmp_list)
110     {
111       g_list_free (children);
112       return NULL;
113     }  
114   accessible = gtk_widget_get_accessible (GTK_WIDGET (tmp_list->data));
115
116   g_list_free (children);
117   g_object_ref (accessible);
118   return accessible; 
119 }
120
121 static gint
122 gail_container_add_gtk (GtkContainer *container,
123                         GtkWidget    *widget,
124                         gpointer     data)
125 {
126   GailContainer *gail_container = GAIL_CONTAINER (data);
127   GailContainerClass *klass;
128
129   klass = GAIL_CONTAINER_GET_CLASS (gail_container);
130
131   if (klass->add_gtk)
132     return klass->add_gtk (container, widget, data);
133   else
134     return 1;
135 }
136  
137 static gint
138 gail_container_remove_gtk (GtkContainer *container,
139                            GtkWidget    *widget,
140                            gpointer     data)
141 {
142   GailContainer *gail_container = GAIL_CONTAINER (data);
143   GailContainerClass *klass;
144
145   klass = GAIL_CONTAINER_GET_CLASS (gail_container);
146
147   if (klass->remove_gtk)
148     return klass->remove_gtk (container, widget, data);
149   else
150     return 1;
151 }
152  
153 static gint
154 gail_container_real_add_gtk (GtkContainer *container,
155                              GtkWidget    *widget,
156                              gpointer     data)
157 {
158   AtkObject* atk_parent = ATK_OBJECT (data);
159   AtkObject* atk_child = gtk_widget_get_accessible (widget);
160   GailContainer *gail_container = GAIL_CONTAINER (atk_parent);
161   gint       index;
162
163   g_object_notify (G_OBJECT (atk_child), "accessible_parent");
164
165   g_list_free (gail_container->children);
166   gail_container->children = gtk_container_get_children (container);
167   index = g_list_index (gail_container->children, widget);
168   g_signal_emit_by_name (atk_parent, "children_changed::add", 
169                          index, atk_child, NULL);
170
171   return 1;
172 }
173
174 static gint
175 gail_container_real_remove_gtk (GtkContainer       *container,
176                                 GtkWidget          *widget,
177                                 gpointer           data)
178 {
179   AtkPropertyValues values = { NULL };
180   AtkObject* atk_parent;
181   AtkObject *atk_child;
182   GailContainer *gail_container;
183   gint       index;
184
185   atk_parent = ATK_OBJECT (data);
186   atk_child = gtk_widget_get_accessible (widget);
187
188   if (atk_child)
189     {
190       g_value_init (&values.old_value, G_TYPE_POINTER);
191       g_value_set_pointer (&values.old_value, atk_parent);
192     
193       values.property_name = "accessible-parent";
194
195       g_object_ref (atk_child);
196       g_signal_emit_by_name (atk_child,
197                              "property_change::accessible-parent", &values, NULL);
198       g_object_unref (atk_child);
199     }
200   gail_container = GAIL_CONTAINER (atk_parent);
201   index = g_list_index (gail_container->children, widget);
202   g_list_free (gail_container->children);
203   gail_container->children = gtk_container_get_children (container);
204   if (index >= 0 && index <= g_list_length (gail_container->children))
205     g_signal_emit_by_name (atk_parent, "children_changed::remove", 
206                            index, atk_child, NULL);
207
208   return 1;
209 }
210
211 static void
212 gail_container_real_initialize (AtkObject *obj,
213                                 gpointer  data)
214 {
215   GailContainer *container = GAIL_CONTAINER (obj);
216   guint handler_id;
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   /*
223    * We store the handler ids for these signals in case some objects
224    * need to remove these handlers.
225    */
226   handler_id = g_signal_connect (data,
227                                  "add",
228                                  G_CALLBACK (gail_container_add_gtk),
229                                  obj);
230   g_object_set_data (G_OBJECT (obj), "gail-add-handler-id", 
231                      GUINT_TO_POINTER (handler_id));
232   handler_id = g_signal_connect (data,
233                                  "remove",
234                                  G_CALLBACK (gail_container_remove_gtk),
235                                  obj);
236   g_object_set_data (G_OBJECT (obj), "gail-remove-handler-id", 
237                      GUINT_TO_POINTER (handler_id));
238
239   if (GTK_IS_TOOLBAR (data))
240     obj->role = ATK_ROLE_TOOL_BAR;
241   else if (GTK_IS_VIEWPORT (data))
242     obj->role = ATK_ROLE_VIEWPORT;
243   else
244     obj->role = ATK_ROLE_PANEL;
245 }
246
247 static void
248 gail_container_finalize (GObject *object)
249 {
250   GailContainer *container = GAIL_CONTAINER (object);
251
252   g_list_free (container->children);
253   G_OBJECT_CLASS (gail_container_parent_class)->finalize (object);
254 }