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