1 /* GAIL - The GNOME Accessibility Implementation Library
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, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
24 #include "gtkbuttonaccessible.h"
25 #include <libgail-util/gailmisc.h>
28 static void atk_action_interface_init (AtkActionIface *iface);
29 static void atk_image_interface_init (AtkImageIface *iface);
31 G_DEFINE_TYPE_WITH_CODE (GtkButtonAccessible, gtk_button_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE,
32 G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init)
33 G_IMPLEMENT_INTERFACE (ATK_TYPE_IMAGE, atk_image_interface_init))
36 state_changed_cb (GtkWidget *widget, GtkStateFlags previous_flags)
38 AtkObject *accessible;
43 flags = gtk_widget_get_state_flags (widget);
45 was_active = (previous_flags & GTK_STATE_FLAG_ACTIVE) != 0;
46 active = (flags & GTK_STATE_FLAG_ACTIVE) != 0;
48 accessible = gtk_widget_get_accessible (widget);
49 if (active && !was_active)
50 atk_object_notify_state_change (accessible, ATK_STATE_ARMED, TRUE);
51 else if (!active && was_active)
52 atk_object_notify_state_change (accessible, ATK_STATE_ARMED, FALSE);
56 gtk_button_accessible_initialize (AtkObject *obj,
61 ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->initialize (obj, data);
63 g_signal_connect (data, "state-flags-changed", G_CALLBACK (state_changed_cb), NULL);
65 parent = gtk_widget_get_parent (gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)));
66 if (GTK_IS_TREE_VIEW (parent))
68 /* Even though the accessible parent of the column header will
69 * be reported as the table because the parent widget of the
70 * GtkTreeViewColumn's button is the GtkTreeView we set
71 * the accessible parent for column header to be the table
72 * to ensure that atk_object_get_index_in_parent() returns
73 * the correct value; see gail_widget_get_index_in_parent().
75 atk_object_set_parent (obj, gtk_widget_get_accessible (parent));
76 obj->role = ATK_ROLE_TABLE_COLUMN_HEADER;
79 obj->role = ATK_ROLE_PUSH_BUTTON;
83 get_image_from_button (GtkWidget *button)
87 image = gtk_button_get_image (GTK_BUTTON (button));
88 if (GTK_IS_IMAGE (image))
95 find_label_child (GtkContainer *container)
97 GList *children, *tmp_list;
100 children = gtk_container_get_children (container);
103 for (tmp_list = children; tmp_list != NULL; tmp_list = tmp_list->next)
105 if (GTK_IS_LABEL (tmp_list->data))
107 child = GTK_WIDGET (tmp_list->data);
110 else if (GTK_IS_CONTAINER (tmp_list->data))
112 child = find_label_child (GTK_CONTAINER (tmp_list->data));
117 g_list_free (children);
122 get_label_from_button (GtkWidget *button)
126 child = gtk_bin_get_child (GTK_BIN (button));
127 if (GTK_IS_ALIGNMENT (child))
128 child = gtk_bin_get_child (GTK_BIN (child));
130 if (GTK_IS_CONTAINER (child))
131 child = find_label_child (GTK_CONTAINER (child));
132 else if (!GTK_IS_LABEL (child))
139 gtk_button_accessible_get_name (AtkObject *obj)
141 const gchar *name = NULL;
145 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
149 name = ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->get_name (obj);
153 child = get_label_from_button (widget);
154 if (GTK_IS_LABEL (child))
155 name = gtk_label_get_text (GTK_LABEL (child));
160 image = get_image_from_button (widget);
161 if (GTK_IS_IMAGE (image))
165 atk_obj = gtk_widget_get_accessible (image);
166 name = atk_object_get_name (atk_obj);
174 gtk_button_accessible_get_n_children (AtkObject* obj)
180 gtk_button_accessible_ref_child (AtkObject *obj,
187 gtk_button_accessible_ref_state_set (AtkObject *obj)
189 AtkStateSet *state_set;
192 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
196 state_set = ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->ref_state_set (obj);
198 if ((gtk_widget_get_state_flags (widget) & GTK_STATE_FLAG_ACTIVE) != 0)
199 atk_state_set_add_state (state_set, ATK_STATE_ARMED);
201 if (!gtk_widget_get_can_focus (widget))
202 atk_state_set_remove_state (state_set, ATK_STATE_SELECTABLE);
208 gtk_button_accessible_notify_gtk (GObject *obj,
211 GtkWidget *widget = GTK_WIDGET (obj);
212 AtkObject *atk_obj = gtk_widget_get_accessible (widget);
214 if (strcmp (pspec->name, "label") == 0)
216 if (atk_obj->name == NULL)
217 g_object_notify (G_OBJECT (atk_obj), "accessible-name");
219 g_signal_emit_by_name (atk_obj, "visible_data_changed");
222 GTK_WIDGET_ACCESSIBLE_CLASS (gtk_button_accessible_parent_class)->notify_gtk (obj, pspec);
226 gtk_button_accessible_class_init (GtkButtonAccessibleClass *klass)
228 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
229 GtkContainerAccessibleClass *container_class = (GtkContainerAccessibleClass*)klass;
230 GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
232 class->get_name = gtk_button_accessible_get_name;
233 class->get_n_children = gtk_button_accessible_get_n_children;
234 class->ref_child = gtk_button_accessible_ref_child;
235 class->ref_state_set = gtk_button_accessible_ref_state_set;
236 class->initialize = gtk_button_accessible_initialize;
238 widget_class->notify_gtk = gtk_button_accessible_notify_gtk;
240 container_class->add_gtk = NULL;
241 container_class->remove_gtk = NULL;
245 gtk_button_accessible_init (GtkButtonAccessible *button)
250 gtk_button_accessible_do_action (AtkAction *action,
255 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
262 if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_visible (widget))
265 gtk_button_clicked (GTK_BUTTON (widget));
270 gtk_button_accessible_get_n_actions (AtkAction *action)
276 gtk_button_accessible_get_keybinding (AtkAction *action,
279 gchar *return_value = NULL;
284 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
291 label = get_label_from_button (widget);
292 if (GTK_IS_LABEL (label))
294 key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
295 if (key_val != GDK_KEY_VoidSymbol)
296 return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK);
298 if (return_value == NULL)
300 /* Find labelled-by relation */
302 AtkRelation *relation;
304 gpointer target_object;
306 set = atk_object_ref_relation_set (ATK_OBJECT (action));
309 relation = atk_relation_set_get_relation_by_type (set, ATK_RELATION_LABELLED_BY);
312 target = atk_relation_get_target (relation);
313 target_object = g_ptr_array_index (target, 0);
314 label = gtk_accessible_get_widget (GTK_ACCESSIBLE (target_object));
316 g_object_unref (set);
319 if (GTK_IS_LABEL (label))
321 key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
322 if (key_val != GDK_KEY_VoidSymbol)
323 return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK);
330 gtk_button_accessible_action_get_name (AtkAction *action,
340 atk_action_interface_init (AtkActionIface *iface)
342 iface->do_action = gtk_button_accessible_do_action;
343 iface->get_n_actions = gtk_button_accessible_get_n_actions;
344 iface->get_keybinding = gtk_button_accessible_get_keybinding;
345 iface->get_name = gtk_button_accessible_action_get_name;
349 gtk_button_accessible_get_image_description (AtkImage *image)
352 GtkWidget *button_image;
355 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
359 button_image = get_image_from_button (widget);
360 if (GTK_IS_IMAGE (button_image))
362 obj = gtk_widget_get_accessible (button_image);
363 return atk_image_get_image_description (ATK_IMAGE (obj));
370 gtk_button_accessible_get_image_position (AtkImage *image,
373 AtkCoordType coord_type)
376 GtkWidget *button_image;
379 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
387 button_image = get_image_from_button (widget);
388 if (button_image != NULL)
390 obj = gtk_widget_get_accessible (button_image);
391 atk_component_get_position (ATK_COMPONENT (obj), x, y, coord_type);
401 gtk_button_accessible_get_image_size (AtkImage *image,
406 GtkWidget *button_image;
409 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
417 button_image = get_image_from_button (widget);
418 if (GTK_IS_IMAGE (button_image))
420 obj = gtk_widget_get_accessible (GTK_WIDGET (button_image));
421 atk_image_get_image_size (ATK_IMAGE (obj), width, height);
431 gtk_button_accessible_set_image_description (AtkImage *image,
432 const gchar *description)
435 GtkWidget *button_image;
438 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
443 button_image = get_image_from_button (widget);
444 if (GTK_IMAGE (button_image))
446 obj = gtk_widget_get_accessible (GTK_WIDGET (button_image));
447 return atk_image_set_image_description (ATK_IMAGE (obj), description);
454 atk_image_interface_init (AtkImageIface *iface)
456 iface->get_image_description = gtk_button_accessible_get_image_description;
457 iface->get_image_position = gtk_button_accessible_get_image_position;
458 iface->get_image_size = gtk_button_accessible_get_image_size;
459 iface->set_image_description = gtk_button_accessible_set_image_description;