| |
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 } |