evolution-3.6.4/widgets/table/gal-a11y-e-cell-tree.c

No issues found

  1 /*
  2  * This program is free software; you can redistribute it and/or
  3  * modify it under the terms of the GNU Lesser General Public
  4  * License as published by the Free Software Foundation; either
  5  * version 2 of the License, or (at your option) version 3.
  6  *
  7  * This program is distributed in the hope that it will be useful,
  8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 10  * Lesser General Public License for more details.
 11  *
 12  * You should have received a copy of the GNU Lesser General Public
 13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 14  *
 15  *
 16  * Authors:
 17  *		Tim Wo <tim.wo@sun.com>
 18  *
 19  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 20  *
 21  */
 22 
 23 #ifdef HAVE_CONFIG_H
 24 #include <config.h>
 25 #endif
 26 
 27 #include <atk/atk.h>
 28 
 29 #include "a11y/gal-a11y-util.h"
 30 #include "table/e-cell-tree.h"
 31 #include "table/e-table.h"
 32 #include "table/e-tree-table-adapter.h"
 33 #include <glib/gi18n.h>
 34 
 35 #include "gal-a11y-e-cell-tree.h"
 36 #include "gal-a11y-e-cell-registry.h"
 37 
 38 #define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellTreeClass))
 39 static AtkObjectClass *a11y_parent_class;
 40 #define A11Y_PARENT_TYPE (gal_a11y_e_cell_get_type ())
 41 
 42 #define d(x)
 43 
 44 static void
 45 ectr_model_row_changed_cb (ETableModel *etm,
 46                            gint row,
 47                            GalA11yECell *a11y)
 48 {
 49 	ETreePath node;
 50 	ETreeModel *tree_model;
 51 	ETreeTableAdapter *tree_table_adapter;
 52 
 53 	g_return_if_fail (a11y);
 54 	if (a11y->row != row)
 55 		return;
 56 
 57 	node = e_table_model_value_at (etm, -1, a11y->row);
 58 	tree_model = e_table_model_value_at (etm, -2, a11y->row);
 59 	tree_table_adapter = e_table_model_value_at (etm, -3, a11y->row);
 60 
 61 	if (e_tree_model_node_is_expandable (tree_model, node)) {
 62 		gboolean is_exp = e_tree_table_adapter_node_is_expanded (tree_table_adapter, node);
 63 		if (is_exp)
 64 			gal_a11y_e_cell_add_state (a11y, ATK_STATE_EXPANDED, TRUE);
 65 		else
 66 			gal_a11y_e_cell_remove_state (a11y, ATK_STATE_EXPANDED, TRUE);
 67 	}
 68 }
 69 
 70 static void
 71 kill_view_cb (ECellView *subcell_view,
 72              gpointer psubcell_a11ies)
 73 {
 74 	GList *node;
 75 	GList *subcell_a11ies = (GList *) psubcell_a11ies;
 76 	GalA11yECell *subcell;
 77 
 78 	for (node = subcell_a11ies; node != NULL; node = g_list_next (node))
 79 	{
 80 	    subcell = GAL_A11Y_E_CELL (node->data);
 81 	    if (subcell && subcell->cell_view == subcell_view)
 82 	    {
 83 		d (fprintf (stderr, "subcell_view %p deleted before the a11y object %p\n", subcell_view, subcell));
 84 		subcell->cell_view = NULL;
 85 	    }
 86 	}
 87 }
 88 
 89 static void
 90 ectr_subcell_weak_ref (GalA11yECellTree *a11y,
 91                        GalA11yECell *subcell_a11y)
 92 {
 93 	ECellView *subcell_view = subcell_a11y ? subcell_a11y->cell_view : NULL;
 94 	if (subcell_a11y && subcell_view && subcell_view->kill_view_cb_data)
 95 	    subcell_view->kill_view_cb_data = g_list_remove (subcell_view->kill_view_cb_data, subcell_a11y);
 96 
 97 	g_signal_handler_disconnect (
 98 		GAL_A11Y_E_CELL (a11y)->item->table_model,
 99 		a11y->model_row_changed_id);
100 	g_object_unref (a11y);
101 }
102 
103 static void
104 ectr_do_action_expand (AtkAction *action)
105 {
106 	GalA11yECell *a11y;
107 	ETableModel *table_model;
108 	ETreePath node;
109 	ETreeModel *tree_model;
110 	ETreeTableAdapter *tree_table_adapter;
111 
112 	a11y = GAL_A11Y_E_CELL (action);
113 	table_model = a11y->item->table_model;
114 	node = e_table_model_value_at (table_model, -1, a11y->row);
115 	tree_model = e_table_model_value_at (table_model, -2, a11y->row);
116 	tree_table_adapter = e_table_model_value_at (table_model, -3, a11y->row);
117 
118 	if (e_tree_model_node_is_expandable (tree_model, node)) {
119 		e_tree_table_adapter_node_set_expanded (
120 			tree_table_adapter, node, TRUE);
121 		gal_a11y_e_cell_add_state (a11y, ATK_STATE_EXPANDED, TRUE);
122 	}
123 }
124 
125 static void
126 ectr_do_action_collapse (AtkAction *action)
127 {
128 	GalA11yECell *a11y;
129 	ETableModel *table_model;
130 	ETreePath node;
131 	ETreeModel *tree_model;
132 	ETreeTableAdapter *tree_table_adapter;
133 
134 	a11y = GAL_A11Y_E_CELL (action);
135 	table_model = a11y->item->table_model;
136 	node = e_table_model_value_at (table_model, -1, a11y->row);
137 	tree_model = e_table_model_value_at (table_model, -2, a11y->row);
138 	tree_table_adapter = e_table_model_value_at (table_model, -3, a11y->row);
139 
140 	if (e_tree_model_node_is_expandable (tree_model, node)) {
141 		e_tree_table_adapter_node_set_expanded (
142 			tree_table_adapter, node, FALSE);
143 		gal_a11y_e_cell_remove_state (a11y, ATK_STATE_EXPANDED, TRUE);
144 	}
145 }
146 
147 static void
148 ectr_class_init (GalA11yECellTreeClass *class)
149 {
150 	a11y_parent_class        = g_type_class_ref (A11Y_PARENT_TYPE);
151 }
152 
153 static void
154 ectr_init (GalA11yECellTree *a11y)
155 {
156 }
157 
158 GType
159 gal_a11y_e_cell_tree_get_type (void)
160 {
161 	static GType type = 0;
162 
163 	if (!type) {
164 		GTypeInfo info = {
165 			sizeof (GalA11yECellTreeClass),
166 			(GBaseInitFunc) NULL,
167 			(GBaseFinalizeFunc) NULL,
168 			(GClassInitFunc) ectr_class_init,
169 			(GClassFinalizeFunc) NULL,
170 			NULL, /* class_data */
171 			sizeof (GalA11yECellTree),
172 			0,
173 			(GInstanceInitFunc) ectr_init,
174 			NULL /* value_cell_text */
175 		};
176 
177 		type = g_type_register_static (A11Y_PARENT_TYPE, "GalA11yECellTree", &info, 0);
178 		gal_a11y_e_cell_type_add_action_interface (type);
179 	}
180 
181 	return type;
182 }
183 
184 AtkObject *
185 gal_a11y_e_cell_tree_new (ETableItem *item,
186                           ECellView *cell_view,
187                           AtkObject *parent,
188                           gint model_col,
189                           gint view_col,
190                           gint row)
191 {
192 	AtkObject *subcell_a11y;
193 	GalA11yECellTree *a11y;
194 
195 	ETreePath node;
196 	ETreeModel *tree_model;
197 	ETreeTableAdapter *tree_table_adapter;
198 
199 	ECellView *subcell_view;
200 	subcell_view = e_cell_tree_view_get_subcell_view (cell_view);
201 
202 	if (subcell_view->ecell) {
203 		subcell_a11y = gal_a11y_e_cell_registry_get_object (
204 			NULL,
205 			item,
206 			subcell_view,
207 			parent,
208 			model_col,
209 			view_col,
210 			row);
211 		gal_a11y_e_cell_add_action (
212 			GAL_A11Y_E_CELL (subcell_a11y),
213 			"expand",
214 			/* Translators: description of an "expand" action */
215 			_("expands the row in the ETree containing this cell"),
216 			NULL,
217 			(ACTION_FUNC) ectr_do_action_expand);
218 
219 		gal_a11y_e_cell_add_action (
220 			GAL_A11Y_E_CELL (subcell_a11y),
221 			"collapse",
222 			/* Translators: description of a "collapse" action */
223 			_("collapses the row in the ETree containing this cell"),
224 			NULL,
225 			(ACTION_FUNC) ectr_do_action_collapse);
226 
227 		/* init AtkStates for the cell's a11y object */
228 		node = e_table_model_value_at (item->table_model, -1, row);
229 		tree_model = e_table_model_value_at (item->table_model, -2, row);
230 		tree_table_adapter = e_table_model_value_at (item->table_model, -3, row);
231 		if (e_tree_model_node_is_expandable (tree_model, node)) {
232 			gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (subcell_a11y), ATK_STATE_EXPANDABLE, FALSE);
233 			if (e_tree_table_adapter_node_is_expanded (tree_table_adapter, node))
234 				gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (subcell_a11y), ATK_STATE_EXPANDED, FALSE);
235 		}
236 	}
237 	else
238 		subcell_a11y = NULL;
239 
240 	/* create a companion a11y object, this object has type GalA11yECellTree
241 	 * and it connects to some signals to determine whether a tree cell is
242 	 * expanded or collapsed */
243 	a11y = g_object_new (gal_a11y_e_cell_tree_get_type (), NULL);
244 	gal_a11y_e_cell_construct (
245 		ATK_OBJECT (a11y),
246 		item,
247 		cell_view,
248 		parent,
249 		model_col,
250 		view_col,
251 		row);
252 	a11y->model_row_changed_id = g_signal_connect (
253 		item->table_model, "model_row_changed",
254 		G_CALLBACK (ectr_model_row_changed_cb), subcell_a11y);
255 
256 	if (subcell_a11y && subcell_view)
257 	{
258 	    subcell_view->kill_view_cb = kill_view_cb;
259 	    if (!g_list_find (subcell_view->kill_view_cb_data, subcell_a11y))
260 		subcell_view->kill_view_cb_data = g_list_append (subcell_view->kill_view_cb_data, subcell_a11y);
261 	}
262 
263 	g_object_weak_ref (G_OBJECT (subcell_a11y), (GWeakNotify) ectr_subcell_weak_ref, a11y);
264 
265 	return subcell_a11y;
266 }