1 /* GAIL - The GNOME Accessibility Implementation Library
2 * Copyright 2001 Sun Microsystems Inc.
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.
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.
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.
25 #include "gailcontainercell.h"
27 #include "gailcellparent.h"
29 static void gail_cell_class_init (GailCellClass *klass);
30 static void gail_cell_destroyed (GtkWidget *widget,
33 static void gail_cell_init (GailCell *cell);
34 static void gail_cell_object_finalize (GObject *cell);
35 static AtkStateSet* gail_cell_ref_state_set (AtkObject *obj);
36 static gint gail_cell_get_index_in_parent (AtkObject *obj);
40 static void atk_action_interface_init
41 (AtkActionIface *iface);
42 static ActionInfo * _gail_cell_get_action_info (GailCell *cell,
44 static void _gail_cell_destroy_action_info
48 static gint gail_cell_action_get_n_actions
51 gail_cell_action_get_name (AtkAction *action,
54 gail_cell_action_get_description
57 static gboolean gail_cell_action_set_description
62 gail_cell_action_get_keybinding
65 static gboolean gail_cell_action_do_action (AtkAction *action,
67 static gboolean idle_do_action (gpointer data);
69 static void atk_component_interface_init (AtkComponentIface *iface);
70 static void gail_cell_get_extents (AtkComponent *component,
75 AtkCoordType coord_type);
76 static gboolean gail_cell_grab_focus (AtkComponent *component);
78 G_DEFINE_TYPE_WITH_CODE (GailCell, gail_cell, ATK_TYPE_OBJECT,
79 G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init)
80 G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init))
83 gail_cell_class_init (GailCellClass *klass)
85 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
86 GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
88 g_object_class->finalize = gail_cell_object_finalize;
90 class->get_index_in_parent = gail_cell_get_index_in_parent;
91 class->ref_state_set = gail_cell_ref_state_set;
95 gail_cell_initialise (GailCell *cell,
100 g_return_if_fail (GAIL_IS_CELL (cell));
101 g_return_if_fail (GTK_IS_WIDGET (widget));
103 cell->widget = widget;
104 atk_object_set_parent (ATK_OBJECT (cell), parent);
107 g_signal_connect_object (G_OBJECT (widget),
109 G_CALLBACK (gail_cell_destroyed ),
114 gail_cell_destroyed (GtkWidget *widget,
118 * This is the signal handler for the "destroy" signal for the
119 * GtkWidget. We set the pointer location to NULL;
125 gail_cell_init (GailCell *cell)
127 cell->state_set = atk_state_set_new ();
129 cell->action_list = NULL;
131 atk_state_set_add_state (cell->state_set, ATK_STATE_TRANSIENT);
132 atk_state_set_add_state (cell->state_set, ATK_STATE_ENABLED);
133 atk_state_set_add_state (cell->state_set, ATK_STATE_SENSITIVE);
134 atk_state_set_add_state (cell->state_set, ATK_STATE_SELECTABLE);
135 cell->refresh_index = NULL;
139 gail_cell_object_finalize (GObject *obj)
141 GailCell *cell = GAIL_CELL (obj);
142 AtkRelationSet *relation_set;
143 AtkRelation *relation;
145 gpointer target_object;
149 g_object_unref (cell->state_set);
150 if (cell->action_list)
152 g_list_foreach (cell->action_list, _gail_cell_destroy_action_info, NULL);
153 g_list_free (cell->action_list);
155 if (cell->action_idle_handler)
157 g_source_remove (cell->action_idle_handler);
158 cell->action_idle_handler = 0;
160 relation_set = atk_object_ref_relation_set (ATK_OBJECT (obj));
161 if (ATK_IS_RELATION_SET (relation_set))
163 relation = atk_relation_set_get_relation_by_type (relation_set,
164 ATK_RELATION_NODE_CHILD_OF);
167 target = atk_relation_get_target (relation);
168 for (i = 0; i < target->len; i++)
170 target_object = g_ptr_array_index (target, i);
171 if (GAIL_IS_CELL (target_object))
173 g_object_unref (target_object);
177 g_object_unref (relation_set);
179 G_OBJECT_CLASS (gail_cell_parent_class)->finalize (obj);
183 gail_cell_ref_state_set (AtkObject *obj)
185 GailCell *cell = GAIL_CELL (obj);
186 g_assert (cell->state_set);
188 g_object_ref(cell->state_set);
189 return cell->state_set;
193 gail_cell_add_state (GailCell *cell,
194 AtkStateType state_type,
195 gboolean emit_signal)
197 if (!atk_state_set_contains_state (cell->state_set, state_type))
202 rc = atk_state_set_add_state (cell->state_set, state_type);
204 * The signal should only be generated if the value changed,
205 * not when the cell is set up. So states that are set
206 * initially should pass FALSE as the emit_signal argument.
211 atk_object_notify_state_change (ATK_OBJECT (cell), state_type, TRUE);
212 /* If state_type is ATK_STATE_VISIBLE, additional notification */
213 if (state_type == ATK_STATE_VISIBLE)
214 g_signal_emit_by_name (cell, "visible_data_changed");
218 * If the parent is a flyweight container cell, propagate the state
222 parent = atk_object_get_parent (ATK_OBJECT (cell));
223 if (GAIL_IS_CONTAINER_CELL (parent))
224 gail_cell_add_state (GAIL_CELL (parent), state_type, emit_signal);
232 gail_cell_remove_state (GailCell *cell,
233 AtkStateType state_type,
234 gboolean emit_signal)
236 if (atk_state_set_contains_state (cell->state_set, state_type))
241 parent = atk_object_get_parent (ATK_OBJECT (cell));
243 rc = atk_state_set_remove_state (cell->state_set, state_type);
245 * The signal should only be generated if the value changed,
246 * not when the cell is set up. So states that are set
247 * initially should pass FALSE as the emit_signal argument.
252 atk_object_notify_state_change (ATK_OBJECT (cell), state_type, FALSE);
253 /* If state_type is ATK_STATE_VISIBLE, additional notification */
254 if (state_type == ATK_STATE_VISIBLE)
255 g_signal_emit_by_name (cell, "visible_data_changed");
259 * If the parent is a flyweight container cell, propagate the state
263 if (GAIL_IS_CONTAINER_CELL (parent))
264 gail_cell_remove_state (GAIL_CELL (parent), state_type, emit_signal);
272 gail_cell_get_index_in_parent (AtkObject *obj)
276 g_assert (GAIL_IS_CELL (obj));
278 cell = GAIL_CELL (obj);
279 if (atk_state_set_contains_state (cell->state_set, ATK_STATE_STALE))
280 if (cell->refresh_index)
282 cell->refresh_index (cell);
283 atk_state_set_remove_state (cell->state_set, ATK_STATE_STALE);
289 atk_action_interface_init (AtkActionIface *iface)
291 iface->get_n_actions = gail_cell_action_get_n_actions;
292 iface->do_action = gail_cell_action_do_action;
293 iface->get_name = gail_cell_action_get_name;
294 iface->get_description = gail_cell_action_get_description;
295 iface->set_description = gail_cell_action_set_description;
296 iface->get_keybinding = gail_cell_action_get_keybinding;
300 gail_cell_add_action (GailCell *cell,
301 const gchar *action_name,
302 const gchar *action_description,
303 const gchar *action_keybinding,
304 ACTION_FUNC action_func)
307 g_return_val_if_fail (GAIL_IS_CELL (cell), FALSE);
308 info = g_new (ActionInfo, 1);
310 if (action_name != NULL)
311 info->name = g_strdup (action_name);
314 if (action_description != NULL)
315 info->description = g_strdup (action_description);
317 info->description = NULL;
318 if (action_keybinding != NULL)
319 info->keybinding = g_strdup (action_keybinding);
321 info->keybinding = NULL;
322 info->do_action_func = action_func;
324 cell->action_list = g_list_append (cell->action_list, (gpointer) info);
329 gail_cell_remove_action (GailCell *cell,
334 g_return_val_if_fail (GAIL_IS_CELL (cell), FALSE);
335 list_node = g_list_nth (cell->action_list, action_index);
338 _gail_cell_destroy_action_info (list_node->data, NULL);
339 cell->action_list = g_list_remove_link (cell->action_list, list_node);
345 gail_cell_remove_action_by_name (GailCell *cell,
346 const gchar *action_name)
349 gboolean action_found= FALSE;
351 g_return_val_if_fail (GAIL_IS_CELL (cell), FALSE);
352 for (list_node = cell->action_list; list_node && !action_found;
353 list_node = list_node->next)
355 if (!strcmp (((ActionInfo *)(list_node->data))->name, action_name))
363 _gail_cell_destroy_action_info (list_node->data, NULL);
364 cell->action_list = g_list_remove_link (cell->action_list, list_node);
369 _gail_cell_get_action_info (GailCell *cell,
374 g_return_val_if_fail (GAIL_IS_CELL (cell), NULL);
375 if (cell->action_list == NULL)
377 list_node = g_list_nth (cell->action_list, index);
380 return (ActionInfo *) (list_node->data);
385 _gail_cell_destroy_action_info (gpointer action_info,
388 ActionInfo *info = (ActionInfo *)action_info;
389 g_assert (info != NULL);
391 g_free (info->description);
392 g_free (info->keybinding);
396 gail_cell_action_get_n_actions (AtkAction *action)
398 GailCell *cell = GAIL_CELL(action);
399 if (cell->action_list != NULL)
400 return g_list_length (cell->action_list);
406 gail_cell_action_get_name (AtkAction *action,
409 GailCell *cell = GAIL_CELL(action);
410 ActionInfo *info = _gail_cell_get_action_info (cell, index);
418 gail_cell_action_get_description (AtkAction *action,
421 GailCell *cell = GAIL_CELL(action);
422 ActionInfo *info = _gail_cell_get_action_info (cell, index);
426 return info->description;
430 gail_cell_action_set_description (AtkAction *action,
434 GailCell *cell = GAIL_CELL(action);
435 ActionInfo *info = _gail_cell_get_action_info (cell, index);
439 g_free (info->description);
440 info->description = g_strdup (desc);
445 gail_cell_action_get_keybinding (AtkAction *action,
448 GailCell *cell = GAIL_CELL(action);
449 ActionInfo *info = _gail_cell_get_action_info (cell, index);
452 return info->keybinding;
456 gail_cell_action_do_action (AtkAction *action,
459 GailCell *cell = GAIL_CELL(action);
460 ActionInfo *info = _gail_cell_get_action_info (cell, index);
463 if (info->do_action_func == NULL)
465 if (cell->action_idle_handler)
467 cell->action_func = info->do_action_func;
468 cell->action_idle_handler = gdk_threads_add_idle (idle_do_action, cell);
473 idle_do_action (gpointer data)
477 cell = GAIL_CELL (data);
478 cell->action_idle_handler = 0;
479 cell->action_func (cell);
485 atk_component_interface_init (AtkComponentIface *iface)
487 iface->get_extents = gail_cell_get_extents;
488 iface->grab_focus = gail_cell_grab_focus;
492 gail_cell_get_extents (AtkComponent *component,
497 AtkCoordType coord_type)
500 AtkObject *cell_parent;
502 g_assert (GAIL_IS_CELL (component));
504 gailcell = GAIL_CELL (component);
506 cell_parent = gtk_widget_get_accessible (gailcell->widget);
508 gail_cell_parent_get_cell_extents (GAIL_CELL_PARENT (cell_parent),
509 gailcell, x, y, width, height, coord_type);
513 gail_cell_grab_focus (AtkComponent *component)
516 AtkObject *cell_parent;
518 g_assert (GAIL_IS_CELL (component));
520 gailcell = GAIL_CELL (component);
522 cell_parent = gtk_widget_get_accessible (gailcell->widget);
524 return gail_cell_parent_grab_focus (GAIL_CELL_PARENT (cell_parent),