AtkValue: refactoring AtkValue
[platform/upstream/atk.git] / atk / atkvalue.c
1 /* ATK -  Accessibility Toolkit
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 <glib/gi18n-lib.h>
24
25 #include "atkvalue.h"
26 #include "atkmarshal.h"
27 #include "atk-enum-types.h"
28 #include "atkprivate.h"
29
30 /**
31  * SECTION:atkvalue
32  * @Short_description: The ATK interface implemented by valuators and
33  *  components which display or select a value from a bounded range of
34  *  values.
35  * @Title:AtkValue
36  *
37  * #AtkValue should be implemented for components which either display
38  * a value from a bounded range, or which allow the user to specify a
39  * value from a bounded range, or both. For instance, most sliders and
40  * range controls, as well as dials, should have #AtkObject
41  * representations which implement #AtkValue on the component's
42  * behalf. #AtKValues may be read-only, in which case attempts to
43  * alter the value return would fail.
44  *
45  * <refsect1 id="current-value-text">
46  * <title>On the subject of current value text</title>
47  * <para>
48  * In addition to providing the current value, implementors can
49  * optionally provide an end-user-consumable textual description
50  * associated with this value. This description should be included
51  * when the numeric value fails to convey the full, on-screen
52  * representation seen by users.
53  * </para>
54  *
55  * <example>
56  * <title>Password strength</title>
57  * A password strength meter whose value changes as the user types
58  * their new password. Red is used for values less than 4.0, yellow
59  * for values between 4.0 and 7.0, and green for values greater than
60  * 7.0. In this instance, value text should be provided by the
61  * implementor. Appropriate value text would be "weak", "acceptable,"
62  * and "strong" respectively.
63  * </example>
64  *
65  * A level bar whose value changes to reflect the battery charge. The
66  * color remains the same regardless of the charge and there is no
67  * on-screen text reflecting the fullness of the battery. In this
68  * case, because the position within the bar is the only indication
69  * the user has of the current charge, value text should not be
70  * provided by the implementor.
71  *
72  * <refsect2 id="implementor-notes">
73  * <title>Implementor Notes</title>
74  * <para>
75  * Implementors should bear in mind that assistive technologies will
76  * likely prefer the value text provided over the numeric value when
77  * presenting a widget's value. As a result, strings not intended for
78  * end users should not be exposed in the value text, and strings
79  * which are exposed should be localized. In the case of widgets which
80  * display value text on screen, for instance through a separate label
81  * in close proximity to the value-displaying widget, it is still
82  * expected that implementors will expose the value text using the
83  * above API.
84  * </para>
85  *
86  * <para>
87  * #AtkValue should NOT be implemented for widgets whose displayed
88  * value is not reflective of a meaningful amount. For instance, a
89  * progress pulse indicator whose value alternates between 0.0 and 1.0
90  * to indicate that some process is still taking place should not
91  * implement #AtkValue because the current value does not reflect
92  * progress towards completion.
93  * </para>
94  * </refsect2>
95  * </refsect1>
96  *
97  * <refsect1 id="ranges">
98  * <title>On the subject of ranges</title>
99  * <para>
100  * In addition to providing the minimum and maximum values,
101  * implementors can optionally provide details about subranges
102  * associated with the widget. These details should be provided by the
103  * implementor when both of the following are communicated visually to
104  * the end user:
105  * </para>
106  * <itemizedlist>
107  *   <listitem>The existence of distinct ranges such as "weak",
108  *   "acceptable", and "strong" indicated by color, bar tick marks,
109  *   and/or on-screen text.</listitem>
110  *   <listitem>Where the current value stands within a given subrange,
111  *   for instance illustrating progression from very "weak" towards
112  *   nearly "acceptable" through changes in shade and/or position on
113  *   the bar within the "weak" subrange.</listitem>
114  * </itemizedlist>
115  * <para>
116  * If both of the above do not apply to the widget, it should be
117  * sufficient to expose the numeric value, along with the value text
118  * if appropriate, to make the widget accessible.
119  * </para>
120  *
121  * <refsect2 id="ranges-implementor-notes">
122  * <title>Implementor Notes</title>
123  * <para>
124  * If providing subrange details is deemed necessary, all possible
125  * values of the widget are expected to fall within one of the
126  * subranges defined by the implementor.
127  * </para>
128  * </refsect2>
129  * </refsect1>
130  *
131  * <refsect1 id="localization">
132  * <title>On the subject of localization of end-user-consumable text
133  * values</title>
134  * <para>
135  * Because value text and subrange descriptors are human-consumable,
136  * implementors are expected to provide localized strings which can be
137  * directly presented to end users via their assistive technology. In
138  * order to simplify this for implementors, implementors can use
139  * atk_value_type_get_localized_name() with the following
140  * already-localized constants for commonly-needed values can be used:
141  * </para>
142  *
143  * <itemizedlist>
144  *   <listitem>ATK_VALUE_VERY_WEAK</listitem>
145  *   <listitem>ATK_VALUE_WEAK</listitem>
146  *   <listitem>ATK_VALUE_ACCEPTABLE</listitem>
147  *   <listitem>ATK_VALUE_STRONG</listitem>
148  *   <listitem>ATK_VALUE_VERY_STRONG</listitem>
149  *   <listitem>ATK_VALUE_VERY_LOW</listitem>
150  *   <listitem>ATK_VALUE_LOW</listitem>
151  *   <listitem>ATK_VALUE_MEDIUM</listitem>
152  *   <listitem>ATK_VALUE_HIGH</listitem>
153  *   <listitem>ATK_VALUE_VERY_HIGH</listitem>
154  *   <listitem>ATK_VALUE_VERY_BAD</listitem>
155  *   <listitem>ATK_VALUE_BAD</listitem>
156  *   <listitem>ATK_VALUE_GOOD</listitem>
157  *   <listitem>ATK_VALUE_VERY_GOOD</listitem>
158  *   <listitem>ATK_VALUE_BEST</listitem>
159  *   <listitem>ATK_VALUE_SUBSUBOPTIMAL</listitem>
160  *   <listitem>ATK_VALUE_SUBOPTIMAL</listitem>
161  *   <listitem>ATK_VALUE_OPTIMAL</listitem>
162  * </itemizedlist>
163  * <para>
164  * Proposals for additional constants, along with their use cases,
165  * should be submitted to the GNOME Accessibility Team.
166  * </para>
167  * </refsect1>
168  *
169  * <refsect1 id="changes">
170  * <title>On the subject of changes</title>
171  * <para>
172  * Note that if there is a textual description associated with the new
173  * numeric value, that description should be included regardless of
174  * whether or not it has also changed.
175  * </para>
176  * </refsect1>
177  */
178
179 static GPtrArray *value_type_names = NULL;
180
181 enum {
182   VALUE_CHANGED,
183   LAST_SIGNAL
184 };
185
186 static void atk_value_base_init (AtkValueIface *class);
187
188 static guint atk_value_signals[LAST_SIGNAL] = {0};
189
190 GType
191 atk_value_get_type (void)
192 {
193   static GType type = 0;
194
195   if (!type) {
196     GTypeInfo tinfo =
197     {
198       sizeof (AtkValueIface),
199       (GBaseInitFunc) atk_value_base_init,
200       (GBaseFinalizeFunc) NULL,
201
202     };
203
204     type = g_type_register_static (G_TYPE_INTERFACE, "AtkValue", &tinfo, 0);
205   }
206
207   return type;
208 }
209
210 static void
211 atk_value_base_init (AtkValueIface *class)
212 {
213   static gboolean initialized = FALSE;
214   if (!initialized)
215     {
216       /**
217        * AtkValue::value-changed:
218        * @atkvalue: the object on which the signal was emitted.
219        * @value: the new value in a numerical form.
220        * @text: human readable text alternative (also called
221        * description) of this object. NULL if not available.
222        *
223        * The 'value-changed' signal is emitted when the current value
224        * that represent the object changes. @value is the numerical
225        * representation of this new value.  @text is the human
226        * readable text alternative of @value, and can be NULL if it is
227        * not available. Note that if there is a textual description
228        * associated with the new numeric value, that description
229        * should be included regardless of whether or not it has also
230        * changed.
231        *
232        * Example: a password meter whose value changes as the user
233        * types their new password. Appropiate value text would be
234        * "weak", "acceptable" and "strong".
235        *
236        * Since: 2.12
237        */
238       atk_value_signals[VALUE_CHANGED] =
239         g_signal_new ("value_changed",
240                       ATK_TYPE_VALUE,
241                       G_SIGNAL_RUN_LAST,
242                       0,
243                       (GSignalAccumulator) NULL, NULL,
244                       atk_marshal_VOID__DOUBLE_STRING,
245                       G_TYPE_NONE,
246                       2, G_TYPE_DOUBLE, G_TYPE_STRING);
247
248       initialized = TRUE;
249     }
250 }
251
252 /**
253  * atk_value_get_current_value:
254  * @obj: a GObject instance that implements AtkValueIface
255  * @value: a #GValue representing the current accessible value
256  *
257  * Gets the value of this object.
258  *
259  * Deprecated: Since 2.12. Use atk_value_get_value_and_text()
260  * instead.
261  **/
262 void
263 atk_value_get_current_value (AtkValue *obj,
264                              GValue   *value)
265 {
266   AtkValueIface *iface;
267
268   g_return_if_fail (value != NULL);
269   g_return_if_fail (ATK_IS_VALUE (obj));
270
271   iface = ATK_VALUE_GET_IFACE (obj);
272
273   if (iface->get_current_value)
274     {
275       if (G_IS_VALUE (value))
276         g_value_unset (value);
277       else
278         memset (value, 0, sizeof (*value));
279
280       (iface->get_current_value) (obj, value);
281     }
282 }
283
284 /**
285  * atk_value_get_maximum_value:
286  * @obj: a GObject instance that implements AtkValueIface
287  * @value: a #GValue representing the maximum accessible value
288  *
289  * Gets the maximum value of this object.
290  *
291  * Deprecated: Since 2.12. Use atk_value_get_range() instead.
292  **/
293 void
294 atk_value_get_maximum_value  (AtkValue *obj,
295                               GValue   *value)
296 {
297   AtkValueIface *iface;
298
299   g_return_if_fail (value != NULL);
300   g_return_if_fail (ATK_IS_VALUE (obj));
301
302   iface = ATK_VALUE_GET_IFACE (obj);
303
304   if (iface->get_maximum_value)
305     {
306       if (G_IS_VALUE (value))
307         g_value_unset (value);
308       else
309         memset (value, 0, sizeof (*value));
310
311       (iface->get_maximum_value) (obj, value);
312     }
313 }
314
315 /**
316  * atk_value_get_minimum_value:
317  * @obj: a GObject instance that implements AtkValueIface
318  * @value: a #GValue representing the minimum accessible value
319  *
320  * Gets the minimum value of this object.
321  *
322  * Deprecated: Since 2.12. Use atk_value_get_range() instead.
323  **/
324 void
325 atk_value_get_minimum_value (AtkValue *obj,
326                              GValue   *value)
327 {
328   AtkValueIface *iface;
329
330   g_return_if_fail (value != NULL);
331   g_return_if_fail (ATK_IS_VALUE (obj));
332
333   iface = ATK_VALUE_GET_IFACE (obj);
334
335   if (iface->get_minimum_value)
336     {
337       if (G_IS_VALUE (value))
338         g_value_unset (value);
339       else
340         memset (value, 0, sizeof (*value));
341
342       (iface->get_minimum_value) (obj, value);
343     }
344 }
345
346 /**
347  * atk_value_get_minimum_increment:
348  * @obj: a GObject instance that implements AtkValueIface
349  * @value: a #GValue representing the minimum increment by which the accessible value may be changed
350  *
351  * Gets the minimum increment by which the value of this object may be changed.  If zero,
352  * the minimum increment is undefined, which may mean that it is limited only by the 
353  * floating point precision of the platform.
354  *
355  * Since: 1.12
356  *
357  * Deprecated: Since 2.12. Use atk_value_get_increment() instead.
358  **/
359 void
360 atk_value_get_minimum_increment (AtkValue *obj,
361                              GValue   *value)
362 {
363   AtkValueIface *iface;
364
365   g_return_if_fail (value != NULL);
366   g_return_if_fail (ATK_IS_VALUE (obj));
367
368   iface = ATK_VALUE_GET_IFACE (obj);
369
370   if (iface->get_minimum_increment)
371     {
372       if (G_IS_VALUE (value))
373         g_value_unset (value);
374       else
375         memset (value, 0, sizeof (*value));
376
377       (iface->get_minimum_increment) (obj, value);
378     }
379 }
380
381 /**
382  * atk_value_set_current_value:
383  * @obj: a GObject instance that implements AtkValueIface
384  * @value: a #GValue which is the desired new accessible value.
385  *
386  * Sets the value of this object.
387  *
388  * Returns: %TRUE if new value is successfully set, %FALSE otherwise.
389  *
390  * Deprecated: Since 2.12. Use atk_value_set_value() instead.
391  **/
392 gboolean
393 atk_value_set_current_value (AtkValue       *obj, 
394                              const GValue   *value)
395 {
396   AtkValueIface *iface;
397
398   g_return_val_if_fail (ATK_IS_VALUE (obj), FALSE);
399   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
400
401   iface = ATK_VALUE_GET_IFACE (obj);
402
403   if (iface->set_current_value)
404     return (iface->set_current_value) (obj, value);
405   else
406     return FALSE;
407 }
408
409
410 /**
411  * atk_value_get_value_and_text:
412  * @obj: a GObject instance that implements AtkValueIface
413  * @value: (out): address of #gdouble to put the current value of @obj
414  * @text: (out) (allow-none): address of #gchar to put the human
415  * readable text alternative for @value
416  *
417  * Gets the current value and the human readable text alternative of
418  * @obj. @text is a newly created string, that must be freed by the
419  * caller. Can be NULL if not descriptor is available.
420  *
421  * Since: 2.12
422  **/
423
424 void
425 atk_value_get_value_and_text (AtkValue *obj,
426                               gdouble *value,
427                               gchar  **text)
428 {
429   AtkValueIface *iface;
430
431   g_return_if_fail (ATK_IS_VALUE (obj));
432
433   iface = ATK_VALUE_GET_IFACE (obj);
434
435   if (iface->get_value_and_text)
436     {
437       (iface->get_value_and_text) (obj, value, text);
438     }
439 }
440
441 /**
442  * atk_value_get_range:
443  * @obj: a GObject instance that implements AtkValueIface
444  *
445  * Gets the range of this object.
446  *
447  * Returns: (transfer full): a newly allocated #AtkRange that
448  * represents the minimum, maximum and descriptor (if available) of
449  * @obj. NULL if that range is not defined.
450  *
451  * Since: 2.12
452  **/
453 AtkRange*
454 atk_value_get_range (AtkValue *obj)
455 {
456   AtkValueIface *iface;
457
458   g_return_val_if_fail (ATK_IS_VALUE (obj), NULL);
459
460   iface = ATK_VALUE_GET_IFACE (obj);
461
462   if (iface->get_range)
463     {
464       return (iface->get_range) (obj);
465     }
466   else
467     return NULL;
468 }
469
470 /**
471  * atk_value_get_increment:
472  * @obj: a GObject instance that implements AtkValueIface
473  *
474  * Gets the minimum increment by which the value of this object may be
475  * changed.  If zero, the minimum increment is undefined, which may
476  * mean that it is limited only by the floating point precision of the
477  * platform.
478  *
479  * Return value: the minimum increment by which the value of this
480  * object may be changed. zero if undefined.
481  *
482  * Since: 2.12
483  **/
484 gdouble
485 atk_value_get_increment (AtkValue *obj)
486 {
487   AtkValueIface *iface;
488
489   g_return_val_if_fail (ATK_IS_VALUE (obj), 0);
490
491   iface = ATK_VALUE_GET_IFACE (obj);
492
493   if (iface->get_increment)
494     {
495       return (iface->get_increment) (obj);
496     }
497   else
498     return 0;
499 }
500
501
502 /**
503  * atk_value_get_sub_ranges:
504  * @obj: a GObject instance that implements AtkValueIface
505  *
506  * Gets the list of subranges defined for this object. See #AtkValue
507  * introduction for examples of subranges and when to expose them.
508  *
509  * Returns: (element-type AtkRange) (transfer full): an #GSList of
510  * #AtkRange which each of the subranges defined for this object. Free
511  * the returns list with g_slist_free().
512  *
513  * Since: 2.12
514  **/
515 GSList*
516 atk_value_get_sub_ranges (AtkValue *obj)
517 {
518   AtkValueIface *iface;
519
520   g_return_val_if_fail (ATK_IS_VALUE (obj), NULL);
521
522   iface = ATK_VALUE_GET_IFACE (obj);
523
524   if (iface->get_sub_ranges)
525     {
526       return (iface->get_sub_ranges) (obj);
527     }
528   else
529     return NULL;
530 }
531
532 /**
533  * atk_value_set_value:
534  * @obj: a GObject instance that implements AtkValueIface
535  * @new_value: a double which is the desired new accessible value.
536  *
537  * Sets the value of this object.
538  *
539  * This method is intended to provide a way to change the value of the
540  * object. In any case, it is possible that the value can't be
541  * modified (ie: a read-only component). If the value changes due this
542  * call, it is possible that the text could change, and will trigger
543  * an #AtkValue::value-changed signal emission.
544  *
545  * Note for implementors: the deprecated atk_value_set_current_value()
546  * method returned TRUE or FALSE depending if the value was assigned
547  * or not. In the practice several implementors were not able to
548  * decide it, and returned TRUE in any case. For that reason it is not
549  * required anymore to return if the value was properly assigned or
550  * not.
551  *
552  * Since: 2.12
553  **/
554 void
555 atk_value_set_value (AtkValue     *obj,
556                      const gdouble new_value)
557 {
558   AtkValueIface *iface;
559
560   g_return_if_fail (ATK_IS_VALUE (obj));
561
562   iface = ATK_VALUE_GET_IFACE (obj);
563
564   if (iface->set_value)
565     {
566       (iface->set_value) (obj, new_value);
567     }
568 }
569
570 static void
571 initialize_value_type_names ()
572 {
573   GTypeClass *enum_class;
574   GEnumValue *enum_value;
575   int i;
576   gchar *value_type_name = NULL;
577
578   if (value_type_names)
579     return;
580
581   value_type_names = g_ptr_array_new ();
582   enum_class = g_type_class_ref (ATK_TYPE_VALUE_TYPE);
583   if (!G_IS_ENUM_CLASS(enum_class))
584     return;
585
586   for (i = 0; i < ATK_VALUE_LAST_DEFINED; i++)
587     {
588       enum_value = g_enum_get_value (G_ENUM_CLASS (enum_class), i);
589       value_type_name = g_strdup (enum_value->value_nick);
590       _compact_name (value_type_name);
591       g_ptr_array_add (value_type_names, value_type_name);
592     }
593
594   g_type_class_unref (enum_class);
595 }
596
597 /**
598  * atk_value_type_get_name:
599  * @role: The #AtkValueType whose name is required
600  *
601  * Gets the description string describing the #AtkValueType @value_type.
602  *
603  * Returns: the string describing the #AtkValueType
604  */
605 const gchar*
606 atk_value_type_get_name (AtkValueType value_type)
607 {
608   g_return_val_if_fail (value_type >= 0, NULL);
609
610   if (!value_type_names)
611     initialize_value_type_names ();
612
613   if (value_type < value_type_names->len)
614     return g_ptr_array_index (value_type_names, value_type);
615
616   return NULL;
617 }
618
619 /**
620  * atk_value_type_get_localized_name:
621  * @value_type: The #AtkValueType whose localized name is required
622  *
623  * Gets the localized description string describing the #AtkValueType @value_type.
624  *
625  * Returns: the localized string describing the #AtkValueType
626  **/
627 const gchar*
628 atk_value_type_get_localized_name (AtkValueType value_type)
629 {
630   _gettext_initialization ();
631
632   return dgettext (GETTEXT_PACKAGE, atk_value_type_get_name (value_type));
633 }