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 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "TableCellAccessible.h"
9 #include "LocalAccessible-inl.h"
10 #include "TableAccessible.h"
12 using namespace mozilla
;
13 using namespace mozilla::a11y
;
15 void TableCellAccessible::RowHeaderCells(nsTArray
<LocalAccessible
*>* aCells
) {
16 uint32_t rowIdx
= RowIdx(), colIdx
= ColIdx();
17 TableAccessible
* table
= Table();
20 // Move to the left to find row header cells
21 for (uint32_t curColIdx
= colIdx
- 1; curColIdx
< colIdx
; curColIdx
--) {
22 LocalAccessible
* cell
= table
->CellAt(rowIdx
, curColIdx
);
25 // CellAt should always return a TableCellAccessible (XXX Bug 587529)
26 TableCellAccessible
* tableCell
= cell
->AsTableCell();
27 NS_ASSERTION(tableCell
, "cell should be a table cell!");
28 if (!tableCell
) continue;
30 // Avoid addding cells multiple times, if this cell spans more columns
31 // we'll get it later.
32 if (tableCell
->ColIdx() == curColIdx
&& cell
->Role() == roles::ROWHEADER
) {
33 aCells
->AppendElement(cell
);
38 LocalAccessible
* TableCellAccessible::PrevColHeader() {
39 TableAccessible
* table
= Table();
44 TableAccessible::HeaderCache
& cache
= table
->GetHeaderCache();
46 LocalAccessible
* cachedHeader
= cache
.GetWeak(this, &inCache
);
48 // Cached but null means we know there is no previous column header.
49 // if defunct, the cell was removed, so behave as if there is no cached
51 if (!cachedHeader
|| !cachedHeader
->IsDefunct()) {
56 uint32_t rowIdx
= RowIdx(), colIdx
= ColIdx();
57 for (uint32_t curRowIdx
= rowIdx
- 1; curRowIdx
< rowIdx
; curRowIdx
--) {
58 LocalAccessible
* cell
= table
->CellAt(curRowIdx
, colIdx
);
62 // CellAt should always return a TableCellAccessible (XXX Bug 587529)
63 TableCellAccessible
* tableCell
= cell
->AsTableCell();
64 MOZ_ASSERT(tableCell
, "cell should be a table cell!");
69 // Check whether the previous table cell has a cached value.
70 cachedHeader
= cache
.GetWeak(tableCell
, &inCache
);
72 // We check the cache first because even though we might not use it,
73 // it's faster than the other conditions.
75 // Only use the cached value if:
76 // 1. cell is a table cell which is not a column header. In that case,
77 // cell is the previous header and cachedHeader is the one before that.
78 // We will return cell later.
79 cell
->Role() != roles::COLUMNHEADER
&&
80 // 2. cell starts in this column. If it starts in a previous column and
81 // extends into this one, its header will be for the starting column,
82 // which is wrong for this cell.
83 // ColExtent is faster than ColIdx, so check that first.
84 (tableCell
->ColExtent() == 1 || tableCell
->ColIdx() == colIdx
)) {
85 if (!cachedHeader
|| !cachedHeader
->IsDefunct()) {
86 // Cache it for this cell.
87 cache
.InsertOrUpdate(this, RefPtr
<LocalAccessible
>(cachedHeader
));
92 // Avoid addding cells multiple times, if this cell spans more rows
93 // we'll get it later.
94 if (cell
->Role() != roles::COLUMNHEADER
||
95 tableCell
->RowIdx() != curRowIdx
) {
99 // Cache the header we found.
100 cache
.InsertOrUpdate(this, RefPtr
<LocalAccessible
>(cell
));
104 // There's no header, so cache that fact.
105 cache
.InsertOrUpdate(this, RefPtr
<LocalAccessible
>(nullptr));
109 void TableCellAccessible::ColHeaderCells(nsTArray
<LocalAccessible
*>* aCells
) {
110 for (LocalAccessible
* cell
= PrevColHeader(); cell
;
111 cell
= cell
->AsTableCell()->PrevColHeader()) {
112 aCells
->AppendElement(cell
);