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