]> Pileus Git - ~andy/gtk/blob - gtk/a11y/gtksubmenuitemaccessible.c
a11y: Rename checksubmenuitem to checkmenuitem
[~andy/gtk] / gtk / a11y / gtksubmenuitemaccessible.c
1 /* GAIL - The GNOME Accessibility Implementation Library
2  * Copyright 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 "gtksubmenuitemaccessible.h"
24
25 static gint menu_item_add_gtk    (GtkContainer   *container,
26                                   GtkWidget      *widget);
27 static gint menu_item_remove_gtk (GtkContainer   *container,
28                                   GtkWidget      *widget);
29
30 static void atk_selection_interface_init (AtkSelectionIface *iface);
31
32 G_DEFINE_TYPE_WITH_CODE (GtkSubmenuItemAccessible, _gtk_submenu_item_accessible, GTK_TYPE_MENU_ITEM_ACCESSIBLE,
33                          G_IMPLEMENT_INTERFACE (ATK_TYPE_SELECTION, atk_selection_interface_init))
34
35 static void
36 gtk_submenu_item_accessible_initialize (AtkObject *obj,
37                                         gpointer   data)
38 {
39   GtkWidget *submenu;
40
41   ATK_OBJECT_CLASS (_gtk_submenu_item_accessible_parent_class)->initialize (obj, data);
42
43   submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (data));
44   if (submenu)
45     {
46       g_signal_connect (submenu, "add", G_CALLBACK (menu_item_add_gtk), NULL);
47       g_signal_connect (submenu, "remove", G_CALLBACK (menu_item_remove_gtk), NULL);
48     }
49 }
50
51 static void
52 _gtk_submenu_item_accessible_class_init (GtkSubmenuItemAccessibleClass *klass)
53 {
54   AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
55
56   class->initialize = gtk_submenu_item_accessible_initialize;
57 }
58
59 static void
60 _gtk_submenu_item_accessible_init (GtkSubmenuItemAccessible *item)
61 {
62 }
63
64 static gboolean
65 gtk_submenu_item_accessible_add_selection (AtkSelection *selection,
66                                            gint          i)
67 {
68   GtkMenuShell *shell;
69   GList *kids;
70   guint length;
71   GtkWidget *widget;
72   GtkWidget *submenu;
73   GtkWidget *child;
74
75   widget =  gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
76   if (widget == NULL)
77     return FALSE;
78
79   submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
80   if (submenu == NULL)
81     return FALSE;
82
83   shell = GTK_MENU_SHELL (submenu);
84   kids = gtk_container_get_children (GTK_CONTAINER (shell));
85   length = g_list_length (kids);
86   if (i < 0 || i > length)
87     {
88       g_list_free (kids);
89       return FALSE;
90     }
91
92   child = g_list_nth_data (kids, i);
93   g_list_free (kids);
94   g_return_val_if_fail (GTK_IS_MENU_ITEM (child), FALSE);
95   gtk_menu_shell_select_item (shell, GTK_WIDGET (child));
96   return TRUE;
97 }
98
99 static gboolean
100 gtk_submenu_item_accessible_clear_selection (AtkSelection *selection)
101 {
102   GtkWidget *widget;
103   GtkWidget *submenu;
104
105   widget =  gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
106   if (widget == NULL)
107     return FALSE;
108
109   submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
110   if (submenu == NULL)
111     return FALSE;
112
113   gtk_menu_shell_deselect (GTK_MENU_SHELL (submenu));
114
115   return TRUE;
116 }
117
118 static AtkObject *
119 gtk_submenu_item_accessible_ref_selection (AtkSelection *selection,
120                                            gint          i)
121 {
122   GtkMenuShell *shell;
123   AtkObject *obj;
124   GtkWidget *widget;
125   GtkWidget *submenu;
126   GtkWidget *item;
127
128   if (i != 0)
129     return NULL;
130
131   widget =  gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
132   if (widget == NULL)
133     return NULL;
134
135   submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
136   if (submenu == NULL)
137     return NULL;
138
139   shell = GTK_MENU_SHELL (submenu);
140
141   item = gtk_menu_shell_get_selected_item (shell);
142   if (item != NULL)
143     {
144       obj = gtk_widget_get_accessible (item);
145       g_object_ref (obj);
146       return obj;
147     }
148
149   return NULL;
150 }
151
152 static gint
153 gtk_submenu_item_accessible_get_selection_count (AtkSelection *selection)
154 {
155   GtkMenuShell *shell;
156   GtkWidget *widget;
157   GtkWidget *submenu;
158
159   widget =  gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
160   if (widget == NULL)
161     return 0;
162
163   submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
164   if (submenu == NULL)
165     return 0;
166
167   shell = GTK_MENU_SHELL (submenu);
168
169   if (gtk_menu_shell_get_selected_item (shell) != NULL)
170     return 1;
171
172   return 0;
173 }
174
175 static gboolean
176 gtk_submenu_item_accessible_is_child_selected (AtkSelection *selection,
177                                                gint          i)
178 {
179   GtkMenuShell *shell;
180   gint j;
181   GtkWidget *widget;
182   GtkWidget *submenu;
183   GtkWidget *item;
184   GList *kids;
185
186   widget =  gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
187   if (widget == NULL)
188     return FALSE;
189
190   submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
191   if (submenu == NULL)
192     return FALSE;
193
194   shell = GTK_MENU_SHELL (submenu);
195
196   item = gtk_menu_shell_get_selected_item (shell);
197   if (item == NULL)
198     return FALSE;
199
200   kids = gtk_container_get_children (GTK_CONTAINER (shell));
201   j = g_list_index (kids, item);
202   g_list_free (kids);
203
204   return j==i;
205 }
206
207 static gboolean
208 gtk_submenu_item_accessible_remove_selection (AtkSelection *selection,
209                                               gint          i)
210 {
211   GtkMenuShell *shell;
212   GtkWidget *widget;
213   GtkWidget *submenu;
214   GtkWidget *item;
215
216   if (i != 0)
217     return FALSE;
218
219   widget =  gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
220   if (widget == NULL)
221     return FALSE;
222
223   submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
224   if (submenu == NULL)
225     return FALSE;
226
227   shell = GTK_MENU_SHELL (submenu);
228
229   item = gtk_menu_shell_get_selected_item (shell);
230   if (item && gtk_menu_item_get_submenu (GTK_MENU_ITEM (item)))
231     gtk_menu_shell_deselect (shell);
232
233   return TRUE;
234 }
235
236 static void
237 atk_selection_interface_init (AtkSelectionIface *iface)
238 {
239   iface->add_selection = gtk_submenu_item_accessible_add_selection;
240   iface->clear_selection = gtk_submenu_item_accessible_clear_selection;
241   iface->ref_selection = gtk_submenu_item_accessible_ref_selection;
242   iface->get_selection_count = gtk_submenu_item_accessible_get_selection_count;
243   iface->is_child_selected = gtk_submenu_item_accessible_is_child_selected;
244   iface->remove_selection = gtk_submenu_item_accessible_remove_selection;
245 }
246
247 static gint
248 menu_item_add_gtk (GtkContainer *container,
249                    GtkWidget    *widget)
250 {
251   GtkWidget *parent_widget;
252   AtkObject *atk_parent;
253   AtkObject *atk_child;
254   GtkContainerAccessible *container_accessible;
255   gint index;
256
257   g_return_val_if_fail (GTK_IS_MENU (container), 1);
258
259   parent_widget = gtk_menu_get_attach_widget (GTK_MENU (container));
260   if (GTK_IS_MENU_ITEM (parent_widget))
261     {
262       atk_parent = gtk_widget_get_accessible (parent_widget);
263       atk_child = gtk_widget_get_accessible (widget);
264
265       g_object_notify (G_OBJECT (atk_child), "accessible-parent");
266       container_accessible = GTK_CONTAINER_ACCESSIBLE (atk_parent);
267       g_list_free (container_accessible->children);
268       container_accessible->children = gtk_container_get_children (container);
269       index = g_list_index (container_accessible->children, widget);
270       g_signal_emit_by_name (atk_parent, "children-changed::add",
271                              index, atk_child, NULL);
272     }
273   return 1;
274 }
275
276 static gint
277 menu_item_remove_gtk (GtkContainer *container,
278                       GtkWidget    *widget)
279 {
280   GtkWidget *parent_widget;
281   AtkObject *atk_parent;
282   AtkObject *atk_child;
283   GtkContainerAccessible *container_accessible;
284   gint index;
285   gint list_length;
286
287   g_return_val_if_fail (GTK_IS_MENU (container), 1);
288
289   parent_widget = gtk_menu_get_attach_widget (GTK_MENU (container));
290   if (GTK_IS_MENU_ITEM (parent_widget))
291     {
292       atk_parent = gtk_widget_get_accessible (parent_widget);
293       atk_child = gtk_widget_get_accessible (widget);
294
295       g_object_notify (G_OBJECT (atk_child), "accessible-parent");
296
297       container_accessible = GTK_CONTAINER_ACCESSIBLE (atk_parent);
298       index = g_list_index (container_accessible->children, widget);
299       list_length = g_list_length (container_accessible->children);
300       g_list_free (container_accessible->children);
301       container_accessible->children = gtk_container_get_children (container);
302       if (index >= 0 && index <= list_length)
303         g_signal_emit_by_name (atk_parent, "children-changed::remove",
304                                index, atk_child, NULL);
305     }
306   return 1;
307 }