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 #ifndef CACHED_TABLE_ACCESSIBLE_H
8 #define CACHED_TABLE_ACCESSIBLE_H
10 #include "mozilla/a11y/TableAccessible.h"
11 #include "mozilla/a11y/TableCellAccessible.h"
12 #include "mozilla/UniquePtr.h"
13 #include "nsTHashMap.h"
15 namespace mozilla::a11y
{
17 const uint32_t kNoCellIdx
= UINT32_MAX
;
21 class CachedTableAccessible
;
23 class CachedTableCellAccessible final
: public TableCellAccessible
{
25 static CachedTableCellAccessible
* GetFrom(Accessible
* aAcc
);
27 virtual TableAccessible
* Table() const override
;
29 virtual uint32_t ColIdx() const override
{
30 return static_cast<int32_t>(mColIdx
);
33 virtual uint32_t RowIdx() const override
{
34 return static_cast<int32_t>(mRowIdx
);
37 virtual uint32_t ColExtent() const override
;
39 virtual uint32_t RowExtent() const override
;
41 virtual void ColHeaderCells(nsTArray
<Accessible
*>* aCells
) override
;
43 virtual void RowHeaderCells(nsTArray
<Accessible
*>* aCells
) override
;
45 virtual bool Selected() override
;
48 CachedTableCellAccessible(uint64_t aAccID
, Accessible
* aAcc
, uint32_t aRowIdx
,
49 uint32_t aColIdx
, uint32_t aPrevColHeaderCellIdx
)
54 mPrevColHeaderCellIdx(aPrevColHeaderCellIdx
) {}
56 // Get the Accessible for this table cell given its ancestor table Accessible,
57 // verifying that the Accessible is valid.
58 Accessible
* Acc(Accessible
* aTableAcc
) const;
60 UniquePtr
<AccIterable
> GetExplicitHeadersIterator();
63 // CachedTableAccessible methods which fetch a cell should retrieve the
64 // Accessible using Acc() rather than using mAcc. We need mAcc for some
65 // methods because we can't fetch a document by id. It's okay to use mAcc in
66 // these methods because the caller has to hold the Accessible in order to
71 // The cell index of the previous implicit column header.
72 uint32_t mPrevColHeaderCellIdx
;
73 friend class CachedTableAccessible
;
77 * TableAccessible implementation which builds and queries a cache.
79 class CachedTableAccessible final
: public TableAccessible
{
81 static CachedTableAccessible
* GetFrom(Accessible
* aAcc
);
84 * This must be called whenever a table is destroyed or the structure of a
85 * table changes; e.g. cells wer added or removed. It can be called with
86 * either a table or a cell.
88 static void Invalidate(Accessible
* aAcc
);
90 virtual Accessible
* Caption() const override
;
91 virtual void Summary(nsString
& aSummary
) override
;
93 virtual uint32_t ColCount() const override
{ return mColCount
; }
95 virtual uint32_t RowCount() override
{ return mRowColToCellIdx
.Length(); }
97 virtual int32_t ColIndexAt(uint32_t aCellIdx
) override
{
98 if (aCellIdx
< mCells
.Length()) {
99 return static_cast<int32_t>(mCells
[aCellIdx
].mColIdx
);
104 virtual int32_t RowIndexAt(uint32_t aCellIdx
) override
{
105 if (aCellIdx
< mCells
.Length()) {
106 return static_cast<int32_t>(mCells
[aCellIdx
].mRowIdx
);
111 virtual void RowAndColIndicesAt(uint32_t aCellIdx
, int32_t* aRowIdx
,
112 int32_t* aColIdx
) override
{
113 if (aCellIdx
< mCells
.Length()) {
114 CachedTableCellAccessible
& cell
= mCells
[aCellIdx
];
115 *aRowIdx
= static_cast<int32_t>(cell
.mRowIdx
);
116 *aColIdx
= static_cast<int32_t>(cell
.mColIdx
);
123 virtual uint32_t ColExtentAt(uint32_t aRowIdx
, uint32_t aColIdx
) override
{
124 int32_t cellIdx
= CellIndexAt(aRowIdx
, aColIdx
);
128 // Verify that the cell's Accessible is valid.
129 mCells
[cellIdx
].Acc(mAcc
);
130 return mCells
[cellIdx
].ColExtent();
133 virtual uint32_t RowExtentAt(uint32_t aRowIdx
, uint32_t aColIdx
) override
{
134 int32_t cellIdx
= CellIndexAt(aRowIdx
, aColIdx
);
138 // Verify that the cell's Accessible is valid.
139 mCells
[cellIdx
].Acc(mAcc
);
140 return mCells
[cellIdx
].RowExtent();
143 virtual int32_t CellIndexAt(uint32_t aRowIdx
, uint32_t aColIdx
) override
{
144 if (aRowIdx
< mRowColToCellIdx
.Length()) {
145 auto& row
= mRowColToCellIdx
[aRowIdx
];
146 if (aColIdx
< row
.Length()) {
147 uint32_t cellIdx
= row
[aColIdx
];
148 if (cellIdx
!= kNoCellIdx
) {
149 return static_cast<int32_t>(cellIdx
);
156 virtual Accessible
* CellAt(uint32_t aRowIdx
, uint32_t aColIdx
) override
;
158 virtual bool IsColSelected(uint32_t aColIdx
) override
{
159 bool selected
= false;
160 for (uint32_t row
= 0; row
< RowCount(); ++row
) {
161 selected
= IsCellSelected(row
, aColIdx
);
169 virtual bool IsRowSelected(uint32_t aRowIdx
) override
{
170 bool selected
= false;
171 for (uint32_t col
= 0; col
< mColCount
; ++col
) {
172 selected
= IsCellSelected(aRowIdx
, col
);
180 virtual bool IsCellSelected(uint32_t aRowIdx
, uint32_t aColIdx
) override
{
181 int32_t cellIdx
= CellIndexAt(aRowIdx
, aColIdx
);
185 // Verify that the cell's Accessible is valid.
186 mCells
[cellIdx
].Acc(mAcc
);
187 return mCells
[cellIdx
].Selected();
190 virtual uint32_t SelectedCellCount() override
{
192 for (auto& cell
: mCells
) {
193 // Verify that the cell's Accessible is valid.
195 if (cell
.Selected()) {
202 virtual uint32_t SelectedColCount() override
{
204 for (uint32_t col
= 0; col
< mColCount
; ++col
) {
205 if (IsColSelected(col
)) {
212 virtual uint32_t SelectedRowCount() override
{
214 for (uint32_t row
= 0; row
< RowCount(); ++row
) {
215 if (IsRowSelected(row
)) {
222 virtual void SelectedCells(nsTArray
<Accessible
*>* aCells
) override
{
223 for (auto& cell
: mCells
) {
224 // Verify that the cell's Accessible is valid.
225 Accessible
* acc
= cell
.Acc(mAcc
);
226 if (cell
.Selected()) {
227 aCells
->AppendElement(acc
);
232 virtual void SelectedCellIndices(nsTArray
<uint32_t>* aCells
) override
{
233 for (uint32_t idx
= 0; idx
< mCells
.Length(); ++idx
) {
234 CachedTableCellAccessible
& cell
= mCells
[idx
];
235 // Verify that the cell's Accessible is valid.
237 if (cell
.Selected()) {
238 aCells
->AppendElement(idx
);
243 virtual void SelectedColIndices(nsTArray
<uint32_t>* aCols
) override
{
244 for (uint32_t col
= 0; col
< mColCount
; ++col
) {
245 if (IsColSelected(col
)) {
246 aCols
->AppendElement(col
);
251 virtual void SelectedRowIndices(nsTArray
<uint32_t>* aRows
) override
{
252 for (uint32_t row
= 0; row
< RowCount(); ++row
) {
253 if (IsRowSelected(row
)) {
254 aRows
->AppendElement(row
);
259 virtual Accessible
* AsAccessible() override
{ return mAcc
; }
261 virtual bool IsProbablyLayoutTable() override
;
264 explicit CachedTableAccessible(Accessible
* aAcc
);
266 // Ensure that the given row exists in our data structure, creating array
267 // elements as needed.
268 void EnsureRow(uint32_t aRowIdx
);
270 // Ensure that the given row and column coordinate exists in our data
271 // structure, creating array elements as needed. A newly created coordinate
272 // will be set to kNoCellIdx.
273 void EnsureRowCol(uint32_t aRowIdx
, uint32_t aColIdx
);
275 Accessible
* mAcc
; // The table Accessible.
276 // We track the column count because it might not be uniform across rows in
278 uint32_t mColCount
= 0;
279 // An array of cell instances. A cell index is an index into this array.
280 nsTArray
<CachedTableCellAccessible
> mCells
;
281 // Maps row and column coordinates to cell indices.
282 nsTArray
<nsTArray
<uint32_t>> mRowColToCellIdx
;
283 // Maps Accessibles to cell indexes to facilitate retrieval of a cell
284 // instance from a cell Accessible. The Accessible* keys should only be used
285 // for lookup. They should not be dereferenced.
286 nsTHashMap
<Accessible
*, uint32_t> mAccToCellIdx
;
287 uint64_t mCaptionAccID
= 0;
289 friend class CachedTableCellAccessible
;
292 } // namespace mozilla::a11y