libgnomeui accessibility patch



Hi, Anders, everyone,

We have a rather large patch that adds accessibility support for
libgnomeui, and would like to see it integrated with the main source
base.  Right now it lives in the ximian-atk-branch of libgnomeui.

The patch is attached.  It is not with respect to HEAD, but rather to a
March 30 snapshot.  However, most of the stuff should still make sense,
and I can merge it myself if you think it is appropriate.

Your opinions on this would be very valuable :)

Thanks,

  Federico


diff -pNaur libgnomeui/libgnomeui/Makefile.am libgnomeui-new/libgnomeui/Makefile.am
--- libgnomeui/libgnomeui/Makefile.am	Thu Apr 18 05:08:48 2002
+++ libgnomeui-new/libgnomeui/Makefile.am	Thu Apr 18 05:08:30 2002
@@ -38,6 +38,8 @@ INCLUDES = \
 EXTRA_HEADERS = 
 
 libgnomeui_2_la_SOURCES = \
+	libgnomeui-access.c		\
+	libgnomeui-access.h		\
 	gnometypebuiltins.h		\
 	gnometypebuiltins.c		\
 	gnome-about.c			\
diff -pNaur libgnomeui/libgnomeui/gnome-color-picker.c libgnomeui-new/libgnomeui/gnome-color-picker.c
--- libgnomeui/libgnomeui/gnome-color-picker.c	Thu Apr 18 05:08:48 2002
+++ libgnomeui-new/libgnomeui/gnome-color-picker.c	Thu Apr 18 05:08:30 2002
@@ -49,6 +49,8 @@
 
 #include <libgnomeuiP.h>
 
+#include "libgnomeui-access.h"
+
 /* These are the dimensions of the color sample in the color picker */
 #define COLOR_PICKER_WIDTH  20
 #define COLOR_PICKER_HEIGHT 12
