/* ATK - Accessibility Toolkit * Copyright 2001, 2002, 2003 Sun Microsystems Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * 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. */ #include "config.h" #include #include #include "atkvalue.h" #include "atkmarshal.h" #include "atk-enum-types.h" #include "atkprivate.h" /** * SECTION:atkvalue * @Short_description: The ATK interface implemented by valuators and * components which display or select a value from a bounded range of * values. * @Title:AtkValue * * #AtkValue should be implemented for components which either display * a value from a bounded range, or which allow the user to specify a * value from a bounded range, or both. For instance, most sliders and * range controls, as well as dials, should have #AtkObject * representations which implement #AtkValue on the component's * behalf. #AtKValues may be read-only, in which case attempts to * alter the value return would fail. * * * On the subject of current value text * * In addition to providing the current value, implementors can * optionally provide an end-user-consumable textual description * associated with this value. This description should be included * when the numeric value fails to convey the full, on-screen * representation seen by users. * * * * Password strength * A password strength meter whose value changes as the user types * their new password. Red is used for values less than 4.0, yellow * for values between 4.0 and 7.0, and green for values greater than * 7.0. In this instance, value text should be provided by the * implementor. Appropriate value text would be "weak", "acceptable," * and "strong" respectively. * * * A level bar whose value changes to reflect the battery charge. The * color remains the same regardless of the charge and there is no * on-screen text reflecting the fullness of the battery. In this * case, because the position within the bar is the only indication * the user has of the current charge, value text should not be * provided by the implementor. * * * Implementor Notes * * Implementors should bear in mind that assistive technologies will * likely prefer the value text provided over the numeric value when * presenting a widget's value. As a result, strings not intended for * end users should not be exposed in the value text, and strings * which are exposed should be localized. In the case of widgets which * display value text on screen, for instance through a separate label * in close proximity to the value-displaying widget, it is still * expected that implementors will expose the value text using the * above API. * * * * #AtkValue should NOT be implemented for widgets whose displayed * value is not reflective of a meaningful amount. For instance, a * progress pulse indicator whose value alternates between 0.0 and 1.0 * to indicate that some process is still taking place should not * implement #AtkValue because the current value does not reflect * progress towards completion. * * * * * * On the subject of ranges * * In addition to providing the minimum and maximum values, * implementors can optionally provide details about subranges * associated with the widget. These details should be provided by the * implementor when both of the following are communicated visually to * the end user: * * * The existence of distinct ranges such as "weak", * "acceptable", and "strong" indicated by color, bar tick marks, * and/or on-screen text. * Where the current value stands within a given subrange, * for instance illustrating progression from very "weak" towards * nearly "acceptable" through changes in shade and/or position on * the bar within the "weak" subrange. * * * If both of the above do not apply to the widget, it should be * sufficient to expose the numeric value, along with the value text * if appropriate, to make the widget accessible. * * * * Implementor Notes * * If providing subrange details is deemed necessary, all possible * values of the widget are expected to fall within one of the * subranges defined by the implementor. * * * * * * On the subject of localization of end-user-consumable text * values * * Because value text and subrange descriptors are human-consumable, * implementors are expected to provide localized strings which can be * directly presented to end users via their assistive technology. In * order to simplify this for implementors, implementors can use * atk_value_type_get_localized_name() with the following * already-localized constants for commonly-needed values can be used: * * * * ATK_VALUE_VERY_WEAK * ATK_VALUE_WEAK * ATK_VALUE_ACCEPTABLE * ATK_VALUE_STRONG * ATK_VALUE_VERY_STRONG * ATK_VALUE_VERY_LOW * ATK_VALUE_LOW * ATK_VALUE_MEDIUM * ATK_VALUE_HIGH * ATK_VALUE_VERY_HIGH * ATK_VALUE_VERY_BAD * ATK_VALUE_BAD * ATK_VALUE_GOOD * ATK_VALUE_VERY_GOOD * ATK_VALUE_BEST * ATK_VALUE_SUBSUBOPTIMAL * ATK_VALUE_SUBOPTIMAL * ATK_VALUE_OPTIMAL * * * Proposals for additional constants, along with their use cases, * should be submitted to the GNOME Accessibility Team. * * * * * On the subject of changes * * Note that if there is a textual description associated with the new * numeric value, that description should be included regardless of * whether or not it has also changed. * * */ static GPtrArray *value_type_names = NULL; enum { VALUE_CHANGED, LAST_SIGNAL }; /* These are listed here for extraction by intltool */ #if 0 /* Translators: This string describes a range within value-related * widgets such as a password-strength meter. Note that what such a * widget presents is controlled by application developers. Thus * assistive technologies such as screen readers are expected to * present this string alone or as a token in a list. */ N_("very weak") /* Translators: This string describes a range within value-related * widgets such as a password-strength meter. Note that what such a * widget presents is controlled by application developers. Thus * assistive technologies such as screen readers are expected to * present this string alone or as a token in a list. */ N_("weak") /* Translators: This string describes a range within value-related * widgets such as a password-strength meter. Note that what such a * widget presents is controlled by application developers. Thus * assistive technologies such as screen readers are expected to * present this string alone or as a token in a list. */ N_("acceptable") /* Translators: This string describes a range within value-related * widgets such as a password-strength meter. Note that what such a * widget presents is controlled by application developers. Thus * assistive technologies such as screen readers are expected to * present this string alone or as a token in a list. */ N_("strong") /* Translators: This string describes a range within value-related * widgets such as a password-strength meter. Note that what such a * widget presents is controlled by application developers. Thus * assistive technologies such as screen readers are expected to * present this string alone or as a token in a list. */ N_("very strong") /* Translators: This string describes a range within value-related * widgets such as a volume slider. Note that what such a widget * presents (e.g. temperature, volume, price) is controlled by * application developers. Thus assistive technologies such as screen * readers are expected to present this string alone or as a token in * a list. */ N_("very low") /* Translators: This string describes a range within value-related * widgets such as a volume slider. Note that what such a widget * presents (e.g. temperature, volume, price) is controlled by * application developers. Thus assistive technologies such as screen * readers are expected to present this string alone or as a token in * a list. */ N_("medium") /* Translators: This string describes a range within value-related * widgets such as a volume slider. Note that what such a widget * presents (e.g. temperature, volume, price) is controlled by * application developers. Thus assistive technologies such as screen * readers are expected to present this string alone or as a token in * a list. */ N_("high") /* Translators: This string describes a range within value-related * widgets such as a volume slider. Note that what such a widget * presents (e.g. temperature, volume, price) is controlled by * application developers. Thus assistive technologies such as screen * readers are expected to present this string alone or as a token in * a list. */ N_("very high") /* Translators: This string describes a range within value-related * widgets such as a hard drive usage. Note that what such a widget * presents (e.g. hard drive usage, network traffic) is controlled by * application developers. Thus assistive technologies such as screen * readers are expected to present this string alone or as a token in * a list. */ N_("very bad") /* Translators: This string describes a range within value-related * widgets such as a hard drive usage. Note that what such a widget * presents (e.g. hard drive usage, network traffic) is controlled by * application developers. Thus assistive technologies such as screen * readers are expected to present this string alone or as a token in * a list. */ N_("bad") /* Translators: This string describes a range within value-related * widgets such as a hard drive usage. Note that what such a widget * presents (e.g. hard drive usage, network traffic) is controlled by * application developers. Thus assistive technologies such as screen * readers are expected to present this string alone or as a token in * a list. */ N_("good") /* Translators: This string describes a range within value-related * widgets such as a hard drive usage. Note that what such a widget * presents (e.g. hard drive usage, network traffic) is controlled by * application developers. Thus assistive technologies such as screen * readers are expected to present this string alone or as a token in * a list. */ N_("very good") /* Translators: This string describes a range within value-related * widgets such as a hard drive usage. Note that what such a widget * presents (e.g. hard drive usage, network traffic) is controlled by * application developers. Thus assistive technologies such as screen * readers are expected to present this string alone or as a token in * a list. */ N_("best") #endif static void atk_value_base_init (AtkValueIface *class); static guint atk_value_signals[LAST_SIGNAL] = {0}; GType atk_value_get_type (void) { static GType type = 0; if (!type) { GTypeInfo tinfo = { sizeof (AtkValueIface), (GBaseInitFunc) atk_value_base_init, (GBaseFinalizeFunc) NULL, }; type = g_type_register_static (G_TYPE_INTERFACE, "AtkValue", &tinfo, 0); } return type; } static void atk_value_base_init (AtkValueIface *class) { static gboolean initialized = FALSE; if (!initialized) { /** * AtkValue::value-changed: * @atkvalue: the object on which the signal was emitted. * @value: the new value in a numerical form. * @text: human readable text alternative (also called * description) of this object. NULL if not available. * * The 'value-changed' signal is emitted when the current value * that represent the object changes. @value is the numerical * representation of this new value. @text is the human * readable text alternative of @value, and can be NULL if it is * not available. Note that if there is a textual description * associated with the new numeric value, that description * should be included regardless of whether or not it has also * changed. * * Example: a password meter whose value changes as the user * types their new password. Appropiate value text would be * "weak", "acceptable" and "strong". * * Since: 2.12 */ atk_value_signals[VALUE_CHANGED] = g_signal_new ("value_changed", ATK_TYPE_VALUE, G_SIGNAL_RUN_LAST, 0, (GSignalAccumulator) NULL, NULL, atk_marshal_VOID__DOUBLE_STRING, G_TYPE_NONE, 2, G_TYPE_DOUBLE, G_TYPE_STRING); initialized = TRUE; } } /** * atk_value_get_current_value: * @obj: a GObject instance that implements AtkValueIface * @value: (out): a #GValue representing the current accessible value * * Gets the value of this object. * * Deprecated: Since 2.12. Use atk_value_get_value_and_text() * instead. **/ void atk_value_get_current_value (AtkValue *obj, GValue *value) { AtkValueIface *iface; g_return_if_fail (value != NULL); g_return_if_fail (ATK_IS_VALUE (obj)); iface = ATK_VALUE_GET_IFACE (obj); if (iface->get_current_value) { if (G_IS_VALUE (value)) g_value_unset (value); else memset (value, 0, sizeof (*value)); (iface->get_current_value) (obj, value); } } /** * atk_value_get_maximum_value: * @obj: a GObject instance that implements AtkValueIface * @value: (out): a #GValue representing the maximum accessible value * * Gets the maximum value of this object. * * Deprecated: Since 2.12. Use atk_value_get_range() instead. **/ void atk_value_get_maximum_value (AtkValue *obj, GValue *value) { AtkValueIface *iface; g_return_if_fail (value != NULL); g_return_if_fail (ATK_IS_VALUE (obj)); iface = ATK_VALUE_GET_IFACE (obj); if (iface->get_maximum_value) { if (G_IS_VALUE (value)) g_value_unset (value); else memset (value, 0, sizeof (*value)); (iface->get_maximum_value) (obj, value); } } /** * atk_value_get_minimum_value: * @obj: a GObject instance that implements AtkValueIface * @value: (out): a #GValue representing the minimum accessible value * * Gets the minimum value of this object. * * Deprecated: Since 2.12. Use atk_value_get_range() instead. **/ void atk_value_get_minimum_value (AtkValue *obj, GValue *value) { AtkValueIface *iface; g_return_if_fail (value != NULL); g_return_if_fail (ATK_IS_VALUE (obj)); iface = ATK_VALUE_GET_IFACE (obj); if (iface->get_minimum_value) { if (G_IS_VALUE (value)) g_value_unset (value); else memset (value, 0, sizeof (*value)); (iface->get_minimum_value) (obj, value); } } /** * atk_value_get_minimum_increment: * @obj: a GObject instance that implements AtkValueIface * @value: (out): a #GValue representing the minimum increment by which the accessible value may be changed * * Gets the minimum increment by which the value of this object may be changed. If zero, * the minimum increment is undefined, which may mean that it is limited only by the * floating point precision of the platform. * * Since: 1.12 * * Deprecated: Since 2.12. Use atk_value_get_increment() instead. **/ void atk_value_get_minimum_increment (AtkValue *obj, GValue *value) { AtkValueIface *iface; g_return_if_fail (value != NULL); g_return_if_fail (ATK_IS_VALUE (obj)); iface = ATK_VALUE_GET_IFACE (obj); if (iface->get_minimum_increment) { if (G_IS_VALUE (value)) g_value_unset (value); else memset (value, 0, sizeof (*value)); (iface->get_minimum_increment) (obj, value); } } /** * atk_value_set_current_value: * @obj: a GObject instance that implements AtkValueIface * @value: a #GValue which is the desired new accessible value. * * Sets the value of this object. * * Returns: %TRUE if new value is successfully set, %FALSE otherwise. * * Deprecated: Since 2.12. Use atk_value_set_value() instead. **/ gboolean atk_value_set_current_value (AtkValue *obj, const GValue *value) { AtkValueIface *iface; g_return_val_if_fail (ATK_IS_VALUE (obj), FALSE); g_return_val_if_fail (G_IS_VALUE (value), FALSE); iface = ATK_VALUE_GET_IFACE (obj); if (iface->set_current_value) return (iface->set_current_value) (obj, value); else return FALSE; } /** * atk_value_get_value_and_text: * @obj: a GObject instance that implements AtkValueIface * @value: (out): address of #gdouble to put the current value of @obj * @text: (out) (allow-none): address of #gchar to put the human * readable text alternative for @value * * Gets the current value and the human readable text alternative of * @obj. @text is a newly created string, that must be freed by the * caller. Can be NULL if no descriptor is available. * * Since: 2.12 **/ void atk_value_get_value_and_text (AtkValue *obj, gdouble *value, gchar **text) { AtkValueIface *iface; g_return_if_fail (ATK_IS_VALUE (obj)); iface = ATK_VALUE_GET_IFACE (obj); if (iface->get_value_and_text) { (iface->get_value_and_text) (obj, value, text); } } /** * atk_value_get_range: * @obj: a GObject instance that implements AtkValueIface * * Gets the range of this object. * * Returns: (nullable) (transfer full): a newly allocated #AtkRange * that represents the minimum, maximum and descriptor (if available) * of @obj. NULL if that range is not defined. * * Since: 2.12 **/ AtkRange* atk_value_get_range (AtkValue *obj) { AtkValueIface *iface; g_return_val_if_fail (ATK_IS_VALUE (obj), NULL); iface = ATK_VALUE_GET_IFACE (obj); if (iface->get_range) { return (iface->get_range) (obj); } else return NULL; } /** * atk_value_get_increment: * @obj: a GObject instance that implements AtkValueIface * * Gets the minimum increment by which the value of this object may be * changed. If zero, the minimum increment is undefined, which may * mean that it is limited only by the floating point precision of the * platform. * * Return value: the minimum increment by which the value of this * object may be changed. zero if undefined. * * Since: 2.12 **/ gdouble atk_value_get_increment (AtkValue *obj) { AtkValueIface *iface; g_return_val_if_fail (ATK_IS_VALUE (obj), 0); iface = ATK_VALUE_GET_IFACE (obj); if (iface->get_increment) { return (iface->get_increment) (obj); } else return 0; } /** * atk_value_get_sub_ranges: * @obj: a GObject instance that implements AtkValueIface * * Gets the list of subranges defined for this object. See #AtkValue * introduction for examples of subranges and when to expose them. * * Returns: (element-type AtkRange) (transfer full): an #GSList of * #AtkRange which each of the subranges defined for this object. Free * the returns list with g_slist_free(). * * Since: 2.12 **/ GSList* atk_value_get_sub_ranges (AtkValue *obj) { AtkValueIface *iface; g_return_val_if_fail (ATK_IS_VALUE (obj), NULL); iface = ATK_VALUE_GET_IFACE (obj); if (iface->get_sub_ranges) { return (iface->get_sub_ranges) (obj); } else return NULL; } /** * atk_value_set_value: * @obj: a GObject instance that implements AtkValueIface * @new_value: a double which is the desired new accessible value. * * Sets the value of this object. * * This method is intended to provide a way to change the value of the * object. In any case, it is possible that the value can't be * modified (ie: a read-only component). If the value changes due this * call, it is possible that the text could change, and will trigger * an #AtkValue::value-changed signal emission. * * Note for implementors: the deprecated atk_value_set_current_value() * method returned TRUE or FALSE depending if the value was assigned * or not. In the practice several implementors were not able to * decide it, and returned TRUE in any case. For that reason it is not * required anymore to return if the value was properly assigned or * not. * * Since: 2.12 **/ void atk_value_set_value (AtkValue *obj, const gdouble new_value) { AtkValueIface *iface; g_return_if_fail (ATK_IS_VALUE (obj)); iface = ATK_VALUE_GET_IFACE (obj); if (iface->set_value) { (iface->set_value) (obj, new_value); } } static void initialize_value_type_names () { GTypeClass *enum_class; GEnumValue *enum_value; int i; gchar *value_type_name = NULL; if (value_type_names) return; value_type_names = g_ptr_array_new (); enum_class = g_type_class_ref (ATK_TYPE_VALUE_TYPE); if (!G_IS_ENUM_CLASS(enum_class)) return; for (i = 0; i < ATK_VALUE_LAST_DEFINED; i++) { enum_value = g_enum_get_value (G_ENUM_CLASS (enum_class), i); value_type_name = g_strdup (enum_value->value_nick); _compact_name (value_type_name); g_ptr_array_add (value_type_names, value_type_name); } g_type_class_unref (enum_class); } /** * atk_value_type_get_name: * @value_type: The #AtkValueType whose name is required * * Gets the description string describing the #AtkValueType @value_type. * * Returns: the string describing the #AtkValueType */ const gchar* atk_value_type_get_name (AtkValueType value_type) { g_return_val_if_fail (value_type >= 0, NULL); if (!value_type_names) initialize_value_type_names (); if (value_type < value_type_names->len) return g_ptr_array_index (value_type_names, value_type); return NULL; } /** * atk_value_type_get_localized_name: * @value_type: The #AtkValueType whose localized name is required * * Gets the localized description string describing the #AtkValueType @value_type. * * Returns: the localized string describing the #AtkValueType **/ const gchar* atk_value_type_get_localized_name (AtkValueType value_type) { _gettext_initialization (); return dgettext (GETTEXT_PACKAGE, atk_value_type_get_name (value_type)); }