1/* gtkaccessibleattributeset.c: Accessible attribute content
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#include "config.h"
22
23#include "gtkaccessibleattributesetprivate.h"
24
25#include "gtkbitmaskprivate.h"
26#include "gtkenums.h"
27
28struct _GtkAccessibleAttributeSet
29{
30 gsize n_attributes;
31
32 GtkAccessibleAttributeNameFunc name_func;
33 GtkAccessibleAttributeDefaultFunc default_func;
34
35 GtkBitmask *attributes_set;
36
37 GtkAccessibleValue **attribute_values;
38};
39
40static GtkAccessibleAttributeSet *
41gtk_accessible_attribute_set_init (GtkAccessibleAttributeSet *self,
42 gsize n_attributes,
43 GtkAccessibleAttributeNameFunc name_func,
44 GtkAccessibleAttributeDefaultFunc default_func)
45{
46 self->n_attributes = n_attributes;
47 self->name_func = name_func;
48 self->default_func = default_func;
49 self->attribute_values = g_new (GtkAccessibleValue *, n_attributes);
50 self->attributes_set = _gtk_bitmask_new ();
51
52 /* Initialize all attribute values, so we can always get the full attribute */
53 for (int i = 0; i < self->n_attributes; i++)
54 self->attribute_values[i] = (* self->default_func) (i);
55
56 return self;
57}
58
59GtkAccessibleAttributeSet *
60gtk_accessible_attribute_set_new (gsize n_attributes,
61 GtkAccessibleAttributeNameFunc name_func,
62 GtkAccessibleAttributeDefaultFunc default_func)
63{
64 GtkAccessibleAttributeSet *set = g_rc_box_new0 (GtkAccessibleAttributeSet);
65
66 return gtk_accessible_attribute_set_init (self: set, n_attributes, name_func, default_func);
67}
68
69GtkAccessibleAttributeSet *
70gtk_accessible_attribute_set_ref (GtkAccessibleAttributeSet *self)
71{
72 g_return_val_if_fail (self != NULL, NULL);
73
74 return g_rc_box_acquire (self);
75}
76
77static void
78gtk_accessible_attribute_set_free (gpointer data)
79{
80 GtkAccessibleAttributeSet *self = data;
81
82 for (int i = 0; i < self->n_attributes; i++)
83 {
84 if (self->attribute_values[i] != NULL)
85 gtk_accessible_value_unref (self: self->attribute_values[i]);
86 }
87
88 g_free (mem: self->attribute_values);
89
90 _gtk_bitmask_free (mask: self->attributes_set);
91}
92
93void
94gtk_accessible_attribute_set_unref (GtkAccessibleAttributeSet *self)
95{
96 g_rc_box_release_full (mem_block: self, clear_func: gtk_accessible_attribute_set_free);
97}
98
99/*< private >
100 * gtk_accessible_attribute_set_add:
101 * @self: a `GtkAccessibleAttributeSet`
102 * @attribute: the attribute to set
103 * @value: (nullable): a `GtkAccessibleValue`
104 *
105 * Adds @attribute to the attributes set, and sets its value.
106 *
107 * If @value is %NULL, the @attribute is reset to its default value.
108 *
109 * If you want to remove @attribute from the set, use gtk_accessible_attribute_set_remove()
110 * instead.
111 *
112 * Returns: %TRUE if the set was modified, and %FALSE otherwise
113 */
114gboolean
115gtk_accessible_attribute_set_add (GtkAccessibleAttributeSet *self,
116 int attribute,
117 GtkAccessibleValue *value)
118{
119 g_return_val_if_fail (attribute >= 0 && attribute < self->n_attributes, FALSE);
120
121 if (value != NULL)
122 {
123 if (gtk_accessible_value_equal (value_a: value, value_b: self->attribute_values[attribute]))
124 return FALSE;
125 }
126 else
127 {
128 if (!_gtk_bitmask_get (mask: self->attributes_set, index_: attribute))
129 return FALSE;
130 }
131
132 g_clear_pointer (&(self->attribute_values[attribute]), gtk_accessible_value_unref);
133
134 if (value != NULL)
135 self->attribute_values[attribute] = gtk_accessible_value_ref (self: value);
136 else
137 self->attribute_values[attribute] = (* self->default_func) (attribute);
138
139 self->attributes_set = _gtk_bitmask_set (mask: self->attributes_set, index_: attribute, TRUE);
140
141 return TRUE;
142}
143
144/*< private >
145 * gtk_accessible_attribute_set_remove:
146 * @self: a `GtkAccessibleAttributeSet`
147 * @attribute: the attribute to be removed
148 *
149 * Resets the @attribute in the given `GtkAccessibleAttributeSet`
150 * to its default value.
151 *
152 * Returns: %TRUE if the set was modified, and %FALSE otherwise
153 */
154gboolean
155gtk_accessible_attribute_set_remove (GtkAccessibleAttributeSet *self,
156 int attribute)
157{
158 g_return_val_if_fail (attribute >= 0 && attribute < self->n_attributes, FALSE);
159
160 if (!_gtk_bitmask_get (mask: self->attributes_set, index_: attribute))
161 return FALSE;
162
163 g_clear_pointer (&(self->attribute_values[attribute]), gtk_accessible_value_unref);
164
165 self->attribute_values[attribute] = (* self->default_func) (attribute);
166 self->attributes_set = _gtk_bitmask_set (mask: self->attributes_set, index_: attribute, FALSE);
167
168 return TRUE;
169}
170
171gboolean
172gtk_accessible_attribute_set_contains (GtkAccessibleAttributeSet *self,
173 int attribute)
174 {
175 g_return_val_if_fail (attribute >= 0 && attribute < self->n_attributes, FALSE);
176
177 return _gtk_bitmask_get (mask: self->attributes_set, index_: attribute);
178}
179
180/*< private >
181 * gtk_accessible_attribute_set_get_value:
182 * @self: a `GtkAccessibleAttributeSet`
183 * @attribute: the attribute to retrieve
184 *
185 * Retrieves the value of the given @attribute in the set.
186 *
187 * Returns: (transfer none): the value for the attribute
188 */
189GtkAccessibleValue *
190gtk_accessible_attribute_set_get_value (GtkAccessibleAttributeSet *self,
191 int attribute)
192{
193 g_return_val_if_fail (attribute >= 0 && attribute < self->n_attributes, NULL);
194
195 return self->attribute_values[attribute];
196}
197
198gsize
199gtk_accessible_attribute_set_get_length (GtkAccessibleAttributeSet *self)
200{
201 return self->n_attributes;
202}
203
204guint
205gtk_accessible_attribute_set_get_changed (GtkAccessibleAttributeSet *self)
206{
207 guint changed = 0;
208
209 for (gsize i = 0; i < self->n_attributes; i++)
210 {
211 if (gtk_accessible_attribute_set_contains (self, attribute: i))
212 changed |= (1 << i);
213 }
214
215 return changed;
216}
217
218/*< private >
219 * gtk_accessible_attribute_set_print:
220 * @self: a `GtkAccessibleAttributeSet`
221 * @only_set: %TRUE if only the set attributes should be printed
222 * @buffer: a `GString`
223 *
224 * Prints the contents of the `GtkAccessibleAttributeSet` into @buffer.
225 */
226void
227gtk_accessible_attribute_set_print (GtkAccessibleAttributeSet *self,
228 gboolean only_set,
229 GString *buffer)
230{
231 if (only_set && _gtk_bitmask_is_empty (mask: self->attributes_set))
232 {
233 g_string_append (string: buffer, val: "{}");
234 return;
235 }
236
237 g_string_append (string: buffer, val: "{\n");
238
239 for (gsize i = 0; i < self->n_attributes; i++)
240 {
241 if (only_set && !_gtk_bitmask_get (mask: self->attributes_set, index_: i))
242 continue;
243
244 g_string_append (string: buffer, val: " ");
245 g_string_append (string: buffer, val: self->name_func (i));
246 g_string_append (string: buffer, val: ": ");
247
248 gtk_accessible_value_print (self: self->attribute_values[i], buffer);
249
250 g_string_append (string: buffer, val: ",\n");
251 }
252
253 g_string_append (string: buffer, val: "}");
254}
255
256/*< private >
257 * gtk_accessible_attribute_set_to_string:
258 * @self: a `GtkAccessibleAttributeSet`
259 *
260 * Prints the contents of a `GtkAccessibleAttributeSet` into a string.
261 *
262 * Returns: (transfer full): a newly allocated string with the contents
263 * of the `GtkAccessibleAttributeSet`
264 */
265char *
266gtk_accessible_attribute_set_to_string (GtkAccessibleAttributeSet *self)
267{
268 GString *buf = g_string_new (NULL);
269
270 gtk_accessible_attribute_set_print (self, TRUE, buffer: buf);
271
272 return g_string_free (string: buf, FALSE);
273}
274

source code of gtk/gtk/gtkaccessibleattributeset.c