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 <glib/gi18n-lib.h>
23 #include "gtkbuttonaccessible.h"
26 static void atk_action_interface_init (AtkActionIface *iface);
27 static void atk_image_interface_init (AtkImageIface *iface);
29 G_DEFINE_TYPE_WITH_CODE (GtkButtonAccessible, gtk_button_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE,
30 G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init)
31 G_IMPLEMENT_INTERFACE (ATK_TYPE_IMAGE, atk_image_interface_init))
34 state_changed_cb (GtkWidget *widget, GtkStateFlags previous_flags)
36 AtkObject *accessible;
41 flags = gtk_widget_get_state_flags (widget);
43 was_active = (previous_flags & GTK_STATE_FLAG_ACTIVE) != 0;
44 active = (flags & GTK_STATE_FLAG_ACTIVE) != 0;
46 accessible = gtk_widget_get_accessible (widget);
47 if (active && !was_active)
48 atk_object_notify_state_change (accessible, ATK_STATE_ARMED, TRUE);
49 else if (!active && was_active)
50 atk_object_notify_state_change (accessible, ATK_STATE_ARMED, FALSE);
54 gtk_button_accessible_initialize (AtkObject *obj,
59 ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->initialize (obj, data);
61 g_signal_connect (data, "state-flags-changed", G_CALLBACK (state_changed_cb), NULL);
63 parent = gtk_widget_get_parent (gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)));
64 if (GTK_IS_TREE_VIEW (parent))
66 /* Even though the accessible parent of the column header will
67 * be reported as the table because the parent widget of the
68 * GtkTreeViewColumn's button is the GtkTreeView we set
69 * the accessible parent for column header to be the table
70 * to ensure that atk_object_get_index_in_parent() returns
71 * the correct value; see gail_widget_get_index_in_parent().
73 atk_object_set_parent (obj, gtk_widget_get_accessible (parent));
74 obj->role = ATK_ROLE_TABLE_COLUMN_HEADER;
77 obj->role = ATK_ROLE_PUSH_BUTTON;
81 get_image_from_button (GtkWidget *button)
85 image = gtk_button_get_image (GTK_BUTTON (button));
86 if (GTK_IS_IMAGE (image))
93 find_label_child (GtkContainer *container)
95 GList *children, *tmp_list;
98 children = gtk_container_get_children (container);
101 for (tmp_list = children; tmp_list != NULL; tmp_list = tmp_list->next)
103 if (GTK_IS_LABEL (tmp_list->data))
105 child = GTK_WIDGET (tmp_list->data);
108 else if (GTK_IS_CONTAINER (tmp_list->data))
110 child = find_label_child (GTK_CONTAINER (tmp_list->data));
115 g_list_free (children);
120 get_label_from_button (GtkWidget *button)
124 child = gtk_bin_get_child (GTK_BIN (button));
125 if (GTK_IS_ALIGNMENT (child))
126 child = gtk_bin_get_child (GTK_BIN (child));
128 if (GTK_IS_CONTAINER (child))
129 child = find_label_child (GTK_CONTAINER (child));
130 else if (!GTK_IS_LABEL (child))
137 gtk_button_accessible_get_name (AtkObject *obj)
139 const gchar *name = NULL;
143 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
147 name = ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->get_name (obj);
151 child = get_label_from_button (widget);
152 if (GTK_IS_LABEL (child))
153 name = gtk_label_get_text (GTK_LABEL (child));
158 image = get_image_from_button (widget);
159 if (GTK_IS_IMAGE (image))
163 atk_obj = gtk_widget_get_accessible (image);
164 name = atk_object_get_name (atk_obj);
172 gtk_button_accessible_get_n_children (AtkObject* obj)
178 gtk_button_accessible_ref_child (AtkObject *obj,
185 gtk_button_accessible_ref_state_set (AtkObject *obj)
187 AtkStateSet *state_set;
190 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
194 state_set = ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->ref_state_set (obj);
196 if ((gtk_widget_get_state_flags (widget) & GTK_STATE_FLAG_ACTIVE) != 0)
197 atk_state_set_add_state (state_set, ATK_STATE_ARMED);
199 if (!gtk_widget_get_can_focus (widget))
200 atk_state_set_remove_state (state_set, ATK_STATE_SELECTABLE);
206 gtk_button_accessible_notify_gtk (GObject *obj,
209 GtkWidget *widget = GTK_WIDGET (obj);
210 AtkObject *atk_obj = gtk_widget_get_accessible (widget);
212 if (strcmp (pspec->name, "label") == 0)
214 if (atk_obj->name == NULL)
215 g_object_notify (G_OBJECT (atk_obj), "accessible-name");
217 g_signal_emit_by_name (atk_obj, "visible-data-changed");
220 GTK_WIDGET_ACCESSIBLE_CLASS (gtk_button_accessible_parent_class)->notify_gtk (obj, pspec);
224 gtk_button_accessible_class_init (GtkButtonAccessibleClass *klass)
226 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
227 GtkContainerAccessibleClass *container_class = (GtkContainerAccessibleClass*)klass;
228 GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
230 class->get_name = gtk_button_accessible_get_name;
231 class->get_n_children = gtk_button_accessible_get_n_children;
232 class->ref_child = gtk_button_accessible_ref_child;
233 class->ref_state_set = gtk_button_accessible_ref_state_set;
234 class->initialize = gtk_button_accessible_initialize;
236 widget_class->notify_gtk = gtk_button_accessible_notify_gtk;
238 container_class->add_gtk = NULL;
239 container_class->remove_gtk = NULL;
243 gtk_button_accessible_init (GtkButtonAccessible *button)
248 gtk_button_accessible_do_action (AtkAction *action,
253 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
260 if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_visible (widget))
263 gtk_button_clicked (GTK_BUTTON (widget));
268 gtk_button_accessible_get_n_actions (AtkAction *action)
274 gtk_button_accessible_get_keybinding (AtkAction *action,
277 gchar *return_value = NULL;
282 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
289 label = get_label_from_button (widget);
290 if (GTK_IS_LABEL (label))
292 key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
293 if (key_val != GDK_KEY_VoidSymbol)
294 return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK);
296 if (return_value == NULL)
298 /* Find labelled-by relation */
300 AtkRelation *relation;
302 gpointer target_object;
304 set = atk_object_ref_relation_set (ATK_OBJECT (action));
307 relation = atk_relation_set_get_relation_by_type (set, ATK_RELATION_LABELLED_BY);
310 target = atk_relation_get_target (relation);
311 target_object = g_ptr_array_index (target, 0);
312 label = gtk_accessible_get_widget (GTK_ACCESSIBLE (target_object));
314 g_object_unref (set);
317 if (GTK_IS_LABEL (label))
319 key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
320 if (key_val != GDK_KEY_VoidSymbol)
321 return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK);
328 gtk_button_accessible_action_get_name (AtkAction *action,
337 gtk_button_accessible_action_get_localized_name (AtkAction *action,
341 return C_("Action name", "Click");
346 gtk_button_accessible_action_get_description (AtkAction *action,
350 return C_("Action description", "Clicks the button");
355 atk_action_interface_init (AtkActionIface *iface)
357 iface->do_action = gtk_button_accessible_do_action;
358 iface->get_n_actions = gtk_button_accessible_get_n_actions;
359 iface->get_keybinding = gtk_button_accessible_get_keybinding;
360 iface->get_name = gtk_button_accessible_action_get_name;
361 iface->get_localized_name = gtk_button_accessible_action_get_localized_name;
362 iface->get_description = gtk_button_accessible_action_get_description;
366 gtk_button_accessible_get_image_description (AtkImage *image)
369 GtkWidget *button_image;
372 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
376 button_image = get_image_from_button (widget);
377 if (GTK_IS_IMAGE (button_image))
379 obj = gtk_widget_get_accessible (button_image);
380 return atk_image_get_image_description (ATK_IMAGE (obj));
387 gtk_button_accessible_get_image_position (AtkImage *image,
390 AtkCoordType coord_type)
393 GtkWidget *button_image;
396 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
404 button_image = get_image_from_button (widget);
405 if (button_image != NULL)
407 obj = gtk_widget_get_accessible (button_image);
408 atk_component_get_position (ATK_COMPONENT (obj), x, y, coord_type);
418 gtk_button_accessible_get_image_size (AtkImage *image,
423 GtkWidget *button_image;
426 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
434 button_image = get_image_from_button (widget);
435 if (GTK_IS_IMAGE (button_image))
437 obj = gtk_widget_get_accessible (GTK_WIDGET (button_image));
438 atk_image_get_image_size (ATK_IMAGE (obj), width, height);
448 gtk_button_accessible_set_image_description (AtkImage *image,
449 const gchar *description)
452 GtkWidget *button_image;
455 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
460 button_image = get_image_from_button (widget);
461 if (GTK_IMAGE (button_image))
463 obj = gtk_widget_get_accessible (GTK_WIDGET (button_image));
464 return atk_image_set_image_description (ATK_IMAGE (obj), description);
471 atk_image_interface_init (AtkImageIface *iface)
473 iface->get_image_description = gtk_button_accessible_get_image_description;
474 iface->get_image_position = gtk_button_accessible_get_image_position;
475 iface->get_image_size = gtk_button_accessible_get_image_size;
476 iface->set_image_description = gtk_button_accessible_set_image_description;