1
/* ATK -  Accessibility Toolkit
2
 * Copyright 2001 Sun Microsystems Inc.
3
 * Copyright 2014 Igalia S.L.
4
 *
5
 * Author: Alejandro PiƱeiro Iglesias <apinheiro@igalia.com>
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Library General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Library General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Library General Public
18
 * License along with this library; if not, write to the
19
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
 * Boston, MA 02111-1307, USA.
21
 */
22
#include <atk/atk.h>
23

            
24
/**
25
 * TestValue:
26
 *
27
 * this example serves as a unit test for AtkValue
28
 *  and also as an example of how to implement #AtkValue on a given
29
 *  GObject.
30
 *
31
 *  This test will represent a volume slider, smart enough to have
32
 *  classify the values on the global range [0,1] with the
33
 *  descriptions "low", "medium", "high" and "very high".  As the
34
 *  clasification is fixed, it also expose all the four possible
35
 *  subranges. To fill the description name it will use some of the
36
 *  already defined #AtkValueType.
37
 *
38
 *  This will implement all the methods of #AtkValue, but note that
39
 *  this is not mandatory on all the cases. In several cases it is not
40
 *  needed to implement the subranges methods. See #AtkValue
41
 *  documentation for further information.
42
 *
43
 */
44

            
45
#define EXPECTED_NUMBER 7
46

            
47
#define LOWER_LIMIT 0
48
#define LOW_THRESHOLD 0.2
49
#define NORMAL_THRESHOLD 0.4
50
#define HIGH_THRESHOLD 0.8
51
#define RISKY_THRESHOLD 1.0
52
#define UPPER_LIMIT 1.0
53
#define INCREMENT 0.15
54

            
55
gboolean test_success = TRUE;
56
GObject *my_value;
57

            
58
#define TEST_TYPE_VALUE (test_value_get_type ())
59
#define TEST_VALUE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_VALUE, TestValue))
60
#define TEST_VALUE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_VALUE, TestValueClass))
61
#define TEST_IS_VALUE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_VALUE))
62
#define TEST_IS_VALUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_VALUE))
63
#define TEST_VALUE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_VALUE, TestValueClass))
64

            
65
typedef struct _TestValue TestValue;
66
typedef struct _TestValueClass TestValueClass;
67

            
68
struct _TestValue
69
{
70
  AtkObject parent;
71

            
72
  GMainLoop *loop;
73
  gint number_emissions;
74

            
75
  gdouble value;
76
};
77

            
78
struct _TestValueClass
79
{
80
  AtkObjectClass parent_class;
81
};
82

            
83
GType test_value_get_type (void) G_GNUC_CONST;
84
static void test_value_interface_init (AtkValueIface *iface);
85

            
86
1
G_DEFINE_TYPE_WITH_CODE (TestValue,
87
                         test_value,
88
                         ATK_TYPE_OBJECT,
89
                         G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE,
90
                                                test_value_interface_init));
91

            
92
static void
93
1
test_value_class_init (TestValueClass *klass)
94
{
95
1
}
96

            
97
static void
98
1
test_value_init (TestValue *value)
99
{
100
1
}
101

            
102
static const gchar *
103
7
get_description (gdouble value)
104
{
105
7
  const gchar *description = NULL;
106

            
107
7
  if (value < LOW_THRESHOLD)
108
1
    description = atk_value_type_get_localized_name (ATK_VALUE_LOW);
109
6
  else if (value < NORMAL_THRESHOLD)
110
1
    description = atk_value_type_get_localized_name (ATK_VALUE_MEDIUM);
111
5
  else if (value < HIGH_THRESHOLD)
112
3
    description = atk_value_type_get_localized_name (ATK_VALUE_HIGH);
113
  else
114
2
    description = atk_value_type_get_localized_name (ATK_VALUE_VERY_HIGH);
115

            
116
7
  return description;
117
}
118

            
119
static void
120
test_value_get_value_and_text (AtkValue *value,
121
                               gdouble *current_value,
122
                               gchar **description)
