-/* GAIL - The GNOME Accessibility Implementation Library
+/* GTK+ - accessibility implementations
* Copyright 2001, 2002, 2003 Sun Microsystems Inc.
*
* This library is free software; you can redistribute it and/or
* 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.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
#include <string.h>
#include <gtk/gtk.h>
#include "gtkmenuitemaccessible.h"
-#include "gtksubmenuitemaccessible.h"
+#include "gtkwidgetaccessibleprivate.h"
#include "gtk/gtkmenuitemprivate.h"
+struct _GtkMenuItemAccessiblePrivate
+{
+ gchar *text;
+ gboolean selected;
+};
+
#define KEYBINDING_SEPARATOR ";"
static void menu_item_select (GtkMenuItem *item);
static GtkWidget *get_label_from_container (GtkWidget *container);
static gchar *get_text_from_label_widget (GtkWidget *widget);
+static gint menu_item_add_gtk (GtkContainer *container,
+ GtkWidget *widget);
+static gint menu_item_remove_gtk (GtkContainer *container,
+ GtkWidget *widget);
-static void atk_action_interface_init (AtkActionIface *iface);
+static void atk_action_interface_init (AtkActionIface *iface);
+static void atk_selection_interface_init (AtkSelectionIface *iface);
-G_DEFINE_TYPE_WITH_CODE (GtkMenuItemAccessible, _gtk_menu_item_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE,
- G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init))
+G_DEFINE_TYPE_WITH_CODE (GtkMenuItemAccessible, gtk_menu_item_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE,
+ G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init);
+ G_IMPLEMENT_INTERFACE (ATK_TYPE_SELECTION, atk_selection_interface_init))
static void
gtk_menu_item_accessible_initialize (AtkObject *obj,
{
GtkWidget *widget;
GtkWidget *parent;
+ GtkWidget *menu;
- ATK_OBJECT_CLASS (_gtk_menu_item_accessible_parent_class)->initialize (obj, data);
+ ATK_OBJECT_CLASS (gtk_menu_item_accessible_parent_class)->initialize (obj, data);
g_signal_connect (data, "select", G_CALLBACK (menu_item_select), NULL);
g_signal_connect (data, "deselect", G_CALLBACK (menu_item_deselect), NULL);
atk_object_set_parent (obj, gtk_widget_get_accessible (parent_widget));
}
- GTK_WIDGET_ACCESSIBLE (obj)->layer = ATK_LAYER_POPUP;
+ _gtk_widget_accessible_set_layer (GTK_WIDGET_ACCESSIBLE (obj), ATK_LAYER_POPUP);
- if (GTK_IS_TEAROFF_MENU_ITEM (data))
- obj->role = ATK_ROLE_TEAR_OFF_MENU_ITEM;
- else if (GTK_IS_SEPARATOR_MENU_ITEM (data))
- obj->role = ATK_ROLE_SEPARATOR;
- else
- obj->role = ATK_ROLE_MENU_ITEM;
+ obj->role = ATK_ROLE_MENU_ITEM;
+
+ menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (data));
+ if (menu)
+ {
+ g_signal_connect (menu, "add", G_CALLBACK (menu_item_add_gtk), NULL);
+ g_signal_connect (menu, "remove", G_CALLBACK (menu_item_remove_gtk), NULL);
+ }
}
static gint
AtkObject *menu_item;
AtkStateSet *state_set, *parent_state_set;
- state_set = ATK_OBJECT_CLASS (_gtk_menu_item_accessible_parent_class)->ref_state_set (obj);
+ state_set = ATK_OBJECT_CLASS (gtk_menu_item_accessible_parent_class)->ref_state_set (obj);
+
+ atk_state_set_add_state (state_set, ATK_STATE_SELECTABLE);
+ if (GTK_MENU_ITEM_ACCESSIBLE (obj)->priv->selected)
+ atk_state_set_add_state (state_set, ATK_STATE_SELECTED);
menu_item = atk_object_get_parent (obj);
gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget)))
return ATK_ROLE_MENU;
- return ATK_OBJECT_CLASS (_gtk_menu_item_accessible_parent_class)->get_role (obj);
+ return ATK_OBJECT_CLASS (gtk_menu_item_accessible_parent_class)->get_role (obj);
}
static const gchar *
if (widget == NULL)
return NULL;
- name = ATK_OBJECT_CLASS (_gtk_menu_item_accessible_parent_class)->get_name (obj);
+ name = ATK_OBJECT_CLASS (gtk_menu_item_accessible_parent_class)->get_name (obj);
if (name)
return name;
accessible = GTK_MENU_ITEM_ACCESSIBLE (obj);
label = get_label_from_container (widget);
- g_free (accessible->text);
- accessible->text = get_text_from_label_widget (label);
+ g_free (accessible->priv->text);
+ accessible->priv->text = get_text_from_label_widget (label);
- return accessible->text;
+ return accessible->priv->text;
}
static void
{
GtkMenuItemAccessible *accessible = GTK_MENU_ITEM_ACCESSIBLE (object);
- g_free (accessible->text);
+ g_free (accessible->priv->text);
- G_OBJECT_CLASS (_gtk_menu_item_accessible_parent_class)->finalize (object);
+ G_OBJECT_CLASS (gtk_menu_item_accessible_parent_class)->finalize (object);
}
static void
g_signal_emit_by_name (atk_obj, "visible-data-changed");
}
else
- GTK_WIDGET_ACCESSIBLE_CLASS (_gtk_menu_item_accessible_parent_class)->notify_gtk (obj, pspec);
+ GTK_WIDGET_ACCESSIBLE_CLASS (gtk_menu_item_accessible_parent_class)->notify_gtk (obj, pspec);
}
static void
-_gtk_menu_item_accessible_class_init (GtkMenuItemAccessibleClass *klass)
+gtk_menu_item_accessible_class_init (GtkMenuItemAccessibleClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
class->initialize = gtk_menu_item_accessible_initialize;
class->get_name = gtk_menu_item_accessible_get_name;
class->get_role = gtk_menu_item_accessible_get_role;
+
+ g_type_class_add_private (klass, sizeof (GtkMenuItemAccessiblePrivate));
}
static void
-_gtk_menu_item_accessible_init (GtkMenuItemAccessible *menu_item)
+gtk_menu_item_accessible_init (GtkMenuItemAccessible *menu_item)
{
+ menu_item->priv = G_TYPE_INSTANCE_GET_PRIVATE (menu_item,
+ GTK_TYPE_MENU_ITEM_ACCESSIBLE,
+ GtkMenuItemAccessiblePrivate);
}
static GtkWidget *
gtk_menu_item_accessible_action_get_name (AtkAction *action,
gint i)
{
- if (i != 0 || gtk_menu_item_accessible_get_n_actions (action) == 0)
- return NULL;
+ if (i == 0 && gtk_menu_item_accessible_get_n_actions (action) > 0)
+ return "click";
+ return NULL;
+}
- return "click";
+static const gchar *
+gtk_menu_item_accessible_action_get_localized_name (AtkAction *action,
+ gint i)
+{
+ if (i == 0 && gtk_menu_item_accessible_get_n_actions (action) > 0)
+ return C_("Action name", "Click");
+ return NULL;
+}
+
+static const gchar *
+gtk_menu_item_accessible_action_get_description (AtkAction *action,
+ gint i)
+{
+ if (i == 0 && gtk_menu_item_accessible_get_n_actions (action) > 0)
+ return C_("Action description", "Clicks the menuitem");
+ return NULL;
}
static gboolean
iface->do_action = gtk_menu_item_accessible_do_action;
iface->get_n_actions = gtk_menu_item_accessible_get_n_actions;
iface->get_name = gtk_menu_item_accessible_action_get_name;
+ iface->get_localized_name = gtk_menu_item_accessible_action_get_localized_name;
+ iface->get_description = gtk_menu_item_accessible_action_get_description;
iface->get_keybinding = gtk_menu_item_accessible_get_keybinding;
}
gint i;
obj = gtk_widget_get_accessible (GTK_WIDGET (item));
+ GTK_MENU_ITEM_ACCESSIBLE (obj)->priv->selected = selected;
atk_object_notify_state_change (obj, ATK_STATE_SELECTED, selected);
for (i = 0; i < atk_object_get_n_accessible_children (obj); i++)
g_signal_emit_by_name (parent, "selection-changed");
}
+static gboolean
+gtk_menu_item_accessible_add_selection (AtkSelection *selection,
+ gint i)
+{
+ GtkMenuShell *shell;
+ GList *kids;
+ guint length;
+ GtkWidget *widget;
+ GtkWidget *menu;
+ GtkWidget *child;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
+ if (widget == NULL)
+ return FALSE;
+
+ menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+ if (menu == NULL)
+ return FALSE;
+
+ shell = GTK_MENU_SHELL (menu);
+ kids = gtk_container_get_children (GTK_CONTAINER (shell));
+ length = g_list_length (kids);
+ if (i < 0 || i > length)
+ {
+ g_list_free (kids);
+ return FALSE;
+ }
+
+ child = g_list_nth_data (kids, i);
+ g_list_free (kids);
+ g_return_val_if_fail (GTK_IS_MENU_ITEM (child), FALSE);
+ gtk_menu_shell_select_item (shell, GTK_WIDGET (child));
+ return TRUE;
+}
+
+static gboolean
+gtk_menu_item_accessible_clear_selection (AtkSelection *selection)
+{
+ GtkWidget *widget;
+ GtkWidget *menu;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
+ if (widget == NULL)
+ return FALSE;
+
+ menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+ if (menu == NULL)
+ return FALSE;
+
+ gtk_menu_shell_deselect (GTK_MENU_SHELL (menu));
+
+ return TRUE;
+}
+
+static AtkObject *
+gtk_menu_item_accessible_ref_selection (AtkSelection *selection,
+ gint i)
+{
+ GtkMenuShell *shell;
+ AtkObject *obj;
+ GtkWidget *widget;
+ GtkWidget *menu;
+ GtkWidget *item;
+
+ if (i != 0)
+ return NULL;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
+ if (widget == NULL)
+ return NULL;
+
+ menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+ if (menu == NULL)
+ return NULL;
+
+ shell = GTK_MENU_SHELL (menu);
+
+ item = gtk_menu_shell_get_selected_item (shell);
+ if (item != NULL)
+ {
+ obj = gtk_widget_get_accessible (item);
+ g_object_ref (obj);
+ return obj;
+ }
+
+ return NULL;
+}
+
+static gint
+gtk_menu_item_accessible_get_selection_count (AtkSelection *selection)
+{
+ GtkMenuShell *shell;
+ GtkWidget *widget;
+ GtkWidget *menu;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
+ if (widget == NULL)
+ return 0;
+
+ menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+ if (menu == NULL)
+ return 0;
+
+ shell = GTK_MENU_SHELL (menu);
+
+ if (gtk_menu_shell_get_selected_item (shell) != NULL)
+ return 1;
+
+ return 0;
+}
+
+static gboolean
+gtk_menu_item_accessible_is_child_selected (AtkSelection *selection,
+ gint i)
+{
+ GtkMenuShell *shell;
+ gint j;
+ GtkWidget *widget;
+ GtkWidget *menu;
+ GtkWidget *item;
+ GList *kids;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
+ if (widget == NULL)
+ return FALSE;
+
+ menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+ if (menu == NULL)
+ return FALSE;
+
+ shell = GTK_MENU_SHELL (menu);
+
+ item = gtk_menu_shell_get_selected_item (shell);
+ if (item == NULL)
+ return FALSE;
+
+ kids = gtk_container_get_children (GTK_CONTAINER (shell));
+ j = g_list_index (kids, item);
+ g_list_free (kids);
+
+ return j==i;
+}
+
+static gboolean
+gtk_menu_item_accessible_remove_selection (AtkSelection *selection,
+ gint i)
+{
+ GtkMenuShell *shell;
+ GtkWidget *widget;
+ GtkWidget *menu;
+ GtkWidget *item;
+
+ if (i != 0)
+ return FALSE;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
+ if (widget == NULL)
+ return FALSE;
+
+ menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+ if (menu == NULL)
+ return FALSE;
+
+ shell = GTK_MENU_SHELL (menu);
+
+ item = gtk_menu_shell_get_selected_item (shell);
+ if (item && gtk_menu_item_get_submenu (GTK_MENU_ITEM (item)))
+ gtk_menu_shell_deselect (shell);
+
+ return TRUE;
+}
+
+static void
+atk_selection_interface_init (AtkSelectionIface *iface)
+{
+ iface->add_selection = gtk_menu_item_accessible_add_selection;
+ iface->clear_selection = gtk_menu_item_accessible_clear_selection;
+ iface->ref_selection = gtk_menu_item_accessible_ref_selection;
+ iface->get_selection_count = gtk_menu_item_accessible_get_selection_count;
+ iface->is_child_selected = gtk_menu_item_accessible_is_child_selected;
+ iface->remove_selection = gtk_menu_item_accessible_remove_selection;
+}
+
+static gint
+menu_item_add_gtk (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkWidget *parent_widget;
+
+ g_return_val_if_fail (GTK_IS_MENU (container), 1);
+
+ parent_widget = gtk_menu_get_attach_widget (GTK_MENU (container));
+ if (GTK_IS_MENU_ITEM (parent_widget))
+ {
+ GTK_CONTAINER_ACCESSIBLE_CLASS (gtk_menu_item_accessible_parent_class)->add_gtk (container, widget, gtk_widget_get_accessible (parent_widget));
+
+ }
+ return 1;
+}
+
+static gint
+menu_item_remove_gtk (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkWidget *parent_widget;
+
+ g_return_val_if_fail (GTK_IS_MENU (container), 1);
+
+ parent_widget = gtk_menu_get_attach_widget (GTK_MENU (container));
+ if (GTK_IS_MENU_ITEM (parent_widget))
+ {
+ GTK_CONTAINER_ACCESSIBLE_CLASS (gtk_menu_item_accessible_parent_class)->remove_gtk (container, widget, gtk_widget_get_accessible (parent_widget));
+ }
+ return 1;
+}
static void
menu_item_select (GtkMenuItem *item)
{