Commit 732578eb authored by Emmanuele Bassi's avatar Emmanuele Bassi 👣
Browse files

a11y: Consolidate the attributes container

While we have split the various attributes for convenience, there's no
reason why we should have specialised data types for the attributes
container object.
parent 1124f250
/* gtkaccessibleattributeset.c: Accessible attribute containt
*
* 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/>.
*/
#include "config.h"
#include "gtkaccessibleattributesetprivate.h"
#include "gtkbitmaskprivate.h"
#include "gtkenums.h"
struct _GtkAccessibleAttributeSet
{
gsize n_attributes;
GtkAccessibleAttributeDefaultFunc default_func;
GtkBitmask *attributes_set;
char **attribute_names;
GtkAccessibleValue **attribute_values;
};
static GtkAccessibleAttributeSet *
gtk_accessible_attribute_set_init (GtkAccessibleAttributeSet *self,
gsize n_attributes,
const char **attribute_names,
GtkAccessibleAttributeDefaultFunc default_func)
{
self->n_attributes = n_attributes;
self->default_func = default_func;
self->attribute_names = g_new (char *, n_attributes);
self->attribute_values = g_new (GtkAccessibleValue *, n_attributes);
self->attributes_set = _gtk_bitmask_new ();
/* Initialize all attribute values, so we can always get the full attribute */
for (int i = 0; i < self->n_attributes; i++)
{
self->attribute_names[i] = g_strdup (attribute_names[i]);
self->attribute_values[i] = (* self->default_func) (i);
}
return self;
}
GtkAccessibleAttributeSet *
gtk_accessible_attribute_set_new (gsize n_attributes,
const char **attribute_names,
GtkAccessibleAttributeDefaultFunc default_func)
{
GtkAccessibleAttributeSet *set = g_rc_box_new0 (GtkAccessibleAttributeSet);
return gtk_accessible_attribute_set_init (set, n_attributes, attribute_names, default_func);
}
GtkAccessibleAttributeSet *
gtk_accessible_attribute_set_ref (GtkAccessibleAttributeSet *self)
{
g_return_val_if_fail (self != NULL, NULL);
return g_rc_box_acquire (self);
}
static void
gtk_accessible_attribute_set_free (gpointer data)
{
GtkAccessibleAttributeSet *self = data;
for (int i = 0; i < self->n_attributes; i++)
{
g_free (self->attribute_names[i]);
if (self->attribute_values[i] != NULL)
gtk_accessible_value_unref (self->attribute_values[i]);
}
g_free (self->attribute_names);
g_free (self->attribute_values);
_gtk_bitmask_free (self->attributes_set);
}
void
gtk_accessible_attribute_set_unref (GtkAccessibleAttributeSet *self)
{
g_rc_box_release_full (self, gtk_accessible_attribute_set_free);
}
/*< private >
* gtk_accessible_attribute_set_add:
* @self: a #GtkAccessibleAttributeSet
* @attribute: the attribute to set
* @value: (nullable): a #GtkAccessibleValue
*
* Adds @attribute to the attributes set, and sets its value.
*
* If @value is %NULL, the @attribute is reset to its default value.
*
* If you want to remove @attribute from the set, use gtk_accessible_attribute_set_remove()
* instead.
*/
void
gtk_accessible_attribute_set_add (GtkAccessibleAttributeSet *self,
int attribute,
GtkAccessibleValue *value)
{
g_return_if_fail (attribute >= 0 && attribute < self->n_attributes);
g_clear_pointer (&(self->attribute_values[attribute]), gtk_accessible_value_unref);
if (value != NULL)
self->attribute_values[attribute] = gtk_accessible_value_ref (value);
else
self->attribute_values[attribute] = (* self->default_func) (attribute);
self->attributes_set = _gtk_bitmask_set (self->attributes_set, attribute, TRUE);
}
void
gtk_accessible_attribute_set_remove (GtkAccessibleAttributeSet *self,
int attribute)
{
g_return_if_fail (attribute >= 0 && attribute < self->n_attributes);
g_clear_pointer (&(self->attribute_values[attribute]), gtk_accessible_value_unref);
self->attribute_values[attribute] = (* self->default_func) (attribute);
self->attributes_set = _gtk_bitmask_set (self->attributes_set, attribute, FALSE);
}
gboolean
gtk_accessible_attribute_set_contains (GtkAccessibleAttributeSet *self,
int attribute)
{
g_return_val_if_fail (attribute >= 0 && attribute < self->n_attributes, FALSE);
return _gtk_bitmask_get (self->attributes_set, attribute);
}
/*< private >
* gtk_accessible_attribute_set_get_value:
* @self: a #GtkAccessibleAttributeSet
* @attribute: the attribute to retrieve
*
* Retrieves the value of the given @attribute in the set.
*
* Returns: (transfer none): the value for the attribute
*/
GtkAccessibleValue *
gtk_accessible_attribute_set_get_value (GtkAccessibleAttributeSet *self,
int attribute)
{
g_return_val_if_fail (attribute >= 0 && attribute < self->n_attributes, NULL);
return self->attribute_values[attribute];
}
gsize
gtk_accessible_attribute_set_get_length (GtkAccessibleAttributeSet *self)
{
return self->n_attributes;
}
guint
gtk_accessible_attribute_set_get_changed (GtkAccessibleAttributeSet *self)
{
guint changed = 0;
for (gsize i = 0; i < self->n_attributes; i++)
{
if (gtk_accessible_attribute_set_contains (self, i))
changed |= (1 << i);
}
return changed;
}
/*< private >
* gtk_accessible_attribute_set_print:
* @self: a #GtkAccessibleAttributeSet
* @only_set: %TRUE if only the set attributes should be printed
* @buffer: a #GString
*
* Prints the contents of the #GtkAccessibleAttributeSet into @buffer.
*/
void
gtk_accessible_attribute_set_print (GtkAccessibleAttributeSet *self,
gboolean only_set,
GString *buffer)
{
if (only_set && _gtk_bitmask_is_empty (self->attributes_set))
{
g_string_append (buffer, "{}");
return;
}
g_string_append (buffer, "{\n");
for (gsize i = 0; i < self->n_attributes; i++)
{
if (only_set && !_gtk_bitmask_get (self->attributes_set, i))
continue;
g_string_append (buffer, " ");
g_string_append (buffer, self->attribute_names[i]);
g_string_append (buffer, ": ");
gtk_accessible_value_print (self->attribute_values[i], buffer);
g_string_append (buffer, ",\n");
}
g_string_append (buffer, "}");
}
/*< private >
* gtk_accessible_attribute_set_to_string:
* @self: a #GtkAccessibleAttributeSet
*
* Prints the contents of a #GtkAccessibleAttributeSet into a string.
*
* Returns: (transfer full): a newly allocated string with the contents
* of the #GtkAccessibleAttributeSet
*/
char *
gtk_accessible_attribute_set_to_string (GtkAccessibleAttributeSet *self)
{
GString *buf = g_string_new (NULL);
gtk_accessible_attribute_set_print (self, TRUE, buf);
return g_string_free (buf, FALSE);
}
/* gtkaccessiblepropertysetprivate.h: Accessible property set
/* gtkaccessibleattributesetprivate.h: Accessible attribute container
*
* Copyright 2020 GNOME Foundation
*
......@@ -25,25 +25,33 @@
G_BEGIN_DECLS
typedef struct _GtkAccessiblePropertySet GtkAccessiblePropertySet;
GtkAccessiblePropertySet * gtk_accessible_property_set_new (void);
GtkAccessiblePropertySet * gtk_accessible_property_set_ref (GtkAccessiblePropertySet *self);
void gtk_accessible_property_set_unref (GtkAccessiblePropertySet *self);
void gtk_accessible_property_set_add (GtkAccessiblePropertySet *self,
GtkAccessibleProperty property,
GtkAccessibleValue *value);
void gtk_accessible_property_set_remove (GtkAccessiblePropertySet *self,
GtkAccessibleProperty property);
gboolean gtk_accessible_property_set_contains (GtkAccessiblePropertySet *self,
GtkAccessibleProperty property);
GtkAccessibleValue * gtk_accessible_property_set_get_value (GtkAccessiblePropertySet *self,
GtkAccessibleProperty property);
void gtk_accessible_property_set_print (GtkAccessiblePropertySet *self,
gboolean only_set,
GString *string);
char * gtk_accessible_property_set_to_string (GtkAccessiblePropertySet *self);
typedef struct _GtkAccessibleAttributeSet GtkAccessibleAttributeSet;
typedef GtkAccessibleValue *(* GtkAccessibleAttributeDefaultFunc) (int attribute);
GtkAccessibleAttributeSet * gtk_accessible_attribute_set_new (gsize n_attributes,
const char **attr_names,
GtkAccessibleAttributeDefaultFunc default_func);
GtkAccessibleAttributeSet * gtk_accessible_attribute_set_ref (GtkAccessibleAttributeSet *self);
void gtk_accessible_attribute_set_unref (GtkAccessibleAttributeSet *self);
gsize gtk_accessible_attribute_set_get_length (GtkAccessibleAttributeSet *self);
void gtk_accessible_attribute_set_add (GtkAccessibleAttributeSet *self,
int attribute,
GtkAccessibleValue *value);
void gtk_accessible_attribute_set_remove (GtkAccessibleAttributeSet *self,
int state);
gboolean gtk_accessible_attribute_set_contains (GtkAccessibleAttributeSet *self,
int state);
GtkAccessibleValue * gtk_accessible_attribute_set_get_value (GtkAccessibleAttributeSet *self,
int state);
guint gtk_accessible_attribute_set_get_changed (GtkAccessibleAttributeSet *self);
void gtk_accessible_attribute_set_print (GtkAccessibleAttributeSet *self,
gboolean only_set,
GString *string);
char * gtk_accessible_attribute_set_to_string (GtkAccessibleAttributeSet *self);
G_END_DECLS
/* gtkaccessiblepropertyset.c: Accessible properties
*
* 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/>.
*/
#include "config.h"
#include "gtkaccessiblepropertysetprivate.h"
#include "gtkbitmaskprivate.h"
#include "gtkenums.h"
/* Keep in sync with GtkAccessibleProperty in gtkenums.h */
#define LAST_PROPERTY GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT
struct _GtkAccessiblePropertySet
{
GtkBitmask *property_set;
GtkAccessibleValue **property_values;
};
static GtkAccessiblePropertySet *
gtk_accessible_property_set_init (GtkAccessiblePropertySet *self)
{
self->property_set = _gtk_bitmask_new ();
self->property_values = g_new (GtkAccessibleValue *, LAST_PROPERTY);
/* Initialize all property values, so we can always get the full set */
for (int i = 0; i < LAST_PROPERTY; i++)
self->property_values[i] = gtk_accessible_value_get_default_for_property (i);
return self;
}
GtkAccessiblePropertySet *
gtk_accessible_property_set_new (void)
{
GtkAccessiblePropertySet *set = g_rc_box_new0 (GtkAccessiblePropertySet);
return gtk_accessible_property_set_init (set);
}
GtkAccessiblePropertySet *
gtk_accessible_property_set_ref (GtkAccessiblePropertySet *self)
{
g_return_val_if_fail (self != NULL, NULL);
return g_rc_box_acquire (self);
}
static void
gtk_accessible_property_set_free (gpointer data)
{
GtkAccessiblePropertySet *self = data;
for (int i = 0; i < LAST_PROPERTY; i++)
{
if (self->property_values[i] != NULL)
gtk_accessible_value_unref (self->property_values[i]);
}
g_free (self->property_values);
_gtk_bitmask_free (self->property_set);
}
void
gtk_accessible_property_set_unref (GtkAccessiblePropertySet *self)
{
g_rc_box_release_full (self, gtk_accessible_property_set_free);
}
void
gtk_accessible_property_set_add (GtkAccessiblePropertySet *self,
GtkAccessibleProperty property,
GtkAccessibleValue *value)
{
g_return_if_fail (property >= GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE &&
property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT);
if (gtk_accessible_property_set_contains (self, property))
gtk_accessible_value_unref (self->property_values[property]);
else
self->property_set = _gtk_bitmask_set (self->property_set, property, TRUE);
self->property_values[property] = gtk_accessible_value_ref (value);
}
void
gtk_accessible_property_set_remove (GtkAccessiblePropertySet *self,
GtkAccessibleProperty property)
{
g_return_if_fail (property >= GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE &&
property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT);
if (gtk_accessible_property_set_contains (self, property))
{
g_clear_pointer (&(self->property_values[property]), gtk_accessible_value_unref);
self->property_set = _gtk_bitmask_set (self->property_set, property, FALSE);
}
}
gboolean
gtk_accessible_property_set_contains (GtkAccessiblePropertySet *self,
GtkAccessibleProperty property)
{
g_return_val_if_fail (property >= GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE &&
property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT,
FALSE);
return _gtk_bitmask_get (self->property_set, property);
}
GtkAccessibleValue *
gtk_accessible_property_set_get_value (GtkAccessiblePropertySet *self,
GtkAccessibleProperty property)
{
g_return_val_if_fail (property >= GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE &&
property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT,
NULL);
return self->property_values[property];
}
static const char *property_names[] = {
[GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE] = "autocomplete",
[GTK_ACCESSIBLE_PROPERTY_DESCRIPTION] = "description",
[GTK_ACCESSIBLE_PROPERTY_HAS_POPUP] = "haspopup",
[GTK_ACCESSIBLE_PROPERTY_KEY_SHORTCUTS] = "keyshortcuts",
[GTK_ACCESSIBLE_PROPERTY_LABEL] = "label",
[GTK_ACCESSIBLE_PROPERTY_LEVEL] = "level",
[GTK_ACCESSIBLE_PROPERTY_MODAL] = "modal",
[GTK_ACCESSIBLE_PROPERTY_MULTI_LINE] = "multiline",
[GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE] = "multiselectable",
[GTK_ACCESSIBLE_PROPERTY_ORIENTATION] = "orientation",
[GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER] = "placeholder",
[GTK_ACCESSIBLE_PROPERTY_READ_ONLY] = "readonly",
[GTK_ACCESSIBLE_PROPERTY_REQUIRED] = "required",
[GTK_ACCESSIBLE_PROPERTY_ROLE_DESCRIPTION] = "roledescription",
[GTK_ACCESSIBLE_PROPERTY_SORT] = "sort",
[GTK_ACCESSIBLE_PROPERTY_VALUE_MAX] = "valuemax",
[GTK_ACCESSIBLE_PROPERTY_VALUE_MIN] = "valuemin",
[GTK_ACCESSIBLE_PROPERTY_VALUE_NOW] = "valuenow",
[GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT] = "valuetext",
};
/*< private >
* gtk_accessible_property_set_print:
* @self: a #GtkAccessiblePropertySet
* @only_set: %TRUE if only the set properties should be printed
* @buffer: a #GString
*
* Prints the contents of the #GtkAccessiblePropertySet into @buffer.
*/
void
gtk_accessible_property_set_print (GtkAccessiblePropertySet *self,
gboolean only_set,
GString *buffer)
{
if (only_set && _gtk_bitmask_is_empty (self->property_set))
{
g_string_append (buffer, "{}");
return;
}
g_string_append (buffer, "{\n");
for (int i = 0; i < G_N_ELEMENTS (property_names); i++)
{
if (only_set && !_gtk_bitmask_get (self->property_set, i))
continue;
g_string_append (buffer, " ");
g_string_append (buffer, property_names[i]);
g_string_append (buffer, ": ");
gtk_accessible_value_print (self->property_values[i], buffer);
g_string_append (buffer, ",\n");
}
g_string_append (buffer, "}");
}
/*< private >
* gtk_accessible_property_set_to_string:
* @self: a #GtkAccessiblePropertySet
*
* Prints the contents of a #GtkAccessiblePropertySet into a string.
*
* Returns: (transfer full): a newly allocated string with the contents
* of the #GtkAccessiblePropertySet
*/
char *
gtk_accessible_property_set_to_string (GtkAccessiblePropertySet *self)
{
GString *buf = g_string_new (NULL);
gtk_accessible_property_set_print (self, TRUE, buf);
return g_string_free (buf, FALSE);
}
/* gtkaccessiblerelationset.c: Accessible relation set
*
* 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/>.
*/
#include "config.h"
#include "gtkaccessiblerelationsetprivate.h"
#include "gtkbitmaskprivate.h"
#include "gtkenums.h"
/* Keep in sync with GtkAccessibleRelation in gtkenums.h */
#define LAST_RELATION GTK_ACCESSIBLE_RELATION_SET_SIZE
struct _GtkAccessibleRelationSet
{
GtkBitmask *relation_set;
GtkAccessibleValue **relation_values;
};
static GtkAccessibleRelationSet *
gtk_accessible_relation_set_init (GtkAccessibleRelationSet *self)
{
self->relation_set = _gtk_bitmask_new ();
self->relation_values = g_new (GtkAccessibleValue *, LAST_RELATION);
/* Initialize all relation values, so we can always get the full set */
for (int i = 0; i < LAST_RELATION; i++)
self->relation_values[i] = gtk_accessible_value_get_default_for_relation (i);
return self;
}
GtkAccessibleRelationSet *
gtk_accessible_relation_set_new (void)
{
GtkAccessibleRelationSet *set = g_rc_box_new0 (GtkAccessibleRelationSet);
return gtk_accessible_relation_set_init (set);
}
GtkAccessibleRelationSet *
gtk_accessible_relation_set_ref (GtkAccessibleRelationSet *self)
{
g_return_val_if_fail (self != NULL, NULL);
return g_rc_box_acquire (self);
}
static void
gtk_accessible_relation_set_free (gpointer data)
{
GtkAccessibleRelationSet *self = data;
for (int i = 0; i < LAST_RELATION; i++)
{
if (self->relation_values[i] != NULL)
gtk_accessible_value_unref (self->relation_values[i]);
}
g_free (self->relation_values);
_gtk_bitmask_free (self->relation_set);
}
void
gtk_accessible_relation_set_unref (GtkAccessibleRelationSet *self)
{
g_rc_box_release_full (self, gtk_accessible_relation_set_free);
}
void
gtk_accessible_relation_set_add (GtkAccessibleRelationSet *self,