1 /*
2  *
3  * This program is free software; you can redistribute it and/or modify it
4  * under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful, but
8  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
10  * for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public License
13  * along with this program; if not, see <http://www.gnu.org/licenses/>.
14  *
15  *
16  * Authors:
17  *		Eric Zhao <eric.zhao@sun.com>
18  *
19  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20  * Copyright (C) 2004 Sun Microsystem, Inc.
21  *
22  */
23 
24 #include "evolution-config.h"
25 
26 #include "gal-a11y-e-cell-vbox.h"
27 
28 #include <atk/atk.h>
29 
30 #include "e-cell-vbox.h"
31 #include "gal-a11y-e-cell-registry.h"
32 
33 static GObjectClass *parent_class;
34 static AtkComponentIface *component_parent_iface;
35 #define PARENT_TYPE (gal_a11y_e_cell_get_type ())
36 
37 static gint
ecv_get_n_children(AtkObject * a11y)38 ecv_get_n_children (AtkObject *a11y)
39 {
40 	g_return_val_if_fail (GAL_A11Y_IS_E_CELL_VBOX (a11y), 0);
41 
42 	return GAL_A11Y_E_CELL_VBOX (a11y)->a11y_subcell_count;
43 }
44 
45 static void
subcell_destroyed(gpointer data)46 subcell_destroyed (gpointer data)
47 {
48 	GalA11yECell *cell;
49 	AtkObject *parent;
50 	GalA11yECellVbox *gaev;
51 
52 	g_return_if_fail (GAL_A11Y_IS_E_CELL (data));
53 	cell = GAL_A11Y_E_CELL (data);
54 
55 	parent = atk_object_get_parent (ATK_OBJECT (cell));
56 	g_return_if_fail (GAL_A11Y_IS_E_CELL_VBOX (parent));
57 	gaev = GAL_A11Y_E_CELL_VBOX (parent);
58 
59 	if (cell->view_col < gaev->a11y_subcell_count)
60 		gaev->a11y_subcells[cell->view_col] = NULL;
61 }
62 
63 static AtkObject *
ecv_ref_child(AtkObject * a11y,gint i)64 ecv_ref_child (AtkObject *a11y,
65                gint i)
66 {
67 	GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (a11y);
68 	GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y);
69 	ECellVboxView *ecvv = (ECellVboxView *) (gaec->cell_view);
70 	AtkObject *ret;
71 	if (i < gaev->a11y_subcell_count) {
72 		if (gaev->a11y_subcells[i] == NULL) {
73 			ECellView *subcell_view;
74 			gint model_col, row;
75 			row = gaec->row;
76 			model_col = ecvv->model_cols[i];
77 			subcell_view = ecvv->subcell_views[i];
78 			/* FIXME Should the view column use a fake
79 			 *       one or the same as its parent? */
80 			ret = gal_a11y_e_cell_registry_get_object (
81 				NULL,
82 				gaec->item,
83 				subcell_view,
84 				a11y,
85 				model_col,
86 				gaec->view_col,
87 				row);
88 			gaev->a11y_subcells[i] = ret;
89 			g_object_ref (ret);
90 			g_object_weak_ref (
91 				G_OBJECT (ret),
92 				(GWeakNotify) subcell_destroyed,
93 				ret);
94 		} else {
95 			ret = (AtkObject *) gaev->a11y_subcells[i];
96 			if (ATK_IS_OBJECT (ret))
97 				g_object_ref (ret);
98 			else
99 				ret = NULL;
100 		}
101 	} else {
102 		ret = NULL;
103 	}
104 
105 	return ret;
106 }
107 
108 static void
ecv_dispose(GObject * object)109 ecv_dispose (GObject *object)
110 {
111 	GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (object);
112 	g_free (gaev->a11y_subcells);
113 
114 	if (parent_class->dispose)
115 		parent_class->dispose (object);
116 }
117 
118 /* AtkComponet interface */
119 static AtkObject *
ecv_ref_accessible_at_point(AtkComponent * component,gint x,gint y,AtkCoordType coord_type)120 ecv_ref_accessible_at_point (AtkComponent *component,
121                              gint x,
122                              gint y,
123                              AtkCoordType coord_type)
124 {
125 	gint x0, y0, width, height;
126 	gint subcell_height, i;
127 
128 	GalA11yECell *gaec = GAL_A11Y_E_CELL (component);
129 	ECellVboxView *ecvv = (ECellVboxView *) (gaec->cell_view);
130 
131 	atk_component_get_extents (component, &x0, &y0, &width, &height, coord_type);
132 	x -= x0;
133 	y -= y0;
134 	if (x < 0 || x > width || y < 0 || y > height)
135 		return NULL;
136 
137 	for (i = 0; i < ecvv->subcell_view_count; i++) {
138 		subcell_height = e_cell_height (
139 			ecvv->subcell_views[i], ecvv->model_cols[i],
140 			gaec->view_col, gaec->row);
141 		if (0 <= y && y <= subcell_height) {
142 			return ecv_ref_child ((AtkObject *) component, i);
143 		} else
144 			y -= subcell_height;
145 	}
146 
147 	return NULL;
148 }
149 
150 static void
ecv_class_init(GalA11yECellVboxClass * class)151 ecv_class_init (GalA11yECellVboxClass *class)
152 {
153 	GObjectClass *object_class = G_OBJECT_CLASS (class);
154 	AtkObjectClass *a11y_class = ATK_OBJECT_CLASS (class);
155 	parent_class = g_type_class_ref (PARENT_TYPE);
156 
157 	object_class->dispose = ecv_dispose;
158 
159 	a11y_class->get_n_children = ecv_get_n_children;
160 	a11y_class->ref_child = ecv_ref_child;
161 }
162 
163 static void
ecv_init(GalA11yECellVbox * a11y)164 ecv_init (GalA11yECellVbox *a11y)
165 {
166 }
167 
168 static void
ecv_atk_component_iface_init(AtkComponentIface * iface)169 ecv_atk_component_iface_init (AtkComponentIface *iface)
170 {
171 	component_parent_iface = g_type_interface_peek_parent (iface);
172 
173 	iface->ref_accessible_at_point = ecv_ref_accessible_at_point;
174 }
175 
176 GType
gal_a11y_e_cell_vbox_get_type(void)177 gal_a11y_e_cell_vbox_get_type (void)
178 {
179 	static GType type = 0;
180 	if (!type) {
181 		GTypeInfo info = {
182 			sizeof (GalA11yECellVboxClass),
183 			(GBaseInitFunc) NULL,
184 			(GBaseFinalizeFunc) NULL,
185 			(GClassInitFunc) ecv_class_init,
186 			(GClassFinalizeFunc) NULL,
187 			NULL, /* class_data */
188 			sizeof (GalA11yECellVbox),
189 			0,
190 			(GInstanceInitFunc) ecv_init,
191 			NULL /* value_cell */
192 		};
193 
194 		static const GInterfaceInfo atk_component_info = {
195 			(GInterfaceInitFunc) ecv_atk_component_iface_init,
196 			(GInterfaceFinalizeFunc) NULL,
197 			NULL
198 		};
199 
200 		type = g_type_register_static (PARENT_TYPE, "GalA11yECellVbox", &info, 0);
201 		gal_a11y_e_cell_type_add_action_interface (type);
202 		g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info);
203 	}
204 
205 	return type;
206 }
207 
gal_a11y_e_cell_vbox_new(ETableItem * item,ECellView * cell_view,AtkObject * parent,gint model_col,gint view_col,gint row)208 AtkObject *gal_a11y_e_cell_vbox_new	(ETableItem *item,
209 					 ECellView  *cell_view,
210 					 AtkObject  *parent,
211 					 gint         model_col,
212 					 gint         view_col,
213 					 gint         row)
214 {
215 	AtkObject *a11y;
216 	GalA11yECell *gaec;
217 	GalA11yECellVbox *gaev;
218 	ECellVboxView *ecvv;
219 
220 	a11y = g_object_new (gal_a11y_e_cell_vbox_get_type (), NULL);
221 
222 	gal_a11y_e_cell_construct (
223 		a11y, item, cell_view, parent, model_col, view_col, row);
224 
225 	gaec = GAL_A11Y_E_CELL (a11y);
226 	gaev = GAL_A11Y_E_CELL_VBOX (a11y);
227 	ecvv = (ECellVboxView *) (gaec->cell_view);
228 	gaev->a11y_subcell_count = ecvv->subcell_view_count;
229 	gaev->a11y_subcells = g_malloc0 (sizeof (AtkObject *) * gaev->a11y_subcell_count);
230 	return a11y;
231 }
232