]> Pileus Git - ~andy/gtk/blob - modules/other/gail/gailoptionmenu.c
Deprecate widget flag: GTK_WIDGET_VISIBLE
[~andy/gtk] / modules / other / gail / gailoptionmenu.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
24 #undef GTK_DISABLE_DEPRECATED
25
26 #include <gtk/gtk.h>
27 #include <gdk/gdkkeysyms.h>
28
29 #include "gailoptionmenu.h"
30
31 static void                  gail_option_menu_class_init       (GailOptionMenuClass *klass);
32 static void                  gail_option_menu_init             (GailOptionMenu  *menu);
33 static void                  gail_option_menu_real_initialize  (AtkObject       *obj,
34                                                                 gpointer        data);
35
36 static gint                  gail_option_menu_get_n_children   (AtkObject       *obj);
37 static AtkObject*            gail_option_menu_ref_child        (AtkObject       *obj,
38                                                                 gint            i);
39 static gint                  gail_option_menu_real_add_gtk     (GtkContainer    *container,
40                                                                 GtkWidget       *widget,
41                                                                 gpointer        data);
42 static gint                  gail_option_menu_real_remove_gtk  (GtkContainer    *container,
43                                                                 GtkWidget       *widget,
44                                                                 gpointer        data);
45
46
47 static void                  atk_action_interface_init         (AtkActionIface  *iface);
48
49 static gboolean              gail_option_menu_do_action        (AtkAction       *action,
50                                                                 gint            i);
51 static gboolean              idle_do_action                    (gpointer        data);
52 static gint                  gail_option_menu_get_n_actions    (AtkAction       *action);
53 static G_CONST_RETURN gchar* gail_option_menu_get_description  (AtkAction       *action,
54                                                                 gint            i);
55 static G_CONST_RETURN gchar* gail_option_menu_action_get_name  (AtkAction       *action,
56                                                                 gint            i);
57 static gboolean              gail_option_menu_set_description  (AtkAction       *action,
58                                                                 gint            i,
59                                                                 const gchar     *desc);
60 static void                  gail_option_menu_changed          (GtkOptionMenu   *option_menu);
61
62 G_DEFINE_TYPE_WITH_CODE (GailOptionMenu, gail_option_menu, GAIL_TYPE_BUTTON,
63                          G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init))
64
65 static void
66 gail_option_menu_class_init (GailOptionMenuClass *klass)
67 {
68   AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
69   GailContainerClass *container_class;
70
71   container_class = (GailContainerClass *) klass;
72
73   class->get_n_children = gail_option_menu_get_n_children;
74   class->ref_child = gail_option_menu_ref_child;
75   class->initialize = gail_option_menu_real_initialize;
76
77   container_class->add_gtk = gail_option_menu_real_add_gtk;
78   container_class->remove_gtk = gail_option_menu_real_remove_gtk;
79 }
80
81 static void
82 gail_option_menu_init (GailOptionMenu  *menu)
83 {
84 }
85
86 static void
87 gail_option_menu_real_initialize (AtkObject *obj,
88                                   gpointer  data)
89 {
90   GtkOptionMenu *option_menu;
91
92   ATK_OBJECT_CLASS (gail_option_menu_parent_class)->initialize (obj, data);
93
94   option_menu = GTK_OPTION_MENU (data);
95
96   g_signal_connect (option_menu, "changed",
97                     G_CALLBACK (gail_option_menu_changed), NULL);
98
99   obj->role = ATK_ROLE_COMBO_BOX;
100 }
101
102 static gint
103 gail_option_menu_get_n_children (AtkObject *obj)
104 {
105   GtkWidget *widget;
106   GtkOptionMenu *option_menu;
107   gint n_children = 0;
108
109   g_return_val_if_fail (GAIL_IS_OPTION_MENU (obj), 0);
110
111   widget = GTK_ACCESSIBLE (obj)->widget;
112   if (widget == NULL)
113     /*
114      * State is defunct
115      */
116     return 0;
117
118   option_menu = GTK_OPTION_MENU (widget);
119   if (gtk_option_menu_get_menu (option_menu))
120       n_children++;
121
122   return n_children;;
123 }
124
125 static AtkObject*
126 gail_option_menu_ref_child (AtkObject *obj,
127                             gint      i)
128 {
129   GtkWidget *widget;
130   AtkObject *accessible;
131
132   g_return_val_if_fail (GAIL_IS_OPTION_MENU (obj), NULL);
133
134   widget = GTK_ACCESSIBLE (obj)->widget;
135   if (widget == NULL)
136     /*
137      * State is defunct
138      */
139     return NULL;
140
141
142   if (i == 0)
143     accessible = g_object_ref (gtk_widget_get_accessible (gtk_option_menu_get_menu (GTK_OPTION_MENU (widget))));
144    else
145     accessible = NULL;
146
147   return accessible;
148 }
149
150 static gint
151 gail_option_menu_real_add_gtk (GtkContainer *container,
152                                GtkWidget    *widget,
153                                gpointer     data)
154 {
155   AtkObject* atk_parent = ATK_OBJECT (data);
156   AtkObject* atk_child = gtk_widget_get_accessible (widget);
157
158   GAIL_CONTAINER_CLASS (gail_option_menu_parent_class)->add_gtk (container, widget, data);
159
160   g_object_notify (G_OBJECT (atk_child), "accessible_parent");
161
162   g_signal_emit_by_name (atk_parent, "children_changed::add",
163                          1, atk_child, NULL);
164
165   return 1;
166 }
167
168 static gint 
169 gail_option_menu_real_remove_gtk (GtkContainer *container,
170                                   GtkWidget    *widget,
171                                   gpointer     data)
172 {
173   AtkPropertyValues values = { NULL };
174   AtkObject* atk_parent = ATK_OBJECT (data);
175   AtkObject *atk_child = gtk_widget_get_accessible (widget);
176
177   g_value_init (&values.old_value, G_TYPE_POINTER);
178   g_value_set_pointer (&values.old_value, atk_parent);
179
180   values.property_name = "accessible-parent";
181   g_signal_emit_by_name (atk_child,
182                          "property_change::accessible-parent", &values, NULL);
183   g_signal_emit_by_name (atk_parent, "children_changed::remove",
184                          1, atk_child, NULL);
185
186   return 1;
187 }
188
189 static void
190 atk_action_interface_init (AtkActionIface *iface)
191 {
192   iface->do_action = gail_option_menu_do_action;
193   iface->get_n_actions = gail_option_menu_get_n_actions;
194   iface->get_description = gail_option_menu_get_description;
195   iface->get_name = gail_option_menu_action_get_name;
196   iface->set_description = gail_option_menu_set_description;
197 }
198
199 static gboolean
200 gail_option_menu_do_action (AtkAction *action,
201                             gint      i)
202 {
203   GtkWidget *widget;
204   GailButton *button; 
205   gboolean return_value = TRUE;
206
207   button = GAIL_BUTTON (action);
208   widget = GTK_ACCESSIBLE (action)->widget;
209   if (widget == NULL)
210     /*
211      * State is defunct
212      */
213     return FALSE;
214
215   if (!gtk_widget_get_sensitive (widget) || !gtk_widget_get_visible (widget))
216     return FALSE;
217
218   switch (i)
219     {
220     case 0:
221       if (button->action_idle_handler)
222         return_value = FALSE;
223       else
224         button->action_idle_handler = gdk_threads_add_idle (idle_do_action, button);
225       break;
226     default:
227       return_value = FALSE;
228       break;
229     }
230   return return_value; 
231 }
232
233 static gboolean 
234 idle_do_action (gpointer data)
235 {
236   GtkButton *button; 
237   GtkWidget *widget;
238   GdkEvent tmp_event;
239   GailButton *gail_button;
240
241   gail_button = GAIL_BUTTON (data);
242   gail_button->action_idle_handler = 0;
243
244   widget = GTK_ACCESSIBLE (gail_button)->widget;
245   if (widget == NULL /* State is defunct */ ||
246       !gtk_widget_get_sensitive (widget) || !gtk_widget_get_visible (widget))
247     return FALSE;
248
249   button = GTK_BUTTON (widget); 
250
251   button->in_button = TRUE;
252   g_signal_emit_by_name (button, "enter");
253   /*
254    * Simulate a button press event. calling gtk_button_pressed() does
255    * not get the job done for a GtkOptionMenu.  
256    */
257   tmp_event.button.type = GDK_BUTTON_PRESS;
258   tmp_event.button.window = widget->window;
259   tmp_event.button.button = 1;
260   tmp_event.button.send_event = TRUE;
261   tmp_event.button.time = GDK_CURRENT_TIME;
262   tmp_event.button.axes = NULL;
263
264   gtk_widget_event (widget, &tmp_event);
265
266   return FALSE;
267 }
268
269 static gint
270 gail_option_menu_get_n_actions (AtkAction *action)
271 {
272   return 1;
273 }
274
275 static G_CONST_RETURN gchar*
276 gail_option_menu_get_description (AtkAction *action,
277                                   gint      i)
278 {
279   GailButton *button;
280   G_CONST_RETURN gchar *return_value;
281
282   button = GAIL_BUTTON (action);
283
284   switch (i)
285     {
286     case 0:
287       return_value = button->press_description;
288       break;
289     default:
290       return_value = NULL;
291       break;
292     }
293   return return_value; 
294 }
295
296 static G_CONST_RETURN gchar*
297 gail_option_menu_action_get_name (AtkAction *action,
298                                   gint      i)
299 {
300   G_CONST_RETURN gchar *return_value;
301
302   switch (i)
303     {
304     case 0:
305       /*
306        * This action simulates a button press by simulating moving the
307        * mouse into the button followed by pressing the left mouse button.
308        */
309       return_value = "press";
310       break;
311     default:
312       return_value = NULL;
313       break;
314   }
315   return return_value; 
316 }
317
318 static gboolean
319 gail_option_menu_set_description (AtkAction      *action,
320                                   gint           i,
321                                   const gchar    *desc)
322 {
323   GailButton *button;
324   gchar **value;
325
326   button = GAIL_BUTTON (action);
327
328   switch (i)
329     {
330     case 0:
331       value = &button->press_description;
332       break;
333     default:
334       value = NULL;
335       break;
336     }
337
338   if (value)
339     {
340       g_free (*value);
341       *value = g_strdup (desc);
342       return TRUE;
343     }
344   else
345     return FALSE;
346 }
347
348 static void
349 gail_option_menu_changed (GtkOptionMenu   *option_menu)
350 {
351   GailOptionMenu *gail_option_menu;
352
353   gail_option_menu = GAIL_OPTION_MENU (gtk_widget_get_accessible (GTK_WIDGET (option_menu)));
354   g_object_notify (G_OBJECT (gail_option_menu), "accessible-name");
355 }
356