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