1 /* GTK+ - accessibility implementations
2 * Copyright 2001, 2002, 2003 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, see <http://www.gnu.org/licenses/>.
22 #include "gtkbuttonaccessible.h"
25 static void atk_action_interface_init (AtkActionIface *iface);
26 static void atk_image_interface_init (AtkImageIface *iface);
28 G_DEFINE_TYPE_WITH_CODE (GtkButtonAccessible, gtk_button_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE,
29 G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init)
30 G_IMPLEMENT_INTERFACE (ATK_TYPE_IMAGE, atk_image_interface_init))
33 state_changed_cb (GtkWidget *widget, GtkStateFlags previous_flags)
35 AtkObject *accessible;
40 flags = gtk_widget_get_state_flags (widget);
42 was_active = (previous_flags & GTK_STATE_FLAG_ACTIVE) != 0;
43 active = (flags & GTK_STATE_FLAG_ACTIVE) != 0;
45 accessible = gtk_widget_get_accessible (widget);
46 if (active && !was_active)
47 atk_object_notify_state_change (accessible, ATK_STATE_ARMED, TRUE);
48 else if (!active && was_active)
49 atk_object_notify_state_change (accessible, ATK_STATE_ARMED, FALSE);
53 gtk_button_accessible_initialize (AtkObject *obj,
58 ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->initialize (obj, data);
60 g_signal_connect (data, "state-flags-changed", G_CALLBACK (state_changed_cb), NULL);
62 parent = gtk_widget_get_parent (gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)));
63 if (GTK_IS_TREE_VIEW (parent))
65 /* Even though the accessible parent of the column header will
66 * be reported as the table because the parent widget of the
67 * GtkTreeViewColumn's button is the GtkTreeView we set
68 * the accessible parent for column header to be the table
69 * to ensure that atk_object_get_index_in_parent() returns
70 * the correct value; see gail_widget_get_index_in_parent().
72 atk_object_set_parent (obj, gtk_widget_get_accessible (parent));
73 obj->role = ATK_ROLE_TABLE_COLUMN_HEADER;
76 obj->role = ATK_ROLE_PUSH_BUTTON;
80 get_image_from_button (GtkWidget *button)
84 image = gtk_button_get_image (GTK_BUTTON (button));
85 if (GTK_IS_IMAGE (image))
92 find_label_child (GtkContainer *container)
94 GList *children, *tmp_list;
97 children = gtk_container_get_children (container);
100 for (tmp_list = children; tmp_list != NULL; tmp_list = tmp_list->next)
102 if (GTK_IS_LABEL (tmp_list->data))
104 child = GTK_WIDGET (tmp_list->data);
107 else if (GTK_IS_CONTAINER (tmp_list->data))
109 child = find_label_child (GTK_CONTAINER (tmp_list->data));
114 g_list_free (children);
119 get_label_from_button (GtkWidget *button)
123 child = gtk_bin_get_child (GTK_BIN (button));
124 if (GTK_IS_ALIGNMENT (child))
125 child = gtk_bin_get_child (GTK_BIN (child));
127 if (GTK_IS_CONTAINER (child))
128 child = find_label_child (GTK_CONTAINER (child));
129 else if (!GTK_IS_LABEL (child))
136 gtk_button_accessible_get_name (AtkObject *obj)
138 const gchar *name = NULL;
142 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
146 name = ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->get_name (obj);
150 child = get_label_from_button (widget);
151 if (GTK_IS_LABEL (child))
152 name = gtk_label_get_text (GTK_LABEL (child));
157 image = get_image_from_button (widget);
158 if (GTK_IS_IMAGE (image))
162 atk_obj = gtk_widget_get_accessible (image);
163 name = atk_object_get_name (atk_obj);
171 gtk_button_accessible_get_n_children (AtkObject* obj)
177 gtk_button_accessible_ref_child (AtkObject *obj,
184 gtk_button_accessible_ref_state_set (AtkObject *obj)
186 AtkStateSet *state_set;
189 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
193 state_set = ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->ref_state_set (obj);
195 if ((gtk_widget_get_state_flags (widget) & GTK_STATE_FLAG_ACTIVE) != 0)
196 atk_state_set_add_state (state_set, ATK_STATE_ARMED);
198 if (!gtk_widget_get_can_focus (widget))
199 atk_state_set_remove_state (state_set, ATK_STATE_SELECTABLE);
205 gtk_button_accessible_notify_gtk (GObject *obj,
208 GtkWidget *widget = GTK_WIDGET (obj);
209 AtkObject *atk_obj = gtk_widget_get_accessible (widget);
211 if (strcmp (pspec->name, "label") == 0)
213 if (atk_obj->name == NULL)
214 g_object_notify (G_OBJECT (atk_obj), "accessible-name");
216 g_signal_emit_by_name (atk_obj, "visible-data-changed");
219 GTK_WIDGET_ACCESSIBLE_CLASS (gtk_button_accessible_parent_class)->notify_gtk (obj, pspec);
223 gtk_button_accessible_class_init (GtkButtonAccessibleClass *klass)
225 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
226 GtkContainerAccessibleClass *container_class = (GtkContainerAccessibleClass*)klass;
227 GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
229 class->get_name = gtk_button_accessible_get_name;
230 class->get_n_children = gtk_button_accessible_get_n_children;
231 class->ref_child = gtk_button_accessible_ref_child;
232 class->ref_state_set = gtk_button_accessible_ref_state_set;
233 class->initialize = gtk_button_accessible_initialize;
235 widget_class->notify_gtk = gtk_button_accessible_notify_gtk;
237 container_class->add_gtk = NULL;
238 container_class->remove_gtk = NULL;
242 gtk_button_accessible_init (GtkButtonAccessible *button)
247 gtk_button_accessible_do_action (AtkAction *action,
252 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
259 if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_visible (widget))
262 gtk_button_clicked (GTK_BUTTON (widget));
267 gtk_button_accessible_get_n_actions (AtkAction *action)
273 gtk_button_accessible_get_keybinding (AtkAction *action,
276 gchar *return_value = NULL;
281 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
288 label = get_label_from_button (widget);
289 if (GTK_IS_LABEL (label))
291 key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
292 if (key_val != GDK_KEY_VoidSymbol)
293 return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK);
295 if (return_value == NULL)
297 /* Find labelled-by relation */
299 AtkRelation *relation;
301 gpointer target_object;
303 set = atk_object_ref_relation_set (ATK_OBJECT (action));
306 relation = atk_relation_set_get_relation_by_type (set, ATK_RELATION_LABELLED_BY);
309 target = atk_relation_get_target (relation);
310 target_object = g_ptr_array_index (target, 0);
311 label = gtk_accessible_get_widget (GTK_ACCESSIBLE (target_object));
313 g_object_unref (set);
316 if (GTK_IS_LABEL (label))
318 key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
319 if (key_val != GDK_KEY_VoidSymbol)
320 return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK);
327 gtk_button_accessible_action_get_name (AtkAction *action,
337 atk_action_interface_init (AtkActionIface *iface)
339 iface->do_action = gtk_button_accessible_do_action;
340 iface->get_n_actions = gtk_button_accessible_get_n_actions;
341 iface->get_keybinding = gtk_button_accessible_get_keybinding;
342 iface->get_name = gtk_button_accessible_action_get_name;
346 gtk_button_accessible_get_image_description (AtkImage *image)
349 GtkWidget *button_image;
352 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
356 button_image = get_image_from_button (widget);
357 if (GTK_IS_IMAGE (button_image))
359 obj = gtk_widget_get_accessible (button_image);
360 return atk_image_get_image_description (ATK_IMAGE (obj));
367 gtk_button_accessible_get_image_position (AtkImage *image,
370 AtkCoordType coord_type)
373 GtkWidget *button_image;
376 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
384 button_image = get_image_from_button (widget);
385 if (button_image != NULL)
387 obj = gtk_widget_get_accessible (button_image);
388 atk_component_get_position (ATK_COMPONENT (obj), x, y, coord_type);
398 gtk_button_accessible_get_image_size (AtkImage *image,
403 GtkWidget *button_image;
406 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
414 button_image = get_image_from_button (widget);
415 if (GTK_IS_IMAGE (button_image))
417 obj = gtk_widget_get_accessible (GTK_WIDGET (button_image));
418 atk_image_get_image_size (ATK_IMAGE (obj), width, height);
428 gtk_button_accessible_set_image_description (AtkImage *image,
429 const gchar *description)
432 GtkWidget *button_image;
435 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
440 button_image = get_image_from_button (widget);
441 if (GTK_IMAGE (button_image))
443 obj = gtk_widget_get_accessible (GTK_WIDGET (button_image));
444 return atk_image_set_image_description (ATK_IMAGE (obj), description);
451 atk_image_interface_init (AtkImageIface *iface)
453 iface->get_image_description = gtk_button_accessible_get_image_description;
454 iface->get_image_position = gtk_button_accessible_get_image_position;
455 iface->get_image_size = gtk_button_accessible_get_image_size;
456 iface->set_image_description = gtk_button_accessible_set_image_description;