|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "ARIAGridAccessible-inl.h" |
|
7 |
|
8 #include "Accessible-inl.h" |
|
9 #include "AccIterator.h" |
|
10 #include "nsAccUtils.h" |
|
11 #include "Role.h" |
|
12 #include "States.h" |
|
13 |
|
14 #include "nsIMutableArray.h" |
|
15 #include "nsIPersistentProperties2.h" |
|
16 #include "nsComponentManagerUtils.h" |
|
17 |
|
18 using namespace mozilla; |
|
19 using namespace mozilla::a11y; |
|
20 |
|
21 //////////////////////////////////////////////////////////////////////////////// |
|
22 // ARIAGridAccessible |
|
23 //////////////////////////////////////////////////////////////////////////////// |
|
24 |
|
25 |
|
26 //////////////////////////////////////////////////////////////////////////////// |
|
27 // Constructor |
|
28 |
|
29 ARIAGridAccessible:: |
|
30 ARIAGridAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
31 AccessibleWrap(aContent, aDoc), xpcAccessibleTable(this) |
|
32 { |
|
33 } |
|
34 |
|
35 //////////////////////////////////////////////////////////////////////////////// |
|
36 // nsISupports |
|
37 |
|
38 NS_IMPL_ISUPPORTS_INHERITED(ARIAGridAccessible, |
|
39 Accessible, |
|
40 nsIAccessibleTable) |
|
41 |
|
42 //////////////////////////////////////////////////////////////////////////////// |
|
43 // Accessible |
|
44 |
|
45 void |
|
46 ARIAGridAccessible::Shutdown() |
|
47 { |
|
48 mTable = nullptr; |
|
49 AccessibleWrap::Shutdown(); |
|
50 } |
|
51 |
|
52 //////////////////////////////////////////////////////////////////////////////// |
|
53 // nsIAccessibleTable |
|
54 |
|
55 uint32_t |
|
56 ARIAGridAccessible::ColCount() |
|
57 { |
|
58 AccIterator rowIter(this, filters::GetRow); |
|
59 Accessible* row = rowIter.Next(); |
|
60 if (!row) |
|
61 return 0; |
|
62 |
|
63 AccIterator cellIter(row, filters::GetCell); |
|
64 Accessible* cell = nullptr; |
|
65 |
|
66 uint32_t colCount = 0; |
|
67 while ((cell = cellIter.Next())) |
|
68 colCount++; |
|
69 |
|
70 return colCount; |
|
71 } |
|
72 |
|
73 uint32_t |
|
74 ARIAGridAccessible::RowCount() |
|
75 { |
|
76 uint32_t rowCount = 0; |
|
77 AccIterator rowIter(this, filters::GetRow); |
|
78 while (rowIter.Next()) |
|
79 rowCount++; |
|
80 |
|
81 return rowCount; |
|
82 } |
|
83 |
|
84 Accessible* |
|
85 ARIAGridAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex) |
|
86 { |
|
87 Accessible* row = GetRowAt(aRowIndex); |
|
88 if (!row) |
|
89 return nullptr; |
|
90 |
|
91 return GetCellInRowAt(row, aColumnIndex); |
|
92 } |
|
93 |
|
94 bool |
|
95 ARIAGridAccessible::IsColSelected(uint32_t aColIdx) |
|
96 { |
|
97 AccIterator rowIter(this, filters::GetRow); |
|
98 Accessible* row = rowIter.Next(); |
|
99 if (!row) |
|
100 return false; |
|
101 |
|
102 do { |
|
103 if (!nsAccUtils::IsARIASelected(row)) { |
|
104 Accessible* cell = GetCellInRowAt(row, aColIdx); |
|
105 if (!cell || !nsAccUtils::IsARIASelected(cell)) |
|
106 return false; |
|
107 } |
|
108 } while ((row = rowIter.Next())); |
|
109 |
|
110 return true; |
|
111 } |
|
112 |
|
113 bool |
|
114 ARIAGridAccessible::IsRowSelected(uint32_t aRowIdx) |
|
115 { |
|
116 Accessible* row = GetRowAt(aRowIdx); |
|
117 if(!row) |
|
118 return false; |
|
119 |
|
120 if (!nsAccUtils::IsARIASelected(row)) { |
|
121 AccIterator cellIter(row, filters::GetCell); |
|
122 Accessible* cell = nullptr; |
|
123 while ((cell = cellIter.Next())) { |
|
124 if (!nsAccUtils::IsARIASelected(cell)) |
|
125 return false; |
|
126 } |
|
127 } |
|
128 |
|
129 return true; |
|
130 } |
|
131 |
|
132 bool |
|
133 ARIAGridAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx) |
|
134 { |
|
135 Accessible* row = GetRowAt(aRowIdx); |
|
136 if(!row) |
|
137 return false; |
|
138 |
|
139 if (!nsAccUtils::IsARIASelected(row)) { |
|
140 Accessible* cell = GetCellInRowAt(row, aColIdx); |
|
141 if (!cell || !nsAccUtils::IsARIASelected(cell)) |
|
142 return false; |
|
143 } |
|
144 |
|
145 return true; |
|
146 } |
|
147 |
|
148 uint32_t |
|
149 ARIAGridAccessible::SelectedCellCount() |
|
150 { |
|
151 uint32_t count = 0, colCount = ColCount(); |
|
152 |
|
153 AccIterator rowIter(this, filters::GetRow); |
|
154 Accessible* row = nullptr; |
|
155 |
|
156 while ((row = rowIter.Next())) { |
|
157 if (nsAccUtils::IsARIASelected(row)) { |
|
158 count += colCount; |
|
159 continue; |
|
160 } |
|
161 |
|
162 AccIterator cellIter(row, filters::GetCell); |
|
163 Accessible* cell = nullptr; |
|
164 |
|
165 while ((cell = cellIter.Next())) { |
|
166 if (nsAccUtils::IsARIASelected(cell)) |
|
167 count++; |
|
168 } |
|
169 } |
|
170 |
|
171 return count; |
|
172 } |
|
173 |
|
174 uint32_t |
|
175 ARIAGridAccessible::SelectedColCount() |
|
176 { |
|
177 uint32_t colCount = ColCount(); |
|
178 if (!colCount) |
|
179 return 0; |
|
180 |
|
181 AccIterator rowIter(this, filters::GetRow); |
|
182 Accessible* row = rowIter.Next(); |
|
183 if (!row) |
|
184 return 0; |
|
185 |
|
186 nsTArray<bool> isColSelArray(colCount); |
|
187 isColSelArray.AppendElements(colCount); |
|
188 memset(isColSelArray.Elements(), true, colCount * sizeof(bool)); |
|
189 |
|
190 uint32_t selColCount = colCount; |
|
191 do { |
|
192 if (nsAccUtils::IsARIASelected(row)) |
|
193 continue; |
|
194 |
|
195 AccIterator cellIter(row, filters::GetCell); |
|
196 Accessible* cell = nullptr; |
|
197 for (uint32_t colIdx = 0; |
|
198 (cell = cellIter.Next()) && colIdx < colCount; colIdx++) |
|
199 if (isColSelArray[colIdx] && !nsAccUtils::IsARIASelected(cell)) { |
|
200 isColSelArray[colIdx] = false; |
|
201 selColCount--; |
|
202 } |
|
203 } while ((row = rowIter.Next())); |
|
204 |
|
205 return selColCount; |
|
206 } |
|
207 |
|
208 uint32_t |
|
209 ARIAGridAccessible::SelectedRowCount() |
|
210 { |
|
211 uint32_t count = 0; |
|
212 |
|
213 AccIterator rowIter(this, filters::GetRow); |
|
214 Accessible* row = nullptr; |
|
215 |
|
216 while ((row = rowIter.Next())) { |
|
217 if (nsAccUtils::IsARIASelected(row)) { |
|
218 count++; |
|
219 continue; |
|
220 } |
|
221 |
|
222 AccIterator cellIter(row, filters::GetCell); |
|
223 Accessible* cell = cellIter.Next(); |
|
224 if (!cell) |
|
225 continue; |
|
226 |
|
227 bool isRowSelected = true; |
|
228 do { |
|
229 if (!nsAccUtils::IsARIASelected(cell)) { |
|
230 isRowSelected = false; |
|
231 break; |
|
232 } |
|
233 } while ((cell = cellIter.Next())); |
|
234 |
|
235 if (isRowSelected) |
|
236 count++; |
|
237 } |
|
238 |
|
239 return count; |
|
240 } |
|
241 |
|
242 void |
|
243 ARIAGridAccessible::SelectedCells(nsTArray<Accessible*>* aCells) |
|
244 { |
|
245 AccIterator rowIter(this, filters::GetRow); |
|
246 |
|
247 Accessible* row = nullptr; |
|
248 while ((row = rowIter.Next())) { |
|
249 AccIterator cellIter(row, filters::GetCell); |
|
250 Accessible* cell = nullptr; |
|
251 |
|
252 if (nsAccUtils::IsARIASelected(row)) { |
|
253 while ((cell = cellIter.Next())) |
|
254 aCells->AppendElement(cell); |
|
255 |
|
256 continue; |
|
257 } |
|
258 |
|
259 while ((cell = cellIter.Next())) { |
|
260 if (nsAccUtils::IsARIASelected(cell)) |
|
261 aCells->AppendElement(cell); |
|
262 } |
|
263 } |
|
264 } |
|
265 |
|
266 void |
|
267 ARIAGridAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells) |
|
268 { |
|
269 uint32_t colCount = ColCount(); |
|
270 |
|
271 AccIterator rowIter(this, filters::GetRow); |
|
272 Accessible* row = nullptr; |
|
273 for (uint32_t rowIdx = 0; (row = rowIter.Next()); rowIdx++) { |
|
274 if (nsAccUtils::IsARIASelected(row)) { |
|
275 for (uint32_t colIdx = 0; colIdx < colCount; colIdx++) |
|
276 aCells->AppendElement(rowIdx * colCount + colIdx); |
|
277 |
|
278 continue; |
|
279 } |
|
280 |
|
281 AccIterator cellIter(row, filters::GetCell); |
|
282 Accessible* cell = nullptr; |
|
283 for (uint32_t colIdx = 0; (cell = cellIter.Next()); colIdx++) { |
|
284 if (nsAccUtils::IsARIASelected(cell)) |
|
285 aCells->AppendElement(rowIdx * colCount + colIdx); |
|
286 } |
|
287 } |
|
288 } |
|
289 |
|
290 void |
|
291 ARIAGridAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols) |
|
292 { |
|
293 uint32_t colCount = ColCount(); |
|
294 if (!colCount) |
|
295 return; |
|
296 |
|
297 AccIterator rowIter(this, filters::GetRow); |
|
298 Accessible* row = rowIter.Next(); |
|
299 if (!row) |
|
300 return; |
|
301 |
|
302 nsTArray<bool> isColSelArray(colCount); |
|
303 isColSelArray.AppendElements(colCount); |
|
304 memset(isColSelArray.Elements(), true, colCount * sizeof(bool)); |
|
305 |
|
306 do { |
|
307 if (nsAccUtils::IsARIASelected(row)) |
|
308 continue; |
|
309 |
|
310 AccIterator cellIter(row, filters::GetCell); |
|
311 Accessible* cell = nullptr; |
|
312 for (uint32_t colIdx = 0; |
|
313 (cell = cellIter.Next()) && colIdx < colCount; colIdx++) |
|
314 if (isColSelArray[colIdx] && !nsAccUtils::IsARIASelected(cell)) { |
|
315 isColSelArray[colIdx] = false; |
|
316 } |
|
317 } while ((row = rowIter.Next())); |
|
318 |
|
319 for (uint32_t colIdx = 0; colIdx < colCount; colIdx++) |
|
320 if (isColSelArray[colIdx]) |
|
321 aCols->AppendElement(colIdx); |
|
322 } |
|
323 |
|
324 void |
|
325 ARIAGridAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows) |
|
326 { |
|
327 AccIterator rowIter(this, filters::GetRow); |
|
328 Accessible* row = nullptr; |
|
329 for (uint32_t rowIdx = 0; (row = rowIter.Next()); rowIdx++) { |
|
330 if (nsAccUtils::IsARIASelected(row)) { |
|
331 aRows->AppendElement(rowIdx); |
|
332 continue; |
|
333 } |
|
334 |
|
335 AccIterator cellIter(row, filters::GetCell); |
|
336 Accessible* cell = cellIter.Next(); |
|
337 if (!cell) |
|
338 continue; |
|
339 |
|
340 bool isRowSelected = true; |
|
341 do { |
|
342 if (!nsAccUtils::IsARIASelected(cell)) { |
|
343 isRowSelected = false; |
|
344 break; |
|
345 } |
|
346 } while ((cell = cellIter.Next())); |
|
347 |
|
348 if (isRowSelected) |
|
349 aRows->AppendElement(rowIdx); |
|
350 } |
|
351 } |
|
352 |
|
353 void |
|
354 ARIAGridAccessible::SelectRow(uint32_t aRowIdx) |
|
355 { |
|
356 AccIterator rowIter(this, filters::GetRow); |
|
357 |
|
358 Accessible* row = nullptr; |
|
359 for (uint32_t rowIdx = 0; (row = rowIter.Next()); rowIdx++) { |
|
360 DebugOnly<nsresult> rv = SetARIASelected(row, rowIdx == aRowIdx); |
|
361 NS_ASSERTION(NS_SUCCEEDED(rv), "SetARIASelected() Shouldn't fail!"); |
|
362 } |
|
363 } |
|
364 |
|
365 void |
|
366 ARIAGridAccessible::SelectCol(uint32_t aColIdx) |
|
367 { |
|
368 AccIterator rowIter(this, filters::GetRow); |
|
369 |
|
370 Accessible* row = nullptr; |
|
371 while ((row = rowIter.Next())) { |
|
372 // Unselect all cells in the row. |
|
373 DebugOnly<nsresult> rv = SetARIASelected(row, false); |
|
374 NS_ASSERTION(NS_SUCCEEDED(rv), "SetARIASelected() Shouldn't fail!"); |
|
375 |
|
376 // Select cell at the column index. |
|
377 Accessible* cell = GetCellInRowAt(row, aColIdx); |
|
378 if (cell) |
|
379 SetARIASelected(cell, true); |
|
380 } |
|
381 } |
|
382 |
|
383 void |
|
384 ARIAGridAccessible::UnselectRow(uint32_t aRowIdx) |
|
385 { |
|
386 Accessible* row = GetRowAt(aRowIdx); |
|
387 |
|
388 if (row) |
|
389 SetARIASelected(row, false); |
|
390 } |
|
391 |
|
392 void |
|
393 ARIAGridAccessible::UnselectCol(uint32_t aColIdx) |
|
394 { |
|
395 AccIterator rowIter(this, filters::GetRow); |
|
396 |
|
397 Accessible* row = nullptr; |
|
398 while ((row = rowIter.Next())) { |
|
399 Accessible* cell = GetCellInRowAt(row, aColIdx); |
|
400 if (cell) |
|
401 SetARIASelected(cell, false); |
|
402 } |
|
403 } |
|
404 |
|
405 //////////////////////////////////////////////////////////////////////////////// |
|
406 // Protected |
|
407 |
|
408 bool |
|
409 ARIAGridAccessible::IsValidRow(int32_t aRow) |
|
410 { |
|
411 if (aRow < 0) |
|
412 return false; |
|
413 |
|
414 int32_t rowCount = 0; |
|
415 GetRowCount(&rowCount); |
|
416 return aRow < rowCount; |
|
417 } |
|
418 |
|
419 bool |
|
420 ARIAGridAccessible::IsValidColumn(int32_t aColumn) |
|
421 { |
|
422 if (aColumn < 0) |
|
423 return false; |
|
424 |
|
425 int32_t colCount = 0; |
|
426 GetColumnCount(&colCount); |
|
427 return aColumn < colCount; |
|
428 } |
|
429 |
|
430 Accessible* |
|
431 ARIAGridAccessible::GetRowAt(int32_t aRow) |
|
432 { |
|
433 int32_t rowIdx = aRow; |
|
434 |
|
435 AccIterator rowIter(this, filters::GetRow); |
|
436 |
|
437 Accessible* row = rowIter.Next(); |
|
438 while (rowIdx != 0 && (row = rowIter.Next())) |
|
439 rowIdx--; |
|
440 |
|
441 return row; |
|
442 } |
|
443 |
|
444 Accessible* |
|
445 ARIAGridAccessible::GetCellInRowAt(Accessible* aRow, int32_t aColumn) |
|
446 { |
|
447 int32_t colIdx = aColumn; |
|
448 |
|
449 AccIterator cellIter(aRow, filters::GetCell); |
|
450 Accessible* cell = cellIter.Next(); |
|
451 while (colIdx != 0 && (cell = cellIter.Next())) |
|
452 colIdx--; |
|
453 |
|
454 return cell; |
|
455 } |
|
456 |
|
457 nsresult |
|
458 ARIAGridAccessible::SetARIASelected(Accessible* aAccessible, |
|
459 bool aIsSelected, bool aNotify) |
|
460 { |
|
461 nsIContent *content = aAccessible->GetContent(); |
|
462 NS_ENSURE_STATE(content); |
|
463 |
|
464 nsresult rv = NS_OK; |
|
465 if (aIsSelected) |
|
466 rv = content->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected, |
|
467 NS_LITERAL_STRING("true"), aNotify); |
|
468 else |
|
469 rv = content->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected, |
|
470 NS_LITERAL_STRING("false"), aNotify); |
|
471 |
|
472 NS_ENSURE_SUCCESS(rv, rv); |
|
473 |
|
474 // No "smart" select/unselect for internal call. |
|
475 if (!aNotify) |
|
476 return NS_OK; |
|
477 |
|
478 // If row or cell accessible was selected then we're able to not bother about |
|
479 // selection of its cells or its row because our algorithm is row oriented, |
|
480 // i.e. we check selection on row firstly and then on cells. |
|
481 if (aIsSelected) |
|
482 return NS_OK; |
|
483 |
|
484 roles::Role role = aAccessible->Role(); |
|
485 |
|
486 // If the given accessible is row that was unselected then remove |
|
487 // aria-selected from cell accessible. |
|
488 if (role == roles::ROW) { |
|
489 AccIterator cellIter(aAccessible, filters::GetCell); |
|
490 Accessible* cell = nullptr; |
|
491 |
|
492 while ((cell = cellIter.Next())) { |
|
493 rv = SetARIASelected(cell, false, false); |
|
494 NS_ENSURE_SUCCESS(rv, rv); |
|
495 } |
|
496 return NS_OK; |
|
497 } |
|
498 |
|
499 // If the given accessible is cell that was unselected and its row is selected |
|
500 // then remove aria-selected from row and put aria-selected on |
|
501 // siblings cells. |
|
502 if (role == roles::GRID_CELL || role == roles::ROWHEADER || |
|
503 role == roles::COLUMNHEADER) { |
|
504 Accessible* row = aAccessible->Parent(); |
|
505 |
|
506 if (row && row->Role() == roles::ROW && |
|
507 nsAccUtils::IsARIASelected(row)) { |
|
508 rv = SetARIASelected(row, false, false); |
|
509 NS_ENSURE_SUCCESS(rv, rv); |
|
510 |
|
511 AccIterator cellIter(row, filters::GetCell); |
|
512 Accessible* cell = nullptr; |
|
513 while ((cell = cellIter.Next())) { |
|
514 if (cell != aAccessible) { |
|
515 rv = SetARIASelected(cell, true, false); |
|
516 NS_ENSURE_SUCCESS(rv, rv); |
|
517 } |
|
518 } |
|
519 } |
|
520 } |
|
521 |
|
522 return NS_OK; |
|
523 } |
|
524 |
|
525 //////////////////////////////////////////////////////////////////////////////// |
|
526 // ARIAGridCellAccessible |
|
527 //////////////////////////////////////////////////////////////////////////////// |
|
528 |
|
529 |
|
530 //////////////////////////////////////////////////////////////////////////////// |
|
531 // Constructor |
|
532 |
|
533 ARIAGridCellAccessible:: |
|
534 ARIAGridCellAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
535 HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this) |
|
536 { |
|
537 mGenericTypes |= eTableCell; |
|
538 } |
|
539 |
|
540 //////////////////////////////////////////////////////////////////////////////// |
|
541 // nsISupports |
|
542 |
|
543 NS_IMPL_ISUPPORTS_INHERITED(ARIAGridCellAccessible, |
|
544 HyperTextAccessible, |
|
545 nsIAccessibleTableCell) |
|
546 |
|
547 //////////////////////////////////////////////////////////////////////////////// |
|
548 // nsIAccessibleTableCell |
|
549 |
|
550 TableAccessible* |
|
551 ARIAGridCellAccessible::Table() const |
|
552 { |
|
553 Accessible* table = TableFor(Row()); |
|
554 return table ? table->AsTable() : nullptr; |
|
555 } |
|
556 |
|
557 uint32_t |
|
558 ARIAGridCellAccessible::ColIdx() const |
|
559 { |
|
560 Accessible* row = Row(); |
|
561 if (!row) |
|
562 return 0; |
|
563 |
|
564 int32_t indexInRow = IndexInParent(); |
|
565 uint32_t colIdx = 0; |
|
566 for (int32_t idx = 0; idx < indexInRow; idx++) { |
|
567 Accessible* cell = row->GetChildAt(idx); |
|
568 roles::Role role = cell->Role(); |
|
569 if (role == roles::GRID_CELL || role == roles::ROWHEADER || |
|
570 role == roles::COLUMNHEADER) |
|
571 colIdx++; |
|
572 } |
|
573 |
|
574 return colIdx; |
|
575 } |
|
576 |
|
577 uint32_t |
|
578 ARIAGridCellAccessible::RowIdx() const |
|
579 { |
|
580 return RowIndexFor(Row()); |
|
581 } |
|
582 |
|
583 bool |
|
584 ARIAGridCellAccessible::Selected() |
|
585 { |
|
586 Accessible* row = Row(); |
|
587 if (!row) |
|
588 return false; |
|
589 |
|
590 return nsAccUtils::IsARIASelected(row) || nsAccUtils::IsARIASelected(this); |
|
591 } |
|
592 |
|
593 //////////////////////////////////////////////////////////////////////////////// |
|
594 // Accessible |
|
595 |
|
596 void |
|
597 ARIAGridCellAccessible::ApplyARIAState(uint64_t* aState) const |
|
598 { |
|
599 HyperTextAccessibleWrap::ApplyARIAState(aState); |
|
600 |
|
601 // Return if the gridcell has aria-selected="true". |
|
602 if (*aState & states::SELECTED) |
|
603 return; |
|
604 |
|
605 // Check aria-selected="true" on the row. |
|
606 Accessible* row = Parent(); |
|
607 if (!row || row->Role() != roles::ROW) |
|
608 return; |
|
609 |
|
610 nsIContent *rowContent = row->GetContent(); |
|
611 if (nsAccUtils::HasDefinedARIAToken(rowContent, |
|
612 nsGkAtoms::aria_selected) && |
|
613 !rowContent->AttrValueIs(kNameSpaceID_None, |
|
614 nsGkAtoms::aria_selected, |
|
615 nsGkAtoms::_false, eCaseMatters)) |
|
616 *aState |= states::SELECTABLE | states::SELECTED; |
|
617 } |
|
618 |
|
619 already_AddRefed<nsIPersistentProperties> |
|
620 ARIAGridCellAccessible::NativeAttributes() |
|
621 { |
|
622 nsCOMPtr<nsIPersistentProperties> attributes = |
|
623 HyperTextAccessibleWrap::NativeAttributes(); |
|
624 |
|
625 // Expose "table-cell-index" attribute. |
|
626 Accessible* thisRow = Row(); |
|
627 if (!thisRow) |
|
628 return attributes.forget(); |
|
629 |
|
630 int32_t colIdx = 0, colCount = 0; |
|
631 uint32_t childCount = thisRow->ChildCount(); |
|
632 for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) { |
|
633 Accessible* child = thisRow->GetChildAt(childIdx); |
|
634 if (child == this) |
|
635 colIdx = colCount; |
|
636 |
|
637 roles::Role role = child->Role(); |
|
638 if (role == roles::GRID_CELL || role == roles::ROWHEADER || |
|
639 role == roles::COLUMNHEADER) |
|
640 colCount++; |
|
641 } |
|
642 |
|
643 int32_t rowIdx = RowIndexFor(thisRow); |
|
644 |
|
645 nsAutoString stringIdx; |
|
646 stringIdx.AppendInt(rowIdx * colCount + colIdx); |
|
647 nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx); |
|
648 |
|
649 return attributes.forget(); |
|
650 } |
|
651 |
|
652 void |
|
653 ARIAGridCellAccessible::Shutdown() |
|
654 { |
|
655 mTableCell = nullptr; |
|
656 HyperTextAccessibleWrap::Shutdown(); |
|
657 } |