forked from AuroraMiddleware/gtk
fe50286e14
Bail out early, instead of going deep into the GtkAccessibleValue type equal() implementation, where we expect both accessible values to have the same type.
1600 lines
47 KiB
C
1600 lines
47 KiB
C
/* gtkaccessiblevalue.c: Accessible value
|
|
*
|
|
* Copyright 2020 GNOME Foundation
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
*
|
|
* 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.1 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/*< private >
|
|
* SECTION: gtkaccessiblevalue
|
|
* @Title: GtkAccessibleValue
|
|
* @Short_description: Container for accessible state and property values
|
|
*
|
|
* GtkAccessibleValue is a reference counted, generic container for values used
|
|
* to represent the state and properties of a #GtkAccessible implementation.
|
|
*
|
|
* There are two kinds of accessible value types:
|
|
*
|
|
* - hard coded, static values; GTK owns them, and their contents, and are
|
|
* guaranteed to exist for the duration of the application's life time
|
|
* - dynamic values; the accessible state owns the value and their contents,
|
|
* and they can be allocated and freed
|
|
*
|
|
* Typically, the former type of values is used for boolean, tristate, and
|
|
* token value; the latter is used for numbers, strings, and token lists.
|
|
*
|
|
* For more information on the types of values, see the [WAI-ARIA](https://www.w3.org/WAI/PF/aria/states_and_properties#propcharacteristic_value)
|
|
* reference.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "gtkaccessiblevalueprivate.h"
|
|
|
|
#include "gtkaccessible.h"
|
|
#include "gtkenums.h"
|
|
|
|
#include <math.h>
|
|
#include <float.h>
|
|
|
|
G_DEFINE_QUARK (gtk-accessible-value-error-quark, gtk_accessible_value_error)
|
|
|
|
G_DEFINE_BOXED_TYPE (GtkAccessibleValue, gtk_accessible_value,
|
|
gtk_accessible_value_ref,
|
|
gtk_accessible_value_unref)
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_alloc:
|
|
* @value_class: a #GtkAccessibleValueClass structure
|
|
*
|
|
* Allocates a new #GtkAccessibleValue subclass using @value_class as the
|
|
* type definition.
|
|
*
|
|
* Returns: (transfer full): the newly allocated #GtkAccessibleValue
|
|
*/
|
|
GtkAccessibleValue *
|
|
gtk_accessible_value_alloc (const GtkAccessibleValueClass *value_class)
|
|
{
|
|
g_return_val_if_fail (value_class != NULL, NULL);
|
|
g_return_val_if_fail (value_class->instance_size >= sizeof (GtkAccessibleValue), NULL);
|
|
|
|
GtkAccessibleValue *res = g_malloc0 (value_class->instance_size);
|
|
|
|
/* We do not use grefcount, here, because we want to have statically
|
|
* allocated GtkAccessibleValue subclasses, and those cannot be initialized
|
|
* with g_ref_count_init()
|
|
*/
|
|
res->ref_count = 1;
|
|
res->value_class = value_class;
|
|
|
|
if (res->value_class->init != NULL)
|
|
res->value_class->init (res);
|
|
|
|
return res;
|
|
}
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_ref:
|
|
* @self: a #GtkAccessibleValue
|
|
*
|
|
* Acquires a reference on the given #GtkAccessibleValue.
|
|
*
|
|
* Returns: (transfer full): the value, with an additional reference
|
|
*/
|
|
GtkAccessibleValue *
|
|
gtk_accessible_value_ref (GtkAccessibleValue *self)
|
|
{
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
self->ref_count += 1;
|
|
|
|
return self;
|
|
}
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_unref:
|
|
* @self: (transfer full): a #GtkAccessibleValue
|
|
*
|
|
* Releases a reference on the given #GtkAccessibleValue.
|
|
*/
|
|
void
|
|
gtk_accessible_value_unref (GtkAccessibleValue *self)
|
|
{
|
|
g_return_if_fail (self != NULL);
|
|
|
|
self->ref_count -= 1;
|
|
if (self->ref_count == 0)
|
|
{
|
|
if (self->value_class->finalize != NULL)
|
|
self->value_class->finalize (self);
|
|
|
|
g_free (self);
|
|
}
|
|
}
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_print:
|
|
* @self: a #GtkAccessibleValue
|
|
* @buffer: a #GString
|
|
*
|
|
* Prints the contents of a #GtkAccessibleValue into the given @buffer.
|
|
*/
|
|
void
|
|
gtk_accessible_value_print (const GtkAccessibleValue *self,
|
|
GString *buffer)
|
|
{
|
|
g_return_if_fail (self != NULL);
|
|
g_return_if_fail (buffer != NULL);
|
|
|
|
if (self->value_class->print != NULL)
|
|
self->value_class->print (self, buffer);
|
|
}
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_to_string:
|
|
* @self: a #GtkAccessibleValue
|
|
*
|
|
* Fills a string with the contents of the given #GtkAccessibleValue.
|
|
*
|
|
* Returns: (transfer full): a string with the contents of the value
|
|
*/
|
|
char *
|
|
gtk_accessible_value_to_string (const GtkAccessibleValue *self)
|
|
{
|
|
g_return_val_if_fail (self != NULL, NULL);
|
|
|
|
GString *buffer = g_string_new (NULL);
|
|
|
|
gtk_accessible_value_print (self, buffer);
|
|
|
|
return g_string_free (buffer, FALSE);
|
|
}
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_equal:
|
|
* @value_a: (nullable): the first #GtkAccessibleValue
|
|
* @value_b: (nullable): the second #GtkAccessibleValue
|
|
*
|
|
* Checks whether @value_a and @value_b are equal.
|
|
*
|
|
* This function is %NULL-safe.
|
|
*
|
|
* Returns: %TRUE if the given #GtkAccessibleValue instances are equal,
|
|
* and %FALSE otherwise
|
|
*/
|
|
gboolean
|
|
gtk_accessible_value_equal (const GtkAccessibleValue *value_a,
|
|
const GtkAccessibleValue *value_b)
|
|
{
|
|
if (value_a == value_b)
|
|
return TRUE;
|
|
|
|
if (value_a == NULL || value_b == NULL)
|
|
return FALSE;
|
|
|
|
if (value_a->value_class != value_b->value_class)
|
|
return FALSE;
|
|
|
|
if (value_a->value_class->equal == NULL)
|
|
return FALSE;
|
|
|
|
return value_a->value_class->equal (value_a, value_b);
|
|
}
|
|
|
|
/* {{{ Basic allocated types */
|
|
|
|
typedef struct {
|
|
GtkAccessibleValue parent;
|
|
|
|
int value;
|
|
} GtkIntAccessibleValue;
|
|
|
|
static gboolean
|
|
gtk_int_accessible_value_equal (const GtkAccessibleValue *value_a,
|
|
const GtkAccessibleValue *value_b)
|
|
{
|
|
const GtkIntAccessibleValue *self_a = (GtkIntAccessibleValue *) value_a;
|
|
const GtkIntAccessibleValue *self_b = (GtkIntAccessibleValue *) value_b;
|
|
|
|
return self_a->value == self_b->value;
|
|
}
|
|
|
|
static void
|
|
gtk_int_accessible_value_print (const GtkAccessibleValue *value,
|
|
GString *buffer)
|
|
{
|
|
const GtkIntAccessibleValue *self = (GtkIntAccessibleValue *) value;
|
|
|
|
g_string_append_printf (buffer, "%d", self->value);
|
|
}
|
|
|
|
static const GtkAccessibleValueClass GTK_INT_ACCESSIBLE_VALUE = {
|
|
.type = GTK_ACCESSIBLE_VALUE_TYPE_INTEGER,
|
|
.type_name = "GtkIntAccessibleValue",
|
|
.instance_size = sizeof (GtkIntAccessibleValue),
|
|
.equal = gtk_int_accessible_value_equal,
|
|
.print = gtk_int_accessible_value_print,
|
|
};
|
|
|
|
GtkAccessibleValue *
|
|
gtk_int_accessible_value_new (int value)
|
|
{
|
|
GtkAccessibleValue *res = gtk_accessible_value_alloc (>K_INT_ACCESSIBLE_VALUE);
|
|
|
|
/* XXX: Possible optimization: statically allocate the first N values
|
|
* and hand out references to them, instead of dynamically
|
|
* allocating a new GtkAccessibleValue instance. Needs some profiling
|
|
* to figure out the common integer values used by large applications
|
|
*/
|
|
GtkIntAccessibleValue *self = (GtkIntAccessibleValue *) res;
|
|
self->value = value;
|
|
|
|
return res;
|
|
}
|
|
|
|
int
|
|
gtk_int_accessible_value_get (const GtkAccessibleValue *value)
|
|
{
|
|
GtkIntAccessibleValue *self = (GtkIntAccessibleValue *) value;
|
|
|
|
g_return_val_if_fail (value != NULL, 0);
|
|
g_return_val_if_fail (value->value_class == >K_INT_ACCESSIBLE_VALUE, 0);
|
|
|
|
return self->value;
|
|
}
|
|
|
|
typedef struct {
|
|
GtkAccessibleValue parent;
|
|
|
|
double value;
|
|
} GtkNumberAccessibleValue;
|
|
|
|
static gboolean
|
|
gtk_number_accessible_value_equal (const GtkAccessibleValue *value_a,
|
|
const GtkAccessibleValue *value_b)
|
|
{
|
|
const GtkNumberAccessibleValue *self_a = (GtkNumberAccessibleValue *) value_a;
|
|
const GtkNumberAccessibleValue *self_b = (GtkNumberAccessibleValue *) value_b;
|
|
|
|
return G_APPROX_VALUE (self_a->value, self_b->value, 0.001);
|
|
}
|
|
|
|
static void
|
|
gtk_number_accessible_value_print (const GtkAccessibleValue *value,
|
|
GString *buffer)
|
|
{
|
|
const GtkNumberAccessibleValue *self = (GtkNumberAccessibleValue *) value;
|
|
|
|
g_string_append_printf (buffer, "%g", self->value);
|
|
}
|
|
|
|
static const GtkAccessibleValueClass GTK_NUMBER_ACCESSIBLE_VALUE = {
|
|
.type = GTK_ACCESSIBLE_VALUE_TYPE_NUMBER,
|
|
.type_name = "GtkNumberAccessibleValue",
|
|
.instance_size = sizeof (GtkNumberAccessibleValue),
|
|
.equal = gtk_number_accessible_value_equal,
|
|
.print = gtk_number_accessible_value_print,
|
|
};
|
|
|
|
GtkAccessibleValue *
|
|
gtk_number_accessible_value_new (double value)
|
|
{
|
|
GtkAccessibleValue *res = gtk_accessible_value_alloc (>K_NUMBER_ACCESSIBLE_VALUE);
|
|
|
|
GtkNumberAccessibleValue *self = (GtkNumberAccessibleValue *) res;
|
|
self->value = value;
|
|
|
|
return res;
|
|
}
|
|
|
|
double
|
|
gtk_number_accessible_value_get (const GtkAccessibleValue *value)
|
|
{
|
|
GtkNumberAccessibleValue *self = (GtkNumberAccessibleValue *) value;
|
|
|
|
g_return_val_if_fail (value != NULL, 0);
|
|
g_return_val_if_fail (value->value_class == >K_NUMBER_ACCESSIBLE_VALUE, 0);
|
|
|
|
return self->value;
|
|
}
|
|
|
|
typedef struct {
|
|
GtkAccessibleValue parent;
|
|
|
|
char *value;
|
|
gsize length;
|
|
} GtkStringAccessibleValue;
|
|
|
|
static void
|
|
gtk_string_accessible_value_finalize (GtkAccessibleValue *value)
|
|
{
|
|
GtkStringAccessibleValue *self = (GtkStringAccessibleValue *) value;
|
|
|
|
g_free (self->value);
|
|
}
|
|
|
|
static gboolean
|
|
gtk_string_accessible_value_equal (const GtkAccessibleValue *value_a,
|
|
const GtkAccessibleValue *value_b)
|
|
{
|
|
const GtkStringAccessibleValue *self_a = (GtkStringAccessibleValue *) value_a;
|
|
const GtkStringAccessibleValue *self_b = (GtkStringAccessibleValue *) value_b;
|
|
|
|
if (self_a->length != self_b->length)
|
|
return FALSE;
|
|
|
|
return g_strcmp0 (self_a->value, self_b->value) == 0;
|
|
}
|
|
|
|
static void
|
|
gtk_string_accessible_value_print (const GtkAccessibleValue *value,
|
|
GString *buffer)
|
|
{
|
|
const GtkStringAccessibleValue *self = (GtkStringAccessibleValue *) value;
|
|
|
|
g_string_append (buffer, self->value);
|
|
}
|
|
|
|
static const GtkAccessibleValueClass GTK_STRING_ACCESSIBLE_VALUE = {
|
|
.type = GTK_ACCESSIBLE_VALUE_TYPE_STRING,
|
|
.type_name = "GtkStringAccessibleValue",
|
|
.instance_size = sizeof (GtkStringAccessibleValue),
|
|
.finalize = gtk_string_accessible_value_finalize,
|
|
.equal = gtk_string_accessible_value_equal,
|
|
.print = gtk_string_accessible_value_print,
|
|
};
|
|
|
|
GtkAccessibleValue *
|
|
gtk_string_accessible_value_new (const char *str)
|
|
{
|
|
GtkAccessibleValue *res = gtk_accessible_value_alloc (>K_STRING_ACCESSIBLE_VALUE);
|
|
|
|
GtkStringAccessibleValue *self = (GtkStringAccessibleValue *) res;
|
|
|
|
self->value = g_strdup (str);
|
|
self->length = strlen (str);
|
|
|
|
return res;
|
|
}
|
|
|
|
const char *
|
|
gtk_string_accessible_value_get (const GtkAccessibleValue *value)
|
|
{
|
|
GtkStringAccessibleValue *self = (GtkStringAccessibleValue *) value;
|
|
|
|
g_return_val_if_fail (value != NULL, 0);
|
|
g_return_val_if_fail (value->value_class == >K_STRING_ACCESSIBLE_VALUE, 0);
|
|
|
|
return self->value;
|
|
}
|
|
|
|
typedef struct {
|
|
GtkAccessibleValue parent;
|
|
|
|
GtkAccessible *ref;
|
|
} GtkReferenceAccessibleValue;
|
|
|
|
static void
|
|
remove_weak_ref (gpointer data,
|
|
GObject *old_reference)
|
|
{
|
|
GtkReferenceAccessibleValue *self = data;
|
|
|
|
self->ref = NULL;
|
|
}
|
|
|
|
static void
|
|
gtk_reference_accessible_value_finalize (GtkAccessibleValue *value)
|
|
{
|
|
GtkReferenceAccessibleValue *self = (GtkReferenceAccessibleValue *) value;
|
|
|
|
if (self->ref != NULL)
|
|
g_object_weak_unref (G_OBJECT (self->ref), remove_weak_ref, self);
|
|
}
|
|
|
|
static gboolean
|
|
gtk_reference_accessible_value_equal (const GtkAccessibleValue *value_a,
|
|
const GtkAccessibleValue *value_b)
|
|
{
|
|
const GtkReferenceAccessibleValue *self_a = (GtkReferenceAccessibleValue *) value_a;
|
|
const GtkReferenceAccessibleValue *self_b = (GtkReferenceAccessibleValue *) value_b;
|
|
|
|
return self_a->ref == self_b->ref;
|
|
}
|
|
|
|
static void
|
|
gtk_reference_accessible_value_print (const GtkAccessibleValue *value,
|
|
GString *buffer)
|
|
{
|
|
const GtkReferenceAccessibleValue *self = (GtkReferenceAccessibleValue *) value;
|
|
|
|
if (self->ref != NULL)
|
|
{
|
|
g_string_append_printf (buffer, "%s<%p>",
|
|
G_OBJECT_TYPE_NAME (self->ref),
|
|
self->ref);
|
|
}
|
|
else
|
|
{
|
|
g_string_append (buffer, "<null>");
|
|
}
|
|
}
|
|
|
|
static const GtkAccessibleValueClass GTK_REFERENCE_ACCESSIBLE_VALUE = {
|
|
.type = GTK_ACCESSIBLE_VALUE_TYPE_REFERENCE,
|
|
.type_name = "GtkReferenceAccessibleValue",
|
|
.instance_size = sizeof (GtkReferenceAccessibleValue),
|
|
.finalize = gtk_reference_accessible_value_finalize,
|
|
.equal = gtk_reference_accessible_value_equal,
|
|
.print = gtk_reference_accessible_value_print,
|
|
};
|
|
|
|
GtkAccessibleValue *
|
|
gtk_reference_accessible_value_new (GtkAccessible *ref)
|
|
{
|
|
g_return_val_if_fail (GTK_IS_ACCESSIBLE (ref), NULL);
|
|
|
|
GtkAccessibleValue *res = gtk_accessible_value_alloc (>K_REFERENCE_ACCESSIBLE_VALUE);
|
|
|
|
GtkReferenceAccessibleValue *self = (GtkReferenceAccessibleValue *) res;
|
|
|
|
self->ref = ref;
|
|
g_object_weak_ref (G_OBJECT (self->ref), remove_weak_ref, self);
|
|
|
|
return res;
|
|
}
|
|
|
|
GtkAccessible *
|
|
gtk_reference_accessible_value_get (const GtkAccessibleValue *value)
|
|
{
|
|
GtkReferenceAccessibleValue *self = (GtkReferenceAccessibleValue *) value;
|
|
|
|
g_return_val_if_fail (value != NULL, 0);
|
|
g_return_val_if_fail (value->value_class == >K_REFERENCE_ACCESSIBLE_VALUE, 0);
|
|
|
|
return self->ref;
|
|
}
|
|
|
|
typedef struct {
|
|
GtkAccessibleValue parent;
|
|
|
|
GList *refs;
|
|
} GtkReferenceListAccessibleValue;
|
|
|
|
static void
|
|
remove_weak_ref_from_list (gpointer data,
|
|
GObject *old_reference)
|
|
{
|
|
GtkReferenceListAccessibleValue *self = data;
|
|
|
|
GList *item = g_list_find (self->refs, old_reference);
|
|
|
|
if (item != NULL)
|
|
{
|
|
self->refs = g_list_remove_link (self->refs, item);
|
|
g_list_free (item);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gtk_reference_list_accessible_value_finalize (GtkAccessibleValue *value)
|
|
{
|
|
GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) value;
|
|
|
|
for (GList *l = self->refs; l != NULL; l = l->next)
|
|
{
|
|
if (l->data != NULL)
|
|
g_object_weak_unref (G_OBJECT (l->data), remove_weak_ref_from_list, self);
|
|
}
|
|
|
|
g_list_free (self->refs);
|
|
}
|
|
|
|
static gboolean
|
|
gtk_reference_list_accessible_value_equal (const GtkAccessibleValue *value_a,
|
|
const GtkAccessibleValue *value_b)
|
|
{
|
|
const GtkReferenceListAccessibleValue *self_a = (GtkReferenceListAccessibleValue *) value_a;
|
|
const GtkReferenceListAccessibleValue *self_b = (GtkReferenceListAccessibleValue *) value_b;
|
|
|
|
if (g_list_length (self_a->refs) != g_list_length (self_b->refs))
|
|
return FALSE;
|
|
|
|
for (GList *l = self_a->refs; l != NULL; l = l->next)
|
|
{
|
|
if (g_list_find (self_b->refs, l->data) == NULL)
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gtk_reference_list_accessible_value_print (const GtkAccessibleValue *value,
|
|
GString *buffer)
|
|
{
|
|
const GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) value;
|
|
|
|
if (self->refs == NULL)
|
|
{
|
|
g_string_append (buffer, "<null>");
|
|
return;
|
|
}
|
|
|
|
for (GList *l = self->refs; l != NULL; l = l->next)
|
|
{
|
|
g_string_append_printf (buffer, "%s<%p>",
|
|
G_OBJECT_TYPE_NAME (l->data),
|
|
l->data);
|
|
}
|
|
}
|
|
|
|
static const GtkAccessibleValueClass GTK_REFERENCE_LIST_ACCESSIBLE_VALUE = {
|
|
.type = GTK_ACCESSIBLE_VALUE_TYPE_REFERENCE_LIST,
|
|
.type_name = "GtkReferenceListAccessibleValue",
|
|
.instance_size = sizeof (GtkReferenceListAccessibleValue),
|
|
.finalize = gtk_reference_list_accessible_value_finalize,
|
|
.equal = gtk_reference_list_accessible_value_equal,
|
|
.print = gtk_reference_list_accessible_value_print,
|
|
};
|
|
|
|
/*< private >
|
|
* gtk_reference_list_accessible_value_new:
|
|
* @value: (element-type GtkAccessible) (transfer full): a list of accessible objects
|
|
*
|
|
* Creates a new #GtkAccessible that stores a list of references to #GtkAccessible objects.
|
|
*
|
|
* Returns: (transfer full): the newly created #GtkAccessible
|
|
*/
|
|
GtkAccessibleValue *
|
|
gtk_reference_list_accessible_value_new (GList *value)
|
|
{
|
|
GtkAccessibleValue *res = gtk_accessible_value_alloc (>K_REFERENCE_LIST_ACCESSIBLE_VALUE);
|
|
|
|
GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) res;
|
|
|
|
self->refs = g_list_copy (value);
|
|
if (self->refs != NULL)
|
|
{
|
|
for (GList *l = self->refs; l != NULL; l = l->next)
|
|
g_object_weak_ref (l->data, remove_weak_ref_from_list, self);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
GList *
|
|
gtk_reference_list_accessible_value_get (const GtkAccessibleValue *value)
|
|
{
|
|
GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) value;
|
|
|
|
g_return_val_if_fail (value != NULL, 0);
|
|
g_return_val_if_fail (value->value_class == >K_REFERENCE_LIST_ACCESSIBLE_VALUE, 0);
|
|
|
|
return self->refs;
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
/* {{{ Collection API */
|
|
|
|
typedef enum {
|
|
GTK_ACCESSIBLE_COLLECT_INVALID = -1,
|
|
|
|
/* true/false */
|
|
GTK_ACCESSIBLE_COLLECT_BOOLEAN = 0,
|
|
|
|
/* true/false/mixed/undefined */
|
|
GTK_ACCESSIBLE_COLLECT_TRISTATE,
|
|
|
|
/* one token */
|
|
GTK_ACCESSIBLE_COLLECT_TOKEN,
|
|
|
|
/* integer number */
|
|
GTK_ACCESSIBLE_COLLECT_INTEGER,
|
|
|
|
/* real number */
|
|
GTK_ACCESSIBLE_COLLECT_NUMBER,
|
|
|
|
/* string */
|
|
GTK_ACCESSIBLE_COLLECT_STRING,
|
|
|
|
/* reference */
|
|
GTK_ACCESSIBLE_COLLECT_REFERENCE,
|
|
|
|
/* references list */
|
|
GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
|
|
|
|
/* allows collecting GTK_ACCESSIBLE_VALUE_UNDEFINED; implied
|
|
* by GTK_ACCESSIBLE_COLLECT_TRISTATE
|
|
*/
|
|
GTK_ACCESSIBLE_COLLECT_UNDEFINED = 1 << 16
|
|
} GtkAccessibleCollectType;
|
|
|
|
typedef struct {
|
|
int value;
|
|
GtkAccessibleCollectType ctype;
|
|
const char *name;
|
|
|
|
/* The constructor and getter will be derived by the
|
|
* @ctype field and by the collected value, except for the
|
|
* GTK_ACCESSIBLE_COLLECT_TOKEN collection type. You can
|
|
* override the default ones by filling out these two
|
|
* pointers
|
|
*/
|
|
GCallback ctor;
|
|
GCallback getter;
|
|
} GtkAccessibleCollect;
|
|
|
|
static const GtkAccessibleCollect collect_states[] = {
|
|
[GTK_ACCESSIBLE_STATE_BUSY] = {
|
|
.value = GTK_ACCESSIBLE_STATE_BUSY,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
|
|
.name = "busy"
|
|
},
|
|
[GTK_ACCESSIBLE_STATE_CHECKED] = {
|
|
.value = GTK_ACCESSIBLE_STATE_CHECKED,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_TRISTATE,
|
|
.name = "checked"
|
|
},
|
|
[GTK_ACCESSIBLE_STATE_DISABLED] = {
|
|
.value = GTK_ACCESSIBLE_STATE_DISABLED,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
|
|
.name = "disabled"
|
|
},
|
|
[GTK_ACCESSIBLE_STATE_EXPANDED] = {
|
|
.value = GTK_ACCESSIBLE_STATE_EXPANDED,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN | GTK_ACCESSIBLE_COLLECT_UNDEFINED,
|
|
.name = "expanded"
|
|
},
|
|
[GTK_ACCESSIBLE_STATE_HIDDEN] = {
|
|
.value = GTK_ACCESSIBLE_STATE_HIDDEN,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
|
|
.name = "hidden"
|
|
},
|
|
[GTK_ACCESSIBLE_STATE_INVALID] = {
|
|
.value = GTK_ACCESSIBLE_STATE_INVALID,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_TOKEN,
|
|
.name = "invalid",
|
|
.ctor = (GCallback) gtk_invalid_accessible_value_new,
|
|
.getter = (GCallback) gtk_invalid_accessible_value_get
|
|
},
|
|
[GTK_ACCESSIBLE_STATE_PRESSED] = {
|
|
.value = GTK_ACCESSIBLE_STATE_PRESSED,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_TRISTATE,
|
|
.name = "pressed"
|
|
},
|
|
[GTK_ACCESSIBLE_STATE_SELECTED] = {
|
|
.value = GTK_ACCESSIBLE_STATE_SELECTED,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN | GTK_ACCESSIBLE_COLLECT_UNDEFINED,
|
|
.name = "selected"
|
|
},
|
|
};
|
|
|
|
/* § 6.6.1 Widget attributes */
|
|
static const GtkAccessibleCollect collect_props[] = {
|
|
[GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_TOKEN,
|
|
.name = "autocomplete",
|
|
.ctor = (GCallback) gtk_autocomplete_accessible_value_new,
|
|
.getter = (GCallback) gtk_autocomplete_accessible_value_get
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_DESCRIPTION] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_DESCRIPTION,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_STRING,
|
|
.name = "description"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_HAS_POPUP] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_HAS_POPUP,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
|
|
.name = "haspopup"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_KEY_SHORTCUTS] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_KEY_SHORTCUTS,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_STRING,
|
|
.name = "keyshortcuts"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_LABEL] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_LABEL,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_STRING,
|
|
.name = "label"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_LEVEL] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_LEVEL,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
|
|
.name = "level"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_MODAL] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_MODAL,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
|
|
.name = "modal"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_MULTI_LINE] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_MULTI_LINE,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
|
|
.name = "multiline"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
|
|
.name = "multiselectable"
|
|
},
|
|
/* "orientation" is a bit special; it maps to GtkOrientation, but it
|
|
* can also be "undefined". This means we need to override constructor
|
|
* and getter, in order to properly handle GTK_ACCESSIBLE_VALUE_UNDEFINED
|
|
*/
|
|
[GTK_ACCESSIBLE_PROPERTY_ORIENTATION] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_ORIENTATION,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_TOKEN | GTK_ACCESSIBLE_COLLECT_UNDEFINED,
|
|
.name = "orientation",
|
|
.ctor = (GCallback) gtk_orientation_accessible_value_new,
|
|
.getter = (GCallback) gtk_orientation_accessible_value_get
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_STRING,
|
|
.name = "placeholder"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_READ_ONLY] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_READ_ONLY,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
|
|
.name = "readonly"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_REQUIRED] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_REQUIRED,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_BOOLEAN,
|
|
.name = "required"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_ROLE_DESCRIPTION] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_ROLE_DESCRIPTION,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_STRING,
|
|
.name = "roledescription"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_SORT] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_SORT,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_TOKEN,
|
|
.name = "sort",
|
|
.ctor = (GCallback) gtk_sort_accessible_value_new,
|
|
.getter = (GCallback) gtk_sort_accessible_value_get
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_VALUE_MAX] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_VALUE_MAX,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_NUMBER,
|
|
.name = "valuemax"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_VALUE_MIN] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_VALUE_MIN,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_NUMBER,
|
|
.name = "valuemin"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_VALUE_NOW] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_VALUE_NOW,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_NUMBER,
|
|
.name = "valuenow"
|
|
},
|
|
[GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT] = {
|
|
.value = GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_STRING,
|
|
.name = "valuetext"
|
|
},
|
|
};
|
|
|
|
/* § 6.6.4 Relationship Attributes */
|
|
static const GtkAccessibleCollect collect_rels[] = {
|
|
[GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE,
|
|
.name = "activedescendant"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_COL_COUNT] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_COL_COUNT,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
|
|
.name = "colcount"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_COL_INDEX] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_COL_INDEX,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
|
|
.name = "colindex"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_STRING,
|
|
.name = "colindextext"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_COL_SPAN] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_COL_SPAN,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
|
|
.name = "colspan"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_CONTROLS] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_CONTROLS,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
|
|
.name = "controls"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_DESCRIBED_BY] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_DESCRIBED_BY,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
|
|
.name = "describedby"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_DETAILS] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_DETAILS,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
|
|
.name = "details"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE,
|
|
.name = "errormessage"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_FLOW_TO] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_FLOW_TO,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
|
|
.name = "flowto"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_LABELLED_BY] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_LABELLED_BY,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
|
|
.name = "labelledby"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_OWNS] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_OWNS,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
|
|
.name = "owns"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_POS_IN_SET] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_POS_IN_SET,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
|
|
.name = "posinset"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_ROW_COUNT] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_ROW_COUNT,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
|
|
.name = "rowcount"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_ROW_INDEX] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_ROW_INDEX,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
|
|
.name = "rowindex"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_STRING,
|
|
.name = "rowindextext"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_ROW_SPAN] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_ROW_SPAN,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
|
|
.name = "rowspan"
|
|
},
|
|
[GTK_ACCESSIBLE_RELATION_SET_SIZE] = {
|
|
.value = GTK_ACCESSIBLE_RELATION_SET_SIZE,
|
|
.ctype = GTK_ACCESSIBLE_COLLECT_INTEGER,
|
|
.name = "posinset"
|
|
},
|
|
};
|
|
|
|
typedef GtkAccessibleValue * (* GtkAccessibleValueBooleanCtor) (gboolean value);
|
|
typedef GtkAccessibleValue * (* GtkAccessibleValueIntCtor) (int value);
|
|
typedef GtkAccessibleValue * (* GtkAccessibleValueTristateCtor) (int value);
|
|
typedef GtkAccessibleValue * (* GtkAccessibleValueEnumCtor) (int value);
|
|
typedef GtkAccessibleValue * (* GtkAccessibleValueNumberCtor) (double value);
|
|
typedef GtkAccessibleValue * (* GtkAccessibleValueStringCtor) (const char *value);
|
|
typedef GtkAccessibleValue * (* GtkAccessibleValueRefCtor) (GtkAccessible *value);
|
|
typedef GtkAccessibleValue * (* GtkAccessibleValueRefListCtor) (GList *value);
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_get_default_for_state:
|
|
* @state: a #GtkAccessibleState
|
|
*
|
|
* Retrieves the #GtkAccessibleValue that contains the default for the
|
|
* given @state.
|
|
*
|
|
* Returns: (transfer full): the #GtkAccessibleValue
|
|
*/
|
|
GtkAccessibleValue *
|
|
gtk_accessible_value_get_default_for_state (GtkAccessibleState state)
|
|
{
|
|
const GtkAccessibleCollect *cstate = &collect_states[state];
|
|
|
|
g_return_val_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED, NULL);
|
|
|
|
switch (cstate->value)
|
|
{
|
|
case GTK_ACCESSIBLE_STATE_BUSY:
|
|
case GTK_ACCESSIBLE_STATE_DISABLED:
|
|
case GTK_ACCESSIBLE_STATE_HIDDEN:
|
|
return gtk_boolean_accessible_value_new (FALSE);
|
|
|
|
case GTK_ACCESSIBLE_STATE_CHECKED:
|
|
case GTK_ACCESSIBLE_STATE_EXPANDED:
|
|
case GTK_ACCESSIBLE_STATE_PRESSED:
|
|
case GTK_ACCESSIBLE_STATE_SELECTED:
|
|
return gtk_undefined_accessible_value_new ();
|
|
|
|
case GTK_ACCESSIBLE_STATE_INVALID:
|
|
return gtk_invalid_accessible_value_new (GTK_ACCESSIBLE_INVALID_FALSE);
|
|
|
|
default:
|
|
g_critical ("Unknown value for accessible state “%s”", cstate->name);
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static GtkAccessibleValue *
|
|
gtk_accessible_value_collect_valist (const GtkAccessibleCollect *cstate,
|
|
GError **error,
|
|
va_list *args)
|
|
{
|
|
GtkAccessibleValue *res = NULL;
|
|
GtkAccessibleCollectType ctype = cstate->ctype;
|
|
gboolean collects_undef = (ctype & GTK_ACCESSIBLE_COLLECT_UNDEFINED) != 0;
|
|
|
|
ctype &= (GTK_ACCESSIBLE_COLLECT_UNDEFINED - 1);
|
|
|
|
/* Tristate values include "undefined" by definition */
|
|
if (ctype == GTK_ACCESSIBLE_COLLECT_TRISTATE)
|
|
collects_undef = TRUE;
|
|
|
|
switch (ctype)
|
|
{
|
|
case GTK_ACCESSIBLE_COLLECT_BOOLEAN:
|
|
{
|
|
if (collects_undef)
|
|
{
|
|
int value = va_arg (*args, int);
|
|
|
|
if (value == GTK_ACCESSIBLE_VALUE_UNDEFINED)
|
|
res = gtk_undefined_accessible_value_new ();
|
|
else
|
|
res = gtk_boolean_accessible_value_new (value == 0 ? FALSE : TRUE);
|
|
}
|
|
else
|
|
{
|
|
gboolean value = va_arg (*args, gboolean);
|
|
|
|
res = gtk_boolean_accessible_value_new (value);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_TRISTATE:
|
|
{
|
|
int value = va_arg (*args, int);
|
|
|
|
if (collects_undef && value == GTK_ACCESSIBLE_VALUE_UNDEFINED)
|
|
res = gtk_undefined_accessible_value_new ();
|
|
else
|
|
res = gtk_tristate_accessible_value_new (value);
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_TOKEN:
|
|
{
|
|
GtkAccessibleValueEnumCtor ctor =
|
|
(GtkAccessibleValueEnumCtor) cstate->ctor;
|
|
|
|
int value = va_arg (*args, int);
|
|
|
|
if (collects_undef && value == GTK_ACCESSIBLE_VALUE_UNDEFINED)
|
|
{
|
|
res = gtk_undefined_accessible_value_new ();
|
|
}
|
|
else
|
|
{
|
|
/* Token collection requires a constructor */
|
|
g_assert (ctor != NULL);
|
|
|
|
res = (* ctor) (value);
|
|
}
|
|
|
|
if (res == NULL)
|
|
{
|
|
g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR,
|
|
GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN,
|
|
"Invalid value for token attribute: %d",
|
|
value);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_INTEGER:
|
|
{
|
|
GtkAccessibleValueEnumCtor ctor =
|
|
(GtkAccessibleValueEnumCtor) cstate->ctor;
|
|
|
|
int value = va_arg (*args, int);
|
|
|
|
if (ctor == NULL)
|
|
res = gtk_int_accessible_value_new (value);
|
|
else
|
|
res = (* ctor) (value);
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_NUMBER:
|
|
{
|
|
GtkAccessibleValueNumberCtor ctor =
|
|
(GtkAccessibleValueNumberCtor) cstate->ctor;
|
|
|
|
double value = va_arg (*args, double);
|
|
|
|
if (isnan (value) || isinf (value))
|
|
{
|
|
g_set_error_literal (error, GTK_ACCESSIBLE_VALUE_ERROR,
|
|
GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
|
|
"Invalid numeric value");
|
|
return NULL;
|
|
}
|
|
|
|
if (ctor == NULL)
|
|
res = gtk_number_accessible_value_new (value);
|
|
else
|
|
res = (* ctor) (value);
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_STRING:
|
|
{
|
|
GtkAccessibleValueStringCtor ctor =
|
|
(GtkAccessibleValueStringCtor) cstate->ctor;
|
|
|
|
const char *value = va_arg (*args, char*);
|
|
|
|
if (ctor == NULL)
|
|
{
|
|
if (value != NULL)
|
|
res = gtk_string_accessible_value_new (value);
|
|
}
|
|
else
|
|
{
|
|
res = (* ctor) (value);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_REFERENCE:
|
|
{
|
|
GtkAccessibleValueRefCtor ctor =
|
|
(GtkAccessibleValueRefCtor) cstate->ctor;
|
|
|
|
gpointer value = va_arg (*args, gpointer);
|
|
|
|
if (value != NULL && !GTK_IS_ACCESSIBLE (value))
|
|
{
|
|
g_set_error_literal (error, GTK_ACCESSIBLE_VALUE_ERROR,
|
|
GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
|
|
"Reference does not implement GtkAccessible");
|
|
return NULL;
|
|
}
|
|
|
|
if (ctor == NULL)
|
|
{
|
|
if (value != NULL)
|
|
res = gtk_reference_accessible_value_new (value);
|
|
}
|
|
else
|
|
{
|
|
res = (* ctor) (value);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST:
|
|
{
|
|
GtkAccessibleValueRefListCtor ctor =
|
|
(GtkAccessibleValueRefListCtor) cstate->ctor;
|
|
|
|
GList *value = va_arg (*args, gpointer);
|
|
|
|
if (ctor == NULL)
|
|
{
|
|
if (value == NULL)
|
|
res = NULL;
|
|
else
|
|
res = gtk_reference_list_accessible_value_new (value);
|
|
}
|
|
else
|
|
{
|
|
res = (* ctor) (value);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_UNDEFINED:
|
|
case GTK_ACCESSIBLE_COLLECT_INVALID:
|
|
default:
|
|
g_assert_not_reached ();
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static GtkAccessibleValue *
|
|
gtk_accessible_value_collect_value (const GtkAccessibleCollect *cstate,
|
|
const GValue *value_,
|
|
GError **error)
|
|
{
|
|
GtkAccessibleValue *res = NULL;
|
|
GtkAccessibleCollectType ctype = cstate->ctype;
|
|
gboolean collects_undef = (ctype & GTK_ACCESSIBLE_COLLECT_UNDEFINED) != 0;
|
|
|
|
ctype &= (GTK_ACCESSIBLE_COLLECT_UNDEFINED - 1);
|
|
|
|
/* Tristate values include "undefined" by definition */
|
|
if (ctype == GTK_ACCESSIBLE_COLLECT_TRISTATE)
|
|
collects_undef = TRUE;
|
|
|
|
switch (ctype)
|
|
{
|
|
case GTK_ACCESSIBLE_COLLECT_BOOLEAN:
|
|
{
|
|
if (collects_undef)
|
|
{
|
|
int value = g_value_get_int (value_);
|
|
|
|
if (value == GTK_ACCESSIBLE_VALUE_UNDEFINED)
|
|
res = gtk_undefined_accessible_value_new ();
|
|
else
|
|
res = gtk_boolean_accessible_value_new (value == 0 ? FALSE : TRUE);
|
|
}
|
|
else
|
|
{
|
|
gboolean value = g_value_get_boolean (value_);
|
|
|
|
res = gtk_boolean_accessible_value_new (value);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_TRISTATE:
|
|
{
|
|
int value = g_value_get_int (value_);
|
|
|
|
if (collects_undef && value == GTK_ACCESSIBLE_VALUE_UNDEFINED)
|
|
res = gtk_undefined_accessible_value_new ();
|
|
else
|
|
res = gtk_tristate_accessible_value_new (value);
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_TOKEN:
|
|
{
|
|
GtkAccessibleValueEnumCtor ctor =
|
|
(GtkAccessibleValueEnumCtor) cstate->ctor;
|
|
|
|
int value = g_value_get_int (value_);
|
|
|
|
if (collects_undef && value == GTK_ACCESSIBLE_VALUE_UNDEFINED)
|
|
{
|
|
res = gtk_undefined_accessible_value_new ();
|
|
}
|
|
else
|
|
{
|
|
/* Token collection requires a constructor */
|
|
g_assert (ctor != NULL);
|
|
|
|
res = (* ctor) (value);
|
|
}
|
|
|
|
if (res == NULL)
|
|
{
|
|
g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR,
|
|
GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN,
|
|
"Invalid value for token attribute: %d",
|
|
value);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_INTEGER:
|
|
{
|
|
GtkAccessibleValueEnumCtor ctor =
|
|
(GtkAccessibleValueEnumCtor) cstate->ctor;
|
|
|
|
int value = g_value_get_int (value_);
|
|
|
|
if (ctor == NULL)
|
|
res = gtk_int_accessible_value_new (value);
|
|
else
|
|
res = (* ctor) (value);
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_NUMBER:
|
|
{
|
|
GtkAccessibleValueNumberCtor ctor =
|
|
(GtkAccessibleValueNumberCtor) cstate->ctor;
|
|
|
|
double value = g_value_get_double (value_);
|
|
|
|
if (isnan (value) || isinf (value))
|
|
{
|
|
g_set_error_literal (error, GTK_ACCESSIBLE_VALUE_ERROR,
|
|
GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
|
|
"Invalid numeric value");
|
|
return NULL;
|
|
}
|
|
|
|
if (ctor == NULL)
|
|
res = gtk_number_accessible_value_new (value);
|
|
else
|
|
res = (* ctor) (value);
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_STRING:
|
|
{
|
|
GtkAccessibleValueStringCtor ctor =
|
|
(GtkAccessibleValueStringCtor) cstate->ctor;
|
|
|
|
const char *value = g_value_get_string (value_);
|
|
|
|
if (ctor == NULL)
|
|
{
|
|
if (value != NULL)
|
|
res = gtk_string_accessible_value_new (value);
|
|
}
|
|
else
|
|
{
|
|
res = (* ctor) (value);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_REFERENCE:
|
|
{
|
|
GtkAccessibleValueRefCtor ctor =
|
|
(GtkAccessibleValueRefCtor) cstate->ctor;
|
|
|
|
gpointer value = g_value_get_object (value_);
|
|
|
|
if (value != NULL && !GTK_IS_ACCESSIBLE (value))
|
|
{
|
|
g_set_error_literal (error, GTK_ACCESSIBLE_VALUE_ERROR,
|
|
GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
|
|
"Reference does not implement GtkAccessible");
|
|
return NULL;
|
|
}
|
|
|
|
if (ctor == NULL)
|
|
{
|
|
if (value != NULL)
|
|
res = gtk_reference_accessible_value_new (value);
|
|
}
|
|
else
|
|
{
|
|
res = (* ctor) (value);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST:
|
|
{
|
|
GtkAccessibleValueRefListCtor ctor =
|
|
(GtkAccessibleValueRefListCtor) cstate->ctor;
|
|
|
|
GList *value = g_value_get_pointer (value_);
|
|
|
|
if (ctor == NULL)
|
|
{
|
|
if (value != NULL)
|
|
res = gtk_reference_list_accessible_value_new (value);
|
|
}
|
|
else
|
|
{
|
|
res = (* ctor) (value);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GTK_ACCESSIBLE_COLLECT_UNDEFINED:
|
|
case GTK_ACCESSIBLE_COLLECT_INVALID:
|
|
default:
|
|
g_assert_not_reached ();
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_collect_for_state:
|
|
* @state: a #GtkAccessibleState
|
|
* @error: return location for a #GError
|
|
* @args: a `va_list` reference
|
|
*
|
|
* Collects and consumes the next item in the @args variadic arguments list,
|
|
* and returns a #GtkAccessibleValue for it.
|
|
*
|
|
* If the collection fails, @error is set and %NULL is returned.
|
|
*
|
|
* The returned value could be %NULL even on success, in which case the state
|
|
* should be reset to its default value by the caller.
|
|
*
|
|
* Returns: (transfer full) (nullable): a #GtkAccessibleValue
|
|
*/
|
|
GtkAccessibleValue *
|
|
gtk_accessible_value_collect_for_state (GtkAccessibleState state,
|
|
GError **error,
|
|
va_list *args)
|
|
{
|
|
const GtkAccessibleCollect *cstate = &collect_states[state];
|
|
|
|
g_return_val_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED, NULL);
|
|
|
|
return gtk_accessible_value_collect_valist (cstate, error, args);
|
|
}
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_collect_for_state_value:
|
|
* @state: a #GtkAccessibleState
|
|
* @value: a #GValue
|
|
* @error: return location for a #GError
|
|
*
|
|
* Retrieves the value stored inside @value and returns a #GtkAccessibleValue
|
|
* for the given @state.
|
|
*
|
|
* If the collection fails, @error is set and %NULL is returned.
|
|
*
|
|
* The returned value could be %NULL even on success, in which case the state
|
|
* should be reset to its default value by the caller.
|
|
*
|
|
* Returns: (transfer full) (nullable): a #GtkAccessibleValue
|
|
*/
|
|
GtkAccessibleValue *
|
|
gtk_accessible_value_collect_for_state_value (GtkAccessibleState state,
|
|
const GValue *value,
|
|
GError **error)
|
|
{
|
|
const GtkAccessibleCollect *cstate = &collect_states[state];
|
|
|
|
g_return_val_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED, NULL);
|
|
|
|
return gtk_accessible_value_collect_value (cstate, value, error);
|
|
}
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_get_default_for_property:
|
|
* @property: a #GtkAccessibleProperty
|
|
*
|
|
* Retrieves the #GtkAccessibleValue that contains the default for the
|
|
* given @property.
|
|
*
|
|
* Returns: (transfer full): the #GtkAccessibleValue
|
|
*/
|
|
GtkAccessibleValue *
|
|
gtk_accessible_value_get_default_for_property (GtkAccessibleProperty property)
|
|
{
|
|
const GtkAccessibleCollect *cstate = &collect_props[property];
|
|
|
|
g_return_val_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, NULL);
|
|
|
|
switch (cstate->value)
|
|
{
|
|
/* Boolean properties */
|
|
case GTK_ACCESSIBLE_PROPERTY_HAS_POPUP:
|
|
case GTK_ACCESSIBLE_PROPERTY_MODAL:
|
|
case GTK_ACCESSIBLE_PROPERTY_MULTI_LINE:
|
|
case GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE:
|
|
case GTK_ACCESSIBLE_PROPERTY_READ_ONLY:
|
|
case GTK_ACCESSIBLE_PROPERTY_REQUIRED:
|
|
return gtk_boolean_accessible_value_new (FALSE);
|
|
|
|
/* Integer properties */
|
|
case GTK_ACCESSIBLE_PROPERTY_LEVEL:
|
|
return gtk_int_accessible_value_new (0);
|
|
|
|
/* Number properties */
|
|
case GTK_ACCESSIBLE_PROPERTY_VALUE_MAX:
|
|
case GTK_ACCESSIBLE_PROPERTY_VALUE_MIN:
|
|
case GTK_ACCESSIBLE_PROPERTY_VALUE_NOW:
|
|
return gtk_number_accessible_value_new (0);
|
|
|
|
/* String properties */
|
|
case GTK_ACCESSIBLE_PROPERTY_DESCRIPTION:
|
|
case GTK_ACCESSIBLE_PROPERTY_KEY_SHORTCUTS:
|
|
case GTK_ACCESSIBLE_PROPERTY_LABEL:
|
|
case GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER:
|
|
case GTK_ACCESSIBLE_PROPERTY_ROLE_DESCRIPTION:
|
|
case GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT:
|
|
return gtk_undefined_accessible_value_new ();
|
|
|
|
/* Token properties */
|
|
case GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE:
|
|
return gtk_autocomplete_accessible_value_new (GTK_ACCESSIBLE_AUTOCOMPLETE_NONE);
|
|
|
|
case GTK_ACCESSIBLE_PROPERTY_ORIENTATION:
|
|
return gtk_undefined_accessible_value_new ();
|
|
|
|
case GTK_ACCESSIBLE_PROPERTY_SORT:
|
|
return gtk_sort_accessible_value_new (GTK_ACCESSIBLE_SORT_NONE);
|
|
|
|
default:
|
|
g_critical ("Unknown value for accessible property “%s”", cstate->name);
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_collect_for_property:
|
|
* @property: a #GtkAccessibleProperty
|
|
* @error: return location for a #GError
|
|
* @args: a `va_list` reference
|
|
*
|
|
* Collects and consumes the next item in the @args variadic arguments list,
|
|
* and returns a #GtkAccessibleValue for it.
|
|
*
|
|
* If the collection fails, @error is set.
|
|
*
|
|
* Returns: (transfer full) (nullable): a #GtkAccessibleValue
|
|
*/
|
|
GtkAccessibleValue *
|
|
gtk_accessible_value_collect_for_property (GtkAccessibleProperty property,
|
|
GError **error,
|
|
va_list *args)
|
|
{
|
|
const GtkAccessibleCollect *cstate = &collect_props[property];
|
|
|
|
g_return_val_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, NULL);
|
|
|
|
return gtk_accessible_value_collect_valist (cstate, error, args);
|
|
}
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_collect_for_property_value:
|
|
* @property: a #GtkAccessibleProperty
|
|
* @value: a #GValue
|
|
* @error: return location for a #GError
|
|
*
|
|
* Retrieves the value stored inside @value and returns a #GtkAccessibleValue
|
|
* for the given @property.
|
|
*
|
|
* If the collection fails, @error is set.
|
|
*
|
|
* The returned value could be %NULL even on success, in which case the property
|
|
* should be reset to its default value by the caller.
|
|
*
|
|
* Returns: (transfer full) (nullable): a #GtkAccessibleValue
|
|
*/
|
|
GtkAccessibleValue *
|
|
gtk_accessible_value_collect_for_property_value (GtkAccessibleProperty property,
|
|
const GValue *value,
|
|
GError **error)
|
|
{
|
|
const GtkAccessibleCollect *cstate = &collect_props[property];
|
|
|
|
g_return_val_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, NULL);
|
|
|
|
return gtk_accessible_value_collect_value (cstate, value, error);
|
|
}
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_get_default_for_relation:
|
|
* @relation: a #GtkAccessibleRelation
|
|
*
|
|
* Retrieves the #GtkAccessibleValue that contains the default for the
|
|
* given @relation.
|
|
*
|
|
* Returns: (transfer full): the #GtkAccessibleValue
|
|
*/
|
|
GtkAccessibleValue *
|
|
gtk_accessible_value_get_default_for_relation (GtkAccessibleRelation relation)
|
|
{
|
|
const GtkAccessibleCollect *cstate = &collect_rels[relation];
|
|
|
|
g_return_val_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE, NULL);
|
|
|
|
switch (cstate->value)
|
|
{
|
|
/* References */
|
|
case GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT:
|
|
case GTK_ACCESSIBLE_RELATION_CONTROLS:
|
|
case GTK_ACCESSIBLE_RELATION_DESCRIBED_BY:
|
|
case GTK_ACCESSIBLE_RELATION_DETAILS:
|
|
case GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE:
|
|
case GTK_ACCESSIBLE_RELATION_FLOW_TO:
|
|
case GTK_ACCESSIBLE_RELATION_LABELLED_BY:
|
|
case GTK_ACCESSIBLE_RELATION_OWNS:
|
|
return gtk_undefined_accessible_value_new ();
|
|
|
|
/* Integers */
|
|
case GTK_ACCESSIBLE_RELATION_COL_COUNT:
|
|
case GTK_ACCESSIBLE_RELATION_COL_INDEX:
|
|
case GTK_ACCESSIBLE_RELATION_COL_SPAN:
|
|
case GTK_ACCESSIBLE_RELATION_POS_IN_SET:
|
|
case GTK_ACCESSIBLE_RELATION_ROW_COUNT:
|
|
case GTK_ACCESSIBLE_RELATION_ROW_INDEX:
|
|
case GTK_ACCESSIBLE_RELATION_ROW_SPAN:
|
|
case GTK_ACCESSIBLE_RELATION_SET_SIZE:
|
|
return gtk_int_accessible_value_new (0);
|
|
|
|
/* Strings */
|
|
case GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT:
|
|
case GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT:
|
|
return gtk_undefined_accessible_value_new ();
|
|
|
|
default:
|
|
g_critical ("Unknown value for accessible property “%s”", cstate->name);
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_collect_for_relation:
|
|
* @relation: a #GtkAccessibleRelation
|
|
* @error: return location for a #GError
|
|
* @args: a `va_list` reference
|
|
*
|
|
* Collects and consumes the next item in the @args variadic arguments list,
|
|
* and returns a #GtkAccessibleValue for it.
|
|
*
|
|
* If the collection fails, @error is set and %NULL is returned.
|
|
*
|
|
* The returned value could be %NULL even on success, in which case the relation
|
|
* should be reset to its default value by the caller.
|
|
*
|
|
* Returns: (transfer full) (nullable): a #GtkAccessibleValue
|
|
*/
|
|
GtkAccessibleValue *
|
|
gtk_accessible_value_collect_for_relation (GtkAccessibleRelation relation,
|
|
GError **error,
|
|
va_list *args)
|
|
{
|
|
const GtkAccessibleCollect *cstate = &collect_rels[relation];
|
|
|
|
g_return_val_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE, NULL);
|
|
|
|
return gtk_accessible_value_collect_valist (cstate, error, args);
|
|
}
|
|
|
|
/*< private >
|
|
* gtk_accessible_value_collect_for_relation_value:
|
|
* @relation: a #GtkAccessibleRelation
|
|
* @value: a #GValue
|
|
* @error: return location for a #GError
|
|
*
|
|
* Retrieves the value stored inside @value and returns a #GtkAccessibleValue
|
|
* for the given @relation.
|
|
*
|
|
* If the collection fails, @error is set and %NULL is returned.
|
|
*
|
|
* The returned value could be %NULL even on success, in which case the relation
|
|
* should be reset to its default value by the caller.
|
|
*
|
|
* Returns: (transfer full) (nullable): a #GtkAccessibleValue
|
|
*/
|
|
GtkAccessibleValue *
|
|
gtk_accessible_value_collect_for_relation_value (GtkAccessibleRelation relation,
|
|
const GValue *value,
|
|
GError **error)
|
|
{
|
|
const GtkAccessibleCollect *cstate = &collect_rels[relation];
|
|
|
|
g_return_val_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE, NULL);
|
|
|
|
return gtk_accessible_value_collect_value (cstate, value, error);
|
|
}
|
|
|
|
/* }}} */
|