1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 et sw=2 tw=80: */
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Sun Microsystems, Inc.
20 : * Portions created by the Initial Developer are Copyright (C) 2002
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Bolian Yin (bolian.yin@sun.com)
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "nsMaiInterfaceTable.h"
41 :
42 : #include "nsAccUtils.h"
43 :
44 : #include "nsArrayUtils.h"
45 :
46 : void
47 0 : tableInterfaceInitCB(AtkTableIface *aIface)
48 :
49 : {
50 0 : g_return_if_fail(aIface != NULL);
51 :
52 0 : aIface->ref_at = refAtCB;
53 0 : aIface->get_index_at = getIndexAtCB;
54 0 : aIface->get_column_at_index = getColumnAtIndexCB;
55 0 : aIface->get_row_at_index = getRowAtIndexCB;
56 0 : aIface->get_n_columns = getColumnCountCB;
57 0 : aIface->get_n_rows = getRowCountCB;
58 0 : aIface->get_column_extent_at = getColumnExtentAtCB;
59 0 : aIface->get_row_extent_at = getRowExtentAtCB;
60 0 : aIface->get_caption = getCaptionCB;
61 0 : aIface->get_column_description = getColumnDescriptionCB;
62 0 : aIface->get_column_header = getColumnHeaderCB;
63 0 : aIface->get_row_description = getRowDescriptionCB;
64 0 : aIface->get_row_header = getRowHeaderCB;
65 0 : aIface->get_summary = getSummaryCB;
66 0 : aIface->get_selected_columns = getSelectedColumnsCB;
67 0 : aIface->get_selected_rows = getSelectedRowsCB;
68 0 : aIface->is_column_selected = isColumnSelectedCB;
69 0 : aIface->is_row_selected = isRowSelectedCB;
70 0 : aIface->is_selected = isCellSelectedCB;
71 : }
72 :
73 : /* static */
74 : AtkObject*
75 0 : refAtCB(AtkTable *aTable, gint aRow, gint aColumn)
76 : {
77 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
78 0 : if (!accWrap)
79 0 : return nsnull;
80 :
81 0 : nsCOMPtr<nsIAccessibleTable> accTable;
82 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
83 0 : getter_AddRefs(accTable));
84 0 : NS_ENSURE_TRUE(accTable, nsnull);
85 :
86 0 : nsCOMPtr<nsIAccessible> cell;
87 0 : nsresult rv = accTable->GetCellAt(aRow, aColumn,getter_AddRefs(cell));
88 0 : if (NS_FAILED(rv) || !cell)
89 0 : return nsnull;
90 :
91 0 : AtkObject *cellAtkObj = nsAccessibleWrap::GetAtkObject(cell);
92 0 : if (cellAtkObj) {
93 0 : g_object_ref(cellAtkObj);
94 : }
95 0 : return cellAtkObj;
96 : }
97 :
98 : gint
99 0 : getIndexAtCB(AtkTable *aTable, gint aRow, gint aColumn)
100 : {
101 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
102 0 : if (!accWrap)
103 0 : return -1;
104 :
105 0 : nsCOMPtr<nsIAccessibleTable> accTable;
106 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
107 0 : getter_AddRefs(accTable));
108 0 : NS_ENSURE_TRUE(accTable, -1);
109 :
110 : PRInt32 index;
111 0 : nsresult rv = accTable->GetCellIndexAt(aRow, aColumn, &index);
112 0 : NS_ENSURE_SUCCESS(rv, -1);
113 :
114 0 : return static_cast<gint>(index);
115 : }
116 :
117 : gint
118 0 : getColumnAtIndexCB(AtkTable *aTable, gint aIndex)
119 : {
120 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
121 0 : if (!accWrap)
122 0 : return -1;
123 :
124 0 : nsCOMPtr<nsIAccessibleTable> accTable;
125 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
126 0 : getter_AddRefs(accTable));
127 0 : NS_ENSURE_TRUE(accTable, -1);
128 :
129 : PRInt32 col;
130 0 : nsresult rv = accTable->GetColumnIndexAt(aIndex, &col);
131 0 : NS_ENSURE_SUCCESS(rv, -1);
132 :
133 0 : return static_cast<gint>(col);
134 : }
135 :
136 : gint
137 0 : getRowAtIndexCB(AtkTable *aTable, gint aIndex)
138 : {
139 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
140 0 : if (!accWrap)
141 0 : return -1;
142 :
143 0 : nsCOMPtr<nsIAccessibleTable> accTable;
144 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
145 0 : getter_AddRefs(accTable));
146 0 : NS_ENSURE_TRUE(accTable, -1);
147 :
148 : PRInt32 row;
149 0 : nsresult rv = accTable->GetRowIndexAt(aIndex, &row);
150 0 : NS_ENSURE_SUCCESS(rv, -1);
151 :
152 0 : return static_cast<gint>(row);
153 : }
154 :
155 : gint
156 0 : getColumnCountCB(AtkTable *aTable)
157 : {
158 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
159 0 : if (!accWrap)
160 0 : return -1;
161 :
162 0 : nsCOMPtr<nsIAccessibleTable> accTable;
163 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
164 0 : getter_AddRefs(accTable));
165 0 : NS_ENSURE_TRUE(accTable, -1);
166 :
167 : PRInt32 count;
168 0 : nsresult rv = accTable->GetColumnCount(&count);
169 0 : NS_ENSURE_SUCCESS(rv, -1);
170 :
171 0 : return static_cast<gint>(count);
172 : }
173 :
174 : gint
175 0 : getRowCountCB(AtkTable *aTable)
176 : {
177 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
178 0 : if (!accWrap)
179 0 : return -1;
180 :
181 0 : nsCOMPtr<nsIAccessibleTable> accTable;
182 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
183 0 : getter_AddRefs(accTable));
184 0 : NS_ENSURE_TRUE(accTable, -1);
185 :
186 : PRInt32 count;
187 0 : nsresult rv = accTable->GetRowCount(&count);
188 0 : NS_ENSURE_SUCCESS(rv, -1);
189 :
190 0 : return static_cast<gint>(count);
191 : }
192 :
193 : gint
194 0 : getColumnExtentAtCB(AtkTable *aTable,
195 : gint aRow, gint aColumn)
196 : {
197 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
198 0 : if (!accWrap)
199 0 : return -1;
200 :
201 0 : nsCOMPtr<nsIAccessibleTable> accTable;
202 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
203 0 : getter_AddRefs(accTable));
204 0 : NS_ENSURE_TRUE(accTable, -1);
205 :
206 : PRInt32 extent;
207 0 : nsresult rv = accTable->GetColumnExtentAt(aRow, aColumn, &extent);
208 0 : NS_ENSURE_SUCCESS(rv, -1);
209 :
210 0 : return static_cast<gint>(extent);
211 : }
212 :
213 : gint
214 0 : getRowExtentAtCB(AtkTable *aTable,
215 : gint aRow, gint aColumn)
216 : {
217 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
218 0 : if (!accWrap)
219 0 : return -1;
220 :
221 0 : nsCOMPtr<nsIAccessibleTable> accTable;
222 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
223 0 : getter_AddRefs(accTable));
224 0 : NS_ENSURE_TRUE(accTable, -1);
225 :
226 : PRInt32 extent;
227 0 : nsresult rv = accTable->GetRowExtentAt(aRow, aColumn, &extent);
228 0 : NS_ENSURE_SUCCESS(rv, -1);
229 :
230 0 : return static_cast<gint>(extent);
231 : }
232 :
233 : AtkObject*
234 0 : getCaptionCB(AtkTable *aTable)
235 : {
236 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
237 0 : if (!accWrap)
238 0 : return nsnull;
239 :
240 0 : nsCOMPtr<nsIAccessibleTable> accTable;
241 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
242 0 : getter_AddRefs(accTable));
243 0 : NS_ENSURE_TRUE(accTable, nsnull);
244 :
245 0 : nsCOMPtr<nsIAccessible> caption;
246 0 : nsresult rv = accTable->GetCaption(getter_AddRefs(caption));
247 0 : if (NS_FAILED(rv) || !caption)
248 0 : return nsnull;
249 :
250 0 : return nsAccessibleWrap::GetAtkObject(caption);
251 : }
252 :
253 : const gchar*
254 0 : getColumnDescriptionCB(AtkTable *aTable, gint aColumn)
255 : {
256 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
257 0 : if (!accWrap)
258 0 : return nsnull;
259 :
260 0 : nsCOMPtr<nsIAccessibleTable> accTable;
261 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
262 0 : getter_AddRefs(accTable));
263 0 : NS_ENSURE_TRUE(accTable, nsnull);
264 :
265 0 : nsAutoString autoStr;
266 0 : nsresult rv = accTable->GetColumnDescription(aColumn, autoStr);
267 0 : NS_ENSURE_SUCCESS(rv, nsnull);
268 :
269 0 : return nsAccessibleWrap::ReturnString(autoStr);
270 : }
271 :
272 : AtkObject*
273 0 : getColumnHeaderCB(AtkTable *aTable, gint aColumn)
274 : {
275 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
276 0 : if (!accWrap)
277 0 : return nsnull;
278 :
279 0 : nsCOMPtr<nsIAccessibleTable> accTable;
280 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
281 0 : getter_AddRefs(accTable));
282 0 : NS_ENSURE_TRUE(accTable, nsnull);
283 :
284 0 : nsCOMPtr<nsIAccessible> accCell;
285 0 : accTable->GetCellAt(0, aColumn, getter_AddRefs(accCell));
286 0 : if (!accCell)
287 0 : return nsnull;
288 :
289 : // If the cell at the first row is column header then assume it is column
290 : // header for all rows,
291 0 : if (nsAccUtils::Role(accCell) == nsIAccessibleRole::ROLE_COLUMNHEADER)
292 0 : return nsAccessibleWrap::GetAtkObject(accCell);
293 :
294 : // otherwise get column header for the data cell at the first row.
295 : nsCOMPtr<nsIAccessibleTableCell> accTableCell =
296 0 : do_QueryInterface(accCell);
297 :
298 0 : if (accTableCell) {
299 0 : nsCOMPtr<nsIArray> headerCells;
300 0 : accTableCell->GetColumnHeaderCells(getter_AddRefs(headerCells));
301 0 : if (headerCells) {
302 : nsresult rv;
303 : nsCOMPtr<nsIAccessible> accHeaderCell =
304 0 : do_QueryElementAt(headerCells, 0, &rv);
305 0 : NS_ENSURE_SUCCESS(rv, nsnull);
306 :
307 0 : return nsAccessibleWrap::GetAtkObject(accHeaderCell);
308 : }
309 : }
310 :
311 0 : return nsnull;
312 : }
313 :
314 : const gchar*
315 0 : getRowDescriptionCB(AtkTable *aTable, gint aRow)
316 : {
317 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
318 0 : if (!accWrap)
319 0 : return nsnull;
320 :
321 0 : nsCOMPtr<nsIAccessibleTable> accTable;
322 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
323 0 : getter_AddRefs(accTable));
324 0 : NS_ENSURE_TRUE(accTable, nsnull);
325 :
326 0 : nsAutoString autoStr;
327 0 : nsresult rv = accTable->GetRowDescription(aRow, autoStr);
328 0 : NS_ENSURE_SUCCESS(rv, nsnull);
329 :
330 0 : return nsAccessibleWrap::ReturnString(autoStr);
331 : }
332 :
333 : AtkObject*
334 0 : getRowHeaderCB(AtkTable *aTable, gint aRow)
335 : {
336 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
337 0 : if (!accWrap)
338 0 : return nsnull;
339 :
340 0 : nsCOMPtr<nsIAccessibleTable> accTable;
341 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
342 0 : getter_AddRefs(accTable));
343 0 : NS_ENSURE_TRUE(accTable, nsnull);
344 :
345 0 : nsCOMPtr<nsIAccessible> accCell;
346 0 : accTable->GetCellAt(aRow, 0, getter_AddRefs(accCell));
347 0 : if (!accCell)
348 0 : return nsnull;
349 :
350 : // If the cell at the first column is row header then assume it is row
351 : // header for all columns,
352 0 : if (nsAccUtils::Role(accCell) == nsIAccessibleRole::ROLE_ROWHEADER)
353 0 : return nsAccessibleWrap::GetAtkObject(accCell);
354 :
355 : // otherwise get row header for the data cell at the first column.
356 : nsCOMPtr<nsIAccessibleTableCell> accTableCell =
357 0 : do_QueryInterface(accCell);
358 :
359 0 : if (accTableCell) {
360 0 : nsCOMPtr<nsIArray> headerCells;
361 0 : accTableCell->GetRowHeaderCells(getter_AddRefs(headerCells));
362 0 : if (headerCells) {
363 : nsresult rv;
364 : nsCOMPtr<nsIAccessible> accHeaderCell =
365 0 : do_QueryElementAt(headerCells, 0, &rv);
366 0 : NS_ENSURE_SUCCESS(rv, nsnull);
367 :
368 0 : return nsAccessibleWrap::GetAtkObject(accHeaderCell);
369 : }
370 : }
371 :
372 0 : return nsnull;
373 : }
374 :
375 : AtkObject*
376 0 : getSummaryCB(AtkTable *aTable)
377 : {
378 : // Neither html:table nor xul:tree nor ARIA grid/tree have an ability to
379 : // link an accessible object to specify a summary. There is closes method
380 : // in nsIAccessibleTable::summary to get a summary as a string which is not
381 : // mapped directly to ATK.
382 0 : return nsnull;
383 : }
384 :
385 : gint
386 0 : getSelectedColumnsCB(AtkTable *aTable, gint **aSelected)
387 : {
388 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
389 0 : if (!accWrap)
390 0 : return 0;
391 :
392 0 : nsCOMPtr<nsIAccessibleTable> accTable;
393 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
394 0 : getter_AddRefs(accTable));
395 0 : NS_ENSURE_TRUE(accTable, 0);
396 :
397 0 : PRUint32 size = 0;
398 0 : PRInt32 *columns = NULL;
399 0 : nsresult rv = accTable->GetSelectedColumnIndices(&size, &columns);
400 0 : if (NS_FAILED(rv) || (size == 0) || !columns) {
401 0 : *aSelected = nsnull;
402 0 : return 0;
403 : }
404 :
405 0 : gint *atkColumns = g_new(gint, size);
406 0 : if (!atkColumns) {
407 0 : NS_WARNING("OUT OF MEMORY");
408 0 : return nsnull;
409 : }
410 :
411 : //copy
412 0 : for (PRUint32 index = 0; index < size; ++index)
413 0 : atkColumns[index] = static_cast<gint>(columns[index]);
414 0 : nsMemory::Free(columns);
415 :
416 0 : *aSelected = atkColumns;
417 0 : return size;
418 : }
419 :
420 : gint
421 0 : getSelectedRowsCB(AtkTable *aTable, gint **aSelected)
422 : {
423 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
424 0 : if (!accWrap)
425 0 : return 0;
426 :
427 0 : nsCOMPtr<nsIAccessibleTable> accTable;
428 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
429 0 : getter_AddRefs(accTable));
430 0 : NS_ENSURE_TRUE(accTable, 0);
431 :
432 0 : PRUint32 size = 0;
433 0 : PRInt32 *rows = NULL;
434 0 : nsresult rv = accTable->GetSelectedRowIndices(&size, &rows);
435 0 : if (NS_FAILED(rv) || (size == 0) || !rows) {
436 0 : *aSelected = nsnull;
437 0 : return 0;
438 : }
439 :
440 0 : gint *atkRows = g_new(gint, size);
441 0 : if (!atkRows) {
442 0 : NS_WARNING("OUT OF MEMORY");
443 0 : return nsnull;
444 : }
445 :
446 : //copy
447 0 : for (PRUint32 index = 0; index < size; ++index)
448 0 : atkRows[index] = static_cast<gint>(rows[index]);
449 0 : nsMemory::Free(rows);
450 :
451 0 : *aSelected = atkRows;
452 0 : return size;
453 : }
454 :
455 : gboolean
456 0 : isColumnSelectedCB(AtkTable *aTable, gint aColumn)
457 : {
458 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
459 0 : if (!accWrap)
460 0 : return FALSE;
461 :
462 0 : nsCOMPtr<nsIAccessibleTable> accTable;
463 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
464 0 : getter_AddRefs(accTable));
465 0 : NS_ENSURE_TRUE(accTable, FALSE);
466 :
467 : bool outValue;
468 0 : nsresult rv = accTable->IsColumnSelected(aColumn, &outValue);
469 0 : return NS_FAILED(rv) ? FALSE : static_cast<gboolean>(outValue);
470 : }
471 :
472 : gboolean
473 0 : isRowSelectedCB(AtkTable *aTable, gint aRow)
474 : {
475 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
476 0 : if (!accWrap)
477 0 : return FALSE;
478 :
479 0 : nsCOMPtr<nsIAccessibleTable> accTable;
480 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
481 0 : getter_AddRefs(accTable));
482 0 : NS_ENSURE_TRUE(accTable, FALSE);
483 :
484 : bool outValue;
485 0 : nsresult rv = accTable->IsRowSelected(aRow, &outValue);
486 0 : return NS_FAILED(rv) ? FALSE : static_cast<gboolean>(outValue);
487 : }
488 :
489 : gboolean
490 0 : isCellSelectedCB(AtkTable *aTable, gint aRow, gint aColumn)
491 : {
492 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
493 0 : if (!accWrap)
494 0 : return FALSE;
495 :
496 0 : nsCOMPtr<nsIAccessibleTable> accTable;
497 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
498 0 : getter_AddRefs(accTable));
499 0 : NS_ENSURE_TRUE(accTable, FALSE);
500 :
501 : bool outValue;
502 0 : nsresult rv = accTable->IsCellSelected(aRow, aColumn, &outValue);
503 0 : return NS_FAILED(rv) ? FALSE : static_cast<gboolean>(outValue);
504 : }
|