diff options
author | Matthias Clasen <mclasen@redhat.com> | 2011-07-01 21:25:53 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2011-07-05 16:08:57 -0400 |
commit | 8432ea3574bc71a8a32d8613b84b54bbd84d0057 (patch) | |
tree | 644bae16f11286e18c622e34d03002f9aeb9da50 /gtk/a11y/gtkbuttonaccessible.c | |
parent | a3113386dffbacbc6eb9c3b14d0e91e3c11b324b (diff) | |
download | gtk+-8432ea3574bc71a8a32d8613b84b54bbd84d0057.tar.gz |
Convert GailButton to GtkButtonAccessible
This drops the AtkText implementation, and also strips handling
of children out. Instead of listening for enter/leave/press/released,
just listen for state changes on the widget.
Diffstat (limited to 'gtk/a11y/gtkbuttonaccessible.c')
-rw-r--r-- | gtk/a11y/gtkbuttonaccessible.c | 466 |
1 files changed, 466 insertions, 0 deletions
diff --git a/gtk/a11y/gtkbuttonaccessible.c b/gtk/a11y/gtkbuttonaccessible.c new file mode 100644 index 0000000000..64b6d251a3 --- /dev/null +++ b/gtk/a11y/gtkbuttonaccessible.c @@ -0,0 +1,466 @@ +/* GAIL - The GNOME Accessibility Implementation Library + * Copyright 2001, 2002, 2003 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include <string.h> +#include <gtk/gtk.h> +#include "gtkbuttonaccessible.h" +#include <libgail-util/gailmisc.h> + + +static void atk_action_interface_init (AtkActionIface *iface); +static void atk_image_interface_init (AtkImageIface *iface); + +G_DEFINE_TYPE_WITH_CODE (GtkButtonAccessible, gtk_button_accessible, GAIL_TYPE_CONTAINER, + G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init) + G_IMPLEMENT_INTERFACE (ATK_TYPE_IMAGE, atk_image_interface_init)) + +static void +state_changed_cb (GtkWidget *widget, GtkStateFlags previous_flags) +{ + AtkObject *accessible; + GtkStateFlags flags; + gboolean was_active; + gboolean active; + + flags = gtk_widget_get_state_flags (widget); + + was_active = (previous_flags & GTK_STATE_FLAG_ACTIVE) != 0; + active = (flags & GTK_STATE_FLAG_ACTIVE) != 0; + + accessible = gtk_widget_get_accessible (widget); + if (active && !was_active) + atk_object_notify_state_change (accessible, ATK_STATE_ARMED, TRUE); + else if (!active && was_active) + atk_object_notify_state_change (accessible, ATK_STATE_ARMED, FALSE); +} + +static void +gtk_button_accessible_initialize (AtkObject *obj, + gpointer data) +{ + GtkWidget *parent; + + ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->initialize (obj, data); + + g_signal_connect (data, "state-flags-changed", G_CALLBACK (state_changed_cb), NULL); + + parent = gtk_widget_get_parent (gtk_accessible_get_widget (GTK_ACCESSIBLE (obj))); + if (GTK_IS_TREE_VIEW (parent)) + { + /* Even though the accessible parent of the column header will + * be reported as the table because the parent widget of the + * GtkTreeViewColumn's button is the GtkTreeView we set + * the accessible parent for column header to be the table + * to ensure that atk_object_get_index_in_parent() returns + * the correct value; see gail_widget_get_index_in_parent(). + */ + atk_object_set_parent (obj, gtk_widget_get_accessible (parent)); + obj->role = ATK_ROLE_TABLE_COLUMN_HEADER; + } + else + obj->role = ATK_ROLE_PUSH_BUTTON; +} + +static GtkWidget * +get_image_from_button (GtkWidget *button) +{ + GtkWidget *image; + + image = gtk_button_get_image (GTK_BUTTON (button)); + if (GTK_IS_IMAGE (image)) + return image; + + return NULL; +} + +static GtkWidget * +find_label_child (GtkContainer *container) +{ + GList *children, *tmp_list; + GtkWidget *child; + + children = gtk_container_get_children (container); + + child = NULL; + for (tmp_list = children; tmp_list != NULL; tmp_list = tmp_list->next) + { + if (GTK_IS_LABEL (tmp_list->data)) + { + child = GTK_WIDGET (tmp_list->data); + break; + } + else if (GTK_IS_CONTAINER (tmp_list->data)) + { + child = find_label_child (GTK_CONTAINER (tmp_list->data)); + if (child) + break; + } + } + g_list_free (children); + return child; +} + +static GtkWidget * +get_label_from_button (GtkWidget *button) +{ + GtkWidget *child; + + child = gtk_bin_get_child (GTK_BIN (button)); + if (GTK_IS_ALIGNMENT (child)) + child = gtk_bin_get_child (GTK_BIN (child)); + + if (GTK_IS_CONTAINER (child)) + child = find_label_child (GTK_CONTAINER (child)); + else if (!GTK_IS_LABEL (child)) + child = NULL; + + return child; +} + +static const gchar * +gtk_button_accessible_get_name (AtkObject *obj) +{ + const gchar *name = NULL; + GtkWidget *widget; + GtkWidget *child; + + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)); + if (widget == NULL) + return NULL; + + name = ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->get_name (obj); + if (name != NULL) + return name; + + child = get_label_from_button (widget); + if (GTK_IS_LABEL (child)) + name = gtk_label_get_text (GTK_LABEL (child)); + else + { + GtkWidget *image; + + image = get_image_from_button (widget); + if (GTK_IS_IMAGE (image)) + { + AtkObject *atk_obj; + + atk_obj = gtk_widget_get_accessible (image); + name = atk_object_get_name (atk_obj); + } + } + + return name; +} + +static gint +gtk_button_accessible_get_n_children (AtkObject* obj) +{ + return 0; +} + +static AtkObject * +gtk_button_accessible_ref_child (AtkObject *obj, + gint i) +{ + return NULL; +} + +static AtkStateSet * +gtk_button_accessible_ref_state_set (AtkObject *obj) +{ + AtkStateSet *state_set; + GtkWidget *widget; + + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)); + if (widget == NULL) + return NULL; + + state_set = ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->ref_state_set (obj); + + if ((gtk_widget_get_state_flags (widget) & GTK_STATE_FLAG_ACTIVE) != 0) + atk_state_set_add_state (state_set, ATK_STATE_ARMED); + + if (!gtk_widget_get_can_focus (widget)) + atk_state_set_remove_state (state_set, ATK_STATE_SELECTABLE); + + return state_set; +} + +static void +gtk_button_accessible_notify_gtk (GObject *obj, + GParamSpec *pspec) +{ + GtkWidget *widget = GTK_WIDGET (obj); + AtkObject *atk_obj = gtk_widget_get_accessible (widget); + + if (strcmp (pspec->name, "label") == 0) + { + if (atk_obj->name == NULL) + g_object_notify (G_OBJECT (atk_obj), "accessible-name"); + + g_signal_emit_by_name (atk_obj, "visible_data_changed"); + } + else + GAIL_WIDGET_CLASS (gtk_button_accessible_parent_class)->notify_gtk (obj, pspec); +} + +static void +gtk_button_accessible_class_init (GtkButtonAccessibleClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + GailContainerClass *container_class = (GailContainerClass*)klass; + GailWidgetClass *widget_class = (GailWidgetClass*)klass; + + class->get_name = gtk_button_accessible_get_name; + class->get_n_children = gtk_button_accessible_get_n_children; + class->ref_child = gtk_button_accessible_ref_child; + class->ref_state_set = gtk_button_accessible_ref_state_set; + class->initialize = gtk_button_accessible_initialize; + + widget_class->notify_gtk = gtk_button_accessible_notify_gtk; + + container_class->add_gtk = NULL; + container_class->remove_gtk = NULL; +} + +static void +gtk_button_accessible_init (GtkButtonAccessible *button) +{ +} + +static gboolean +gtk_button_accessible_do_action (AtkAction *action, + gint i) +{ + GtkWidget *widget; + + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action)); + if (widget == NULL) + return FALSE; + + if (i != 0) + return FALSE; + + if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_visible (widget)) + return FALSE; + + gtk_button_clicked (GTK_BUTTON (widget)); + return TRUE; +} + +static gint +gtk_button_accessible_get_n_actions (AtkAction *action) +{ + return 1; +} + +static const gchar * +gtk_button_accessible_get_keybinding (AtkAction *action, + gint i) +{ + GtkButtonAccessible *button; + gchar *return_value = NULL; + GtkWidget *widget; + GtkWidget *label; + guint key_val; + + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action)); + if (widget == NULL) + return NULL; + + if (i != 0) + return NULL; + + button = GTK_BUTTON_ACCESSIBLE (action); + + label = get_label_from_button (widget); + if (GTK_IS_LABEL (label)) + { + key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label)); + if (key_val != GDK_KEY_VoidSymbol) + return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK); + } + if (return_value == NULL) + { + /* Find labelled-by relation */ + AtkRelationSet *set; + AtkRelation *relation; + GPtrArray *target; + gpointer target_object; + + set = atk_object_ref_relation_set (ATK_OBJECT (action)); + if (set) + { + relation = atk_relation_set_get_relation_by_type (set, ATK_RELATION_LABELLED_BY); + if (relation) + { + target = atk_relation_get_target (relation); + target_object = g_ptr_array_index (target, 0); + label = gtk_accessible_get_widget (GTK_ACCESSIBLE (target_object)); + } + g_object_unref (set); + } + + if (GTK_IS_LABEL (label)) + { + key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label)); + if (key_val != GDK_KEY_VoidSymbol) + return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK); + } + } + return return_value; +} + +static const gchar * +gtk_button_accessible_action_get_name (AtkAction *action, + gint i) +{ + if (i != 0) + return NULL; + + return "click"; +} + +static void +atk_action_interface_init (AtkActionIface *iface) +{ + iface->do_action = gtk_button_accessible_do_action; + iface->get_n_actions = gtk_button_accessible_get_n_actions; + iface->get_keybinding = gtk_button_accessible_get_keybinding; + iface->get_name = gtk_button_accessible_action_get_name; +} + +static const gchar * +gtk_button_accessible_get_image_description (AtkImage *image) +{ + GtkWidget *widget; + GtkWidget *button_image; + AtkObject *obj; + + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image)); + if (widget == NULL) + return NULL; + + button_image = get_image_from_button (widget); + if (GTK_IS_IMAGE (button_image)) + { + obj = gtk_widget_get_accessible (button_image); + return atk_image_get_image_description (ATK_IMAGE (obj)); + } + + return NULL; +} + +static void +gtk_button_accessible_get_image_position (AtkImage *image, + gint *x, + gint *y, + AtkCoordType coord_type) +{ + GtkWidget *widget; + GtkImage *button_image; + AtkObject *obj; + + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image)); + if (widget == NULL) + { + *x = G_MININT; + *y = G_MININT; + return; + } + + button_image = get_image_from_button (widget); + + if (button_image != NULL) + { + obj = gtk_widget_get_accessible (GTK_WIDGET (button_image)); + atk_component_get_position (ATK_COMPONENT (obj), x, y, coord_type); + } + else + { + *x = G_MININT; + *y = G_MININT; + } +} + +static void +gtk_button_accessible_get_image_size (AtkImage *image, + gint *width, + gint *height) +{ + GtkWidget *widget; + GtkImage *button_image; + AtkObject *obj; + + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image)); + if (widget == NULL) + { + *width = -1; + *height = -1; + return; + } + + button_image = get_image_from_button (widget); + + if (button_image != NULL) + { + obj = gtk_widget_get_accessible (GTK_WIDGET (button_image)); + atk_image_get_image_size (ATK_IMAGE (obj), width, height); + } + else + { + *width = -1; + *height = -1; + } +} + +static gboolean +gtk_button_accessible_set_image_description (AtkImage *image, + const gchar *description) +{ + GtkWidget *widget; + GtkImage *button_image; + AtkObject *obj; + + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image)); + + if (widget == NULL) + return FALSE; + + button_image = get_image_from_button (widget); + + if (button_image != NULL) + { + obj = gtk_widget_get_accessible (GTK_WIDGET (button_image)); + return atk_image_set_image_description (ATK_IMAGE (obj), description); + } + + return FALSE; +} + +static void +atk_image_interface_init (AtkImageIface *iface) +{ + iface->get_image_description = gtk_button_accessible_get_image_description; + iface->get_image_position = gtk_button_accessible_get_image_position; + iface->get_image_size = gtk_button_accessible_get_image_size; + iface->set_image_description = gtk_button_accessible_set_image_description; +} |