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

            
20
#include "config.h"
21

            
22
#include <glib-object.h>
23

            
24
#include "atkobject.h"
25
#include "atkstateset.h"
26

            
27
/**
28
 * AtkStateSet:
29
 *
30
 * An AtkStateSet contains the states of an object.
31
 *
32
 * An AtkStateSet is a read-only representation of the full set of #AtkStates
33
 * that apply to an object at a given time. This set is not meant to be
34
 * modified, but rather created when #atk_object_ref_state_set() is called.
35
 */
36

            
37
#define ATK_STATE(state_enum) ((AtkState) ((guint64) 1 << ((state_enum) % 64)))
38

            
39
struct _AtkRealStateSet
40
{
41
  GObject parent;
42

            
43
  AtkState state;
44
};
45

            
46
typedef struct _AtkRealStateSet AtkRealStateSet;
47

            
48
static void atk_state_set_class_init (AtkStateSetClass *klass);
49

            
50
GType
51
78251
atk_state_set_get_type (void)
52
{
53
  static GType type = 0;
54

            
55
78251
  if (!type)
56
    {
57
      static const GTypeInfo typeInfo = {
58
        sizeof (AtkStateSetClass),
59
        (GBaseInitFunc) NULL,
60
        (GBaseFinalizeFunc) NULL,
61
        (GClassInitFunc) atk_state_set_class_init,
62
        (GClassFinalizeFunc) NULL,
63
        NULL,
64
        sizeof (AtkRealStateSet),
65
        0,
66
        (GInstanceInitFunc) NULL,
67
      };
68
162
      type = g_type_register_static (G_TYPE_OBJECT, "AtkStateSet", &typeInfo, 0);
69
    }
70
78251
  return type;
71
}
72

            
73
static void
74
162
atk_state_set_class_init (AtkStateSetClass *klass)
75
{
76
162
}
77

            
78
/**
79
 * atk_state_set_new:
80
 *
81
 * Creates a new empty state set.
82
 *
83
 * Returns: a new #AtkStateSet
84
 **/
85
AtkStateSet *
86
1600
atk_state_set_new (void)
87
{
88
1600
  return (AtkStateSet *) g_object_new (ATK_TYPE_STATE_SET, NULL);
89
}
90

            
91
/**
92
 * atk_state_set_is_empty:
93
 * @set: an #AtkStateType
94
 *
95
 * Checks whether the state set is empty, i.e. has no states set.
96
 *
97
 * Returns: %TRUE if @set has no states set, otherwise %FALSE
98
 **/
99
gboolean
100
2
atk_state_set_is_empty (AtkStateSet *set)
101
{
102
  AtkRealStateSet *real_set;
103
2
  g_return_val_if_fail (ATK_IS_STATE_SET (set), FALSE);
104

            
105
2
  real_set = (AtkRealStateSet *) set;
106

            
107
2
  if (real_set->state)
108
1
    return FALSE;
109
  else
110
1
    return TRUE;
111
}
112

            
113
/**
114
 * atk_state_set_add_state:
115
 * @set: an #AtkStateSet
116
 * @type: an #AtkStateType
117
 *
118
 * Adds the state of the specified type to the state set if it is not already
119
 * present.
120
 *
121
 * Note that because an #AtkStateSet is a read-only object, this method should
122
 * be used to add a state to a newly-created set which will then be returned by
123
 * #atk_object_ref_state_set. It should not be used to modify the existing state
124
 * of an object. See also #atk_object_notify_state_change.
125
 *
126
 * Returns: %TRUE if  the state for @type is not already in @set.
127
 **/
128
gboolean
129
288
atk_state_set_add_state (AtkStateSet *set,
130
                         AtkStateType type)
131
{
132
  AtkRealStateSet *real_set;
133
288
  g_return_val_if_fail (ATK_IS_STATE_SET (set), FALSE);
134

            
135
288
  real_set = (AtkRealStateSet *) set;
136

            
137
288
  if (real_set->state & ATK_STATE (type))
138
4
    return FALSE;
139
  else
140
    {
141
284
      real_set->state |= ATK_STATE (type);
142
284
      return TRUE;
143
    }
144
}
145
/**
146
 * atk_state_set_add_states:
147
 * @set: an #AtkStateSet
148
 * @types: (array length=n_types): an array of #AtkStateType
149
 * @n_types: The number of elements in the array
150
 *
151
 * Adds the states of the specified types to the state set.
152
 *
153
 * Note that because an #AtkStateSet is a read-only object, this method should
154
 * be used to add states to a newly-created set which will then be returned by
155
 * #atk_object_ref_state_set. It should not be used to modify the existing state
156
 * of an object. See also #atk_object_notify_state_change.
157
 **/
