1 /* GAIL - The GNOME Accessibility Implementation Library
2 * Copyright 2004 Sun Microsystems Inc.
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.
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.
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.
21 #include <gdk/gdkkeysyms.h>
22 #include "gailcombobox.h"
24 static void gail_combo_box_class_init (GailComboBoxClass *klass);
25 static void gail_combo_box_init (GailComboBox *combo_box);
26 static void gail_combo_box_real_initialize (AtkObject *obj,
29 static void gail_combo_box_changed_gtk (GtkWidget *widget);
31 static G_CONST_RETURN gchar* gail_combo_box_get_name (AtkObject *obj);
32 static gint gail_combo_box_get_n_children (AtkObject *obj);
33 static AtkObject* gail_combo_box_ref_child (AtkObject *obj,
35 static void gail_combo_box_finalize (GObject *object);
36 static void atk_action_interface_init (AtkActionIface *iface);
38 static gboolean gail_combo_box_do_action (AtkAction *action,
40 static gboolean idle_do_action (gpointer data);
41 static gint gail_combo_box_get_n_actions (AtkAction *action);
42 static G_CONST_RETURN gchar* gail_combo_box_get_description(AtkAction *action,
44 static G_CONST_RETURN gchar* gail_combo_box_get_keybinding (AtkAction *action,
46 static G_CONST_RETURN gchar* gail_combo_box_action_get_name(AtkAction *action,
48 static gboolean gail_combo_box_set_description(AtkAction *action,
51 static void atk_selection_interface_init (AtkSelectionIface *iface);
52 static gboolean gail_combo_box_add_selection (AtkSelection *selection,
54 static gboolean gail_combo_box_clear_selection (AtkSelection *selection);
55 static AtkObject* gail_combo_box_ref_selection (AtkSelection *selection,
57 static gint gail_combo_box_get_selection_count (AtkSelection *selection);
58 static gboolean gail_combo_box_is_child_selected (AtkSelection *selection,
60 static gboolean gail_combo_box_remove_selection (AtkSelection *selection,
63 G_DEFINE_TYPE_WITH_CODE (GailComboBox, gail_combo_box, GAIL_TYPE_CONTAINER,
64 G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init)
65 G_IMPLEMENT_INTERFACE (ATK_TYPE_SELECTION, atk_selection_interface_init))
68 gail_combo_box_class_init (GailComboBoxClass *klass)
70 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
71 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
73 gobject_class->finalize = gail_combo_box_finalize;
75 class->get_name = gail_combo_box_get_name;
76 class->get_n_children = gail_combo_box_get_n_children;
77 class->ref_child = gail_combo_box_ref_child;
78 class->initialize = gail_combo_box_real_initialize;
82 gail_combo_box_init (GailComboBox *combo_box)
84 combo_box->press_description = NULL;
85 combo_box->press_keybinding = NULL;
86 combo_box->old_selection = -1;
87 combo_box->name = NULL;
88 combo_box->popup_set = FALSE;
92 gail_combo_box_new (GtkWidget *widget)
95 AtkObject *accessible;
97 g_return_val_if_fail (GTK_IS_COMBO_BOX (widget), NULL);
99 object = g_object_new (GAIL_TYPE_COMBO_BOX, NULL);
101 accessible = ATK_OBJECT (object);
102 atk_object_initialize (accessible, widget);
108 gail_combo_box_real_initialize (AtkObject *obj,
111 GtkComboBox *combo_box;
112 GailComboBox *gail_combo_box;
115 ATK_OBJECT_CLASS (gail_combo_box_parent_class)->initialize (obj, data);
117 combo_box = GTK_COMBO_BOX (data);
119 gail_combo_box = GAIL_COMBO_BOX (obj);
121 g_signal_connect (combo_box,
123 G_CALLBACK (gail_combo_box_changed_gtk),
125 gail_combo_box->old_selection = gtk_combo_box_get_active (combo_box);
127 popup = gtk_combo_box_get_popup_accessible (combo_box);
130 atk_object_set_parent (popup, obj);
131 gail_combo_box->popup_set = TRUE;
133 if (GTK_IS_COMBO_BOX_ENTRY (combo_box))
134 atk_object_set_parent (gtk_widget_get_accessible (gtk_bin_get_child (GTK_BIN (combo_box))), obj);
136 obj->role = ATK_ROLE_COMBO_BOX;
140 gail_combo_box_changed_gtk (GtkWidget *widget)
142 GtkComboBox *combo_box;
144 GailComboBox *gail_combo_box;
147 combo_box = GTK_COMBO_BOX (widget);
149 index = gtk_combo_box_get_active (combo_box);
150 obj = gtk_widget_get_accessible (widget);
151 gail_combo_box = GAIL_COMBO_BOX (obj);
152 if (gail_combo_box->old_selection != index)
154 gail_combo_box->old_selection = index;
155 g_signal_emit_by_name (obj, "selection_changed");
159 static G_CONST_RETURN gchar*
160 gail_combo_box_get_name (AtkObject *obj)
163 GtkComboBox *combo_box;
164 GailComboBox *gail_combo_box;
166 G_CONST_RETURN gchar *name;
171 g_return_val_if_fail (GAIL_IS_COMBO_BOX (obj), NULL);
173 name = ATK_OBJECT_CLASS (gail_combo_box_parent_class)->get_name (obj);
177 widget = GTK_ACCESSIBLE (obj)->widget;
184 combo_box = GTK_COMBO_BOX (widget);
185 gail_combo_box = GAIL_COMBO_BOX (obj);
186 if (gtk_combo_box_get_active_iter (combo_box, &iter))
188 model = gtk_combo_box_get_model (combo_box);
189 n_columns = gtk_tree_model_get_n_columns (model);
190 for (i = 0; i < n_columns; i++)
192 GValue value = { 0, };
194 gtk_tree_model_get_value (model, &iter, i, &value);
195 if (G_VALUE_HOLDS_STRING (&value))
197 if (gail_combo_box->name) g_free (gail_combo_box->name);
198 gail_combo_box->name = g_strdup ((gchar *)
199 g_value_get_string (&value));
200 g_value_unset (&value);
204 g_value_unset (&value);
207 return gail_combo_box->name;
211 * The children of a GailComboBox are the list of items and the entry field
215 gail_combo_box_get_n_children (AtkObject* obj)
220 g_return_val_if_fail (GAIL_IS_COMBO_BOX (obj), 0);
222 widget = GTK_ACCESSIBLE (obj)->widget;
230 if (GTK_IS_COMBO_BOX_ENTRY (widget))
237 gail_combo_box_ref_child (AtkObject *obj,
244 g_return_val_if_fail (GAIL_IS_COMBO_BOX (obj), NULL);
246 widget = GTK_ACCESSIBLE (obj)->widget;
256 child = gtk_combo_box_get_popup_accessible (GTK_COMBO_BOX (widget));
257 box = GAIL_COMBO_BOX (obj);
258 if (box->popup_set == FALSE)
260 atk_object_set_parent (child, obj);
261 box->popup_set = TRUE;
264 else if (i == 1 && GTK_IS_COMBO_BOX_ENTRY (widget))
266 child = gtk_widget_get_accessible (gtk_bin_get_child (GTK_BIN (widget)));
272 return g_object_ref (child);
276 atk_action_interface_init (AtkActionIface *iface)
278 iface->do_action = gail_combo_box_do_action;
279 iface->get_n_actions = gail_combo_box_get_n_actions;
280 iface->get_description = gail_combo_box_get_description;
281 iface->get_keybinding = gail_combo_box_get_keybinding;
282 iface->get_name = gail_combo_box_action_get_name;
283 iface->set_description = gail_combo_box_set_description;
287 gail_combo_box_do_action (AtkAction *action,
290 GailComboBox *combo_box;
293 widget = GTK_ACCESSIBLE (action)->widget;
300 if (!GTK_WIDGET_SENSITIVE (widget) || !GTK_WIDGET_VISIBLE (widget))
303 combo_box = GAIL_COMBO_BOX (action);
306 if (combo_box->action_idle_handler)
309 combo_box->action_idle_handler = gdk_threads_add_idle (idle_do_action, combo_box);
317 idle_do_action (gpointer data)
319 GtkComboBox *combo_box;
321 GailComboBox *gail_combo_box;
325 gail_combo_box = GAIL_COMBO_BOX (data);
326 gail_combo_box->action_idle_handler = 0;
327 widget = GTK_ACCESSIBLE (gail_combo_box)->widget;
328 if (widget == NULL || /* State is defunct */
329 !GTK_WIDGET_SENSITIVE (widget) || !GTK_WIDGET_VISIBLE (widget))
332 combo_box = GTK_COMBO_BOX (widget);
334 popup = gtk_combo_box_get_popup_accessible (combo_box);
335 do_popup = !GTK_WIDGET_MAPPED (GTK_ACCESSIBLE (popup)->widget);
337 gtk_combo_box_popup (combo_box);
339 gtk_combo_box_popdown (combo_box);
345 gail_combo_box_get_n_actions (AtkAction *action)
348 * The default behavior of a combo_box box is to have one action -
353 static G_CONST_RETURN gchar*
354 gail_combo_box_get_description (AtkAction *action,
359 GailComboBox *combo_box;
361 combo_box = GAIL_COMBO_BOX (action);
362 return combo_box->press_description;
368 static G_CONST_RETURN gchar*
369 gail_combo_box_get_keybinding (AtkAction *action,
372 GailComboBox *combo_box;
373 gchar *return_value = NULL;
374 combo_box = GAIL_COMBO_BOX (action);
382 AtkRelation *relation;
384 gpointer target_object;
387 combo_box = GAIL_COMBO_BOX (action);
388 widget = GTK_ACCESSIBLE (combo_box)->widget;
391 set = atk_object_ref_relation_set (ATK_OBJECT (action));
395 relation = atk_relation_set_get_relation_by_type (set, ATK_RELATION_LABELLED_BY);
398 target = atk_relation_get_target (relation);
399 target_object = g_ptr_array_index (target, 0);
400 if (GTK_IS_ACCESSIBLE (target_object))
402 label = GTK_ACCESSIBLE (target_object)->widget;
405 g_object_unref (set);
406 if (GTK_IS_LABEL (label))
408 key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
409 if (key_val != GDK_VoidSymbol)
410 return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK);
412 g_free (combo_box->press_keybinding);
413 combo_box->press_keybinding = return_value;
422 static G_CONST_RETURN gchar*
423 gail_combo_box_action_get_name (AtkAction *action,
433 gail_combo_box_set_description (AtkAction *action,
439 GailComboBox *combo_box;
441 combo_box = GAIL_COMBO_BOX (action);
442 g_free (combo_box->press_description);
443 combo_box->press_description = g_strdup (desc);
451 atk_selection_interface_init (AtkSelectionIface *iface)
453 iface->add_selection = gail_combo_box_add_selection;
454 iface->clear_selection = gail_combo_box_clear_selection;
455 iface->ref_selection = gail_combo_box_ref_selection;
456 iface->get_selection_count = gail_combo_box_get_selection_count;
457 iface->is_child_selected = gail_combo_box_is_child_selected;
458 iface->remove_selection = gail_combo_box_remove_selection;
460 * select_all_selection does not make sense for a combo_box
461 * so no implementation is provided.
466 gail_combo_box_add_selection (AtkSelection *selection,
469 GtkComboBox *combo_box;
472 widget = GTK_ACCESSIBLE (selection)->widget;
479 combo_box = GTK_COMBO_BOX (widget);
481 gtk_combo_box_set_active (combo_box, i);
486 gail_combo_box_clear_selection (AtkSelection *selection)
488 GtkComboBox *combo_box;
491 widget = GTK_ACCESSIBLE (selection)->widget;
498 combo_box = GTK_COMBO_BOX (widget);
500 gtk_combo_box_set_active (combo_box, -1);
505 gail_combo_box_ref_selection (AtkSelection *selection,
508 GtkComboBox *combo_box;
513 widget = GTK_ACCESSIBLE (selection)->widget;
520 combo_box = GTK_COMBO_BOX (widget);
523 * A combo_box box can have only one selection.
528 obj = gtk_combo_box_get_popup_accessible (combo_box);
529 index = gtk_combo_box_get_active (combo_box);
530 return atk_object_ref_accessible_child (obj, index);
534 gail_combo_box_get_selection_count (AtkSelection *selection)
536 GtkComboBox *combo_box;
539 widget = GTK_ACCESSIBLE (selection)->widget;
546 combo_box = GTK_COMBO_BOX (widget);
548 return (gtk_combo_box_get_active (combo_box) == -1) ? 0 : 1;
552 gail_combo_box_is_child_selected (AtkSelection *selection,
555 GtkComboBox *combo_box;
559 widget = GTK_ACCESSIBLE (selection)->widget;
566 combo_box = GTK_COMBO_BOX (widget);
568 j = gtk_combo_box_get_active (combo_box);
574 gail_combo_box_remove_selection (AtkSelection *selection,
577 if (atk_selection_is_child_selected (selection, i))
578 atk_selection_clear_selection (selection);
584 gail_combo_box_finalize (GObject *object)
586 GailComboBox *combo_box = GAIL_COMBO_BOX (object);
588 g_free (combo_box->press_description);
589 g_free (combo_box->press_keybinding);
590 g_free (combo_box->name);
591 if (combo_box->action_idle_handler)
593 g_source_remove (combo_box->action_idle_handler);
594 combo_box->action_idle_handler = 0;
596 G_OBJECT_CLASS (gail_combo_box_parent_class)->finalize (object);