]> Pileus Git - ~andy/gtk/blob - gtk/a11y/gtkrangeaccessible.c
treeview: Signal selection changes to the accessible
[~andy/gtk] / gtk / a11y / gtkrangeaccessible.c
1 /* GAIL - The GNOME Accessibility Implementation Library
2  * Copyright 2001, 2002, 2003 Sun Microsystems Inc.
3  *
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.
8  *
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.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include <string.h>
23 #include <gtk/gtk.h>
24 #include "gtkrangeaccessible.h"
25
26
27 static void atk_action_interface_init (AtkActionIface *iface);
28 static void atk_value_interface_init  (AtkValueIface  *iface);
29
30 G_DEFINE_TYPE_WITH_CODE (GtkRangeAccessible, _gtk_range_accessible, GTK_TYPE_WIDGET_ACCESSIBLE,
31                          G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init)
32                          G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init))
33
34 static void
35 gtk_range_accessible_value_changed (GtkAdjustment *adjustment,
36                                     gpointer       data)
37 {
38   g_object_notify (G_OBJECT (data), "accessible-value");
39 }
40
41 static void
42 gtk_range_accessible_initialize (AtkObject *obj,
43                                  gpointer   data)
44 {
45   GtkRangeAccessible *range = GTK_RANGE_ACCESSIBLE (obj);
46   GtkAdjustment *adj;
47   GtkRange *gtk_range;
48
49   ATK_OBJECT_CLASS (_gtk_range_accessible_parent_class)->initialize (obj, data);
50
51   gtk_range = GTK_RANGE (data);
52   /*
53    * If a GtkAdjustment already exists for the GtkRange,
54    * create the GailAdjustment
55    */
56   adj = gtk_range_get_adjustment (gtk_range);
57   if (adj)
58     g_signal_connect (adj, "value-changed",
59                       G_CALLBACK (gtk_range_accessible_value_changed),
60                       range);
61
62   obj->role = ATK_ROLE_SLIDER;
63 }
64
65 static void
66 gtk_range_accessible_finalize (GObject *object)
67 {
68   GtkRangeAccessible *range = GTK_RANGE_ACCESSIBLE (object);
69   GtkWidget *widget;
70   GtkAdjustment *adj;
71
72   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (object));
73   if (widget)
74     {
75       adj = gtk_range_get_adjustment (GTK_RANGE (widget));
76       if (adj)
77         g_signal_handlers_disconnect_by_func (adj,
78                                               gtk_range_accessible_value_changed,
79                                               range);
80     }
81
82   G_OBJECT_CLASS (_gtk_range_accessible_parent_class)->finalize (object);
83 }
84
85 static void
86 gtk_range_accessible_notify_gtk (GObject    *obj,
87                                  GParamSpec *pspec)
88 {
89   GtkWidget *widget = GTK_WIDGET (obj);
90   GtkAdjustment *adj;
91   AtkObject *range;
92
93   if (strcmp (pspec->name, "adjustment") == 0)
94     {
95       range = gtk_widget_get_accessible (widget);
96       adj = gtk_range_get_adjustment (GTK_RANGE (widget));
97       g_signal_connect (adj, "value-changed",
98                         G_CALLBACK (gtk_range_accessible_value_changed),
99                         range);
100     }
101   else
102     GTK_WIDGET_ACCESSIBLE_CLASS (_gtk_range_accessible_parent_class)->notify_gtk (obj, pspec);
103 }
104
105
106 static void
107 _gtk_range_accessible_class_init (GtkRangeAccessibleClass *klass)
108 {
109   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
110   AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
111   GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
112
113   widget_class->notify_gtk = gtk_range_accessible_notify_gtk;
114
115   class->initialize = gtk_range_accessible_initialize;
116
117   gobject_class->finalize = gtk_range_accessible_finalize;
118 }
119
120 static void
121 _gtk_range_accessible_init (GtkRangeAccessible *range)
122 {
123 }
124
125 static void
126 gtk_range_accessible_get_current_value (AtkValue *obj,
127                                         GValue   *value)
128 {
129   GtkWidget *widget;
130   GtkAdjustment *adjustment;
131
132   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
133   adjustment = gtk_range_get_adjustment (GTK_RANGE (widget));
134   if (adjustment == NULL)
135     return;
136
137   memset (value,  0, sizeof (GValue));
138   g_value_init (value, G_TYPE_DOUBLE);
139   g_value_set_double (value, gtk_adjustment_get_value (adjustment));
140 }
141
142 static void
143 gtk_range_accessible_get_maximum_value (AtkValue *obj,
144                                         GValue   *value)
145 {
146   GtkWidget *widget;
147   GtkAdjustment *adjustment;
148   gdouble max;
149
150   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
151   adjustment = gtk_range_get_adjustment (GTK_RANGE (widget));
152   if (adjustment == NULL)
153     return;
154
155   max = gtk_adjustment_get_upper (adjustment)
156         - gtk_adjustment_get_page_size (adjustment);
157
158   if (gtk_range_get_restrict_to_fill_level (GTK_RANGE (widget)))
159     max = MIN (max, gtk_range_get_fill_level (GTK_RANGE (widget)));
160
161   memset (value,  0, sizeof (GValue));
162   g_value_init (value, G_TYPE_DOUBLE);
163   g_value_set_double (value, max);
164 }
165
166 static void
167 gtk_range_accessible_get_minimum_value (AtkValue *obj,
168                                         GValue   *value)
169 {
170   GtkWidget *widget;
171   GtkAdjustment *adjustment;
172
173   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
174   adjustment = gtk_range_get_adjustment (GTK_RANGE (widget));
175   if (adjustment == NULL)
176     return;
177
178   memset (value,  0, sizeof (GValue));
179   g_value_init (value, G_TYPE_DOUBLE);
180   g_value_set_double (value, gtk_adjustment_get_lower (adjustment));
181 }
182
183 static void
184 gtk_range_accessible_get_minimum_increment (AtkValue *obj,
185                                             GValue   *value)
186 {
187   GtkWidget *widget;
188   GtkAdjustment *adjustment;
189
190   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
191   adjustment = gtk_range_get_adjustment (GTK_RANGE (widget));
192   if (adjustment == NULL)
193     return;
194
195   memset (value,  0, sizeof (GValue));
196   g_value_init (value, G_TYPE_DOUBLE);
197   g_value_set_double (value, gtk_adjustment_get_minimum_increment (adjustment));
198 }
199
200 static gboolean
201 gtk_range_accessible_set_current_value (AtkValue     *obj,
202                                         const GValue *value)
203 {
204  GtkWidget *widget;
205   GtkAdjustment *adjustment;
206
207   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
208   adjustment = gtk_range_get_adjustment (GTK_RANGE (widget));
209   if (adjustment == NULL)
210     return FALSE;
211
212   gtk_adjustment_set_value (adjustment, g_value_get_double (value));
213
214   return TRUE;
215 }
216
217 static void
218 atk_value_interface_init (AtkValueIface *iface)
219 {
220   iface->get_current_value = gtk_range_accessible_get_current_value;
221   iface->get_maximum_value = gtk_range_accessible_get_maximum_value;
222   iface->get_minimum_value = gtk_range_accessible_get_minimum_value;
223   iface->get_minimum_increment = gtk_range_accessible_get_minimum_increment;
224   iface->set_current_value = gtk_range_accessible_set_current_value;
225 }
226
227 static gboolean
228 gtk_range_accessible_do_action (AtkAction *action,
229                                 gint       i)
230 {
231   GtkWidget *widget;
232
233   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
234   if (widget == NULL)
235     return FALSE;
236
237   if (!gtk_widget_get_sensitive (widget) || !gtk_widget_get_visible (widget))
238     return FALSE;
239
240   if (i != 0)
241     return FALSE;
242
243   gtk_widget_activate (widget);
244
245   return TRUE;
246 }
247
248 static gint
249 gtk_range_accessible_get_n_actions (AtkAction *action)
250 {
251     return 1;
252 }
253
254 static const gchar *
255 gtk_range_accessible_get_keybinding (AtkAction *action,
256                                      gint       i)
257 {
258   GtkRangeAccessible *range = GTK_RANGE_ACCESSIBLE (action);
259   GtkWidget *widget;
260   GtkWidget *label;
261   AtkRelationSet *set;
262   AtkRelation *relation;
263   GPtrArray *target;
264   gpointer target_object;
265   guint key_val;
266   gchar *return_value = NULL;
267
268   if (i != 0)
269     return NULL;
270
271   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (range));
272   if (widget == NULL)
273    return NULL;
274
275   set = atk_object_ref_relation_set (ATK_OBJECT (action));
276
277   if (!set)
278     return NULL;
279
280   label = NULL;
281   relation = atk_relation_set_get_relation_by_type (set, ATK_RELATION_LABELLED_BY);
282   if (relation)
283     {
284       target = atk_relation_get_target (relation);
285       target_object = g_ptr_array_index (target, 0);
286       label = gtk_accessible_get_widget (GTK_ACCESSIBLE (target_object));
287     }
288   g_object_unref (set);
289
290   if (GTK_IS_LABEL (label))
291     {
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);
295     }
296
297   return return_value;
298 }
299
300 static const gchar *
301 gtk_range_accessible_action_get_name (AtkAction *action,
302                                       gint       i)
303 {
304   if (i != 0)
305     return NULL;
306
307   return "activate";
308 }
309
310 static void
311 atk_action_interface_init (AtkActionIface *iface)
312 {
313   iface->do_action = gtk_range_accessible_do_action;
314   iface->get_n_actions = gtk_range_accessible_get_n_actions;
315   iface->get_keybinding = gtk_range_accessible_get_keybinding;
316   iface->get_name = gtk_range_accessible_action_get_name;
317 }