158
void
159
2
atk_state_set_add_states (AtkStateSet *set,
160
                          AtkStateType *types,
161
                          gint n_types)
162
{
163
  AtkRealStateSet *real_set;
164
  gint i;
165
2
  g_return_if_fail (ATK_IS_STATE_SET (set));
166

            
167
2
  real_set = (AtkRealStateSet *) set;
168

            
169
8
  for (i = 0; i < n_types; i++)
170
    {
171
6
      real_set->state |= ATK_STATE (types[i]);
172
    }
173
}
174

            
175
/**
176
 * atk_state_set_clear_states:
177
 * @set: an #AtkStateSet
178
 *
179
 * Removes all states from the state set.
180
 **/
181
void
182
1
atk_state_set_clear_states (AtkStateSet *set)
183
{
184
  AtkRealStateSet *real_set;
185
1
  g_return_if_fail (ATK_IS_STATE_SET (set));
186

            
187
1
  real_set = (AtkRealStateSet *) set;
188

            
189
1
  real_set->state = 0;
190
}
191

            
192
/**
193
 * atk_state_set_contains_state:
194
 * @set: an #AtkStateSet
195
 * @type: an #AtkStateType
196
 *
197
 * Checks whether the state for the specified type is in the specified set.
198
 *
199
 * Returns: %TRUE if @type is the state type is in @set.
200
 **/
201
gboolean
202
72527
atk_state_set_contains_state (AtkStateSet *set,
203
                              AtkStateType type)
204
{
205
  AtkRealStateSet *real_set;
206
72527
  g_return_val_if_fail (ATK_IS_STATE_SET (set), FALSE);
207

            
208
72527
  real_set = (AtkRealStateSet *) set;
209

            
210
72527
  if (real_set->state & ATK_STATE (type))
211
371
    return TRUE;
212
  else
213
72156
    return FALSE;
214
}
215

            
216
/**
217
 * atk_state_set_contains_states:
218
 * @set: an #AtkStateSet
219
 * @types: (array length=n_types): an array of #AtkStateType
220
 * @n_types: The number of elements in the array
221
 *
222
 * Checks whether the states for all the specified types are in the
223
 * specified set.
224
 *
225
 * Returns: %TRUE if all the states for @type are in @set.
226
 **/
227
gboolean
228
2
atk_state_set_contains_states (AtkStateSet *set,
229
                               AtkStateType *types,
230
                               gint n_types)
231
{
232
  AtkRealStateSet *real_set;
233
  gint i;
234
2
  g_return_val_if_fail (ATK_IS_STATE_SET (set), FALSE);
235

            
236
2
  real_set = (AtkRealStateSet *) set;
237

            
238
6
  for (i = 0; i < n_types; i++)
239
    {
240
5
      if (!(real_set->state & ATK_STATE (types[i])))
241
1
        return FALSE;
242
    }
243
1
  return TRUE;
244
}
245

            
246
/**
247
 * atk_state_set_remove_state:
248
 * @set: an #AtkStateSet
249
 * @type: an #AtkType
250
 *
251
 * Removes the state for the specified type from the state set.
252
 *
253
 * Note that because an #AtkStateSet is a read-only object, this method should
254
 * be used to remove a state to a newly-created set which will then be returned
255
 * by #atk_object_ref_state_set. It should not be used to modify the existing
256
 * state of an object. See also #atk_object_notify_state_change.
257
 *
258
 * Returns: %TRUE if @type was the state type is in @set.
259
 **/
260
gboolean
261
11
atk_state_set_remove_state (AtkStateSet *set,
262
                            AtkStateType type)
