Index: ChangeLog
===================================================================
--- ChangeLog   （版本 1284）
+++ ChangeLog   （工作副本）
@@ -1,3 +1,9 @@
+2007-09-29  Liyan Zhang  <Li-Yan.Zhang@sun.com>
+
+       * gail/gailrange.c: (gail_range_get_keybinding):
+       Bug #474575. Add the function of get keybinding to range and implement
+       the action interface as well.
+
 2007-08-07  Sunil Mohan Adapa  <sunil@atc.tcs.com>
 
        * configure.in: Added Telugu (te) to ALL_LINGUAS.
Index: gail/gailrange.c
===================================================================
--- gail/gailrange.c    （版本 1284）
+++ gail/gailrange.c    （工作副本）
@@ -19,6 +19,7 @@
 
 #include <string.h>
 #include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
 #include "gailrange.h"
 #include "gailadjustment.h"
 #include "gail-private-macros.h"
@@ -29,6 +30,7 @@
                                                   gpointer      data);
 
 static void         gail_range_finalize          (GObject        *object);
+
 static AtkStateSet* gail_range_ref_state_set     (AtkObject      *obj);
 
 
@@ -46,6 +48,21 @@
                                                   const GValue   *value);
 static void         gail_range_value_changed     (GtkAdjustment  *adjustment,
                                                   gpointer       data);
+
+static void         atk_action_interface_init    (AtkActionIface *iface);
+static gboolean     gail_range_do_action        (AtkAction       *action,
+                                                gint            i);
+static gboolean     idle_do_action              (gpointer        data);
+static gint         gail_range_get_n_actions    (AtkAction       *action);
+static G_CONST_RETURN gchar* gail_range_get_description  (AtkAction    *action, 
+                                                         gint          i);
+static G_CONST_RETURN gchar* gail_range_get_keybinding   (AtkAction     *action,
+                                                         gint            i);
+static G_CONST_RETURN gchar* gail_range_action_get_name  (AtkAction    *action,
+                                                        gint            i);
+static gboolean   gail_range_set_description  (AtkAction       *action,
+                                              gint            i,
+                                              const gchar     *desc);
 static GailWidgetClass *parent_class = NULL;
 
 GType
@@ -69,6 +86,14 @@
         NULL /* value table */
       };
 
+      static const GInterfaceInfo atk_action_info =
+      {
+       (GInterfaceInitFunc) atk_action_interface_init,
+       (GInterfaceFinalizeFunc) NULL,
+       NULL
+      };
+
+
       static const GInterfaceInfo atk_value_info =
       {
         (GInterfaceInitFunc) atk_value_interface_init,
@@ -79,6 +104,9 @@
       type = g_type_register_static (GAIL_TYPE_WIDGET,
                                      "GailRange", &tinfo, 0);
 
+      g_type_add_interface_static (type, ATK_TYPE_ACTION,
+                                       &atk_action_info);
+
       g_type_add_interface_static (type, ATK_TYPE_VALUE,
                                    &atk_value_info);
     }
@@ -144,7 +172,8 @@
     }
   else
     range->adjustment = NULL;
-
+  range->activate_keybinding=NULL;
+  range->activate_description=NULL;
   /*
    * Assumed to GtkScale (either GtkHScale or GtkVScale)
    */
@@ -290,6 +319,14 @@
       g_object_unref (range->adjustment);
       range->adjustment = NULL;
     }
+  range->activate_keybinding=NULL;
+  range->activate_description=NULL;
+  if (range->action_idle_handler)
+   {
+    g_source_remove (range->action_idle_handler);
+    range->action_idle_handler = 0;
+   }
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -339,3 +376,179 @@
 
   g_object_notify (G_OBJECT (range), "accessible-value");
 }
