1 | /* gtkaccessiblevalue.c: Accessible value |
2 | * |
3 | * Copyright 2020 GNOME Foundation |
4 | * |
5 | * SPDX-License-Identifier: LGPL-2.1-or-later |
6 | * |
7 | * This library is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 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 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
19 | */ |
20 | |
21 | /*< private > |
22 | * GtkAccessibleValue: |
23 | * |
24 | * GtkAccessibleValue is a reference counted, generic container for values used |
25 | * to represent the state and properties of a `GtkAccessible` implementation. |
26 | * |
27 | * There are two kinds of accessible value types: |
28 | * |
29 | * - hard coded, static values; GTK owns them, and their contents, and are |
30 | * guaranteed to exist for the duration of the application's life time |
31 | * - dynamic values; the accessible state owns the value and their contents, |
32 | * and they can be allocated and freed |
33 | * |
34 | * Typically, the former type of values is used for boolean, tristate, and |
35 | * token value; the latter is used for numbers, strings, and token lists. |
36 | * |
37 | * For more information on the types of values, see the [WAI-ARIA](https://www.w3.org/WAI/PF/aria/states_and_properties#propcharacteristic_value) |
38 | * reference. |
39 | */ |
40 | |
41 | #include "config.h" |
42 | |
43 | #include "gtkaccessiblevalueprivate.h" |
44 | |
45 | #include "gtkaccessible.h" |
46 | #include "gtkbuilderprivate.h" |
47 | #include "gtkenums.h" |
48 | #include "gtktypebuiltins.h" |
49 | |
50 | #include <math.h> |
51 | #include <float.h> |
52 | #include <errno.h> |
53 | |
54 | G_DEFINE_QUARK (gtk-accessible-value-error-quark, gtk_accessible_value_error) |
55 | |
56 | G_DEFINE_BOXED_TYPE (GtkAccessibleValue, gtk_accessible_value, |
57 | gtk_accessible_value_ref, |
58 | gtk_accessible_value_unref) |
59 | |
60 | /*< private > |
61 | * gtk_accessible_value_alloc: |
62 | * @value_class: a `GtkAccessibleValueClass` structure |
63 | * |
64 | * Allocates a new `GtkAccessibleValue` subclass using @value_class as the |
65 | * type definition. |
66 | * |
67 | * Returns: (transfer full): the newly allocated `GtkAccessibleValue` |
68 | */ |
69 | GtkAccessibleValue * |
70 | gtk_accessible_value_alloc (const GtkAccessibleValueClass *value_class) |
71 | { |
72 | g_return_val_if_fail (value_class != NULL, NULL); |
73 | g_return_val_if_fail (value_class->instance_size >= sizeof (GtkAccessibleValue), NULL); |
74 | |
75 | GtkAccessibleValue *res = g_malloc0 (n_bytes: value_class->instance_size); |
76 | |
77 | /* We do not use grefcount, here, because we want to have statically |
78 | * allocated GtkAccessibleValue subclasses, and those cannot be initialized |
79 | * with g_ref_count_init() |
80 | */ |
81 | res->ref_count = 1; |
82 | res->value_class = value_class; |
83 | |
84 | if (res->value_class->init != NULL) |
85 | res->value_class->init (res); |
86 | |
87 | return res; |
88 | } |
89 | |
90 | /*< private > |
91 | * gtk_accessible_value_ref: |
92 | * @self: a `GtkAccessibleValue` |
93 | * |
94 | * Acquires a reference on the given `GtkAccessibleValue`. |
95 | * |
96 | * Returns: (transfer full): the value, with an additional reference |
97 | */ |
98 | GtkAccessibleValue * |
99 | gtk_accessible_value_ref (GtkAccessibleValue *self) |
100 | { |
101 | g_return_val_if_fail (self != NULL, NULL); |
102 | |
103 | self->ref_count += 1; |
104 | |
105 | return self; |
106 | } |
107 | |
108 | /*< private > |
109 | * gtk_accessible_value_unref: |
110 | * @self: (transfer full): a `GtkAccessibleValue` |
111 | * |
112 | * Releases a reference on the given `GtkAccessibleValue`. |
113 | */ |
114 | void |
115 | gtk_accessible_value_unref (GtkAccessibleValue *self) |
116 | { |
117 | g_return_if_fail (self != NULL); |
118 | |
119 | self->ref_count -= 1; |
120 | if (self->ref_count == 0) |
121 | { |
122 | if (self->value_class->finalize != NULL) |
123 | self->value_class->finalize (self); |
124 | |
125 | g_free (mem: self); |
126 | } |
127 | } |
128 | |
129 | /*< private > |
130 | * gtk_accessible_value_print: |
131 | * @self: a `GtkAccessibleValue` |
132 | * @buffer: a `GString` |
133 | * |
134 | * Prints the contents of a `GtkAccessibleValue` into the given @buffer. |
135 | */ |
136 | void |
137 | gtk_accessible_value_print (const GtkAccessibleValue *self, |
138 | GString *buffer) |
139 | { |
140 | g_return_if_fail (self != NULL); |
141 | g_return_if_fail (buffer != NULL); |
142 | |
143 | if (self->value_class->print != NULL) |
144 | self->value_class->print (self, buffer); |
145 | } |
146 | |
147 | /*< private > |
148 | * gtk_accessible_value_to_string: |
149 | * @self: a `GtkAccessibleValue` |
150 | * |
151 | * Fills a string with the contents of the given `GtkAccessibleValue`. |
152 | * |
153 | * Returns: (transfer full): a string with the contents of the value |
154 | */ |
155 | char * |
156 | gtk_accessible_value_to_string (const GtkAccessibleValue *self) |
157 | { |
158 | g_return_val_if_fail (self != NULL, NULL); |
159 | |
160 | GString *buffer = g_string_new (NULL); |
161 | |
162 | gtk_accessible_value_print (self, buffer); |
163 | |
164 | return g_string_free (string: buffer, FALSE); |
165 | } |
166 | |
167 | /*< private > |
168 | * gtk_accessible_value_equal: |
169 | * @value_a: (nullable): the first `GtkAccessibleValue` |
170 | * @value_b: (nullable): the second `GtkAccessibleValue` |
171 | * |
172 | * Checks whether @value_a and @value_b are equal. |
173 | * |
174 | * This function is %NULL-safe. |
175 | * |
176 | * Returns: %TRUE if the given `GtkAccessibleValue` instances are equal, |
177 | * and %FALSE otherwise |
178 | */ |
179 | gboolean |
180 | gtk_accessible_value_equal (const GtkAccessibleValue *value_a, |
181 | const GtkAccessibleValue *value_b) |
182 | { |
183 | if (value_a == value_b) |
184 | return TRUE; |
185 | |
186 | if (value_a == NULL || value_b == NULL) |
187 | return FALSE; |
188 | |
189 | if (value_a->value_class != value_b->value_class) |
190 | return FALSE; |
191 | |
192 | if (value_a->value_class->equal == NULL) |
193 | return FALSE; |
194 | |
195 | return value_a->value_class->equal (value_a, value_b); |
196 | } |
197 | |
198 | /* {{{ Basic allocated types */ |
199 | |
200 | typedef struct { |
201 | GtkAccessibleValue parent; |
202 | |
203 | int value; |
204 | } GtkIntAccessibleValue; |
205 | |
206 | static gboolean |
207 | gtk_int_accessible_value_equal (const GtkAccessibleValue *value_a, |
208 | const GtkAccessibleValue *value_b) |
209 | { |
210 | const GtkIntAccessibleValue *self_a = (GtkIntAccessibleValue *) value_a; |
211 | const GtkIntAccessibleValue *self_b = (GtkIntAccessibleValue *) value_b; |
212 | |
213 | return self_a->value == self_b->value; |
214 | } |
215 | |
216 | static void |
217 | gtk_int_accessible_value_print (const GtkAccessibleValue *value, |
218 | GString *buffer) |
219 | { |
220 | const GtkIntAccessibleValue *self = (GtkIntAccessibleValue *) value; |
221 | |
222 | g_string_append_printf (string: buffer, format: "%d" , self->value); |
223 | } |
224 | |
225 | static const GtkAccessibleValueClass GTK_INT_ACCESSIBLE_VALUE = { |
226 | .type = GTK_ACCESSIBLE_VALUE_TYPE_INTEGER, |
227 | .type_name = "GtkIntAccessibleValue" , |
228 | .instance_size = sizeof (GtkIntAccessibleValue), |
229 | .equal = gtk_int_accessible_value_equal, |
230 | .print = gtk_int_accessible_value_print, |
231 | }; |
232 | |
233 | GtkAccessibleValue * |
234 | gtk_int_accessible_value_new (int value) |
235 | { |
236 | GtkAccessibleValue *res = gtk_accessible_value_alloc (value_class: >K_INT_ACCESSIBLE_VALUE); |
237 | |
238 | /* XXX: Possible optimization: statically allocate the first N values |
239 | * and hand out references to them, instead of dynamically |
240 | * allocating a new GtkAccessibleValue instance. Needs some profiling |
241 | * to figure out the common integer values used by large applications |
242 | */ |
243 | GtkIntAccessibleValue *self = (GtkIntAccessibleValue *) res; |
244 | self->value = value; |
245 | |
246 | return res; |
247 | } |
248 | |
249 | int |
250 | gtk_int_accessible_value_get (const GtkAccessibleValue *value) |
251 | { |
252 | GtkIntAccessibleValue *self = (GtkIntAccessibleValue *) value; |
253 | |
254 | g_return_val_if_fail (value != NULL, 0); |
255 | g_return_val_if_fail (value->value_class == >K_INT_ACCESSIBLE_VALUE, 0); |
256 | |
257 | return self->value; |
258 | } |
259 | |
260 | typedef struct { |
261 | GtkAccessibleValue parent; |
262 | |
263 | double value; |
264 | } GtkNumberAccessibleValue; |
265 | |
266 | static gboolean |
267 | gtk_number_accessible_value_equal (const GtkAccessibleValue *value_a, |
268 | const GtkAccessibleValue *value_b) |
269 | { |
270 | const GtkNumberAccessibleValue *self_a = (GtkNumberAccessibleValue *) value_a; |
271 | const GtkNumberAccessibleValue *self_b = (GtkNumberAccessibleValue *) value_b; |
272 | |
273 | return G_APPROX_VALUE (self_a->value, self_b->value, 0.001); |
274 | } |
275 | |
276 | static void |
277 | gtk_number_accessible_value_print (const GtkAccessibleValue *value, |
278 | GString *buffer) |
279 | { |
280 | const GtkNumberAccessibleValue *self = (GtkNumberAccessibleValue *) value; |
281 | |
282 | g_string_append_printf (string: buffer, format: "%g" , self->value); |
283 | } |
284 | |
285 | static const GtkAccessibleValueClass GTK_NUMBER_ACCESSIBLE_VALUE = { |
286 | .type = GTK_ACCESSIBLE_VALUE_TYPE_NUMBER, |
287 | .type_name = "GtkNumberAccessibleValue" , |
288 | .instance_size = sizeof (GtkNumberAccessibleValue), |
289 | .equal = gtk_number_accessible_value_equal, |
290 | .print = gtk_number_accessible_value_print, |
291 | }; |
292 | |
293 | GtkAccessibleValue * |
294 | gtk_number_accessible_value_new (double value) |
295 | { |
296 | GtkAccessibleValue *res = gtk_accessible_value_alloc (value_class: >K_NUMBER_ACCESSIBLE_VALUE); |
297 | |
298 | GtkNumberAccessibleValue *self = (GtkNumberAccessibleValue *) res; |
299 | self->value = value; |
300 | |
301 | return res; |
302 | } |
303 | |
304 | double |
305 | gtk_number_accessible_value_get (const GtkAccessibleValue *value) |
306 | { |
307 | GtkNumberAccessibleValue *self = (GtkNumberAccessibleValue *) value; |
308 | |
309 | g_return_val_if_fail (value != NULL, 0); |
310 | g_return_val_if_fail (value->value_class == >K_NUMBER_ACCESSIBLE_VALUE, 0); |
311 | |
312 | return self->value; |
313 | } |
314 | |
315 | typedef struct { |
316 | GtkAccessibleValue parent; |
317 | |
318 | char *value; |
319 | gsize length; |
320 | } GtkStringAccessibleValue; |
321 | |
322 | static void |
323 | gtk_string_accessible_value_finalize (GtkAccessibleValue *value) |
324 | { |
325 | GtkStringAccessibleValue *self = (GtkStringAccessibleValue *) value; |
326 | |
327 | g_free (mem: self->value); |
328 | } |
329 | |
330 | static gboolean |
331 | gtk_string_accessible_value_equal (const GtkAccessibleValue *value_a, |
332 | const GtkAccessibleValue *value_b) |
333 | { |
334 | const GtkStringAccessibleValue *self_a = (GtkStringAccessibleValue *) value_a; |
335 | const GtkStringAccessibleValue *self_b = (GtkStringAccessibleValue *) value_b; |
336 | |
337 | if (self_a->length != self_b->length) |
338 | return FALSE; |
339 | |
340 | return g_strcmp0 (str1: self_a->value, str2: self_b->value) == 0; |
341 | } |
342 | |
343 | static void |
344 | gtk_string_accessible_value_print (const GtkAccessibleValue *value, |
345 | GString *buffer) |
346 | { |
347 | const GtkStringAccessibleValue *self = (GtkStringAccessibleValue *) value; |
348 | |
349 | g_string_append (string: buffer, val: self->value); |
350 | } |
351 | |
352 | static const GtkAccessibleValueClass GTK_STRING_ACCESSIBLE_VALUE = { |
353 | .type = GTK_ACCESSIBLE_VALUE_TYPE_STRING, |
354 | .type_name = "GtkStringAccessibleValue" , |
355 | .instance_size = sizeof (GtkStringAccessibleValue), |
356 | .finalize = gtk_string_accessible_value_finalize, |
357 | .equal = gtk_string_accessible_value_equal, |
358 | .print = gtk_string_accessible_value_print, |
359 | }; |
360 | |
361 | GtkAccessibleValue * |
362 | gtk_string_accessible_value_new (const char *str) |
363 | { |
364 | GtkAccessibleValue *res = gtk_accessible_value_alloc (value_class: >K_STRING_ACCESSIBLE_VALUE); |
365 | |
366 | GtkStringAccessibleValue *self = (GtkStringAccessibleValue *) res; |
367 | |
368 | self->value = g_strdup (str); |
369 | self->length = strlen (s: str); |
370 | |
371 | return res; |
372 | } |
373 | |
374 | const char * |
375 | gtk_string_accessible_value_get (const GtkAccessibleValue *value) |
376 | { |
377 | GtkStringAccessibleValue *self = (GtkStringAccessibleValue *) value; |
378 | |
379 | g_return_val_if_fail (value != NULL, 0); |
380 | g_return_val_if_fail (value->value_class == >K_STRING_ACCESSIBLE_VALUE, 0); |
381 | |
382 | return self->value; |
383 | } |
384 | |
385 | typedef struct { |
386 | GtkAccessibleValue parent; |
387 | |
388 | GtkAccessible *ref; |
389 | } GtkReferenceAccessibleValue; |
390 | |
391 | static void |
392 | remove_weak_ref (gpointer data, |
393 | GObject *old_reference) |
394 | { |
395 | GtkReferenceAccessibleValue *self = data; |
396 | |
397 | self->ref = NULL; |
398 | } |
399 | |
400 | static void |
401 | gtk_reference_accessible_value_finalize (GtkAccessibleValue *value) |
402 | { |
403 | GtkReferenceAccessibleValue *self = (GtkReferenceAccessibleValue *) value; |
404 | |
405 | if (self->ref != NULL) |
406 | g_object_weak_unref (G_OBJECT (self->ref), notify: remove_weak_ref, data: self); |
407 | } |
408 | |
409 | static gboolean |
410 | gtk_reference_accessible_value_equal (const GtkAccessibleValue *value_a, |
411 | const GtkAccessibleValue *value_b) |
412 | { |
413 | const GtkReferenceAccessibleValue *self_a = (GtkReferenceAccessibleValue *) value_a; |
414 | const GtkReferenceAccessibleValue *self_b = (GtkReferenceAccessibleValue *) value_b; |
415 | |
416 | return self_a->ref == self_b->ref; |
417 | } |
418 | |
419 | static void |
420 | gtk_reference_accessible_value_print (const GtkAccessibleValue *value, |
421 | GString *buffer) |
422 | { |
423 | const GtkReferenceAccessibleValue *self = (GtkReferenceAccessibleValue *) value; |
424 | |
425 | if (self->ref != NULL) |
426 | { |
427 | g_string_append_printf (string: buffer, format: "%s<%p>" , |
428 | G_OBJECT_TYPE_NAME (self->ref), |
429 | self->ref); |
430 | } |
431 | else |
432 | { |
433 | g_string_append (string: buffer, val: "<null>" ); |
434 | } |
435 | } |
436 | |
437 | static const GtkAccessibleValueClass GTK_REFERENCE_ACCESSIBLE_VALUE = { |
438 | .type = GTK_ACCESSIBLE_VALUE_TYPE_REFERENCE, |
439 | .type_name = "GtkReferenceAccessibleValue" , |
440 | .instance_size = sizeof (GtkReferenceAccessibleValue), |
441 | .finalize = gtk_reference_accessible_value_finalize, |
442 | .equal = gtk_reference_accessible_value_equal, |
443 | .print = gtk_reference_accessible_value_print, |
444 | }; |
445 | |
446 | GtkAccessibleValue * |
447 | gtk_reference_accessible_value_new (GtkAccessible *ref) |
448 | { |
449 | g_return_val_if_fail (GTK_IS_ACCESSIBLE (ref), NULL); |
450 | |
451 | GtkAccessibleValue *res = gtk_accessible_value_alloc (value_class: >K_REFERENCE_ACCESSIBLE_VALUE); |
452 | |
453 | GtkReferenceAccessibleValue *self = (GtkReferenceAccessibleValue *) res; |
454 | |
455 | self->ref = ref; |
456 | g_object_weak_ref (G_OBJECT (self->ref), notify: remove_weak_ref, data: self); |
457 | |
458 | return res; |
459 | } |
460 | |
461 | GtkAccessible * |
462 | gtk_reference_accessible_value_get (const GtkAccessibleValue *value) |
463 | { |
464 | GtkReferenceAccessibleValue *self = (GtkReferenceAccessibleValue *) value; |
465 | |
466 | g_return_val_if_fail (value != NULL, 0); |
467 | g_return_val_if_fail (value->value_class == >K_REFERENCE_ACCESSIBLE_VALUE, 0); |
468 | |
469 | return self->ref; |
470 | } |
471 | |
472 | typedef struct { |
473 | GtkAccessibleValue parent; |
474 | |
475 | GList *refs; |
476 | } GtkReferenceListAccessibleValue; |
477 | |
478 | static void |
479 | remove_weak_ref_from_list (gpointer data, |
480 | GObject *old_reference) |
481 | { |
482 | GtkReferenceListAccessibleValue *self = data; |
483 | |
484 | GList *item = g_list_find (list: self->refs, data: old_reference); |
485 | |
486 | if (item != NULL) |
487 | { |
488 | self->refs = g_list_remove_link (list: self->refs, llink: item); |
489 | g_list_free (list: item); |
490 | } |
491 | } |
492 | |
493 | static void |
494 | gtk_reference_list_accessible_value_finalize (GtkAccessibleValue *value) |
495 | { |
496 | GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) value; |
497 | |
498 | for (GList *l = self->refs; l != NULL; l = l->next) |
499 | { |
500 | if (l->data != NULL) |
501 | g_object_weak_unref (G_OBJECT (l->data), notify: remove_weak_ref_from_list, data: self); |
502 | } |
503 | |
504 | g_list_free (list: self->refs); |
505 | } |
506 | |
507 | static gboolean |
508 | gtk_reference_list_accessible_value_equal (const GtkAccessibleValue *value_a, |
509 | const GtkAccessibleValue *value_b) |
510 | { |
511 | const GtkReferenceListAccessibleValue *self_a = (GtkReferenceListAccessibleValue *) value_a; |
512 | const GtkReferenceListAccessibleValue *self_b = (GtkReferenceListAccessibleValue *) value_b; |
513 | |
514 | if (g_list_length (list: self_a->refs) != g_list_length (list: self_b->refs)) |
515 | return FALSE; |
516 | |
517 | for (GList *l = self_a->refs; l != NULL; l = l->next) |
518 | { |
519 | if (g_list_find (list: self_b->refs, data: l->data) == NULL) |
520 | return FALSE; |
521 | } |
522 | |
523 | return TRUE; |
524 | } |
525 | |
526 | static void |
527 | gtk_reference_list_accessible_value_print (const GtkAccessibleValue *value, |
528 | GString *buffer) |
529 | { |
530 | const GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) value; |
531 | |
532 | if (self->refs == NULL) |
533 | { |
534 | g_string_append (string: buffer, val: "<null>" ); |
535 | return; |
536 | } |
537 | |
538 | for (GList *l = self->refs; l != NULL; l = l->next) |
539 | { |
540 | g_string_append_printf (string: buffer, format: "%s<%p>" , |
541 | G_OBJECT_TYPE_NAME (l->data), |
542 | l->data); |
543 | } |
544 | } |
545 | |
546 | static const GtkAccessibleValueClass GTK_REFERENCE_LIST_ACCESSIBLE_VALUE = { |
547 | .type = GTK_ACCESSIBLE_VALUE_TYPE_REFERENCE_LIST, |
548 | .type_name = "GtkReferenceListAccessibleValue" , |
549 | .instance_size = sizeof (GtkReferenceListAccessibleValue), |
550 | .finalize = gtk_reference_list_accessible_value_finalize, |
551 | .equal = gtk_reference_list_accessible_value_equal, |
552 | .print = gtk_reference_list_accessible_value_print, |
553 | }; |
554 | |
555 | /*< private > |
556 | * gtk_reference_list_accessible_value_new: |
557 | * @value: (element-type GtkAccessible) (transfer full): a list of accessible objects |
558 | * |
559 | * Creates a new `GtkAccessible` that stores a list of references |
560 | * to `GtkAccessible` objects. |
561 | * |
562 | * Returns: (transfer full): the newly created `GtkAccessible` |
563 | */ |
564 | GtkAccessibleValue * |
565 | gtk_reference_list_accessible_value_new (GList *value) |
566 | { |
567 | GtkAccessibleValue *res = gtk_accessible_value_alloc (value_class: >K_REFERENCE_LIST_ACCESSIBLE_VALUE); |
568 | |
569 | GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) res; |
570 | |
571 | self->refs = value; |
572 | if (self->refs != NULL) |
573 | { |
574 | for (GList *l = self->refs; l != NULL; l = l->next) |
575 | g_object_weak_ref (object: l->data, notify: remove_weak_ref_from_list, data: self); |
576 | } |
577 | |
578 | return res; |
579 | } |
580 | |
581 | GList * |
582 | gtk_reference_list_accessible_value_get (const GtkAccessibleValue *value) |
583 | { |
584 | GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) value; |
585 | |
586 | g_return_val_if_fail (value != NULL, 0); |
587 | g_return_val_if_fail (value->value_class == >K_REFERENCE_LIST_ACCESSIBLE_VALUE, 0); |
588 | |
589 | return self->refs; |
590 | } |
591 | |
592 | /* }}} */ |
593 | |
594 | /* {{{ Collection API */ |
595 | |
596 | typedef enum { |
597 | GTK_ACCESSIBLE_COLLECT_INVALID = -1, |
598 | |
599 | /* true/false */ |
600 | GTK_ACCESSIBLE_COLLECT_BOOLEAN = 0, |
601 | |
602 | /* true/false/mixed/undefined */ |
603 | GTK_ACCESSIBLE_COLLECT_TRISTATE, |
604 | |
605 | /* one token */ |
606 | GTK_ACCESSIBLE_COLLECT_TOKEN, |
607 | |
608 | /* integer number */ |
609 | GTK_ACCESSIBLE_COLLECT_INTEGER, |
610 | |
611 | /* real number */ |
612 | GTK_ACCESSIBLE_COLLECT_NUMBER, |
613 | |
614 | /* string */ |
615 | GTK_ACCESSIBLE_COLLECT_STRING, |
616 | |
617 | /* reference */ |
618 | GTK_ACCESSIBLE_COLLECT_REFERENCE, |
619 | |
620 | /* references list */ |
621 | GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST, |
622 | |
623 | /* allows collecting GTK_ACCESSIBLE_VALUE_UNDEFINED; implied |
624 | * by GTK_ACCESSIBLE_COLLECT_TRISTATE |
625 | */ |
626 | GTK_ACCESSIBLE_COLLECT_UNDEFINED = 1 << 16 |
627 | } GtkAccessibleCollectType; |
628 | |
629 | typedef struct { |
630 | int value; |
631 | GtkAccessibleCollectType ctype; |
632 | const char *name; |
633 | |
634 | /* The constructor and getter will be derived by the |
635 | * @ctype field and by the collected value, except for the |
636 | * GTK_ACCESSIBLE_COLLECT_TOKEN collection type. You can |
637 | * override the default ones by filling out these two |
638 | * pointers |
639 | */ |
640 | GCallback ctor; |
641 | GCallback getter; |
642 | GCallback parser; |
643 | GCallback init_value; |
644 | } GtkAccessibleCollect; |
645 | |
646 | static const GtkAccessibleCollect collect_states[] = { |
647 | [GTK_ACCESSIBLE_STATE_BUSY] = { |
648 | .value = GTK_ACCESSIBLE_STATE_BUSY, |
649 | .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN, |
650 | .name = "busy" |
651 | }, |
652 | [GTK_ACCESSIBLE_STATE_CHECKED] = { |
653 | .value = GTK_ACCESSIBLE_STATE_CHECKED, |
654 | .ctype = GTK_ACCESSIBLE_COLLECT_TRISTATE, |
655 | .name = "checked" |
656 | }, |
657 | [GTK_ACCESSIBLE_STATE_DISABLED] = { |
658 | .value = GTK_ACCESSIBLE_STATE_DISABLED, |
659 | .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN, |
660 | .name = "disabled" |
661 | }, |
662 | [GTK_ACCESSIBLE_STATE_EXPANDED] = { |
663 | .value = GTK_ACCESSIBLE_STATE_EXPANDED, |
664 | .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN | GTK_ACCESSIBLE_COLLECT_UNDEFINED, |
665 | .name = "expanded" |
666 | }, |
667 | [GTK_ACCESSIBLE_STATE_HIDDEN] = { |
668 | .value = GTK_ACCESSIBLE_STATE_HIDDEN, |
669 | .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN, |
670 | .name = "hidden" |
671 | }, |
672 | [GTK_ACCESSIBLE_STATE_INVALID] = { |
673 | .value = GTK_ACCESSIBLE_STATE_INVALID, |
674 | .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN, |
675 | .name = "invalid" , |
676 | .ctor = (GCallback) gtk_invalid_accessible_value_new, |
677 | .getter = (GCallback) gtk_invalid_accessible_value_get, |
678 | .parser = (GCallback) gtk_invalid_accessible_value_parse, |
679 | .init_value = (GCallback) gtk_invalid_accessible_value_init_value, |
680 | }, |
681 | [GTK_ACCESSIBLE_STATE_PRESSED] = { |
682 | .value = GTK_ACCESSIBLE_STATE_PRESSED, |
683 | .ctype = GTK_ACCESSIBLE_COLLECT_TRISTATE, |
684 | .name = "pressed" |
685 | }, |
686 | [GTK_ACCESSIBLE_STATE_SELECTED] = { |
687 | .value = GTK_ACCESSIBLE_STATE_SELECTED, |
688 | .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN | GTK_ACCESSIBLE_COLLECT_UNDEFINED, |
689 | .name = "selected" |
690 | }, |
691 | }; |
692 | |
693 | /* § 6.6.1 Widget attributes */ |
694 | static const GtkAccessibleCollect collect_props[] = { |
695 | [GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE] = { |
696 | .value = GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE, |
697 | .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN, |
698 | .name = "autocomplete" , |
699 | .ctor = (GCallback) gtk_autocomplete_accessible_value_new, |
700 | .getter = (GCallback) gtk_autocomplete_accessible_value_get, |
701 | .parser = (GCallback) gtk_autocomplete_accessible_value_parse, |
702 | .init_value = (GCallback) gtk_autocomplete_accessible_value_init_value, |
703 | }, |
704 | [GTK_ACCESSIBLE_PROPERTY_DESCRIPTION] = { |
705 | .value = GTK_ACCESSIBLE_PROPERTY_DESCRIPTION, |
706 | .ctype = GTK_ACCESSIBLE_COLLECT_STRING, |
707 | .name = "description" |
708 | }, |
709 | [GTK_ACCESSIBLE_PROPERTY_HAS_POPUP] = { |
710 | .value = GTK_ACCESSIBLE_PROPERTY_HAS_POPUP, |
711 | .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN, |
712 | .name = "haspopup" |
713 | }, |
714 | [GTK_ACCESSIBLE_PROPERTY_KEY_SHORTCUTS] = { |
715 | .value = GTK_ACCESSIBLE_PROPERTY_KEY_SHORTCUTS, |
716 | .ctype = GTK_ACCESSIBLE_COLLECT_STRING, |
717 | .name = "keyshortcuts" |
718 | }, |
719 | [GTK_ACCESSIBLE_PROPERTY_LABEL] = { |
720 | .value = GTK_ACCESSIBLE_PROPERTY_LABEL, |
721 | .ctype = GTK_ACCESSIBLE_COLLECT_STRING, |
722 | .name = "label" |
723 | }, |
724 | [GTK_ACCESSIBLE_PROPERTY_LEVEL] = { |
725 | .value = GTK_ACCESSIBLE_PROPERTY_LEVEL, |
726 | .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER, |
727 | .name = "level" |
728 | }, |
729 | [GTK_ACCESSIBLE_PROPERTY_MODAL] = { |
730 | .value = GTK_ACCESSIBLE_PROPERTY_MODAL, |
731 | .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN, |
732 | .name = "modal" |
733 | }, |
734 | [GTK_ACCESSIBLE_PROPERTY_MULTI_LINE] = { |
735 | .value = GTK_ACCESSIBLE_PROPERTY_MULTI_LINE, |
736 | .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN, |
737 | .name = "multiline" |
738 | }, |
739 | [GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE] = { |
740 | .value = GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE, |
741 | .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN, |
742 | .name = "multiselectable" |
743 | }, |
744 | /* "orientation" is a bit special; it maps to GtkOrientation, but it |
745 | * can also be "undefined". This means we need to override constructor |
746 | * and getter, in order to properly handle GTK_ACCESSIBLE_VALUE_UNDEFINED |
747 | */ |
748 | [GTK_ACCESSIBLE_PROPERTY_ORIENTATION] = { |
749 | .value = GTK_ACCESSIBLE_PROPERTY_ORIENTATION, |
750 | .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN | GTK_ACCESSIBLE_COLLECT_UNDEFINED, |
751 | .name = "orientation" , |
752 | .ctor = (GCallback) gtk_orientation_accessible_value_new, |
753 | .getter = (GCallback) gtk_orientation_accessible_value_get, |
754 | .parser = (GCallback) gtk_orientation_accessible_value_parse, |
755 | .init_value = (GCallback) gtk_orientation_accessible_value_init_value, |
756 | }, |
757 | [GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER] = { |
758 | .value = GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER, |
759 | .ctype = GTK_ACCESSIBLE_COLLECT_STRING, |
760 | .name = "placeholder" |
761 | }, |
762 | [GTK_ACCESSIBLE_PROPERTY_READ_ONLY] = { |
763 | .value = GTK_ACCESSIBLE_PROPERTY_READ_ONLY, |
764 | .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN, |
765 | .name = "readonly" |
766 | }, |
767 | [GTK_ACCESSIBLE_PROPERTY_REQUIRED] = { |
768 | .value = GTK_ACCESSIBLE_PROPERTY_REQUIRED, |
769 | .ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN, |
770 | .name = "required" |
771 | }, |
772 | [GTK_ACCESSIBLE_PROPERTY_ROLE_DESCRIPTION] = { |
773 | .value = GTK_ACCESSIBLE_PROPERTY_ROLE_DESCRIPTION, |
774 | .ctype = GTK_ACCESSIBLE_COLLECT_STRING, |
775 | .name = "roledescription" |
776 | }, |
777 | [GTK_ACCESSIBLE_PROPERTY_SORT] = { |
778 | .value = GTK_ACCESSIBLE_PROPERTY_SORT, |
779 | .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN, |
780 | .name = "sort" , |
781 | .ctor = (GCallback) gtk_sort_accessible_value_new, |
782 | .getter = (GCallback) gtk_sort_accessible_value_get, |
783 | .parser = (GCallback) gtk_sort_accessible_value_parse, |
784 | .init_value = (GCallback) gtk_sort_accessible_value_init_value, |
785 | }, |
786 | [GTK_ACCESSIBLE_PROPERTY_VALUE_MAX] = { |
787 | .value = GTK_ACCESSIBLE_PROPERTY_VALUE_MAX, |
788 | .ctype = GTK_ACCESSIBLE_COLLECT_NUMBER, |
789 | .name = "valuemax" |
790 | }, |
791 | [GTK_ACCESSIBLE_PROPERTY_VALUE_MIN] = { |
792 | .value = GTK_ACCESSIBLE_PROPERTY_VALUE_MIN, |
793 | .ctype = GTK_ACCESSIBLE_COLLECT_NUMBER, |
794 | .name = "valuemin" |
795 | }, |
796 | [GTK_ACCESSIBLE_PROPERTY_VALUE_NOW] = { |
797 | .value = GTK_ACCESSIBLE_PROPERTY_VALUE_NOW, |
798 | .ctype = GTK_ACCESSIBLE_COLLECT_NUMBER, |
799 | .name = "valuenow" |
800 | }, |
801 | [GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT] = { |
802 | .value = GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, |
803 | .ctype = GTK_ACCESSIBLE_COLLECT_STRING, |
804 | .name = "valuetext" |
805 | }, |
806 | }; |
807 | |
808 | /* § 6.6.4 Relationship Attributes */ |
809 | static const GtkAccessibleCollect collect_rels[] = { |
810 | [GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT] = { |
811 | .value = GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT, |
812 | .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE, |
813 | .name = "activedescendant" |
814 | }, |
815 | [GTK_ACCESSIBLE_RELATION_COL_COUNT] = { |
816 | .value = GTK_ACCESSIBLE_RELATION_COL_COUNT, |
817 | .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER, |
818 | .name = "colcount" |
819 | }, |
820 | [GTK_ACCESSIBLE_RELATION_COL_INDEX] = { |
821 | .value = GTK_ACCESSIBLE_RELATION_COL_INDEX, |
822 | .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER, |
823 | .name = "colindex" |
824 | }, |
825 | [GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT] = { |
826 | .value = GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT, |
827 | .ctype = GTK_ACCESSIBLE_COLLECT_STRING, |
828 | .name = "colindextext" |
829 | }, |
830 | [GTK_ACCESSIBLE_RELATION_COL_SPAN] = { |
831 | .value = GTK_ACCESSIBLE_RELATION_COL_SPAN, |
832 | .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER, |
833 | .name = "colspan" |
834 | }, |
835 | [GTK_ACCESSIBLE_RELATION_CONTROLS] = { |
836 | .value = GTK_ACCESSIBLE_RELATION_CONTROLS, |
837 | .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST, |
838 | .name = "controls" |
839 | }, |
840 | [GTK_ACCESSIBLE_RELATION_DESCRIBED_BY] = { |
841 | .value = GTK_ACCESSIBLE_RELATION_DESCRIBED_BY, |
842 | .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST, |
843 | .name = "describedby" |
844 | }, |
845 | [GTK_ACCESSIBLE_RELATION_DETAILS] = { |
846 | .value = GTK_ACCESSIBLE_RELATION_DETAILS, |
847 | .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST, |
848 | .name = "details" |
849 | }, |
850 | [GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE] = { |
851 | .value = GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE, |
852 | .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE, |
853 | .name = "errormessage" |
854 | }, |
855 | [GTK_ACCESSIBLE_RELATION_FLOW_TO] = { |
856 | .value = GTK_ACCESSIBLE_RELATION_FLOW_TO, |
857 | .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST, |
858 | .name = "flowto" |
859 | }, |
860 | [GTK_ACCESSIBLE_RELATION_LABELLED_BY] = { |
861 | .value = GTK_ACCESSIBLE_RELATION_LABELLED_BY, |
862 | .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST, |
863 | .name = "labelledby" |
864 | }, |
865 | [GTK_ACCESSIBLE_RELATION_OWNS] = { |
866 | .value = GTK_ACCESSIBLE_RELATION_OWNS, |
867 | .ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST, |
868 | .name = "owns" |
869 | }, |
870 | [GTK_ACCESSIBLE_RELATION_POS_IN_SET] = { |
871 | .value = GTK_ACCESSIBLE_RELATION_POS_IN_SET, |
872 | .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER, |
873 | .name = "posinset" |
874 | }, |
875 | [GTK_ACCESSIBLE_RELATION_ROW_COUNT] = { |
876 | .value = GTK_ACCESSIBLE_RELATION_ROW_COUNT, |
877 | .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER, |
878 | .name = "rowcount" |
879 | }, |
880 | [GTK_ACCESSIBLE_RELATION_ROW_INDEX] = { |
881 | .value = GTK_ACCESSIBLE_RELATION_ROW_INDEX, |
882 | .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER, |
883 | .name = "rowindex" |
884 | }, |
885 | [GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT] = { |
886 | .value = GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT, |
887 | .ctype = GTK_ACCESSIBLE_COLLECT_STRING, |
888 | .name = "rowindextext" |
889 | }, |
890 | [GTK_ACCESSIBLE_RELATION_ROW_SPAN] = { |
891 | .value = GTK_ACCESSIBLE_RELATION_ROW_SPAN, |
892 | .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER, |
893 | .name = "rowspan" |
894 | }, |
895 | [GTK_ACCESSIBLE_RELATION_SET_SIZE] = { |
896 | .value = GTK_ACCESSIBLE_RELATION_SET_SIZE, |
897 | .ctype = GTK_ACCESSIBLE_COLLECT_INTEGER, |
898 | .name = "posinset" |
899 | }, |
900 | }; |
901 | |
902 | typedef GtkAccessibleValue * (* GtkAccessibleValueBooleanCtor) (gboolean value); |
903 | typedef GtkAccessibleValue * (* GtkAccessibleValueIntCtor) (int value); |
904 | typedef GtkAccessibleValue * (* GtkAccessibleValueTristateCtor) (int value); |
905 | typedef GtkAccessibleValue * (* GtkAccessibleValueEnumCtor) (int value); |
906 | typedef GtkAccessibleValue * (* GtkAccessibleValueNumberCtor) (double value); |
907 | typedef GtkAccessibleValue * (* GtkAccessibleValueStringCtor) (const char *value); |
908 | typedef GtkAccessibleValue * (* GtkAccessibleValueRefCtor) (GtkAccessible *value); |
909 | typedef GtkAccessibleValue * (* GtkAccessibleValueRefListCtor) (GList *value); |
910 | |
911 | typedef GtkAccessibleValue * (* GtkAccessibleValueEnumParser) (const char *str, |
912 | gsize len, |
913 | GError **error); |
914 | typedef void (* GtkAccessibleValueEnumInit) (GValue *value); |
915 | |
916 | /*< private > |
917 | * gtk_accessible_value_get_default_for_state: |
918 | * @state: a `GtkAccessibleState` |
919 | * |
920 | * Retrieves the `GtkAccessibleValue` that contains the default for the |
921 | * given @state. |
922 | * |
923 | * Returns: (transfer full): the `GtkAccessibleValue` |
924 | */ |
925 | GtkAccessibleValue * |
926 | gtk_accessible_value_get_default_for_state (GtkAccessibleState state) |
927 | { |
928 | const GtkAccessibleCollect *cstate = &collect_states[state]; |
929 | |
930 | g_return_val_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED, NULL); |
931 | |
932 | switch (cstate->value) |
933 | { |
934 | case GTK_ACCESSIBLE_STATE_BUSY: |
935 | case GTK_ACCESSIBLE_STATE_DISABLED: |
936 | case GTK_ACCESSIBLE_STATE_HIDDEN: |
937 | return gtk_boolean_accessible_value_new (FALSE); |
938 | |
939 | case GTK_ACCESSIBLE_STATE_CHECKED: |
940 | case GTK_ACCESSIBLE_STATE_EXPANDED: |
941 | case GTK_ACCESSIBLE_STATE_PRESSED: |
942 | case GTK_ACCESSIBLE_STATE_SELECTED: |
943 | return gtk_undefined_accessible_value_new (); |
944 | |
945 | case GTK_ACCESSIBLE_STATE_INVALID: |
946 | return gtk_invalid_accessible_value_new (value: GTK_ACCESSIBLE_INVALID_FALSE); |
947 | |
948 | default: |
949 | g_critical ("Unknown value for accessible state “%s”" , cstate->name); |
950 | break; |
951 | } |
952 | |
953 | return NULL; |
954 | } |
955 | |
956 | static GtkAccessibleValue * |
957 | gtk_accessible_value_collect_valist (const GtkAccessibleCollect *cstate, |
958 | GError **error, |
959 | va_list *args) |
960 | { |
961 | GtkAccessibleValue *res = NULL; |
962 | GtkAccessibleCollectType ctype = cstate->ctype; |
963 | gboolean collects_undef = (ctype & GTK_ACCESSIBLE_COLLECT_UNDEFINED) != 0; |
964 | |
965 | ctype &= (GTK_ACCESSIBLE_COLLECT_UNDEFINED - 1); |
966 | |
967 | /* Tristate values include "undefined" by definition */ |
968 | if (ctype == GTK_ACCESSIBLE_COLLECT_TRISTATE) |
969 | collects_undef = TRUE; |
970 | |
971 | switch (ctype) |
972 | { |
973 | case GTK_ACCESSIBLE_COLLECT_BOOLEAN: |
974 | { |
975 | if (collects_undef) |
976 | { |
977 | int value = va_arg (*args, int); |
978 | |
979 | if (value == GTK_ACCESSIBLE_VALUE_UNDEFINED) |
980 | res = gtk_undefined_accessible_value_new (); |
981 | else |
982 | res = gtk_boolean_accessible_value_new (value: value == 0 ? FALSE : TRUE); |
983 | } |
984 | else |
985 | { |
986 | gboolean value = va_arg (*args, gboolean); |
987 | |
988 | res = gtk_boolean_accessible_value_new (value); |
989 | } |
990 | } |
991 | break; |
992 | |
993 | case GTK_ACCESSIBLE_COLLECT_TRISTATE: |
994 | { |
995 | int value = va_arg (*args, int); |
996 | |
997 | if (collects_undef && value == GTK_ACCESSIBLE_VALUE_UNDEFINED) |
998 | res = gtk_undefined_accessible_value_new (); |
999 | else |
1000 | res = gtk_tristate_accessible_value_new (value); |
1001 | } |
1002 | break; |
1003 | |
1004 | case GTK_ACCESSIBLE_COLLECT_TOKEN: |
1005 | { |
1006 | GtkAccessibleValueEnumCtor ctor = |
1007 | (GtkAccessibleValueEnumCtor) cstate->ctor; |
1008 | |
1009 | int value = va_arg (*args, int); |
1010 | |
1011 | if (collects_undef && value == GTK_ACCESSIBLE_VALUE_UNDEFINED) |
1012 | { |
1013 | res = gtk_undefined_accessible_value_new (); |
1014 | } |
1015 | else |
1016 | { |
1017 | /* Token collection requires a constructor */ |
1018 | g_assert (ctor != NULL); |
1019 | |
1020 | res = (* ctor) (value); |
1021 | } |
1022 | |
1023 | if (res == NULL) |
1024 | { |
1025 | g_set_error (err: error, GTK_ACCESSIBLE_VALUE_ERROR, |
1026 | code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN, |
1027 | format: "Invalid value for token attribute: %d" , |
1028 | value); |
1029 | } |
1030 | } |
1031 | break; |
1032 | |
1033 | case GTK_ACCESSIBLE_COLLECT_INTEGER: |
1034 | { |
1035 | GtkAccessibleValueEnumCtor ctor = |
1036 | (GtkAccessibleValueEnumCtor) cstate->ctor; |
1037 | |
1038 | int value = va_arg (*args, int); |
1039 | |
1040 | if (ctor == NULL) |
1041 | res = gtk_int_accessible_value_new (value); |
1042 | else |
1043 | res = (* ctor) (value); |
1044 | } |
1045 | break; |
1046 | |
1047 | case GTK_ACCESSIBLE_COLLECT_NUMBER: |
1048 | { |
1049 | GtkAccessibleValueNumberCtor ctor = |
1050 | (GtkAccessibleValueNumberCtor) cstate->ctor; |
1051 | |
1052 | double value = va_arg (*args, double); |
1053 | |
1054 | if (isnan (value) || isinf (value)) |
1055 | { |
1056 | g_set_error_literal (err: error, GTK_ACCESSIBLE_VALUE_ERROR, |
1057 | code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE, |
1058 | message: "Invalid numeric value" ); |
1059 | return NULL; |
1060 | } |
1061 | |
1062 | if (ctor == NULL) |
1063 | res = gtk_number_accessible_value_new (value); |
1064 | else |
1065 | res = (* ctor) (value); |
1066 | } |
1067 | break; |
1068 | |
1069 | case GTK_ACCESSIBLE_COLLECT_STRING: |
1070 | { |
1071 | GtkAccessibleValueStringCtor ctor = |
1072 | (GtkAccessibleValueStringCtor) cstate->ctor; |
1073 | |
1074 | const char *value = va_arg (*args, char*); |
1075 | |
1076 | if (ctor == NULL) |
1077 | { |
1078 | if (value != NULL) |
1079 | res = gtk_string_accessible_value_new (str: value); |
1080 | } |
1081 | else |
1082 | { |
1083 | res = (* ctor) (value); |
1084 | } |
1085 | } |
1086 | break; |
1087 | |
1088 | case GTK_ACCESSIBLE_COLLECT_REFERENCE: |
1089 | { |
1090 | GtkAccessibleValueRefCtor ctor = |
1091 | (GtkAccessibleValueRefCtor) cstate->ctor; |
1092 | |
1093 | gpointer value = va_arg (*args, gpointer); |
1094 | |
1095 | if (value != NULL && !GTK_IS_ACCESSIBLE (ptr: value)) |
1096 | { |
1097 | g_set_error_literal (err: error, GTK_ACCESSIBLE_VALUE_ERROR, |
1098 | code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE, |
1099 | message: "Reference does not implement GtkAccessible" ); |
1100 | return NULL; |
1101 | } |
1102 | |
1103 | if (ctor == NULL) |
1104 | { |
1105 | if (value != NULL) |
1106 | res = gtk_reference_accessible_value_new (ref: value); |
1107 | else |
1108 | res = gtk_undefined_accessible_value_new (); |
1109 | } |
1110 | else |
1111 | { |
1112 | res = (* ctor) (value); |
1113 | } |
1114 | } |
1115 | break; |
1116 | |
1117 | case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST: |
1118 | { |
1119 | GtkAccessibleValueRefListCtor ctor = |
1120 | (GtkAccessibleValueRefListCtor) cstate->ctor; |
1121 | |
1122 | GtkAccessible *ref = va_arg (*args, gpointer); |
1123 | GList *value = NULL; |
1124 | |
1125 | while (ref != NULL) |
1126 | { |
1127 | if (!GTK_IS_ACCESSIBLE (ptr: ref)) |
1128 | { |
1129 | g_set_error (err: error, GTK_ACCESSIBLE_VALUE_ERROR, |
1130 | code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE, |
1131 | format: "Reference of type “%s” [%p] does not implement GtkAccessible" , |
1132 | G_OBJECT_TYPE_NAME (ref), ref); |
1133 | return NULL; |
1134 | } |
1135 | |
1136 | value = g_list_prepend (list: value, data: ref); |
1137 | |
1138 | ref = va_arg (*args, gpointer); |
1139 | } |
1140 | |
1141 | if (value == NULL) |
1142 | res = gtk_undefined_accessible_value_new (); |
1143 | else |
1144 | { |
1145 | value = g_list_reverse (list: value); |
1146 | |
1147 | if (ctor == NULL) |
1148 | res = gtk_reference_list_accessible_value_new (value); |
1149 | else |
1150 | res = (* ctor) (value); |
1151 | } |
1152 | } |
1153 | break; |
1154 | |
1155 | case GTK_ACCESSIBLE_COLLECT_UNDEFINED: |
1156 | case GTK_ACCESSIBLE_COLLECT_INVALID: |
1157 | default: |
1158 | g_assert_not_reached (); |
1159 | break; |
1160 | } |
1161 | |
1162 | return res; |
1163 | } |
1164 | |
1165 | static GtkAccessibleValue * |
1166 | gtk_accessible_value_collect_value (const GtkAccessibleCollect *cstate, |
1167 | const GValue *value_, |
1168 | GError **error) |
1169 | { |
1170 | GtkAccessibleValue *res = NULL; |
1171 | GtkAccessibleCollectType ctype = cstate->ctype; |
1172 | gboolean collects_undef = (ctype & GTK_ACCESSIBLE_COLLECT_UNDEFINED) != 0; |
1173 | |
1174 | ctype &= (GTK_ACCESSIBLE_COLLECT_UNDEFINED - 1); |
1175 | |
1176 | /* Tristate values include "undefined" by definition */ |
1177 | if (ctype == GTK_ACCESSIBLE_COLLECT_TRISTATE) |
1178 | collects_undef = TRUE; |
1179 | |
1180 | switch (ctype) |
1181 | { |
1182 | case GTK_ACCESSIBLE_COLLECT_BOOLEAN: |
1183 | { |
1184 | if (collects_undef) |
1185 | { |
1186 | int value = g_value_get_int (value: value_); |
1187 | |
1188 | if (value == GTK_ACCESSIBLE_VALUE_UNDEFINED) |
1189 | res = gtk_undefined_accessible_value_new (); |
1190 | else |
1191 | res = gtk_boolean_accessible_value_new (value: value == 0 ? FALSE : TRUE); |
1192 | } |
1193 | else |
1194 | { |
1195 | gboolean value = g_value_get_boolean (value: value_); |
1196 | |
1197 | res = gtk_boolean_accessible_value_new (value); |
1198 | } |
1199 | } |
1200 | break; |
1201 | |
1202 | case GTK_ACCESSIBLE_COLLECT_TRISTATE: |
1203 | { |
1204 | int value = g_value_get_int (value: value_); |
1205 | |
1206 | if (collects_undef && value == GTK_ACCESSIBLE_VALUE_UNDEFINED) |
1207 | res = gtk_undefined_accessible_value_new (); |
1208 | else |
1209 | res = gtk_tristate_accessible_value_new (value); |
1210 | } |
1211 | break; |
1212 | |
1213 | case GTK_ACCESSIBLE_COLLECT_TOKEN: |
1214 | { |
1215 | GtkAccessibleValueEnumCtor ctor = |
1216 | (GtkAccessibleValueEnumCtor) cstate->ctor; |
1217 | |
1218 | int value = g_value_get_int (value: value_); |
1219 | |
1220 | if (collects_undef && value == GTK_ACCESSIBLE_VALUE_UNDEFINED) |
1221 | { |
1222 | res = gtk_undefined_accessible_value_new (); |
1223 | } |
1224 | else |
1225 | { |
1226 | /* Token collection requires a constructor */ |
1227 | g_assert (ctor != NULL); |
1228 | |
1229 | res = (* ctor) (value); |
1230 | } |
1231 | |
1232 | if (res == NULL) |
1233 | { |
1234 | g_set_error (err: error, GTK_ACCESSIBLE_VALUE_ERROR, |
1235 | code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN, |
1236 | format: "Invalid value for token attribute: %d" , |
1237 | value); |
1238 | } |
1239 | } |
1240 | break; |
1241 | |
1242 | case GTK_ACCESSIBLE_COLLECT_INTEGER: |
1243 | { |
1244 | GtkAccessibleValueEnumCtor ctor = |
1245 | (GtkAccessibleValueEnumCtor) cstate->ctor; |
1246 | |
1247 | int value = g_value_get_int (value: value_); |
1248 | |
1249 | if (ctor == NULL) |
1250 | res = gtk_int_accessible_value_new (value); |
1251 | else |
1252 | res = (* ctor) (value); |
1253 | } |
1254 | break; |
1255 | |
1256 | case GTK_ACCESSIBLE_COLLECT_NUMBER: |
1257 | { |
1258 | GtkAccessibleValueNumberCtor ctor = |
1259 | (GtkAccessibleValueNumberCtor) cstate->ctor; |
1260 | |
1261 | double value = g_value_get_double (value: value_); |
1262 | |
1263 | if (isnan (value) || isinf (value)) |
1264 | { |
1265 | g_set_error_literal (err: error, GTK_ACCESSIBLE_VALUE_ERROR, |
1266 | code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE, |
1267 | message: "Invalid numeric value" ); |
1268 | return NULL; |
1269 | } |
1270 | |
1271 | if (ctor == NULL) |
1272 | res = gtk_number_accessible_value_new (value); |
1273 | else |
1274 | res = (* ctor) (value); |
1275 | } |
1276 | break; |
1277 | |
1278 | case GTK_ACCESSIBLE_COLLECT_STRING: |
1279 | { |
1280 | GtkAccessibleValueStringCtor ctor = |
1281 | (GtkAccessibleValueStringCtor) cstate->ctor; |
1282 | |
1283 | const char *value = g_value_get_string (value: value_); |
1284 | |
1285 | if (ctor == NULL) |
1286 | { |
1287 | if (value != NULL) |
1288 | res = gtk_string_accessible_value_new (str: value); |
1289 | } |
1290 | else |
1291 | { |
1292 | res = (* ctor) (value); |
1293 | } |
1294 | } |
1295 | break; |
1296 | |
1297 | case GTK_ACCESSIBLE_COLLECT_REFERENCE: |
1298 | { |
1299 | GtkAccessibleValueRefCtor ctor = |
1300 | (GtkAccessibleValueRefCtor) cstate->ctor; |
1301 | |
1302 | gpointer value = g_value_get_object (value: value_); |
1303 | |
1304 | if (value != NULL && !GTK_IS_ACCESSIBLE (ptr: value)) |
1305 | { |
1306 | g_set_error_literal (err: error, GTK_ACCESSIBLE_VALUE_ERROR, |
1307 | code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE, |
1308 | message: "Reference does not implement GtkAccessible" ); |
1309 | return NULL; |
1310 | } |
1311 | |
1312 | if (ctor == NULL) |
1313 | { |
1314 | if (value != NULL) |
1315 | res = gtk_reference_accessible_value_new (ref: value); |
1316 | } |
1317 | else |
1318 | { |
1319 | res = (* ctor) (value); |
1320 | } |
1321 | } |
1322 | break; |
1323 | |
1324 | case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST: |
1325 | { |
1326 | GtkAccessibleValueRefListCtor ctor = |
1327 | (GtkAccessibleValueRefListCtor) cstate->ctor; |
1328 | |
1329 | GList *value = g_value_get_pointer (value: value_); |
1330 | |
1331 | if (ctor == NULL) |
1332 | { |
1333 | if (value != NULL) |
1334 | res = gtk_reference_list_accessible_value_new (value); |
1335 | } |
1336 | else |
1337 | { |
1338 | res = (* ctor) (value); |
1339 | } |
1340 | } |
1341 | break; |
1342 | |
1343 | case GTK_ACCESSIBLE_COLLECT_UNDEFINED: |
1344 | case GTK_ACCESSIBLE_COLLECT_INVALID: |
1345 | default: |
1346 | g_assert_not_reached (); |
1347 | break; |
1348 | } |
1349 | |
1350 | return res; |
1351 | } |
1352 | |
1353 | static GtkAccessibleValue * |
1354 | gtk_accessible_value_parse (const GtkAccessibleCollect *cstate, |
1355 | const char *str, |
1356 | gsize len, |
1357 | GError **error) |
1358 | { |
1359 | GtkAccessibleValue *res = NULL; |
1360 | GtkAccessibleCollectType ctype = cstate->ctype; |
1361 | gboolean collects_undef = (ctype & GTK_ACCESSIBLE_COLLECT_UNDEFINED) != 0; |
1362 | |
1363 | ctype &= (GTK_ACCESSIBLE_COLLECT_UNDEFINED - 1); |
1364 | |
1365 | /* Tristate values include "undefined" by definition */ |
1366 | if (ctype == GTK_ACCESSIBLE_COLLECT_TRISTATE) |
1367 | collects_undef = TRUE; |
1368 | |
1369 | switch (ctype) |
1370 | { |
1371 | case GTK_ACCESSIBLE_COLLECT_BOOLEAN: |
1372 | { |
1373 | gboolean b; |
1374 | |
1375 | if (collects_undef && strncmp (s1: str, s2: "undefined" , n: 9) == 0) |
1376 | res = gtk_undefined_accessible_value_new (); |
1377 | else if (_gtk_builder_boolean_from_string (string: str, value: &b, error)) |
1378 | res = gtk_boolean_accessible_value_new (value: b); |
1379 | } |
1380 | break; |
1381 | |
1382 | case GTK_ACCESSIBLE_COLLECT_TRISTATE: |
1383 | { |
1384 | int value; |
1385 | |
1386 | if (collects_undef && strncmp (s1: str, s2: "undefined" , n: 9) == 0) |
1387 | res = gtk_undefined_accessible_value_new (); |
1388 | else if (_gtk_builder_enum_from_string (type: GTK_TYPE_ACCESSIBLE_TRISTATE, string: str, enum_value: &value, error)) |
1389 | res = gtk_boolean_accessible_value_new (value); |
1390 | } |
1391 | break; |
1392 | |
1393 | case GTK_ACCESSIBLE_COLLECT_TOKEN: |
1394 | { |
1395 | GtkAccessibleValueEnumParser parser = |
1396 | (GtkAccessibleValueEnumParser) cstate->parser; |
1397 | |
1398 | if (collects_undef && strncmp (s1: str, s2: "undefined" , n: 9) == 0) |
1399 | { |
1400 | res = gtk_undefined_accessible_value_new (); |
1401 | } |
1402 | else |
1403 | { |
1404 | /* Token collection requires a constructor */ |
1405 | g_assert (parser != NULL); |
1406 | |
1407 | res = (* parser) (str, len, error); |
1408 | } |
1409 | } |
1410 | break; |
1411 | |
1412 | case GTK_ACCESSIBLE_COLLECT_INTEGER: |
1413 | { |
1414 | char *end = NULL; |
1415 | gint64 value = g_ascii_strtoll (nptr: str, endptr: &end, base: 10); |
1416 | |
1417 | if (str == end) |
1418 | { |
1419 | int saved_errno = errno; |
1420 | g_set_error (err: error, GTK_ACCESSIBLE_VALUE_ERROR, |
1421 | code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE, |
1422 | format: "Invalid integer value “%s”: %s" , |
1423 | str, g_strerror (errnum: saved_errno)); |
1424 | |
1425 | return NULL; |
1426 | } |
1427 | else |
1428 | res = gtk_int_accessible_value_new (value: (int) value); |
1429 | } |
1430 | break; |
1431 | |
1432 | case GTK_ACCESSIBLE_COLLECT_NUMBER: |
1433 | { |
1434 | char *end = NULL; |
1435 | double value = g_ascii_strtod (nptr: str, endptr: &end); |
1436 | |
1437 | if (str == end || isnan (value) || isinf (value)) |
1438 | { |
1439 | g_set_error (err: error, GTK_ACCESSIBLE_VALUE_ERROR, |
1440 | code: GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE, |
1441 | format: "Invalid numeric value “%s”" , |
1442 | str); |
1443 | return NULL; |
1444 | } |
1445 | |
1446 | res = gtk_number_accessible_value_new (value); |
1447 | } |
1448 | break; |
1449 | |
1450 | case GTK_ACCESSIBLE_COLLECT_STRING: |
1451 | { |
1452 | res = gtk_string_accessible_value_new (str); |
1453 | } |
1454 | break; |
1455 | |
1456 | case GTK_ACCESSIBLE_COLLECT_REFERENCE: |
1457 | case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST: |
1458 | { |
1459 | /* We do not error out, to let the caller code deal |
1460 | * with the references themselves |
1461 | */ |
1462 | res = NULL; |
1463 | } |
1464 | break; |
1465 | |
1466 | case GTK_ACCESSIBLE_COLLECT_UNDEFINED: |
1467 | case GTK_ACCESSIBLE_COLLECT_INVALID: |
1468 | default: |
1469 | g_assert_not_reached (); |
1470 | break; |
1471 | } |
1472 | |
1473 | return res; |
1474 | } |
1475 | |
1476 | static void |
1477 | gtk_accessible_attribute_init_value (const GtkAccessibleCollect *cstate, |
1478 | GValue *value) |
1479 | { |
1480 | GtkAccessibleCollectType ctype = cstate->ctype; |
1481 | gboolean collects_undef = (ctype & GTK_ACCESSIBLE_COLLECT_UNDEFINED) != 0; |
1482 | |
1483 | ctype &= (GTK_ACCESSIBLE_COLLECT_UNDEFINED - 1); |
1484 | |
1485 | /* Tristate values include "undefined" by definition */ |
1486 | if (ctype == GTK_ACCESSIBLE_COLLECT_TRISTATE) |
1487 | collects_undef = TRUE; |
1488 | |
1489 | switch (ctype) |
1490 | { |
1491 | case GTK_ACCESSIBLE_COLLECT_BOOLEAN: |
1492 | { |
1493 | if (collects_undef) |
1494 | g_value_init (value, G_TYPE_INT); |
1495 | else |
1496 | g_value_init (value, G_TYPE_BOOLEAN); |
1497 | } |
1498 | break; |
1499 | |
1500 | case GTK_ACCESSIBLE_COLLECT_TRISTATE: |
1501 | g_value_init (value, g_type: GTK_TYPE_ACCESSIBLE_TRISTATE); |
1502 | break; |
1503 | |
1504 | case GTK_ACCESSIBLE_COLLECT_TOKEN: |
1505 | if (cstate->init_value != NULL) |
1506 | { |
1507 | GtkAccessibleValueEnumInit init_value = |
1508 | (GtkAccessibleValueEnumInit) cstate->init_value; |
1509 | |
1510 | (* init_value) (value); |
1511 | } |
1512 | else |
1513 | g_value_init (value, G_TYPE_INT); |
1514 | break; |
1515 | |
1516 | case GTK_ACCESSIBLE_COLLECT_INTEGER: |
1517 | g_value_init (value, G_TYPE_INT); |
1518 | break; |
1519 | |
1520 | case GTK_ACCESSIBLE_COLLECT_NUMBER: |
1521 | g_value_init (value, G_TYPE_DOUBLE); |
1522 | break; |
1523 | |
1524 | case GTK_ACCESSIBLE_COLLECT_STRING: |
1525 | g_value_init (value, G_TYPE_STRING); |
1526 | break; |
1527 | |
1528 | case GTK_ACCESSIBLE_COLLECT_REFERENCE: |
1529 | g_value_init (value, GTK_TYPE_ACCESSIBLE); |
1530 | break; |
1531 | |
1532 | case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST: |
1533 | g_value_init (value, G_TYPE_POINTER); |
1534 | break; |
1535 | |
1536 | case GTK_ACCESSIBLE_COLLECT_UNDEFINED: |
1537 | case GTK_ACCESSIBLE_COLLECT_INVALID: |
1538 | default: |
1539 | g_assert_not_reached (); |
1540 | break; |
1541 | } |
1542 | } |
1543 | |
1544 | /*< private > |
1545 | * gtk_accessible_value_collect_for_state: |
1546 | * @state: a `GtkAccessibleState` |
1547 | * @error: return location for a `GError` |
1548 | * @args: a `va_list` reference |
1549 | * |
1550 | * Collects and consumes the next item in the @args variadic arguments list, |
1551 | * and returns a `GtkAccessibleValue` for it. |
1552 | * |
1553 | * If the collection fails, @error is set and %NULL is returned. |
1554 | * |
1555 | * The returned value could be %NULL even on success, in which case the state |
1556 | * should be reset to its default value by the caller. |
1557 | * |
1558 | * Returns: (transfer full) (nullable): a `GtkAccessibleValue` |
1559 | */ |
1560 | GtkAccessibleValue * |
1561 | gtk_accessible_value_collect_for_state (GtkAccessibleState state, |
1562 | GError **error, |
1563 | va_list *args) |
1564 | { |
1565 | const GtkAccessibleCollect *cstate = &collect_states[state]; |
1566 | |
1567 | g_return_val_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED, NULL); |
1568 | |
1569 | return gtk_accessible_value_collect_valist (cstate, error, args); |
1570 | } |
1571 | |
1572 | /*< private > |
1573 | * gtk_accessible_value_collect_for_state_value: |
1574 | * @state: a `GtkAccessibleState` |
1575 | * @value: a `GValue` |
1576 | * @error: return location for a `GError` |
1577 | * |
1578 | * Retrieves the value stored inside @value and returns a `GtkAccessibleValue` |
1579 | * for the given @state. |
1580 | * |
1581 | * If the collection fails, @error is set and %NULL is returned. |
1582 | * |
1583 | * The returned value could be %NULL even on success, in which case the state |
1584 | * should be reset to its default value by the caller. |
1585 | * |
1586 | * Returns: (transfer full) (nullable): a `GtkAccessibleValue` |
1587 | */ |
1588 | GtkAccessibleValue * |
1589 | gtk_accessible_value_collect_for_state_value (GtkAccessibleState state, |
1590 | const GValue *value, |
1591 | GError **error) |
1592 | { |
1593 | const GtkAccessibleCollect *cstate = &collect_states[state]; |
1594 | |
1595 | g_return_val_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED, NULL); |
1596 | |
1597 | return gtk_accessible_value_collect_value (cstate, value_: value, error); |
1598 | } |
1599 | |
1600 | GtkAccessibleValue * |
1601 | gtk_accessible_value_parse_for_state (GtkAccessibleState state, |
1602 | const char *str, |
1603 | gsize len, |
1604 | GError **error) |
1605 | { |
1606 | const GtkAccessibleCollect *cstate = &collect_states[state]; |
1607 | |
1608 | g_return_val_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED, NULL); |
1609 | |
1610 | return gtk_accessible_value_parse (cstate, str, len, error); |
1611 | } |
1612 | |
1613 | /** |
1614 | * gtk_accessible_state_init_value: |
1615 | * @state: a `GtkAccessibleState` |
1616 | * @value: an uninitialized `GValue` |
1617 | * |
1618 | * Initializes @value with the appropriate type for the @state. |
1619 | * |
1620 | * This function is mostly meant for language bindings, in conjunction |
1621 | * with gtk_accessible_update_relation_state(). |
1622 | */ |
1623 | void |
1624 | gtk_accessible_state_init_value (GtkAccessibleState state, |
1625 | GValue *value) |
1626 | { |
1627 | const GtkAccessibleCollect *cstate = &collect_states[state]; |
1628 | |
1629 | g_return_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED); |
1630 | |
1631 | gtk_accessible_attribute_init_value (cstate, value); |
1632 | } |
1633 | |
1634 | /*< private > |
1635 | * gtk_accessible_value_get_default_for_property: |
1636 | * @property: a `GtkAccessibleProperty` |
1637 | * |
1638 | * Retrieves the `GtkAccessibleValue` that contains the default for the |
1639 | * given @property. |
1640 | * |
1641 | * Returns: (transfer full): the `GtkAccessibleValue` |
1642 | */ |
1643 | GtkAccessibleValue * |
1644 | gtk_accessible_value_get_default_for_property (GtkAccessibleProperty property) |
1645 | { |
1646 | const GtkAccessibleCollect *cstate = &collect_props[property]; |
1647 | |
1648 | g_return_val_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, NULL); |
1649 | |
1650 | switch (cstate->value) |
1651 | { |
1652 | /* Boolean properties */ |
1653 | case GTK_ACCESSIBLE_PROPERTY_HAS_POPUP: |
1654 | case GTK_ACCESSIBLE_PROPERTY_MODAL: |
1655 | case GTK_ACCESSIBLE_PROPERTY_MULTI_LINE: |
1656 | case GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE: |
1657 | case GTK_ACCESSIBLE_PROPERTY_READ_ONLY: |
1658 | case GTK_ACCESSIBLE_PROPERTY_REQUIRED: |
1659 | return gtk_boolean_accessible_value_new (FALSE); |
1660 | |
1661 | /* Integer properties */ |
1662 | case GTK_ACCESSIBLE_PROPERTY_LEVEL: |
1663 | return gtk_int_accessible_value_new (value: 0); |
1664 | |
1665 | /* Number properties */ |
1666 | case GTK_ACCESSIBLE_PROPERTY_VALUE_MAX: |
1667 | case GTK_ACCESSIBLE_PROPERTY_VALUE_MIN: |
1668 | case GTK_ACCESSIBLE_PROPERTY_VALUE_NOW: |
1669 | return gtk_number_accessible_value_new (value: 0); |
1670 | |
1671 | /* String properties */ |
1672 | case GTK_ACCESSIBLE_PROPERTY_DESCRIPTION: |
1673 | case GTK_ACCESSIBLE_PROPERTY_KEY_SHORTCUTS: |
1674 | case GTK_ACCESSIBLE_PROPERTY_LABEL: |
1675 | case GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER: |
1676 | case GTK_ACCESSIBLE_PROPERTY_ROLE_DESCRIPTION: |
1677 | case GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT: |
1678 | return gtk_undefined_accessible_value_new (); |
1679 | |
1680 | /* Token properties */ |
1681 | case GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE: |
1682 | return gtk_autocomplete_accessible_value_new (value: GTK_ACCESSIBLE_AUTOCOMPLETE_NONE); |
1683 | |
1684 | case GTK_ACCESSIBLE_PROPERTY_ORIENTATION: |
1685 | return gtk_undefined_accessible_value_new (); |
1686 | |
1687 | case GTK_ACCESSIBLE_PROPERTY_SORT: |
1688 | return gtk_sort_accessible_value_new (value: GTK_ACCESSIBLE_SORT_NONE); |
1689 | |
1690 | default: |
1691 | g_critical ("Unknown value for accessible property “%s”" , cstate->name); |
1692 | break; |
1693 | } |
1694 | |
1695 | return NULL; |
1696 | } |
1697 | |
1698 | /*< private > |
1699 | * gtk_accessible_value_collect_for_property: |
1700 | * @property: a `GtkAccessibleProperty` |
1701 | * @error: return location for a `GError` |
1702 | * @args: a `va_list` reference |
1703 | * |
1704 | * Collects and consumes the next item in the @args variadic arguments list, |
1705 | * and returns a `GtkAccessibleValue` for it. |
1706 | * |
1707 | * If the collection fails, @error is set. |
1708 | * |
1709 | * Returns: (transfer full) (nullable): a `GtkAccessibleValue` |
1710 | */ |
1711 | GtkAccessibleValue * |
1712 | gtk_accessible_value_collect_for_property (GtkAccessibleProperty property, |
1713 | GError **error, |
1714 | va_list *args) |
1715 | { |
1716 | const GtkAccessibleCollect *cstate = &collect_props[property]; |
1717 | |
1718 | g_return_val_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, NULL); |
1719 | |
1720 | return gtk_accessible_value_collect_valist (cstate, error, args); |
1721 | } |
1722 | |
1723 | /*< private > |
1724 | * gtk_accessible_value_collect_for_property_value: |
1725 | * @property: a `GtkAccessibleProperty` |
1726 | * @value: a `GValue` |
1727 | * @error: return location for a `GError` |
1728 | * |
1729 | * Retrieves the value stored inside @value and returns a `GtkAccessibleValue` |
1730 | * for the given @property. |
1731 | * |
1732 | * If the collection fails, @error is set. |
1733 | * |
1734 | * The returned value could be %NULL even on success, in which case the property |
1735 | * should be reset to its default value by the caller. |
1736 | * |
1737 | * Returns: (transfer full) (nullable): a `GtkAccessibleValue` |
1738 | */ |
1739 | GtkAccessibleValue * |
1740 | gtk_accessible_value_collect_for_property_value (GtkAccessibleProperty property, |
1741 | const GValue *value, |
1742 | GError **error) |
1743 | { |
1744 | const GtkAccessibleCollect *cstate = &collect_props[property]; |
1745 | |
1746 | g_return_val_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, NULL); |
1747 | |
1748 | return gtk_accessible_value_collect_value (cstate, value_: value, error); |
1749 | } |
1750 | |
1751 | GtkAccessibleValue * |
1752 | gtk_accessible_value_parse_for_property (GtkAccessibleProperty property, |
1753 | const char *str, |
1754 | gsize len, |
1755 | GError **error) |
1756 | { |
1757 | const GtkAccessibleCollect *cstate = &collect_props[property]; |
1758 | |
1759 | g_return_val_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, NULL); |
1760 | |
1761 | return gtk_accessible_value_parse (cstate, str, len, error); |
1762 | } |
1763 | |
1764 | /** |
1765 | * gtk_accessible_property_init_value: |
1766 | * @property: a `GtkAccessibleProperty` |
1767 | * @value: an uninitialized `GValue` |
1768 | * |
1769 | * Initializes @value with the appropriate type for the @property. |
1770 | * |
1771 | * This function is mostly meant for language bindings, in conjunction |
1772 | * with gtk_accessible_update_property_value(). |
1773 | */ |
1774 | void |
1775 | gtk_accessible_property_init_value (GtkAccessibleProperty property, |
1776 | GValue *value) |
1777 | { |
1778 | const GtkAccessibleCollect *cstate = &collect_props[property]; |
1779 | |
1780 | g_return_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT); |
1781 | |
1782 | gtk_accessible_attribute_init_value (cstate, value); |
1783 | } |
1784 | |
1785 | /*< private > |
1786 | * gtk_accessible_value_get_default_for_relation: |
1787 | * @relation: a `GtkAccessibleRelation` |
1788 | * |
1789 | * Retrieves the `GtkAccessibleValue` that contains the default for the |
1790 | * given @relation. |
1791 | * |
1792 | * Returns: (transfer full): the `GtkAccessibleValue` |
1793 | */ |
1794 | GtkAccessibleValue * |
1795 | gtk_accessible_value_get_default_for_relation (GtkAccessibleRelation relation) |
1796 | { |
1797 | const GtkAccessibleCollect *cstate = &collect_rels[relation]; |
1798 | |
1799 | g_return_val_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE, NULL); |
1800 | |
1801 | switch (cstate->value) |
1802 | { |
1803 | /* References */ |
1804 | case GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT: |
1805 | case GTK_ACCESSIBLE_RELATION_CONTROLS: |
1806 | case GTK_ACCESSIBLE_RELATION_DESCRIBED_BY: |
1807 | case GTK_ACCESSIBLE_RELATION_DETAILS: |
1808 | case GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE: |
1809 | case GTK_ACCESSIBLE_RELATION_FLOW_TO: |
1810 | case GTK_ACCESSIBLE_RELATION_LABELLED_BY: |
1811 | case GTK_ACCESSIBLE_RELATION_OWNS: |
1812 | return gtk_undefined_accessible_value_new (); |
1813 | |
1814 | /* Integers */ |
1815 | case GTK_ACCESSIBLE_RELATION_COL_COUNT: |
1816 | case GTK_ACCESSIBLE_RELATION_COL_INDEX: |
1817 | case GTK_ACCESSIBLE_RELATION_COL_SPAN: |
1818 | case GTK_ACCESSIBLE_RELATION_POS_IN_SET: |
1819 | case GTK_ACCESSIBLE_RELATION_ROW_COUNT: |
1820 | case GTK_ACCESSIBLE_RELATION_ROW_INDEX: |
1821 | case GTK_ACCESSIBLE_RELATION_ROW_SPAN: |
1822 | case GTK_ACCESSIBLE_RELATION_SET_SIZE: |
1823 | return gtk_int_accessible_value_new (value: 0); |
1824 | |
1825 | /* Strings */ |
1826 | case GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT: |
1827 | case GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT: |
1828 | return gtk_undefined_accessible_value_new (); |
1829 | |
1830 | default: |
1831 | g_critical ("Unknown value for accessible property “%s”" , cstate->name); |
1832 | break; |
1833 | } |
1834 | |
1835 | return NULL; |
1836 | } |
1837 | |
1838 | /*< private > |
1839 | * gtk_accessible_value_collect_for_relation: |
1840 | * @relation: a `GtkAccessibleRelation` |
1841 | * @error: return location for a `GError` |
1842 | * @args: a `va_list` reference |
1843 | * |
1844 | * Collects and consumes the next item in the @args variadic arguments list, |
1845 | * and returns a `GtkAccessibleValue` for it. |
1846 | * |
1847 | * If the collection fails, @error is set and %NULL is returned. |
1848 | * |
1849 | * The returned value could be %NULL even on success, in which case the relation |
1850 | * should be reset to its default value by the caller. |
1851 | * |
1852 | * Returns: (transfer full) (nullable): a `GtkAccessibleValue` |
1853 | */ |
1854 | GtkAccessibleValue * |
1855 | gtk_accessible_value_collect_for_relation (GtkAccessibleRelation relation, |
1856 | GError **error, |
1857 | va_list *args) |
1858 | { |
1859 | const GtkAccessibleCollect *cstate = &collect_rels[relation]; |
1860 | |
1861 | g_return_val_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE, NULL); |
1862 | |
1863 | return gtk_accessible_value_collect_valist (cstate, error, args); |
1864 | } |
1865 | |
1866 | /*< private > |
1867 | * gtk_accessible_value_collect_for_relation_value: |
1868 | * @relation: a `GtkAccessibleRelation` |
1869 | * @value: a `GValue` |
1870 | * @error: return location for a `GError` |
1871 | * |
1872 | * Retrieves the value stored inside @value and returns a `GtkAccessibleValue` |
1873 | * for the given @relation. |
1874 | * |
1875 | * If the collection fails, @error is set and %NULL is returned. |
1876 | * |
1877 | * The returned value could be %NULL even on success, in which case the relation |
1878 | * should be reset to its default value by the caller. |
1879 | * |
1880 | * Returns: (transfer full) (nullable): a `GtkAccessibleValue` |
1881 | */ |
1882 | GtkAccessibleValue * |
1883 | gtk_accessible_value_collect_for_relation_value (GtkAccessibleRelation relation, |
1884 | const GValue *value, |
1885 | GError **error) |
1886 | { |
1887 | const GtkAccessibleCollect *cstate = &collect_rels[relation]; |
1888 | |
1889 | g_return_val_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE, NULL); |
1890 | |
1891 | return gtk_accessible_value_collect_value (cstate, value_: value, error); |
1892 | } |
1893 | |
1894 | GtkAccessibleValue * |
1895 | gtk_accessible_value_parse_for_relation (GtkAccessibleRelation relation, |
1896 | const char *str, |
1897 | gsize len, |
1898 | GError **error) |
1899 | { |
1900 | const GtkAccessibleCollect *cstate = &collect_rels[relation]; |
1901 | |
1902 | g_return_val_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE, NULL); |
1903 | |
1904 | return gtk_accessible_value_parse (cstate, str, len, error); |
1905 | } |
1906 | |
1907 | /** |
1908 | * gtk_accessible_relation_init_value: |
1909 | * @relation: a `GtkAccessibleRelation` |
1910 | * @value: an uninitialized `GValue` |
1911 | * |
1912 | * Initializes @value with the appropriate type for the @relation. |
1913 | * |
1914 | * This function is mostly meant for language bindings, in conjunction |
1915 | * with gtk_accessible_update_relation_value(). |
1916 | */ |
1917 | void |
1918 | gtk_accessible_relation_init_value (GtkAccessibleRelation relation, |
1919 | GValue *value) |
1920 | { |
1921 | const GtkAccessibleCollect *cstate = &collect_rels[relation]; |
1922 | |
1923 | g_return_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE); |
1924 | |
1925 | gtk_accessible_attribute_init_value (cstate, value); |
1926 | } |
1927 | |
1928 | /* }}} */ |
1929 | |