263
{
264
  AtkRealStateSet *real_set;
265
11
  g_return_val_if_fail (ATK_IS_STATE_SET (set), FALSE);
266

            
267
11
  real_set = (AtkRealStateSet *) set;
268

            
269
11
  if (real_set->state & ATK_STATE (type))
270
    {
271
9
      real_set->state ^= ATK_STATE (type);
272
9
      return TRUE;
273
    }
274
  else
275
2
    return FALSE;
276
}
277

            
278
/**
279
 * atk_state_set_and_sets:
280
 * @set: an #AtkStateSet
281
 * @compare_set: another #AtkStateSet
282
 *
283
 * Constructs the intersection of the two sets, returning %NULL if the
284
 * intersection is empty.
285
 *
286
 * Returns: (transfer full): a new #AtkStateSet which is the intersection of
287
 * the two sets.
288
 **/
289
AtkStateSet *
290
2
atk_state_set_and_sets (AtkStateSet *set,
291
                        AtkStateSet *compare_set)
292
{
293
  AtkRealStateSet *real_set, *real_compare_set;
294
2
  AtkStateSet *return_set = NULL;
295
  AtkState state;
296

            
297
2
  g_return_val_if_fail (ATK_IS_STATE_SET (set), NULL);
298
2
  g_return_val_if_fail (ATK_IS_STATE_SET (compare_set), NULL);
299

            
300
2
  real_set = (AtkRealStateSet *) set;
301
2
  real_compare_set = (AtkRealStateSet *) compare_set;
302

            
303
2
  state = real_set->state & real_compare_set->state;
304
2
  if (state)
305
    {
306
1
      return_set = atk_state_set_new ();
307
1
      ((AtkRealStateSet *) return_set)->state = state;
308
    }
309
2
  return return_set;
310
}
311

            
312
/**
313
 * atk_state_set_or_sets:
314
 * @set: an #AtkStateSet
315
 * @compare_set: another #AtkStateSet
316
 *
317
 * Constructs the union of the two sets.
318
 *
319
 * Returns: (nullable) (transfer full): a new #AtkStateSet which is
320
 * the union of the two sets, returning %NULL is empty.
321
 **/
322
AtkStateSet *
323
1
atk_state_set_or_sets (AtkStateSet *set,
324
                       AtkStateSet *compare_set)
325
{
326
  AtkRealStateSet *real_set, *real_compare_set;
327
1
  AtkStateSet *return_set = NULL;
328
  AtkState state;
329

            
330
1
  g_return_val_if_fail (ATK_IS_STATE_SET (set), NULL);
331
1
  g_return_val_if_fail (ATK_IS_STATE_SET (compare_set), NULL);
332

            
333
1
  real_set = (AtkRealStateSet *) set;
334
1
  real_compare_set = (AtkRealStateSet *) compare_set;
335

            
336
1
  state = real_set->state | real_compare_set->state;
337

            
338
1
  if (state)
339
    {
340
1
      return_set = atk_state_set_new ();
341
1
      ((AtkRealStateSet *) return_set)->state = state;
342
    }
343

            
344
1
  return return_set;
345
}
346

            
347
/**
348
 * atk_state_set_xor_sets:
349
 * @set: an #AtkStateSet
350
 * @compare_set: another #AtkStateSet
351
 *
352
 * Constructs the exclusive-or of the two sets, returning %NULL is empty.
353
 * The set returned by this operation contains the states in exactly
354
 * one of the two sets.
355
 *
356
 * Returns: (transfer full): a new #AtkStateSet which contains the states
357
 * which are in exactly one of the two sets.
358
 **/
359
AtkStateSet *
360
1
atk_state_set_xor_sets (AtkStateSet *set,
361
                        AtkStateSet *compare_set)
362
{
363
  AtkRealStateSet *real_set, *real_compare_set;
364
1
  AtkStateSet *return_set = NULL;
365
  AtkState state, state1, state2;
366

            
367
1
  g_return_val_if_fail (ATK_IS_STATE_SET (set), NULL);
368
1
  g_return_val_if_fail (ATK_IS_STATE_SET (compare_set), NULL);
369

            
370
1
  real_set = (AtkRealStateSet *) set;
371
1
  real_compare_set = (AtkRealStateSet *) compare_set;
372

            
373
1
  state1 = real_set->state & (~real_compare_set->state);
374
1
  state2 = (~real_set->state) & real_compare_set->state;
375
1
  state = state1 | state2;
376

            
377
1
  if (state)
378
    {
379
1
      return_set = atk_state_set_new ();
380
1
      ((AtkRealStateSet *) return_set)->state = state;
381
    }
382
1
  return return_set;
383
}