/* ATK - Accessibility Toolkit
* Copyright 2001 Sun Microsystems Inc.
* Copyright 2014 Igalia S.L.
*
* Author: Alejandro PiƱeiro Iglesias <apinheiro@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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 <atk/atk.h>
/**
* SECTION:testvalue
* @Short_description: this example serves as a unit test for AtkValue
* and also as an example of how to implement #AtkValue on a given
* GObject.
*
* This test will represent a volume slider, smart enough to have
* classify the values on the global range [0,1] with the
* descriptions "low", "medium", "high" and "very high". As the
* clasification is fixed, it also expose all the four possible
* subranges. To fill the description name it will use some of the
* already defined #AtkValueType.
*
* This will implement all the methods of #AtkValue, but note that
* this is not mandatory on all the cases. In several cases it is not
* needed to implement the subranges methods. See #AtkValue
* documentation for further information.
*
*/
#define EXPECTED_NUMBER 7
#define LOWER_LIMIT 0
#define LOW_THRESHOLD 0.2
#define NORMAL_THRESHOLD 0.4
#define HIGH_THRESHOLD 0.8
#define RISKY_THRESHOLD 1.0
#define UPPER_LIMIT 1.0
#define INCREMENT 0.15
GMainLoop *global_loop = NULL;
gint global_number_emissions = 0;
gboolean test_success = TRUE;
GObject *my_value;
#define TEST_TYPE_VALUE (test_value_get_type ())
#define TEST_VALUE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_VALUE, TestValue))
#define TEST_VALUE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_VALUE, TestValueClass))
#define TEST_IS_VALUE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_VALUE))
#define TEST_IS_VALUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_VALUE))
#define TEST_VALUE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_VALUE, TestValueClass))
typedef struct _TestValue TestValue;
typedef struct _TestValueClass TestValueClass;
struct _TestValue
{
AtkObject parent;
gdouble value;
};
struct _TestValueClass
{
AtkObjectClass parent_class;
};
GType test_value_get_type (void) G_GNUC_CONST;
static void test_value_interface_init (AtkValueIface *iface);
G_DEFINE_TYPE_WITH_CODE (TestValue,
test_value,
ATK_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE,
test_value_interface_init));
static void
test_value_class_init (TestValueClass *klass)
{
}
static void
test_value_init (TestValue *value)
{
}
static const gchar*
get_description (gdouble value)
{
const gchar *description = NULL;
if (value < LOW_THRESHOLD)
description = atk_value_type_get_localized_name (ATK_VALUE_LOW);
else if (value < NORMAL_THRESHOLD)
description = atk_value_type_get_localized_name (ATK_VALUE_MEDIUM);
else if (value < HIGH_THRESHOLD)
description = atk_value_type_get_localized_name (ATK_VALUE_HIGH);
else description = atk_value_type_get_localized_name (ATK_VALUE_VERY_HIGH);
return description;
}
static void
test_value_get_value_and_text (AtkValue *value,
gdouble *current_value,
gchar **description)
{
TestValue *self;
g_return_if_fail (TEST_IS_VALUE (value));
self = TEST_VALUE (value);
if (current_value != NULL)
*current_value = self->value;
if (description != NULL)
*description = g_strdup (get_description (self->value));
}
AtkRange*
test_value_get_range (AtkValue *value)
{
AtkRange *result;
g_return_val_if_fail (TEST_IS_VALUE (value), NULL);
result = atk_range_new (LOWER_LIMIT,
UPPER_LIMIT,
NULL);
return result;
}
gdouble
test_value_get_increment (AtkValue *value)
{
g_return_val_if_fail (TEST_IS_VALUE (value), 0.0);
return INCREMENT;
}
GSList*
test_value_get_sub_ranges (AtkValue *value)
{
GSList *result = NULL;
AtkRange *range = NULL;
g_return_val_if_fail (TEST_IS_VALUE (value), NULL);
/* low */
range = atk_range_new (LOWER_LIMIT, LOW_THRESHOLD,
get_description (LOWER_LIMIT));
result = g_slist_append (result, range);
/* normal */
range = atk_range_new (LOW_THRESHOLD, NORMAL_THRESHOLD,
get_description (LOW_THRESHOLD));
result = g_slist_append (result, range);
/* high */
range = atk_range_new (NORMAL_THRESHOLD, HIGH_THRESHOLD,
get_description (NORMAL_THRESHOLD));
result = g_slist_append (result, range);
/* very high */
range = atk_range_new (HIGH_THRESHOLD, UPPER_LIMIT,
get_description (HIGH_THRESHOLD));
result = g_slist_append (result, range);
return result;
}
void
test_value_set_value (AtkValue *value,
double new_value)
{
TestValue *self;
g_return_if_fail (TEST_IS_VALUE (value));
self = TEST_VALUE (value);
if (new_value < LOWER_LIMIT)
new_value = LOWER_LIMIT;
if (new_value > UPPER_LIMIT)
new_value = UPPER_LIMIT;
if (new_value != self->value) {
gchar *description = g_strdup (get_description (new_value));
self->value = new_value;
g_signal_emit_by_name (value, "value-changed", new_value, description, NULL);
g_free (description);
}
}
static void
test_value_interface_init (AtkValueIface *iface)
{
iface->get_value_and_text = test_value_get_value_and_text;
iface->get_range = test_value_get_range;
iface->get_increment = test_value_get_increment;
iface->get_sub_ranges = test_value_get_sub_ranges;
iface->set_value = test_value_set_value;
}
static void
value_page_changed_cb (AtkValue *value,
gdouble new_value,
gchar *new_description,
gpointer data)
{
g_print ("value-changed callback=(%f,%s)\n", new_value, new_description);
global_number_emissions++;
}
/**
* This call simulates a user interacting with the slider.
*
*/
static gboolean
do_value_changed (gpointer data)
{
TestValue* test_value = TEST_VALUE (data);
atk_value_set_value (ATK_VALUE (test_value),
test_value->value + INCREMENT);
if (global_number_emissions == EXPECTED_NUMBER) {
g_main_loop_quit (global_loop);
return G_SOURCE_REMOVE;
} else
return G_SOURCE_CONTINUE;
}
/**
* Prints all the info from an AtkValue
*/
static void
print_info (AtkValue *atk_value)
{
double value;
gchar *description;
AtkRange *range;
GSList *sub_ranges;
GSList *iter;
gdouble increment;
gint i = 0;
atk_value_get_value_and_text (atk_value, &value, &description);
range = atk_value_get_range (atk_value);
increment = atk_value_get_increment (atk_value);
atk_value_set_value (atk_value, 0);
g_print ("Current AtkValue data:\n");
g_print ("\t (value,description)=(%f,%s) \n", value, description);
if (range != NULL)
g_print ("\t (min,max,description)=(%f, %f, %s)\n",
atk_range_get_lower_limit (range), atk_range_get_upper_limit (range), atk_range_get_description (range));
else
test_success = FALSE; /* Any AtkValue implementation should provide a range */
g_print ("\t minimum increment=%f\n", increment);
if (range)
atk_range_free (range);
sub_ranges = atk_value_get_sub_ranges (atk_value);
for (iter = sub_ranges; iter != NULL; iter = g_slist_next (iter),i++) {
range = iter->data;
g_print ("\t\t sub_range%i = (%f, %f, %s)\n", i,
atk_range_get_lower_limit (range), atk_range_get_upper_limit (range), atk_range_get_description (range));
}
g_slist_free_full (sub_ranges, (GDestroyNotify) atk_range_free);
}
static gboolean
init_test_value (void)
{
my_value = g_object_new (TEST_TYPE_VALUE, NULL);
g_signal_connect (my_value, "value-changed",
G_CALLBACK (value_page_changed_cb),
NULL);
print_info (ATK_VALUE (my_value));
g_idle_add (do_value_changed, my_value);
return TRUE;
}
int
main (gint argc,
char* argv[])
{
global_loop = g_main_loop_new (NULL, FALSE);
g_print("Starting Value test suite\n\n\n");
init_test_value ();
g_main_loop_run (global_loop);
if (global_number_emissions == EXPECTED_NUMBER && test_success)
g_print ("\n\nValue tests succeeded\n\n\n");
else
g_print ("\n\nValue tests failed\n\n\n");
print_info (ATK_VALUE (my_value));
return 0;
}