1 /* GTK+ - accessibility implementations
2 * Copyright 2001, 2002, 2003 Sun Microsystems Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include "gtkcontaineraccessible.h"
21 #include "gtkcontaineraccessibleprivate.h"
22
23 #include <gtk/gtk.h>
24
25 #include "gtkwidgetprivate.h"
26
27 struct _GtkContainerAccessiblePrivate
28 {
29 GList *children;
30 };
31
G_DEFINE_TYPE_WITH_PRIVATE(GtkContainerAccessible,gtk_container_accessible,GTK_TYPE_WIDGET_ACCESSIBLE)32 G_DEFINE_TYPE_WITH_PRIVATE (GtkContainerAccessible, gtk_container_accessible, GTK_TYPE_WIDGET_ACCESSIBLE)
33
34 static void
35 count_widget (GtkWidget *widget,
36 gint *count)
37 {
38 (*count)++;
39 }
40
41 static gint
gtk_container_accessible_get_n_children(AtkObject * obj)42 gtk_container_accessible_get_n_children (AtkObject* obj)
43 {
44 GtkWidget *widget;
45 gint count = 0;
46
47 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
48 if (widget == NULL)
49 return 0;
50
51 gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback) count_widget, &count);
52 return count;
53 }
54
55 static AtkObject *
gtk_container_accessible_ref_child(AtkObject * obj,gint i)56 gtk_container_accessible_ref_child (AtkObject *obj,
57 gint i)
58 {
59 GList *children, *tmp_list;
60 AtkObject *accessible;
61 GtkWidget *widget;
62
63 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
64 if (widget == NULL)
65 return NULL;
66
67 children = gtk_container_get_children (GTK_CONTAINER (widget));
68 tmp_list = g_list_nth (children, i);
69 if (!tmp_list)
70 {
71 g_list_free (children);
72 return NULL;
73 }
74 accessible = gtk_widget_get_accessible (GTK_WIDGET (tmp_list->data));
75
76 g_list_free (children);
77 g_object_ref (accessible);
78
79 return accessible;
80 }
81
82 void
_gtk_container_accessible_add(GtkWidget * parent,GtkWidget * child)83 _gtk_container_accessible_add (GtkWidget *parent,
84 GtkWidget *child)
85 {
86 GtkContainerAccessible *accessible;
87 GtkContainerAccessibleClass *klass;
88 AtkObject *obj;
89
90 obj = _gtk_widget_peek_accessible (GTK_WIDGET (parent));
91 if (!GTK_IS_CONTAINER_ACCESSIBLE (obj))
92 return;
93
94 accessible = GTK_CONTAINER_ACCESSIBLE (obj);
95 klass = GTK_CONTAINER_ACCESSIBLE_GET_CLASS (accessible);
96
97 if (klass->add_gtk)
98 klass->add_gtk (GTK_CONTAINER (parent), child, obj);
99 }
100
101 void
_gtk_container_accessible_remove(GtkWidget * parent,GtkWidget * child)102 _gtk_container_accessible_remove (GtkWidget *parent,
103 GtkWidget *child)
104 {
105 GtkContainerAccessible *accessible;
106 GtkContainerAccessibleClass *klass;
107 AtkObject *obj;
108
109 obj = _gtk_widget_peek_accessible (GTK_WIDGET (parent));
110 if (!GTK_IS_CONTAINER_ACCESSIBLE (obj))
111 return;
112
113 accessible = GTK_CONTAINER_ACCESSIBLE (obj);
114 klass = GTK_CONTAINER_ACCESSIBLE_GET_CLASS (accessible);
115
116 if (klass->remove_gtk)
117 klass->remove_gtk (GTK_CONTAINER (parent), child, obj);
118 }
119
120 static gint
gtk_container_accessible_real_add_gtk(GtkContainer * container,GtkWidget * widget,gpointer data)121 gtk_container_accessible_real_add_gtk (GtkContainer *container,
122 GtkWidget *widget,
123 gpointer data)
124 {
125 AtkObject *atk_parent;
126 AtkObject *atk_child;
127 GtkContainerAccessible *accessible;
128 gint index;
129
130 atk_parent = ATK_OBJECT (data);
131 atk_child = gtk_widget_get_accessible (widget);
132 accessible = GTK_CONTAINER_ACCESSIBLE (atk_parent);
133
134 g_list_free (accessible->priv->children);
135 accessible->priv->children = gtk_container_get_children (container);
136 index = g_list_index (accessible->priv->children, widget);
137 _gtk_container_accessible_add_child (accessible, atk_child, index);
138
139 return 1;
140 }
141
142 static gint
gtk_container_accessible_real_remove_gtk(GtkContainer * container,GtkWidget * widget,gpointer data)143 gtk_container_accessible_real_remove_gtk (GtkContainer *container,
144 GtkWidget *widget,
145 gpointer data)
146 {
147 AtkObject* atk_parent;
148 AtkObject *atk_child;
149 GtkContainerAccessible *accessible;
150 gint index;
151
152 atk_parent = ATK_OBJECT (data);
153 atk_child = _gtk_widget_peek_accessible (widget);
154 if (atk_child == NULL)
155 return 1;
156 accessible = GTK_CONTAINER_ACCESSIBLE (atk_parent);
157
158 index = g_list_index (accessible->priv->children, widget);
159 g_list_free (accessible->priv->children);
160 accessible->priv->children = gtk_container_get_children (container);
161 if (index >= 0)
162 _gtk_container_accessible_remove_child (accessible, atk_child, index);
163
164 return 1;
165 }
166
167 static void
gtk_container_accessible_real_initialize(AtkObject * obj,gpointer data)168 gtk_container_accessible_real_initialize (AtkObject *obj,
169 gpointer data)
170 {
171 GtkContainerAccessible *accessible = GTK_CONTAINER_ACCESSIBLE (obj);
172
173 ATK_OBJECT_CLASS (gtk_container_accessible_parent_class)->initialize (obj, data);
174
175 accessible->priv->children = gtk_container_get_children (GTK_CONTAINER (data));
176
177 obj->role = ATK_ROLE_PANEL;
178 }
179
180 static void
gtk_container_accessible_finalize(GObject * object)181 gtk_container_accessible_finalize (GObject *object)
182 {
183 GtkContainerAccessible *accessible = GTK_CONTAINER_ACCESSIBLE (object);
184
185 g_list_free (accessible->priv->children);
186
187 G_OBJECT_CLASS (gtk_container_accessible_parent_class)->finalize (object);
188 }
189
190 static void
gtk_container_accessible_class_init(GtkContainerAccessibleClass * klass)191 gtk_container_accessible_class_init (GtkContainerAccessibleClass *klass)
192 {
193 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
194 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
195
196 gobject_class->finalize = gtk_container_accessible_finalize;
197
198 class->get_n_children = gtk_container_accessible_get_n_children;
199 class->ref_child = gtk_container_accessible_ref_child;
200 class->initialize = gtk_container_accessible_real_initialize;
201
202 klass->add_gtk = gtk_container_accessible_real_add_gtk;
203 klass->remove_gtk = gtk_container_accessible_real_remove_gtk;
204 }
205
206 static void
gtk_container_accessible_init(GtkContainerAccessible * container)207 gtk_container_accessible_init (GtkContainerAccessible *container)
208 {
209 container->priv = gtk_container_accessible_get_instance_private (container);
210 }
211
212 void
_gtk_container_accessible_add_child(GtkContainerAccessible * accessible,AtkObject * child,gint index)213 _gtk_container_accessible_add_child (GtkContainerAccessible *accessible,
214 AtkObject *child,
215 gint index)
216 {
217 g_object_notify (G_OBJECT (child), "accessible-parent");
218 g_signal_emit_by_name (accessible, "children-changed::add", index, child, NULL);
219 }
220
221 void
_gtk_container_accessible_remove_child(GtkContainerAccessible * accessible,AtkObject * child,gint index)222 _gtk_container_accessible_remove_child (GtkContainerAccessible *accessible,
223 AtkObject *child,
224 gint index)
225 {
226 g_object_notify (G_OBJECT (child), "accessible-parent");
227 g_signal_emit_by_name (accessible, "children-changed::remove", index, child, NULL);
228 }
229