123
{
124
  TestValue *self;
125

            
126
  g_return_if_fail (TEST_IS_VALUE (value));
127

            
128
  self = TEST_VALUE (value);
129

            
130
  if (current_value != NULL)
131
    *current_value = self->value;
132

            
133
  if (description != NULL)
134
    *description = g_strdup (get_description (self->value));
135
}
136

            
137
AtkRange *
138
test_value_get_range (AtkValue *value)
139
{
140
  AtkRange *result;
141

            
142
  g_return_val_if_fail (TEST_IS_VALUE (value), NULL);
143

            
144
  result = atk_range_new (LOWER_LIMIT,
145
                          UPPER_LIMIT,
146
                          NULL);
147

            
148
  return result;
149
}
150

            
151
gdouble
152
test_value_get_increment (AtkValue *value)
153
{
154
  g_return_val_if_fail (TEST_IS_VALUE (value), 0.0);
155

            
156
  return INCREMENT;
157
}
158

            
159
GSList *
160
test_value_get_sub_ranges (AtkValue *value)
161
{
162
  GSList *result = NULL;
163
  AtkRange *range = NULL;
164

            
165
  g_return_val_if_fail (TEST_IS_VALUE (value), NULL);
166

            
167
  /* low */
168
  range = atk_range_new (LOWER_LIMIT, LOW_THRESHOLD,
169
                         get_description (LOWER_LIMIT));
170

            
171
  result = g_slist_append (result, range);
172

            
173
  /* normal */
174
  range = atk_range_new (LOW_THRESHOLD, NORMAL_THRESHOLD,
175
                         get_description (LOW_THRESHOLD));
176
  result = g_slist_append (result, range);
177

            
178
  /* high */
179
  range = atk_range_new (NORMAL_THRESHOLD, HIGH_THRESHOLD,
180
                         get_description (NORMAL_THRESHOLD));
181
  result = g_slist_append (result, range);
182

            
183
  /* very high */
184
  range = atk_range_new (HIGH_THRESHOLD, UPPER_LIMIT,
185
                         get_description (HIGH_THRESHOLD));
186
  result = g_slist_append (result, range);
187

            
188
  return result;
189
}
190

            
191
void
192
7
test_value_set_value (AtkValue *value,
193
                      double new_value)
194
{
195
  TestValue *self;
196

            
197
7
  g_return_if_fail (TEST_IS_VALUE (value));
198

            
199
7
  self = TEST_VALUE (value);
200

            
201
7
  if (new_value < LOWER_LIMIT)
202
    new_value = LOWER_LIMIT;
203

            
204
7
  if (new_value > UPPER_LIMIT)
205
1
    new_value = UPPER_LIMIT;
206

            
207
7
  if (new_value != self->value)
208
    {
209
7
      gchar *description = g_strdup (get_description (new_value));
210
7
      self->value = new_value;
211
7
      g_signal_emit_by_name (value, "value-changed", new_value, description, NULL);
212
7
      g_free (description);
213
    }
214
}
215

            
216
static void
217
1
test_value_interface_init (AtkValueIface *iface)
218
{
219
1
  iface->get_value_and_text = test_value_get_value_and_text;
220
1
  iface->get_range = test_value_get_range;
221
1
  iface->get_increment = test_value_get_increment;
222
1
  iface->get_sub_ranges = test_value_get_sub_ranges;
223
1
  iface->set_value = test_value_set_value;
224
1
}
225

            
226
static void
227
7
value_page_changed_cb (AtkValue *value,
228
                       gdouble new_value,
229
                       gchar *new_description,
230
                       gpointer data)
231
{
232
7
  TestValue *test_value = TEST_VALUE (value);
233

            
234
7
  g_print ("value-changed callback=(%f,%s)\n", new_value, new_description);
235
7
  test_value->number_emissions++;
236
7
}
237

            
238
/**
239
 * This call simulates a user interacting with the slider.
240
 *
241
 */
242
static gboolean
243
7
do_value_changed (gpointer data)
244
{
245
7
  TestValue *test_value = TEST_VALUE (data);
246

            
247
7
  atk_value_set_value (ATK_VALUE (test_value),
248
7
                       test_value->value + INCREMENT);
249

            
250
7
  if (test_value->number_emissions == EXPECTED_NUMBER)
251
    {
252
1
      g_main_loop_quit (test_value->loop);
253
1
      return G_SOURCE_REMOVE;
254
    }
255
  else
256
6
    return G_SOURCE_CONTINUE;
257
}
258

            
259
static void
260
1
test_page_changed (void)
261
{
262
1
  TestValue *my_value = TEST_VALUE (g_object_new (TEST_TYPE_VALUE, NULL));
263

            
264
1
  g_signal_connect (my_value, "value-changed",
265
                    G_CALLBACK (value_page_changed_cb),
266
                    NULL);
267

            
268
1
  g_idle_add (do_value_changed, my_value);
269

            
270
1
  my_value->loop = g_main_loop_new (NULL, FALSE);
271

            
272
1
  g_main_loop_run (my_value->loop);
273

            
274
1
  g_assert_cmpint (my_value->number_emissions, ==, EXPECTED_NUMBER);
275
1
  g_main_loop_unref (my_value->loop);
276
1
  g_object_unref (my_value);
277
1
}
278

            
279
int
280
1
main (gint argc,
281
      char *argv[])
282
{
283
1
  g_test_init (&argc, &argv, NULL);
284
1
  g_test_add_func ("/atk/value/page_changed", test_page_changed);
285

            
286
1
  return g_test_run ();
287
}