@@ -444,10 +446,17 @@ gnome_color_picker_instance_init (GnomeC
 {
 	GtkWidget *alignment;
 	GtkWidget *frame;
-	/* Create the widgets */
 
+	/* Create the widgets */
 	cp->_priv = g_new0(GnomeColorPickerPrivate, 1);
 
+	/*
+	 * The application may very well override these.
+	 */
+	_add_atk_name_desc (GTK_WIDGET (cp),
+			    _("Color Selector"),
+			    _("Open a dialog to specify the color"));
+
 	alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
 	gtk_container_set_border_width (GTK_CONTAINER (alignment), COLOR_PICKER_PAD);
 	gtk_container_add (GTK_CONTAINER (cp), alignment);
diff -pNaur libgnomeui/libgnomeui/gnome-dateedit.c libgnomeui-new/libgnomeui/gnome-dateedit.c
--- libgnomeui/libgnomeui/gnome-dateedit.c	Thu Apr 18 05:08:48 2002
+++ libgnomeui-new/libgnomeui/gnome-dateedit.c	Thu Apr 18 05:08:30 2002
@@ -45,6 +45,9 @@
 #include <libgnome/gnome-i18n.h>
 
 #include "gnometypebuiltins.h"
+
+#include "libgnomeui-access.h"
+
 struct _GnomeDateEditPrivate {
 	GtkWidget *date_entry;
 	GtkWidget *date_button;
@@ -727,15 +730,24 @@ create_children (GnomeDateEdit *gde)
 	GtkWidget *arrow;
 
 	gde->_priv->date_entry  = gtk_entry_new ();
+	_add_atk_name_desc (GTK_WIDGET (gde->_priv->date_entry), _("Date"), NULL);
+
 	gtk_widget_set_size_request (gde->_priv->date_entry, 90, -1);
 	gtk_box_pack_start (GTK_BOX (gde), gde->_priv->date_entry, TRUE, TRUE, 0);
 	gtk_widget_show (gde->_priv->date_entry);
 
+
 	gde->_priv->date_button = gtk_button_new ();
 	g_signal_connect (gde->_priv->date_button, "clicked",
 			  G_CALLBACK (select_clicked), gde);
 	gtk_box_pack_start (GTK_BOX (gde), gde->_priv->date_button, FALSE, FALSE, 0);
 
+	_add_atk_name_desc (GTK_WIDGET (gde->_priv->date_button),
+			    _("Select Date"), _("Select the date from a calendar"));
+
+	_add_atk_relation (gde->_priv->date_button, gde->_priv->date_entry,
+			   ATK_RELATION_CONTROLLER_FOR, ATK_RELATION_CONTROLLED_BY);
+
 	hbox = gtk_hbox_new (FALSE, 3);
 	gtk_container_add (GTK_CONTAINER (gde->_priv->date_button), hbox);
 	gtk_widget_show (hbox);
@@ -755,11 +767,19 @@ create_children (GnomeDateEdit *gde)
 	gtk_widget_show (gde->_priv->date_button);
 
 	gde->_priv->time_entry = gtk_entry_new ();
+	_add_atk_name_desc (GTK_WIDGET (gde->_priv->time_entry), _("Time"), NULL);
+
 	gtk_entry_set_max_length (GTK_ENTRY (gde->_priv->time_entry), 12);
 	gtk_widget_set_size_request (gde->_priv->time_entry, 88, -1);
 	gtk_box_pack_start (GTK_BOX (gde), gde->_priv->time_entry, TRUE, TRUE, 0);
 
 	gde->_priv->time_popup = gtk_option_menu_new ();
+	_add_atk_name_desc (GTK_WIDGET (gde->_priv->time_popup),
+			    _("Select Time"), _("Select the time from a list"));
+
+	_add_atk_relation (GTK_WIDGET (gde->_priv->time_popup), GTK_WIDGET (gde->_priv->time_entry),
+			   ATK_RELATION_CONTROLLED_BY, ATK_RELATION_CONTROLLER_FOR);
+
 	gtk_box_pack_start (GTK_BOX (gde), gde->_priv->time_popup, FALSE, FALSE, 0);
 
 	/* We do not create the popup menu with the hour range until we are
diff -pNaur libgnomeui/libgnomeui/gnome-entry.c libgnomeui-new/libgnomeui/gnome-entry.c
--- libgnomeui/libgnomeui/gnome-entry.c	Thu Apr 18 05:08:48 2002
+++ libgnomeui-new/libgnomeui/gnome-entry.c	Thu Apr 18 05:08:30 2002
@@ -46,6 +46,7 @@
 
 #include "gnome-gconf-ui.h"
 
+#include "libgnomeui-access.h"
 #include "gnome-entry.h"
 
 enum {
diff -pNaur libgnomeui/libgnomeui/gnome-file-entry.c libgnomeui-new/libgnomeui/gnome-file-entry.c
--- libgnomeui/libgnomeui/gnome-file-entry.c	Thu Apr 18 05:08:48 2002
+++ libgnomeui-new/libgnomeui/gnome-file-entry.c	Thu Apr 18 05:08:30 2002
@@ -51,6 +51,8 @@
 #include <libgnome/gnome-util.h>
 #include "libgnomeuiP.h"
 
+#include "libgnomeui-access.h"
+
 #include "gnome-file-entry.h"
 
 struct _GnomeFileEntryPrivate {
@@ -567,6 +569,8 @@ gnome_file_entry_init (GnomeFileEntry *f
 	fentry->_priv->directory_entry = FALSE;
 
 	fentry->_priv->gentry = gnome_entry_new (NULL);
+	_add_atk_name_desc (fentry->_priv->gentry, _("Path"), _("Path to file"));
+
 	the_gtk_entry = gnome_file_entry_gtk_entry (fentry);
 
 	g_signal_connect (the_gtk_entry, "changed",
@@ -590,11 +594,17 @@ gnome_file_entry_init (GnomeFileEntry *f
 	gtk_widget_show (fentry->_priv->gentry);
 
 	button = gtk_button_new_with_mnemonic (_("_Browse..."));
+	_add_atk_description (button, _("Pop up a file selector to choose a file"));
+
 	g_signal_connect (button, "clicked",
 			  G_CALLBACK (browse_clicked_signal),
 			  fentry);
 	gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
 	gtk_widget_show (button);
+
+	_add_atk_relation (button, the_gtk_entry,
+			   ATK_RELATION_CONTROLLER_FOR,
+			   ATK_RELATION_CONTROLLED_BY);
 }
 
 static void
diff -pNaur libgnomeui/libgnomeui/gnome-href.c libgnomeui-new/libgnomeui/gnome-href.c
--- libgnomeui/libgnomeui/gnome-href.c	Thu Apr 18 05:08:48 2002
+++ libgnomeui-new/libgnomeui/gnome-href.c	Thu Apr 18 05:08:30 2002
@@ -31,6 +31,7 @@
 #include <gtk/gtk.h>
 #include <libgnome/gnome-url.h>
 #include "gnome-href.h"
+#include "libgnomeui-access.h"
 
 struct _GnomeHRefPrivate {
 	gchar *url;
@@ -172,6 +173,14 @@ gnome_href_instance_init (GnomeHRef *hre
 	/* the source dest is set on set_url */
 	g_signal_connect (href, "drag_data_get",
 			  G_CALLBACK (drag_data_get), NULL);
+
+	/* Set our accessible description.  We don't set the name as we want it
+	 * to be the contents of the label, which is the default anyways.
+	 */
+
+	_add_atk_name_desc (GTK_WIDGET (href),
+			    NULL,
+			    _("This button will take you to the URI that it displays."));
 }
 
 static void
diff -pNaur libgnomeui/libgnomeui/gnome-icon-entry.c libgnomeui-new/libgnomeui/gnome-icon-entry.c
--- libgnomeui/libgnomeui/gnome-icon-entry.c	Thu Apr 18 05:08:48 2002
+++ libgnomeui-new/libgnomeui/gnome-icon-entry.c	Thu Apr 18 05:08:30 2002
@@ -61,6 +61,7 @@
 #include "gnome-icon-list.h"
 #include "gnome-icon-sel.h"
 #include "gnome-icon-entry.h"
+#include "libgnomeui-access.h"
 #include <sys/stat.h>
 #include <unistd.h>
 #include <string.h>
@@ -692,7 +693,17 @@ ientry_browse(GnomeIconEntry *ientry)
 				  G_CALLBACK (gtk_widget_destroyed),
 				  &priv->pick_dialog);
 
+		/* Set up accessible properties for the pick dialog */
+		_add_atk_name_desc (priv->pick_dialog,
+				    _("Icon selection dialog"),
+				    _("This dialog box lets you select an icon."));
+		_add_atk_relation (priv->pickbutton, priv->pick_dialog,
+				   ATK_RELATION_CONTROLLER_FOR, ATK_RELATION_CONTROLLED_BY);
+
 		priv->icon_sel = gnome_icon_selection_new ();
+		_add_atk_name_desc (priv->icon_sel,
+				    _("Icon selector"),
+				    _("Please pick the icon you want."));
 
 		gnome_icon_selection_add_directory (GNOME_ICON_SELECTION (priv->icon_sel),
 						    priv->pick_dialog_dir);
@@ -928,6 +939,10 @@ gnome_icon_entry_instance_init (GnomeIco
 	gtk_widget_show (ientry->_priv->pickbutton);
 
 	ientry->_priv->fentry = gnome_file_entry_new (NULL, _("Browse"));
+	_add_atk_name_desc (ientry->_priv->fentry,
+			    _("Icon path"),
+			    _("Here you should enter the name of the directory "
+			      "where icon images are located."));
 	/*BORPORP */
 	gnome_file_entry_set_modal (GNOME_FILE_ENTRY (ientry->_priv->fentry),
 				    TRUE);
@@ -955,6 +970,11 @@ gnome_icon_entry_instance_init (GnomeIco
 
 	/*just in case there is a default that is an image*/
 	entry_changed(w,ientry);
+
+	/* Set our accessible name and description */
+	_add_atk_name_desc (GTK_WIDGET (ientry->_priv->pickbutton),
+			    _("Icon Selector"),
+			    _("This button will open a window to let you select an icon."));
 }
 
 /**
diff -pNaur libgnomeui/libgnomeui/gnome-icon-list.c libgnomeui-new/libgnomeui/gnome-icon-list.c
--- libgnomeui/libgnomeui/gnome-icon-list.c	Thu Apr 18 05:08:48 2002
+++ libgnomeui-new/libgnomeui/gnome-icon-list.c	Thu Apr 18 05:08:30 2002
@@ -50,6 +50,7 @@
 #include <gdk/gdkkeysyms.h>
 
 #include <libgnomeuiP.h>
+#include "libgnomeui-access.h"
 
 /* Aliases to minimize screen use in my laptop */
 #define GIL(x)       GNOME_ICON_LIST(x)
@@ -223,6 +224,9 @@ struct _GnomeIconListPrivate {
 };
 
 
+static GType gil_accessible_get_type (void);
+
+
 static inline int
 icon_line_height (Gil *gil, IconLine *il)
 {
@@ -1055,6 +1059,7 @@ icon_list_append (Gil *gil, Icon *icon)
 {
 	GnomeIconListPrivate *priv;
 	int pos;
+	AtkObject *accessible;
 
 	priv = gil->_priv;
 
@@ -1077,6 +1082,17 @@ icon_list_append (Gil *gil, Icon *icon)
 	} else
 		priv->dirty = TRUE;
 
+	/* Notify the accessible object
+	 *
+	 * FIXME: do we need to pass the accessible object for the new child
+	 * as one of the signal parameters?
+	 */
+
+	accessible = _accessibility_get_atk_object (gil);
+	if (accessible)
+		g_signal_emit_by_name (accessible, "children_changed::add",
+				       priv->icons - 1, NULL, NULL);
+
 	return priv->icons - 1;
 }
 
@@ -1084,6 +1100,7 @@ static void
 icon_list_insert (Gil *gil, int pos, Icon *icon)
 {
 	GnomeIconListPrivate *priv;
+	AtkObject *accessible;
 
 	priv = gil->_priv;
 
@@ -1114,6 +1131,17 @@ icon_list_insert (Gil *gil, int pos, Ico
 		priv->dirty = TRUE;
 
 	sync_selection (gil, pos, SYNC_INSERT);
+
+	/* Notify the accessible object
+	 *
+	 * FIXME: do we need to pass the accessible object for the new child
+	 * as one of the signal parameters?
+	 */
+
+	accessible = _accessibility_get_atk_object (gil);
+	if (accessible)
+		g_signal_emit_by_name (accessible, "children_changed::add",
+				       pos, NULL, NULL);
 }
 
 /**
@@ -1246,6 +1274,7 @@ gnome_icon_list_remove (GnomeIconList *g
 	GnomeIconListPrivate *priv;
 	int was_selected;
 	Icon *icon;
+	AtkObject *accessible;
 
 	g_return_if_fail (gil != NULL);
 	g_return_if_fail (IS_GIL (gil));
@@ -1306,6 +1335,16 @@ gnome_icon_list_remove (GnomeIconList *g
 		gil_scrollbar_adjust (gil);
 	} else
 		priv->dirty = TRUE;
+
+	/* Notify the accessibility object
+	 *
+	 * FIXME: the child no longer exists!  Do we still need to pass its
+	 * corresponding accessible object as one of the signal parameters?
+	 */
+	accessible = _accessibility_get_atk_object (gil);
+	if (accessible)
+		g_signal_emit_by_name (accessible, "children_changed::remove",
+				       pos, NULL, NULL);
 }
 
 /**
@@ -1321,6 +1360,7 @@ gnome_icon_list_clear (GnomeIconList *gi
 {
 	GnomeIconListPrivate *priv;
 	int i;
+	AtkObject *accessible;
 
 	g_return_if_fail (gil != NULL);
 	g_return_if_fail (IS_GIL (gil));
@@ -1344,6 +1384,12 @@ gnome_icon_list_clear (GnomeIconList *gi
 		gil_scrollbar_adjust (gil);
 	} else
 		priv->dirty = TRUE;
+
+	/* Notify the accessible object */
+
+	accessible = _accessibility_get_atk_object (gil);
+	if (accessible)
+		g_signal_emit_by_name (accessible, "children_changed", 0, NULL, NULL);
 }
 
 static void
@@ -1633,6 +1679,23 @@ real_toggle_cursor_selection (Gil *gil)
 }
 
 