+
+static void
+atk_action_interface_init (AtkActionIface *iface)
+{
+  g_return_if_fail (iface != NULL);
+ 
+  iface->do_action = gail_range_do_action;
+  iface->get_n_actions = gail_range_get_n_actions;
+  iface->get_description = gail_range_get_description;
+  iface->get_keybinding = gail_range_get_keybinding;
+  iface->get_name = gail_range_action_get_name;
+  iface->set_description = gail_range_set_description;
+}
+
+static gboolean
+gail_range_do_action (AtkAction *action,
+                     gint      i)
+{
+  GailRange *range;
+  GtkWidget *widget;
+  gboolean return_value = TRUE;
+
+  range = GAIL_RANGE (action);
+  widget = GTK_ACCESSIBLE (action)->widget;
+  if (widget == NULL)
+    /*
+     * State is defunct
+     */
+    return FALSE;
+  if (!GTK_WIDGET_SENSITIVE (widget) || !GTK_WIDGET_VISIBLE (widget))
+    return FALSE;
+  if(i==0)
+   {
+    if (range->action_idle_handler)
+      return_value = FALSE;
+    else
+      range->action_idle_handler = g_idle_add (idle_do_action, range);
+   }
+  else
+     return_value = FALSE;
+  return return_value;
+}
+
+static gboolean
+idle_do_action (gpointer data)
+{
+  GailRange *range;
+  GtkWidget *widget;
+
+  GDK_THREADS_ENTER ();
+
+  range = GAIL_RANGE (data);
+  range->action_idle_handler = 0;
+  widget = GTK_ACCESSIBLE (range)->widget;
+  if (widget == NULL /* State is defunct */ ||
+     !GTK_WIDGET_SENSITIVE (widget) || !GTK_WIDGET_VISIBLE (widget))
+   {
+    GDK_THREADS_LEAVE ();
+    return FALSE;
+   }
+
+   gtk_widget_activate (widget);
+
+   GDK_THREADS_LEAVE ();
+
+   return FALSE;
+}
+
+static gint
+gail_range_get_n_actions (AtkAction *action)
+{
+    return 1;
+}
+
+static G_CONST_RETURN gchar*
+gail_range_get_description (AtkAction *action,
+                              gint      i)
+{
+  GailRange *range;
+  G_CONST_RETURN gchar *return_value;
+
+  range = GAIL_RANGE (action);
+  if (i==0)
+   return_value = range->activate_description;
+  else
+   return_value = NULL;
+  return return_value;
+}
+
+static G_CONST_RETURN gchar*
+gail_range_get_keybinding (AtkAction *action,
+                              gint      i)
+{
+  GailRange *range;
+  gchar *return_value = NULL;
+  range = GAIL_RANGE (action);
+  if(i==0)
+   {
+    GtkWidget *widget;
+    GtkWidget *label;
+    AtkRelationSet *set;
+    AtkRelation *relation;
+    GPtrArray *target;
+    gpointer target_object;
+    guint key_val;
+
+    range = GAIL_RANGE (action);
+    widget = GTK_ACCESSIBLE (range)->widget;
+    if (widget == NULL)
+       return NULL;
+    set = atk_object_ref_relation_set (ATK_OBJECT (action));
+
+    if (!set)
+      return NULL;
+    label = NULL;
+    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);
+      if (GTK_IS_ACCESSIBLE (target_object))
+         label = GTK_ACCESSIBLE (target_object)->widget;
+     }
+    g_object_unref (set);
+    if (GTK_IS_LABEL (label))
+     {
+      key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
+      if (key_val != GDK_VoidSymbol)
+         return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK);
+      }
+    g_free (range->activate_keybinding);
+    range->activate_keybinding = return_value;
+   }
+  return return_value;
+}
+
+static G_CONST_RETURN gchar*
+gail_range_action_get_name (AtkAction *action,
+                           gint      i)
+{
+  G_CONST_RETURN gchar *return_value;
+  
+  if (i==0)
+   return_value = "activate";
+  else
+   return_value = NULL;
+
+  return return_value;
+}
+
+static gboolean
+gail_range_set_description (AtkAction      *action,
+                           gint           i,
+                           const gchar    *desc)
+{
+  GailRange *range;
+  gchar **value;
+
+  range = GAIL_RANGE (action);
+  
+  if (i==0)
+   value = &range->activate_description;
+  else
+   value = NULL;
+
+  if (value)
+   {
+    g_free (*value);
+    *value = g_strdup (desc);
+    return TRUE;
+   }
+  else
+   return FALSE;
+}
+
+
Index: gail/gailrange.h
===================================================================
--- gail/gailrange.h    （版本 1284）
+++ gail/gailrange.h    （工作副本）
@@ -43,6 +43,10 @@
   GailWidget parent;
 
   AtkObject *adjustment;
+  gchar     *activate_description;
+  gchar     *activate_keybinding;
+  guint     action_idle_handler;
+
 };
 
 GType gail_range_get_type (void);

