/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Authors: * Christopher James Lahey * * Copyright (C) 2002 Ximian, Inc. */ #include #include "gal/e-table/e-table.h" #include "gal-a11y-e-cell.h" #include "gal-a11y-util.h" #include #include #include #define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellClass)) static GObjectClass *parent_class; #define PARENT_TYPE (atk_object_get_type ()) #if 0 static void unref_item (gpointer user_data, GObject *obj_loc) { GalA11yECell *a11y = GAL_A11Y_E_CELL (user_data); a11y->item = NULL; g_object_unref (a11y); } static void unref_cell (gpointer user_data, GObject *obj_loc) { GalA11yECell *a11y = GAL_A11Y_E_CELL (user_data); a11y->cell_view = NULL; g_object_unref (a11y); } #endif static void eti_dispose (GObject *object) { GalA11yECell *a11y = GAL_A11Y_E_CELL (object); #if 0 if (a11y->item) g_object_unref (G_OBJECT (a11y->item)); /*, unref_item, a11y); */ if (a11y->cell_view) g_object_unref (G_OBJECT (a11y->cell_view)); /*, unref_cell, a11y); */ if (a11y->parent) g_object_unref (a11y->parent); #endif a11y->item = NULL; a11y->cell_view = NULL; a11y->parent = NULL; a11y->model_col = -1; a11y->view_col = -1; a11y->row = -1; if (a11y->state_set) g_object_unref (a11y->state_set); if (parent_class->dispose) parent_class->dispose (object); } /* Static functions */ static AtkStateSet * eti_ref_state_set (AtkObject *accessible) { GalA11yECell *cell = GAL_A11Y_E_CELL (accessible); g_return_val_if_fail (cell->state_set, NULL); g_object_ref(cell->state_set); return cell->state_set; } static AtkObject* eti_get_parent (AtkObject *accessible) { GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible); return a11y->parent; } static gint eti_get_index_in_parent (AtkObject *accessible) { GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible); return a11y->row * a11y->item->cols + a11y->view_col; } /* Component IFace */ static void eti_get_extents (AtkComponent *component, gint *x, gint *y, gint *width, gint *height, AtkCoordType coord_type) { GalA11yECell *a11y = GAL_A11Y_E_CELL (component); int row; int col; int xval; int yval; row = a11y->row; col = a11y->view_col; e_table_item_get_cell_geometry (a11y->item, &row, &col, &xval, &yval, width, height); atk_component_get_position (ATK_COMPONENT (a11y->parent), x, y, coord_type); if (x && *x != G_MININT) *x += xval; if (y && *y != G_MININT) *y += yval; } static gboolean eti_grab_focus (AtkComponent *component) { GalA11yECell *a11y; gint view_row; GtkWidget *e_table, *toplevel; a11y = GAL_A11Y_E_CELL (component); e_table = gtk_widget_get_parent (GNOME_CANVAS_ITEM (a11y->item)->canvas); view_row = e_table_view_to_model_row (E_TABLE (e_table), a11y->row); e_selection_model_clear (a11y->item->selection); e_selection_model_select_single_row (a11y->item->selection, view_row); gtk_widget_grab_focus (e_table); toplevel = gtk_widget_get_toplevel (e_table); if (GTK_WIDGET_TOPLEVEL (toplevel)) gtk_window_present (toplevel); } /* Table IFace */ static void eti_atk_component_iface_init (AtkComponentIface *iface) { iface->get_extents = eti_get_extents; iface->grab_focus = eti_grab_focus; } static void eti_class_init (GalA11yECellClass *klass) { AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_ref (PARENT_TYPE); object_class->dispose = eti_dispose; atk_object_class->get_parent = eti_get_parent; atk_object_class->get_index_in_parent = eti_get_index_in_parent; atk_object_class->ref_state_set = eti_ref_state_set; } static void eti_init (GalA11yECell *a11y) { a11y->item = NULL; a11y->cell_view = NULL; a11y->parent = NULL; a11y->model_col = -1; a11y->view_col = -1; a11y->row = -1; a11y->state_set = atk_state_set_new (); atk_state_set_add_state (a11y->state_set, ATK_STATE_TRANSIENT); atk_state_set_add_state (a11y->state_set, ATK_STATE_ENABLED); } static ActionInfo * _gal_a11y_e_cell_get_action_info (GalA11yECell *cell, gint index) { GList *list_node; g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), NULL); if (cell->action_list == NULL) return NULL; list_node = g_list_nth (cell->action_list, index); if (!list_node) return NULL; return (ActionInfo *) (list_node->data); } static void _gal_a11y_e_cell_destroy_action_info (gpointer action_info, gpointer user_data) { ActionInfo *info = (ActionInfo *)action_info; g_return_if_fail (info != NULL); g_free (info->name); g_free (info->description); g_free (info->keybinding); g_free (info); } gboolean gal_a11y_e_cell_add_action ( GalA11yECell * cell, const gchar *action_name, const gchar *action_description, const gchar *action_keybinding, ACTION_FUNC action_func) { ActionInfo *info; g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE); info = g_new (ActionInfo, 1); if (action_name != NULL) info->name = g_strdup (action_name); else info->name = NULL; if (action_description != NULL) info->description = g_strdup (action_description); else info->description = NULL; if (action_keybinding != NULL) info->keybinding = g_strdup (action_keybinding); else info->keybinding = NULL; info->do_action_func = action_func; cell->action_list = g_list_append (cell->action_list, (gpointer) info); return TRUE; } gboolean gal_a11y_e_cell_remove_action (GalA11yECell *cell, gint action_index) { GList *list_node; g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE); list_node = g_list_nth (cell->action_list, action_index); if (!list_node) return FALSE; g_return_val_if_fail (list_node->data != NULL, FALSE); _gal_a11y_e_cell_destroy_action_info (list_node->data, NULL); cell->action_list = g_list_remove_link (cell->action_list, list_node); return TRUE; } gboolean gal_a11y_e_cell_remove_action_by_name (GalA11yECell *cell, const gchar *action_name) { GList *list_node; gboolean action_found= FALSE; g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE); for (list_node = cell->action_list; list_node && !action_found; list_node = list_node->next) { if (!g_strcasecmp (((ActionInfo *)(list_node->data))->name, action_name)) { action_found = TRUE; break; } } g_return_val_if_fail (action_found, FALSE); _gal_a11y_e_cell_destroy_action_info (list_node->data, NULL); cell->action_list = g_list_remove_link (cell->action_list, list_node); return TRUE; } static gint gal_a11y_e_cell_action_get_n_actions (AtkAction *action) { GalA11yECell *cell = GAL_A11Y_E_CELL(action); if (cell->action_list != NULL) return g_list_length (cell->action_list); else return 0; } static G_CONST_RETURN gchar * gal_a11y_e_cell_action_get_name (AtkAction *action, gint index) { GalA11yECell *cell = GAL_A11Y_E_CELL(action); ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); if (info == NULL) return NULL; return info->name; } static G_CONST_RETURN gchar * gal_a11y_e_cell_action_get_description (AtkAction *action, gint index) { GalA11yECell *cell = GAL_A11Y_E_CELL(action); ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); if (info == NULL) return NULL; return info->description; } static gboolean gal_a11y_e_cell_action_set_description (AtkAction *action, gint index, const gchar *desc) { GalA11yECell *cell = GAL_A11Y_E_CELL(action); ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); if (info == NULL) return FALSE; g_free (info->description); info->description = g_strdup (desc); return TRUE; } static G_CONST_RETURN gchar * gal_a11y_e_cell_action_get_keybinding (AtkAction *action, gint index) { GalA11yECell *cell = GAL_A11Y_E_CELL(action); ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); if (info == NULL) return NULL; return info->keybinding; } static gboolean idle_do_action (gpointer data) { GalA11yECell *cell; cell = GAL_A11Y_E_CELL (data); cell->action_idle_handler = 0; cell->action_func (cell); return FALSE; } static gboolean gal_a11y_e_cell_action_do_action (AtkAction *action, gint index) { GalA11yECell *cell = GAL_A11Y_E_CELL(action); ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); if (info == NULL) return FALSE; g_return_val_if_fail (info->do_action_func, FALSE); if (cell->action_idle_handler) return FALSE; cell->action_func = info->do_action_func; cell->action_idle_handler = g_idle_add (idle_do_action, cell); return TRUE; } static void gal_a11y_e_cell_atk_action_interface_init (AtkActionIface *iface) { g_return_if_fail (iface != NULL); iface->get_n_actions = gal_a11y_e_cell_action_get_n_actions; iface->do_action = gal_a11y_e_cell_action_do_action; iface->get_name = gal_a11y_e_cell_action_get_name; iface->get_description = gal_a11y_e_cell_action_get_description; iface->set_description = gal_a11y_e_cell_action_set_description; iface->get_keybinding = gal_a11y_e_cell_action_get_keybinding; } void gal_a11y_e_cell_type_add_action_interface (GType type) { static const GInterfaceInfo atk_action_info = { (GInterfaceInitFunc) gal_a11y_e_cell_atk_action_interface_init, (GInterfaceFinalizeFunc) NULL, NULL }; g_type_add_interface_static (type, ATK_TYPE_ACTION, &atk_action_info); } gboolean gal_a11y_e_cell_add_state (GalA11yECell *cell, AtkStateType state_type, gboolean emit_signal) { if (!atk_state_set_contains_state (cell->state_set, state_type)) { gboolean rc; rc = atk_state_set_add_state (cell->state_set, state_type); /* * The signal should only be generated if the value changed, * not when the cell is set up. So states that are set * initially should pass FALSE as the emit_signal argument. */ if (emit_signal) { atk_object_notify_state_change (ATK_OBJECT (cell), state_type, TRUE); /* If state_type is ATK_STATE_VISIBLE, additional notification */ if (state_type == ATK_STATE_VISIBLE) g_signal_emit_by_name (cell, "visible_data_changed"); } return rc; } else return FALSE; } gboolean gal_a11y_e_cell_remove_state (GalA11yECell *cell, AtkStateType state_type, gboolean emit_signal) { if (atk_state_set_contains_state (cell->state_set, state_type)) { gboolean rc; rc = atk_state_set_remove_state (cell->state_set, state_type); /* * The signal should only be generated if the value changed, * not when the cell is set up. So states that are set * initially should pass FALSE as the emit_signal argument. */ if (emit_signal) { atk_object_notify_state_change (ATK_OBJECT (cell), state_type, FALSE); /* If state_type is ATK_STATE_VISIBLE, additional notification */ if (state_type == ATK_STATE_VISIBLE) g_signal_emit_by_name (cell, "visible_data_changed"); } return rc; } else return FALSE; } /** * gal_a11y_e_cell_get_type: * @void: * * Registers the &GalA11yECell class if necessary, and returns the type ID * associated to it. * * Return value: The type ID of the &GalA11yECell class. **/ GType gal_a11y_e_cell_get_type (void) { static GType type = 0; if (!type) { GTypeInfo info = { sizeof (GalA11yECellClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) eti_class_init, (GClassFinalizeFunc) NULL, NULL, /* class_data */ sizeof (GalA11yECell), 0, (GInstanceInitFunc) eti_init, NULL /* value_cell */ }; static const GInterfaceInfo atk_component_info = { (GInterfaceInitFunc) eti_atk_component_iface_init, (GInterfaceFinalizeFunc) NULL, NULL }; type = g_type_register_static (PARENT_TYPE, "GalA11yECell", &info, 0); g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); } return type; } AtkObject * gal_a11y_e_cell_new (ETableItem *item, ECellView *cell_view, AtkObject *parent, int model_col, int view_col, int row) { AtkObject *a11y; a11y = g_object_new (gal_a11y_e_cell_get_type (), NULL); gal_a11y_e_cell_construct (a11y, item, cell_view, parent, model_col, view_col, row); return a11y; } void gal_a11y_e_cell_construct (AtkObject *object, ETableItem *item, ECellView *cell_view, AtkObject *parent, int model_col, int view_col, int row) { GalA11yECell *a11y = GAL_A11Y_E_CELL (object); a11y->item = item; a11y->cell_view = cell_view; a11y->parent = parent; a11y->model_col = model_col; a11y->view_col = view_col; a11y->row = row; ATK_OBJECT (a11y) ->role = ATK_ROLE_TABLE_CELL; #if 0 if (parent) g_object_ref (parent); if (item) g_object_ref (G_OBJECT (item)); /*, unref_item, a11y);*/ if (cell_view) g_object_ref (G_OBJECT (cell_view)); /*, unref_cell, a11y);*/ #endif }