+/* Used from g_list_insert_sorted() */
+static gint
+selection_list_compare_cb (gconstpointer a, gconstpointer b)
+{
+	int ia, ib;
+
+	ia = GPOINTER_TO_INT (a);
+	ib = GPOINTER_TO_INT (b);
+
+	if (ia < ib)
+		return -1;
+	else if (ia > ib)
+		return 1;
+	else
+		return 0;
+}
+
 static void
 real_select_icon (Gil *gil, gint num, GdkEvent *event)
 {
@@ -1652,7 +1715,8 @@ real_select_icon (Gil *gil, gint num, Gd
 
 	icon->selected = TRUE;
 	gnome_icon_text_item_select (icon->text, TRUE);
-	priv->selection = g_list_append (priv->selection, GINT_TO_POINTER (num));
+	priv->selection = g_list_insert_sorted (priv->selection, GINT_TO_POINTER (num),
+						selection_list_compare_cb);
 }
 
 static void
@@ -2103,6 +2167,19 @@ gil_scroll (GtkWidget *widget, GdkEventS
 	return TRUE;
 }
 
+static AtkObject *
+gil_get_accessible (GtkWidget *widget)
+{
+	AtkObject *accessible;
+
+	if ((accessible = _accessibility_get_atk_object (widget)) != NULL)
+		return accessible;
+
+	accessible = g_object_new (gil_accessible_get_type (), NULL);
+
+	return _accessibility_set_atk_object_return (widget, accessible);
+}
+
 static void
 gnome_icon_list_class_init (GilClass *gil_class)
 {
@@ -2207,6 +2284,7 @@ gnome_icon_list_class_init (GilClass *gi
 	widget_class->focus_out_event = gil_focus_out;
 	widget_class->key_press_event = gil_key_press;
 	widget_class->scroll_event = gil_scroll;
+	widget_class->get_accessible = gil_get_accessible;
 
 	/* we override GtkLayout's set_scroll_adjustments signal instead
 	 * of creating a new signal so as to keep binary compatibility.
@@ -3021,3 +3099,303 @@ gnome_icon_list_get_icon_pixbuf_item (Gn
 	return icon->image;
 }
 
+
+
+/*** Accessible object for GnomeIconList ***/
+
+static void selection_interface_init (AtkSelectionIface *iface);
+
+static void gil_accessible_class_init (AtkObjectClass *class);
+
+/* AtkObjectClass implementations */
+static gint impl_get_n_children (AtkObject *accessible);
+static AtkObject *impl_ref_child (AtkObject *accessible, gint i);
+static void impl_initialize (AtkObject *accessible, gpointer data);
+
+/* AtkSelectionIface implementations */
+static gboolean impl_selection_add_selection (AtkSelection *selection, gint i);
+static gboolean impl_selection_clear_selection (AtkSelection *selection);
+static AtkObject* impl_selection_ref_selection (AtkSelection *selection, gint i);
+static gint impl_selection_get_selection_count (AtkSelection *selection);
+static gboolean impl_selection_is_child_selected (AtkSelection *selection, gint i);
+static gboolean impl_selection_remove_selection (AtkSelection *selection, gint i);
+static gboolean impl_selection_select_all_selection (AtkSelection *selection);
+
+static gpointer accessible_parent_class = NULL;
+
+
+/* get_type() function for the accessible object */
+static GType
+gil_accessible_get_type (void)
+{
+	static GType type;
+
+	if (!type) {
+		static GInterfaceInfo selection_info = {
+			(GInterfaceInitFunc) selection_interface_init,
+			NULL, /* interface_finalize */
+			NULL /* interface_data */
+		};
+
+		type = _accessibility_create_derived_type (
+			"GnomeIconListAccessible",
+			GNOME_TYPE_CANVAS,
+			gil_accessible_class_init);
+
+		g_type_add_interface_static (type, ATK_TYPE_SELECTION, &selection_info);
+	}
+
+	return type;
+}
+
+/* Fills the ATK selection interface vtable */
+static void
+selection_interface_init (AtkSelectionIface *iface)
+{
+	iface->add_selection = impl_selection_add_selection;
+	iface->clear_selection = impl_selection_clear_selection;
+	iface->ref_selection = impl_selection_ref_selection;
+	iface->get_selection_count = impl_selection_get_selection_count;
+	iface->is_child_selected = impl_selection_is_child_selected;
+	iface->remove_selection = impl_selection_remove_selection;
+	iface->select_all_selection = impl_selection_select_all_selection;
+}
+
+/* Class initialization function for the accessible object */
+static void
+gil_accessible_class_init (AtkObjectClass *class)
+{
+	accessible_parent_class = g_type_class_peek_parent (class);
+
+	class->get_n_children = impl_get_n_children;
+	class->ref_child = impl_ref_child;
+	class->initialize = impl_initialize;
+}
+
+
+
+/* AtkSelectionIface implementation */
+
+static gboolean
+impl_selection_add_selection (AtkSelection *selection, gint i)
+{
+	GtkWidget *widget;
+	GnomeIconList *gil;
+
+	widget = GTK_ACCESSIBLE (selection)->widget;
+	if (!widget)
+		return FALSE;
+
+	gil = GNOME_ICON_LIST (widget);
+	gnome_icon_list_select_icon (gil, i);
+	return TRUE;
+}
+
+static gboolean
+impl_selection_clear_selection (AtkSelection *selection)
+{
+	GtkWidget *widget;
+	GnomeIconList *gil;
+
+	widget = GTK_ACCESSIBLE (selection)->widget;
+	if (!widget)
+		return FALSE;
+
+	gil = GNOME_ICON_LIST (widget);
+	gnome_icon_list_unselect_all (gil);
+	return TRUE;
+}
+
+static AtkObject *
+impl_selection_ref_selection (AtkSelection *selection, gint i)
+{
+	GtkWidget *widget;
+	GnomeIconList *gil;
+	GList *sel, *l;
+	int n;
+	GnomeIconTextItem *iti;
+	AtkObject *atk_object;
+
+	widget = GTK_ACCESSIBLE (selection)->widget;
+	if (!widget)
+		return FALSE;
+
+	gil = GNOME_ICON_LIST (widget);
+
+	sel = gnome_icon_list_get_selection (gil);
+	l = g_list_nth (sel, i);
+	if (!l)
+		return NULL;
+
+	n = GPOINTER_TO_INT (l->data);
+	iti = gnome_icon_list_get_icon_text_item (gil, n);
+	if (!iti)
+		return NULL;
+
+	/* FIXME: is this what we need to return?  How do we distinguish between
+	 * the icon text item and the pixbuf?
+	 */
+	atk_object = atk_gobject_accessible_for_object (G_OBJECT (iti));
+	g_object_ref (atk_object);
+	return atk_object;
+}
+
+static gint
+impl_selection_get_selection_count (AtkSelection *selection)
+{
+	GtkWidget *widget;
+	GnomeIconList *gil;
+	GList *sel;
+
+	widget = GTK_ACCESSIBLE (selection)->widget;
+	if (!widget)
+		return FALSE;
+
+	gil = GNOME_ICON_LIST (widget);
+	sel = gnome_icon_list_get_selection (gil);
+	return g_list_length (sel);
+}
+
+static gboolean
+impl_selection_is_child_selected (AtkSelection *selection, gint i)
+{
+	GtkWidget *widget;
+	GnomeIconList *gil;
+	GList *l;
+
+	widget = GTK_ACCESSIBLE (selection)->widget;
+	if (!widget)
+		return FALSE;
+
+	gil = GNOME_ICON_LIST (widget);
+	for (l = gnome_icon_list_get_selection (gil); l; l = l->next) {
+		int k;
+
+		k = GPOINTER_TO_INT (l->data);
+		if (k == i)
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+static gboolean
+impl_selection_remove_selection (AtkSelection *selection, gint i)
+{
+	GtkWidget *widget;
+	GnomeIconList *gil;
+	GList *sel, *l;
+	int n;
+
+	widget = GTK_ACCESSIBLE (selection)->widget;
+	if (!widget)
+		return FALSE;
+
+	gil = GNOME_ICON_LIST (widget);
+
+	sel = gnome_icon_list_get_selection (gil);
+	l = g_list_nth (sel, i);
+	if (!l)
+		return FALSE;
+
+	n = GPOINTER_TO_INT (l->data);
+
+	gnome_icon_list_unselect_icon (gil, n);
+	return TRUE;
+}
+
+static gboolean
+impl_selection_select_all_selection (AtkSelection *selection)
+{
+	GtkWidget *widget;
+	GnomeIconList *gil;
+	int n, i;
+
+	widget = GTK_ACCESSIBLE (selection)->widget;
+	if (!widget)
+		return FALSE;
+
+	gil = GNOME_ICON_LIST (widget);
+
+	if (gnome_icon_list_get_selection_mode (gil) != GTK_SELECTION_MULTIPLE)
+		return FALSE;
+
+	n = gnome_icon_list_get_num_icons (gil);
+
+	for (i = 0; i < n; i++)
+		gnome_icon_list_select_icon (gil, i);
+
+	return TRUE;
+}
+
+
+
+/* AtkObjectClass implementations */
+
+static gint
+impl_get_n_children (AtkObject *accessible)
+{
+	GtkWidget *widget;
+	GnomeIconList *gil;
+
+	widget = GTK_ACCESSIBLE (accessible)->widget;
+	if (!widget)
+		return 0;
+
+	gil = GNOME_ICON_LIST (widget);
+
+	return gnome_icon_list_get_num_icons (gil);
+}
+
+static AtkObject *
+impl_ref_child (AtkObject *accessible, gint i)
+{
+	GtkWidget *widget;
+	GnomeIconList *gil;
+	GnomeIconTextItem *iti;
+	AtkObject *atk_object;
+
+	widget = GTK_ACCESSIBLE (accessible)->widget;
+	if (!widget)
+		return NULL;
+
+	gil = GNOME_ICON_LIST (widget);
+
+	iti = gnome_icon_list_get_icon_text_item (gil, i);
+	if (!iti)
+		return NULL;
+
+	/* FIXME: is this what we need to return?  How do we distinguish between
+	 * the icon text item and the pixbuf?
+	 */
+	atk_object = atk_gobject_accessible_for_object (G_OBJECT (iti));
+	g_object_ref (atk_object);
+	return atk_object;
+}
+
+/* Callback used when an icon changes its selection status */
+static void
+select_icon_cb (GnomeIconList *gil, gint num, GdkEvent *event, gpointer data)
+{
+	AtkObject *accessible;
+
+	accessible = ATK_OBJECT (data);
+	g_signal_emit_by_name (accessible, "selection_changed");
+}
+
+static void
+impl_initialize (AtkObject *accessible, gpointer data)
+{
+	GnomeIconList *gil;
+
+	ATK_OBJECT_CLASS (accessible_parent_class)->initialize (accessible, data);
+
+	gil = GNOME_ICON_LIST (GTK_ACCESSIBLE (accessible)->widget);
+
+	/* We use the same callback for both signals as the handler would do the
+	 * same thing for both.
+	 */
+	g_signal_connect (gil, "select_icon", G_CALLBACK (select_icon_cb), accessible);
+	g_signal_connect (gil, "unselect_icon", G_CALLBACK (select_icon_cb), accessible);
+}
+
diff -pNaur libgnomeui/libgnomeui/gnome-icon-sel.c libgnomeui-new/libgnomeui/gnome-icon-sel.c
--- libgnomeui/libgnomeui/gnome-icon-sel.c	Thu Apr 18 05:08:48 2002
+++ libgnomeui-new/libgnomeui/gnome-icon-sel.c	Thu Apr 18 05:08:30 2002
@@ -39,6 +39,7 @@
 #include "gnome-uidefs.h"
 
 #include "gnome-icon-sel.h"
+#include "libgnomeui-access.h"
 
 #include <libgnomevfs/gnome-vfs-ops.h>
 
@@ -409,6 +410,8 @@ gnome_icon_selection_show_icons (GnomeIc
 		return;
 
 	label = gtk_label_new (_("Loading Icons..."));
+	_add_atk_relation (GTK_WIDGET (gis), label,
+			   ATK_RELATION_LABELLED_BY, ATK_RELATION_LABEL_FOR);
 	gtk_box_pack_start (GTK_BOX (gis->_priv->box),
 			    label, FALSE, FALSE, 0);
 	gtk_widget_show (label);
@@ -417,6 +420,8 @@ gnome_icon_selection_show_icons (GnomeIc
 			  &label);
 
 	progressbar = gtk_progress_bar_new ();
+	_add_atk_relation (progressbar, label,
+			   ATK_RELATION_LABELLED_BY, ATK_RELATION_LABEL_FOR);
 	gtk_box_pack_start (GTK_BOX (gis->_priv->box),
 			    progressbar, FALSE, FALSE, 0);
 	gtk_widget_show (progressbar);
diff -pNaur libgnomeui/libgnomeui/gnome-pixmap-entry.c libgnomeui-new/libgnomeui/gnome-pixmap-entry.c
--- libgnomeui/libgnomeui/gnome-pixmap-entry.c	Thu Apr 18 05:08:48 2002
+++ libgnomeui-new/libgnomeui/gnome-pixmap-entry.c	Thu Apr 18 05:08:30 2002
@@ -57,6 +57,8 @@
 
 #include <libgnomevfs/gnome-vfs-uri.h>
 
+#include "libgnomeui-access.h"
+
 struct _GnomePixmapEntryPrivate {
 	GtkWidget *preview;
 	GtkWidget *preview_sw;
@@ -206,6 +208,10 @@ refresh_preview(GnomePixmapEntry *pentry
         } else {
 		gtk_widget_destroy(pentry->_priv->preview->parent);
 		pentry->_priv->preview = gtk_image_new_from_pixbuf (pixbuf);
+		_add_atk_name_desc (pentry->_priv->preview,
+				    _("Image Preview"),
+				    _("A preview of the image currently specified"));
+
 		gtk_widget_show(pentry->_priv->preview);
 		gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(pentry->_priv->preview_sw),
 						      pentry->_priv->preview);
diff -pNaur libgnomeui/libgnomeui/libgnomeui-access.c libgnomeui-new/libgnomeui/libgnomeui-access.c
--- libgnomeui/libgnomeui/libgnomeui-access.c	Wed Dec 31 19:00:00 1969
+++ libgnomeui-new/libgnomeui/libgnomeui-access.c	Thu Apr 18 05:08:30 2002
@@ -0,0 +1,280 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Copyright 2002 Sun Microsystems Inc.
+ *
+ * Lib GNOME UI Accessibility support module
+ *
+ * This code copied from Wipro's panel-access.c.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+#include <config.h>
+#include <gtk/gtkwidget.h>
+#include <gtk/gtkaccessible.h>
+#include <atk/atkrelationset.h>
+#include "libgnomeui-access.h"
+
+static gint is_gail_loaded (GtkWidget *widget);
+
+/* variable that indicates whether GAIL is loaded or not */
+gint gail_loaded = -1;
+
+/* Accessibility support routines for libgnomeui */
+static gint
+is_gail_loaded (GtkWidget *widget)
+{
+	AtkObject *aobj;
+	if (gail_loaded == -1) {
+		aobj = gtk_widget_get_accessible (widget);
+		if (!GTK_IS_ACCESSIBLE (aobj))
+			gail_loaded = 0;
+		else
+			gail_loaded = 1;
+	}
+	return gail_loaded;
+}
+
+/* routine to add accessible name and description to an atk object */
+void
+_add_atk_name_desc (GtkWidget *widget, gchar *name, gchar *desc)
+{
+	AtkObject *aobj;
+
+	g_return_if_fail (GTK_IS_WIDGET (widget));
+
+	if (! is_gail_loaded (widget))
+		return;
+
+	aobj = gtk_widget_get_accessible (widget);
+
+	if (name)
+		atk_object_set_name (aobj, name);
+	if (desc)
+		atk_object_set_description (aobj, desc);
+}
+
+void
+_add_atk_description (GtkWidget *widget,
+		      gchar     *desc)
+{
+	_add_atk_name_desc (widget, NULL, desc);
+}
+
+void
+_add_atk_relation (GtkWidget *widget1, GtkWidget *widget2,
+		   AtkRelationType w1_to_w2, AtkRelationType w2_to_w1)
+{
+	AtkObject      *atk_widget1;
+	AtkObject      *atk_widget2;
+	AtkRelationSet *relation_set;
+	AtkRelation    *relation;
+	AtkObject      *targets[1];
+
+	atk_widget1 = gtk_widget_get_accessible (widget1);
+	atk_widget2 = gtk_widget_get_accessible (widget2);
+
+	/* Create the widget1 -> widget2 relation */
+	relation_set = atk_object_ref_relation_set (atk_widget1);
+	targets[0] = atk_widget2;
+	relation = atk_relation_new (targets, 1, w1_to_w2);
+	atk_relation_set_add (relation_set, relation);
+	g_object_unref (relation);
+
+	/* Create the widget2 -> widget1 relation */
+	relation_set = atk_object_ref_relation_set (atk_widget2);
+	targets[0] = atk_widget1;
+	relation = atk_relation_new (targets, 1, w2_to_w1);
+	atk_relation_set_add (relation_set, relation);
+	g_object_unref (relation);
+}
+
+
+
+/* Copied from eel */
+
+static GQuark
+get_quark_accessible (void)
+{
+	static GQuark quark_accessible_object = 0;
+
+	if (!quark_accessible_object) {
+		quark_accessible_object = g_quark_from_static_string
+			("accessible-object");
+	}
+
+	return quark_accessible_object;
+}
+
+static GQuark
+get_quark_gobject (void)
+{
+	static GQuark quark_accessible_gobject = 0;
+
+	if (!quark_accessible_gobject) {
+		quark_accessible_gobject = g_quark_from_static_string
+			("object-for-accessible");
+	}
+
+	return quark_accessible_gobject;
+}
+
+/**
+ * _accessibility_get_atk_object:
+ * @object: a GObject of some sort
+ * 
+ * gets an AtkObject associated with a GObject
+ * 
+ * Return value: the associated accessible if one exists or NULL
+ **/
+AtkObject *
+_accessibility_get_atk_object (gpointer object)
+{
+	return g_object_get_qdata (object, get_quark_accessible ());
+}
+
+/**
+ * _accessibilty_for_object:
+ * @object: a GObject of some sort
+ * 
+ * gets an AtkObject associated with a GObject and if it doesn't
+ * exist creates a suitable accessible object.
+ * 
+ * Return value: an associated accessible.
+ **/
+AtkObject *
+_accessibility_for_object (gpointer object)
+{
+	if (GTK_IS_WIDGET (object))
+		return gtk_widget_get_accessible (object);
+
+	return atk_gobject_accessible_for_object (object);
+}
+
+/**
+ * _accessibility_get_gobject:
+ * @object: an AtkObject
+ * 
+ * gets the GObject associated with the AtkObject, for which
+ * @object provides accessibility support.
+ * 
+ * Return value: the accessible's associated GObject
+ **/
+gpointer
+_accessibility_get_gobject (AtkObject *object)
+{
+	return g_object_get_qdata (G_OBJECT (object), get_quark_gobject ());
+}
+
+static void
+_accessibility_weak_unref (gpointer data,
+			   GObject *where_the_object_was)
+{
+	g_object_set_qdata (data, get_quark_gobject (), NULL);
+
+	atk_object_notify_state_change
+		(ATK_OBJECT (data), ATK_STATE_DEFUNCT, TRUE); 
+
+	g_object_unref (data);
+}
+
+/**
+ * _accessibility_set_atk_object_return:
+ * @object: a GObject
+ * @atk_object: it's AtkObject
+ * 
+ * used to register and return a new accessible object for something
+ * 
+ * Return value: @atk_object.
+ **/
+AtkObject *
+_accessibility_set_atk_object_return (gpointer   object,
+					 AtkObject *atk_object)
+{
+	atk_object_initialize (atk_object, object);
+
+	if (!ATK_IS_GOBJECT_ACCESSIBLE (atk_object)) {
+		g_object_weak_ref (object, _accessibility_weak_unref, atk_object);
+		g_object_set_qdata
+			(object, get_quark_accessible (), atk_object);
+		g_object_set_qdata
+			(G_OBJECT (atk_object), get_quark_gobject (), object);
+	}
+
+	return atk_object;
+}
+
+/**
+ * _accessibility_create_derived_type:
+ * @type_name: the name for the new accessible type eg. NautilusIconCanvasItemAccessible
+ * @existing_gobject_with_proxy: the GType of an object that has a registered factory that
+ *      manufactures the type we want to inherit from. ie. to inherit from a GailCanvasItem
+ *      we need to pass GNOME_TYPE_CANVAS_ITEM - since GailCanvasItem is registered against
+ *      that type.
+ * @class_init: the init function to run for this class
+ * 
+ * This should be run to register the type, it can subsequently be run with
+ * the same name and will not re-register it, but simply return it.
+ *
+ * NB. to do instance init, you prolly want to override AtkObject::initialize
+ * 
+ * Return value: the registered type, or 0 on failure.
+ **/
+GType
+_accessibility_create_derived_type (const char *type_name,
+				    GType existing_gobject_with_proxy,
+				    _AccessibilityClassInitFn class_init)
+{
+	GType type;
+	GType parent_atk_type;
+	GTypeInfo tinfo = { 0 };
+	GTypeQuery query;
+	AtkObjectFactory *factory;
+
+	if ((type = g_type_from_name (type_name))) {
+		return type;
+	}
+
+	factory = atk_registry_get_factory
+		(atk_get_default_registry (),
+		 existing_gobject_with_proxy);
+	if (!factory) {
+		return G_TYPE_INVALID;
+	}
+	
+	parent_atk_type = atk_object_factory_get_accessible_type (factory);
+	if (!parent_atk_type) {
+		return G_TYPE_INVALID;
+	}
+
+	/*
+	 * Figure out the size of the class and instance 
+	 * we are deriving from
+	 */
+	g_type_query (parent_atk_type, &query);
+
+	if (class_init) {
+		tinfo.class_init = (GClassInitFunc) class_init;
+	}
+
+	tinfo.class_size    = query.class_size;
+	tinfo.instance_size = query.instance_size;
+
+	/* Register the type */
+	type = g_type_register_static (
+		parent_atk_type, type_name, &tinfo, 0);
+
+	return type;
+}
diff -pNaur libgnomeui/libgnomeui/libgnomeui-access.h libgnomeui-new/libgnomeui/libgnomeui-access.h
--- libgnomeui/libgnomeui/libgnomeui-access.h	Wed Dec 31 19:00:00 1969
+++ libgnomeui-new/libgnomeui/libgnomeui-access.h	Thu Apr 18 05:08:30 2002
@@ -0,0 +1,38 @@
+#ifndef __LIBGNOMEUI_ACCESS_H__
+#define __LIBGNOMEUI_ACCESS_H__
+/*
+ * Accessibility convenience functions.
+ *
+ * Copyright 2002, Sun Microsystems.
+ */
+
+#include <glib-object.h>
+#include <atk/atkobject.h>
+#include <atk/atkregistry.h>
+#include <atk/atkrelationset.h>
+#include <atk/atkobjectfactory.h>
+#include <gtk/gtkwidget.h>
+#include <gtk/gtklabel.h>
+
+void _add_atk_name_desc   (GtkWidget *widget, gchar *name, gchar *desc);
+void _add_atk_description (GtkWidget *widget, gchar *desc);
+void _add_atk_relation    (GtkWidget *widget1, GtkWidget *widget2,
+			   AtkRelationType w1_to_w2, AtkRelationType w2_to_w1);
+
+
+
+/* Copied from eel */
+
+typedef void     (*_AccessibilityClassInitFn)    (AtkObjectClass *klass);
+
+AtkObject    *_accessibility_get_atk_object        (gpointer              object);
+AtkObject    *_accessibility_for_object            (gpointer              object);
+gpointer      _accessibility_get_gobject           (AtkObject            *object);
+AtkObject    *_accessibility_set_atk_object_return (gpointer              object,
+						    AtkObject            *atk_object);
+GType         _accessibility_create_derived_type   (const char           *type_name,
+						    GType                 existing_gobject_with_proxy,
+						    _AccessibilityClassInitFn class_init);
+
+
+#endif /* ! __LIBGNOMEUI_ACCESS_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]