]> Pileus Git - ~andy/gtk/blob - gtk/a11y/gtknotebookpageaccessible.c
iconview: Split out iconview accessible
[~andy/gtk] / gtk / a11y / gtknotebookpageaccessible.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 <string.h>
23 #include <gtk/gtk.h>
24 #include "gtknotebookpageaccessible.h"
25
26
27 static void atk_component_interface_init (AtkComponentIface *iface);
28
29 G_DEFINE_TYPE_WITH_CODE (GtkNotebookPageAccessible, _gtk_notebook_page_accessible, ATK_TYPE_OBJECT,
30                          G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init))
31
32
33 static GtkWidget *
34 find_label_child (GtkContainer *container)
35 {
36   GList *children, *tmp_list;
37   GtkWidget *child;
38
39   children = gtk_container_get_children (container);
40
41   child = NULL;
42   for (tmp_list = children; tmp_list != NULL; tmp_list = tmp_list->next)
43     {
44       if (GTK_IS_LABEL (tmp_list->data))
45         {
46           child = GTK_WIDGET (tmp_list->data);
47           break;
48         }
49       else if (GTK_IS_CONTAINER (tmp_list->data))
50         {
51           child = find_label_child (GTK_CONTAINER (tmp_list->data));
52           if (child)
53             break;
54         }
55     }
56   g_list_free (children);
57
58   return child;
59 }
60
61 static GtkWidget *
62 get_label_from_notebook_page (GtkNotebookPageAccessible *page)
63 {
64   GtkWidget *child;
65   GtkNotebook *notebook;
66
67   notebook = GTK_NOTEBOOK (gtk_accessible_get_widget (page->notebook));
68   if (!notebook)
69     return NULL;
70
71   if (!gtk_notebook_get_show_tabs (notebook))
72     return NULL;
73
74   child = gtk_notebook_get_tab_label (notebook, page->child);
75
76   if (GTK_IS_LABEL (child))
77     return child;
78
79   if (GTK_IS_CONTAINER (child))
80     child = find_label_child (GTK_CONTAINER (child));
81
82   return child;
83 }
84
85 static const gchar *
86 gtk_notebook_page_accessible_get_name (AtkObject *accessible)
87 {
88   GtkWidget *label;
89
90   if (accessible->name != NULL)
91     return accessible->name;
92
93   label = get_label_from_notebook_page (GTK_NOTEBOOK_PAGE_ACCESSIBLE (accessible));
94   if (GTK_IS_LABEL (label))
95     return gtk_label_get_text (GTK_LABEL (label));
96
97   return NULL;
98 }
99
100 static AtkObject *
101 gtk_notebook_page_accessible_get_parent (AtkObject *accessible)
102 {
103   GtkNotebookPageAccessible *page;
104
105   page = GTK_NOTEBOOK_PAGE_ACCESSIBLE (accessible);
106
107   return ATK_OBJECT (page->notebook);
108 }
109
110 static gint
111 gtk_notebook_page_accessible_get_n_children (AtkObject *accessible)
112 {
113   return 1;
114 }
115
116 static AtkObject *
117 gtk_notebook_page_accessible_ref_child (AtkObject *accessible,
118                                         gint       i)
119 {
120   AtkObject *child_obj;
121   GtkNotebookPageAccessible *page = NULL;
122
123   if (i != 0)
124     return NULL;
125
126   page = GTK_NOTEBOOK_PAGE_ACCESSIBLE (accessible);
127   if (!page->child)
128     return NULL;
129
130   child_obj = gtk_widget_get_accessible (page->child);
131   g_object_ref (child_obj);
132
133   return child_obj;
134 }
135
136 static AtkStateSet *
137 gtk_notebook_page_accessible_ref_state_set (AtkObject *accessible)
138 {
139   AtkStateSet *state_set, *label_state_set, *merged_state_set;
140   AtkObject *atk_label;
141   GtkWidget *label;
142
143   state_set = ATK_OBJECT_CLASS (_gtk_notebook_page_accessible_parent_class)->ref_state_set (accessible);
144
145   label = get_label_from_notebook_page (GTK_NOTEBOOK_PAGE_ACCESSIBLE (accessible));
146   if (label)
147     {
148       atk_label = gtk_widget_get_accessible (label);
149       label_state_set = atk_object_ref_state_set (atk_label);
150       merged_state_set = atk_state_set_or_sets (state_set, label_state_set);
151       g_object_unref (label_state_set);
152       g_object_unref (state_set);
153     }
154   else
155     {
156       AtkObject *child;
157
158       child = atk_object_ref_accessible_child (accessible, 0);
159       if (!child)
160         return state_set;
161
162       merged_state_set = state_set;
163       state_set = atk_object_ref_state_set (child);
164       if (atk_state_set_contains_state (state_set, ATK_STATE_VISIBLE))
165         {
166           atk_state_set_add_state (merged_state_set, ATK_STATE_VISIBLE);
167           if (atk_state_set_contains_state (state_set, ATK_STATE_ENABLED))
168               atk_state_set_add_state (merged_state_set, ATK_STATE_ENABLED);
169           if (atk_state_set_contains_state (state_set, ATK_STATE_SHOWING))
170               atk_state_set_add_state (merged_state_set, ATK_STATE_SHOWING);
171
172         }
173       g_object_unref (state_set);
174       g_object_unref (child);
175     }
176   return merged_state_set;
177 }
178
179 static gint
180 gtk_notebook_page_accessible_get_index_in_parent (AtkObject *accessible)
181 {
182   GtkNotebookPageAccessible *page;
183
184   page = GTK_NOTEBOOK_PAGE_ACCESSIBLE (accessible);
185   if (!page->child)
186     return -1;
187
188   return gtk_notebook_page_num (GTK_NOTEBOOK (gtk_accessible_get_widget (page->notebook)),
189                                 page->child);
190 }
191
192 static void
193 _gtk_notebook_page_accessible_class_init (GtkNotebookPageAccessibleClass *klass)
194 {
195   AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
196
197   class->get_name = gtk_notebook_page_accessible_get_name;
198   class->get_parent = gtk_notebook_page_accessible_get_parent;
199   class->get_n_children = gtk_notebook_page_accessible_get_n_children;
200   class->ref_child = gtk_notebook_page_accessible_ref_child;
201   class->ref_state_set = gtk_notebook_page_accessible_ref_state_set;
202   class->get_index_in_parent = gtk_notebook_page_accessible_get_index_in_parent;
203 }
204
205 static void
206 _gtk_notebook_page_accessible_init (GtkNotebookPageAccessible *page)
207 {
208 }
209
210 static void
211 notify_tab_label (GObject    *object,
212                   GParamSpec *pspec,
213                   AtkObject  *atk_obj)
214 {
215   if (atk_obj->name == NULL)
216     g_object_notify (G_OBJECT (atk_obj), "accessible-name");
217   g_signal_emit_by_name (atk_obj, "visible-data-changed");
218 }
219
220 AtkObject *
221 _gtk_notebook_page_accessible_new (GtkNotebookAccessible *notebook,
222                                    GtkWidget             *child)
223 {
224   GObject *object;
225   AtkObject *atk_object;
226   GtkNotebookPageAccessible *page;
227
228   g_return_val_if_fail (GTK_IS_NOTEBOOK_ACCESSIBLE (notebook), NULL);
229   g_return_val_if_fail (GTK_WIDGET (child), NULL);
230
231   object = g_object_new (GTK_TYPE_NOTEBOOK_PAGE_ACCESSIBLE, NULL);
232
233   page = GTK_NOTEBOOK_PAGE_ACCESSIBLE (object);
234   page->notebook = GTK_ACCESSIBLE (notebook);
235   page->child = child;
236
237   atk_object = ATK_OBJECT (page);
238   atk_object->role = ATK_ROLE_PAGE_TAB;
239   atk_object->layer = ATK_LAYER_WIDGET;
240
241   atk_object_set_parent (gtk_widget_get_accessible (child), atk_object);
242
243   g_signal_connect (gtk_accessible_get_widget (page->notebook),
244                     "child-notify::tab-label",
245                     G_CALLBACK (notify_tab_label), page);
246
247   return atk_object;
248 }
249
250 void
251 _gtk_notebook_page_accessible_invalidate (GtkNotebookPageAccessible *page)
252 {
253   AtkObject *obj = ATK_OBJECT (page);
254   GtkWidget *notebook;
255
256   notebook = gtk_accessible_get_widget (page->notebook);
257   if (notebook)
258     g_signal_handlers_disconnect_by_func (notebook, notify_tab_label, page);
259
260   atk_object_notify_state_change (obj, ATK_STATE_DEFUNCT, TRUE);
261   atk_object_set_parent (obj, NULL);
262   page->notebook = NULL;
263   atk_object_set_parent (gtk_widget_get_accessible (page->child), NULL);
264   page->child = NULL;
265 }
266
267 static AtkObject*
268 gtk_notebook_page_accessible_ref_accessible_at_point (AtkComponent *component,
269                                                       gint          x,
270                                                       gint          y,
271                                                       AtkCoordType  coord_type)
272 {
273   /* There is only one child so we return it */
274   AtkObject* child;
275
276   child = atk_object_ref_accessible_child (ATK_OBJECT (component), 0);
277
278   return child;
279 }
280
281 static void
282 gtk_notebook_page_accessible_get_extents (AtkComponent *component,
283                                           gint         *x,
284                                           gint         *y,
285                                           gint         *width,
286                                           gint         *height,
287                                           AtkCoordType  coord_type)
288 {
289   GtkWidget *label;
290   AtkObject *atk_label;
291
292   label = get_label_from_notebook_page (GTK_NOTEBOOK_PAGE_ACCESSIBLE (component));
293   if (!label)
294     {
295       AtkObject *child;
296
297       *width = 0;
298       *height = 0;
299
300       child = atk_object_ref_accessible_child (ATK_OBJECT (component), 0);
301       if (!child)
302         return;
303
304       atk_component_get_position (ATK_COMPONENT (child), x, y, coord_type);
305       g_object_unref (child);
306     }
307   else
308     {
309       atk_label = gtk_widget_get_accessible (label);
310       atk_component_get_extents (ATK_COMPONENT (atk_label),
311                                  x, y, width, height, coord_type);
312     }
313 }
314
315 static void
316 atk_component_interface_init (AtkComponentIface *iface)
317 {
318   /* We use the default implementations for contains, get_position, get_size */
319   iface->ref_accessible_at_point = gtk_notebook_page_accessible_ref_accessible_at_point;
320   iface->get_extents = gtk_notebook_page_accessible_get_extents;
321 }