1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/generic/ARIAGridAccessible.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,657 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "ARIAGridAccessible-inl.h" 1.10 + 1.11 +#include "Accessible-inl.h" 1.12 +#include "AccIterator.h" 1.13 +#include "nsAccUtils.h" 1.14 +#include "Role.h" 1.15 +#include "States.h" 1.16 + 1.17 +#include "nsIMutableArray.h" 1.18 +#include "nsIPersistentProperties2.h" 1.19 +#include "nsComponentManagerUtils.h" 1.20 + 1.21 +using namespace mozilla; 1.22 +using namespace mozilla::a11y; 1.23 + 1.24 +//////////////////////////////////////////////////////////////////////////////// 1.25 +// ARIAGridAccessible 1.26 +//////////////////////////////////////////////////////////////////////////////// 1.27 + 1.28 + 1.29 +//////////////////////////////////////////////////////////////////////////////// 1.30 +// Constructor 1.31 + 1.32 +ARIAGridAccessible:: 1.33 + ARIAGridAccessible(nsIContent* aContent, DocAccessible* aDoc) : 1.34 + AccessibleWrap(aContent, aDoc), xpcAccessibleTable(this) 1.35 +{ 1.36 +} 1.37 + 1.38 +//////////////////////////////////////////////////////////////////////////////// 1.39 +// nsISupports 1.40 + 1.41 +NS_IMPL_ISUPPORTS_INHERITED(ARIAGridAccessible, 1.42 + Accessible, 1.43 + nsIAccessibleTable) 1.44 + 1.45 +//////////////////////////////////////////////////////////////////////////////// 1.46 +// Accessible 1.47 + 1.48 +void 1.49 +ARIAGridAccessible::Shutdown() 1.50 +{ 1.51 + mTable = nullptr; 1.52 + AccessibleWrap::Shutdown(); 1.53 +} 1.54 + 1.55 +//////////////////////////////////////////////////////////////////////////////// 1.56 +// nsIAccessibleTable 1.57 + 1.58 +uint32_t 1.59 +ARIAGridAccessible::ColCount() 1.60 +{ 1.61 + AccIterator rowIter(this, filters::GetRow); 1.62 + Accessible* row = rowIter.Next(); 1.63 + if (!row) 1.64 + return 0; 1.65 + 1.66 + AccIterator cellIter(row, filters::GetCell); 1.67 + Accessible* cell = nullptr; 1.68 + 1.69 + uint32_t colCount = 0; 1.70 + while ((cell = cellIter.Next())) 1.71 + colCount++; 1.72 + 1.73 + return colCount; 1.74 +} 1.75 + 1.76 +uint32_t 1.77 +ARIAGridAccessible::RowCount() 1.78 +{ 1.79 + uint32_t rowCount = 0; 1.80 + AccIterator rowIter(this, filters::GetRow); 1.81 + while (rowIter.Next()) 1.82 + rowCount++; 1.83 + 1.84 + return rowCount; 1.85 +} 1.86 + 1.87 +Accessible* 1.88 +ARIAGridAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex) 1.89 +{ 1.90 + Accessible* row = GetRowAt(aRowIndex); 1.91 + if (!row) 1.92 + return nullptr; 1.93 + 1.94 + return GetCellInRowAt(row, aColumnIndex); 1.95 +} 1.96 + 1.97 +bool 1.98 +ARIAGridAccessible::IsColSelected(uint32_t aColIdx) 1.99 +{ 1.100 + AccIterator rowIter(this, filters::GetRow); 1.101 + Accessible* row = rowIter.Next(); 1.102 + if (!row) 1.103 + return false; 1.104 + 1.105 + do { 1.106 + if (!nsAccUtils::IsARIASelected(row)) { 1.107 + Accessible* cell = GetCellInRowAt(row, aColIdx); 1.108 + if (!cell || !nsAccUtils::IsARIASelected(cell)) 1.109 + return false; 1.110 + } 1.111 + } while ((row = rowIter.Next())); 1.112 + 1.113 + return true; 1.114 +} 1.115 + 1.116 +bool 1.117 +ARIAGridAccessible::IsRowSelected(uint32_t aRowIdx) 1.118 +{ 1.119 + Accessible* row = GetRowAt(aRowIdx); 1.120 + if(!row) 1.121 + return false; 1.122 + 1.123 + if (!nsAccUtils::IsARIASelected(row)) { 1.124 + AccIterator cellIter(row, filters::GetCell); 1.125 + Accessible* cell = nullptr; 1.126 + while ((cell = cellIter.Next())) { 1.127 + if (!nsAccUtils::IsARIASelected(cell)) 1.128 + return false; 1.129 + } 1.130 + } 1.131 + 1.132 + return true; 1.133 +} 1.134 + 1.135 +bool 1.136 +ARIAGridAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx) 1.137 +{ 1.138 + Accessible* row = GetRowAt(aRowIdx); 1.139 + if(!row) 1.140 + return false; 1.141 + 1.142 + if (!nsAccUtils::IsARIASelected(row)) { 1.143 + Accessible* cell = GetCellInRowAt(row, aColIdx); 1.144 + if (!cell || !nsAccUtils::IsARIASelected(cell)) 1.145 + return false; 1.146 + } 1.147 + 1.148 + return true; 1.149 +} 1.150 + 1.151 +uint32_t 1.152 +ARIAGridAccessible::SelectedCellCount() 1.153 +{ 1.154 + uint32_t count = 0, colCount = ColCount(); 1.155 + 1.156 + AccIterator rowIter(this, filters::GetRow); 1.157 + Accessible* row = nullptr; 1.158 + 1.159 + while ((row = rowIter.Next())) { 1.160 + if (nsAccUtils::IsARIASelected(row)) { 1.161 + count += colCount; 1.162 + continue; 1.163 + } 1.164 + 1.165 + AccIterator cellIter(row, filters::GetCell); 1.166 + Accessible* cell = nullptr; 1.167 + 1.168 + while ((cell = cellIter.Next())) { 1.169 + if (nsAccUtils::IsARIASelected(cell)) 1.170 + count++; 1.171 + } 1.172 + } 1.173 + 1.174 + return count; 1.175 +} 1.176 + 1.177 +uint32_t 1.178 +ARIAGridAccessible::SelectedColCount() 1.179 +{ 1.180 + uint32_t colCount = ColCount(); 1.181 + if (!colCount) 1.182 + return 0; 1.183 + 1.184 + AccIterator rowIter(this, filters::GetRow); 1.185 + Accessible* row = rowIter.Next(); 1.186 + if (!row) 1.187 + return 0; 1.188 + 1.189 + nsTArray<bool> isColSelArray(colCount); 1.190 + isColSelArray.AppendElements(colCount); 1.191 + memset(isColSelArray.Elements(), true, colCount * sizeof(bool)); 1.192 + 1.193 + uint32_t selColCount = colCount; 1.194 + do { 1.195 + if (nsAccUtils::IsARIASelected(row)) 1.196 + continue; 1.197 + 1.198 + AccIterator cellIter(row, filters::GetCell); 1.199 + Accessible* cell = nullptr; 1.200 + for (uint32_t colIdx = 0; 1.201 + (cell = cellIter.Next()) && colIdx < colCount; colIdx++) 1.202 + if (isColSelArray[colIdx] && !nsAccUtils::IsARIASelected(cell)) { 1.203 + isColSelArray[colIdx] = false; 1.204 + selColCount--; 1.205 + } 1.206 + } while ((row = rowIter.Next())); 1.207 + 1.208 + return selColCount; 1.209 +} 1.210 + 1.211 +uint32_t 1.212 +ARIAGridAccessible::SelectedRowCount() 1.213 +{ 1.214 + uint32_t count = 0; 1.215 + 1.216 + AccIterator rowIter(this, filters::GetRow); 1.217 + Accessible* row = nullptr; 1.218 + 1.219 + while ((row = rowIter.Next())) { 1.220 + if (nsAccUtils::IsARIASelected(row)) { 1.221 + count++; 1.222 + continue; 1.223 + } 1.224 + 1.225 + AccIterator cellIter(row, filters::GetCell); 1.226 + Accessible* cell = cellIter.Next(); 1.227 + if (!cell) 1.228 + continue; 1.229 + 1.230 + bool isRowSelected = true; 1.231 + do { 1.232 + if (!nsAccUtils::IsARIASelected(cell)) { 1.233 + isRowSelected = false; 1.234 + break; 1.235 + } 1.236 + } while ((cell = cellIter.Next())); 1.237 + 1.238 + if (isRowSelected) 1.239 + count++; 1.240 + } 1.241 + 1.242 + return count; 1.243 +} 1.244 + 1.245 +void 1.246 +ARIAGridAccessible::SelectedCells(nsTArray<Accessible*>* aCells) 1.247 +{ 1.248 + AccIterator rowIter(this, filters::GetRow); 1.249 + 1.250 + Accessible* row = nullptr; 1.251 + while ((row = rowIter.Next())) { 1.252 + AccIterator cellIter(row, filters::GetCell); 1.253 + Accessible* cell = nullptr; 1.254 + 1.255 + if (nsAccUtils::IsARIASelected(row)) { 1.256 + while ((cell = cellIter.Next())) 1.257 + aCells->AppendElement(cell); 1.258 + 1.259 + continue; 1.260 + } 1.261 + 1.262 + while ((cell = cellIter.Next())) { 1.263 + if (nsAccUtils::IsARIASelected(cell)) 1.264 + aCells->AppendElement(cell); 1.265 + } 1.266 + } 1.267 +} 1.268 + 1.269 +void 1.270 +ARIAGridAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells) 1.271 +{ 1.272 + uint32_t colCount = ColCount(); 1.273 + 1.274 + AccIterator rowIter(this, filters::GetRow); 1.275 + Accessible* row = nullptr; 1.276 + for (uint32_t rowIdx = 0; (row = rowIter.Next()); rowIdx++) { 1.277 + if (nsAccUtils::IsARIASelected(row)) { 1.278 + for (uint32_t colIdx = 0; colIdx < colCount; colIdx++) 1.279 + aCells->AppendElement(rowIdx * colCount + colIdx); 1.280 + 1.281 + continue; 1.282 + } 1.283 + 1.284 + AccIterator cellIter(row, filters::GetCell); 1.285 + Accessible* cell = nullptr; 1.286 + for (uint32_t colIdx = 0; (cell = cellIter.Next()); colIdx++) { 1.287 + if (nsAccUtils::IsARIASelected(cell)) 1.288 + aCells->AppendElement(rowIdx * colCount + colIdx); 1.289 + } 1.290 + } 1.291 +} 1.292 + 1.293 +void 1.294 +ARIAGridAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols) 1.295 +{ 1.296 + uint32_t colCount = ColCount(); 1.297 + if (!colCount) 1.298 + return; 1.299 + 1.300 + AccIterator rowIter(this, filters::GetRow); 1.301 + Accessible* row = rowIter.Next(); 1.302 + if (!row) 1.303 + return; 1.304 + 1.305 + nsTArray<bool> isColSelArray(colCount); 1.306 + isColSelArray.AppendElements(colCount); 1.307 + memset(isColSelArray.Elements(), true, colCount * sizeof(bool)); 1.308 + 1.309 + do { 1.310 + if (nsAccUtils::IsARIASelected(row)) 1.311 + continue; 1.312 + 1.313 + AccIterator cellIter(row, filters::GetCell); 1.314 + Accessible* cell = nullptr; 1.315 + for (uint32_t colIdx = 0; 1.316 + (cell = cellIter.Next()) && colIdx < colCount; colIdx++) 1.317 + if (isColSelArray[colIdx] && !nsAccUtils::IsARIASelected(cell)) { 1.318 + isColSelArray[colIdx] = false; 1.319 + } 1.320 + } while ((row = rowIter.Next())); 1.321 + 1.322 + for (uint32_t colIdx = 0; colIdx < colCount; colIdx++) 1.323 + if (isColSelArray[colIdx]) 1.324 + aCols->AppendElement(colIdx); 1.325 +} 1.326 + 1.327 +void 1.328 +ARIAGridAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows) 1.329 +{ 1.330 + AccIterator rowIter(this, filters::GetRow); 1.331 + Accessible* row = nullptr; 1.332 + for (uint32_t rowIdx = 0; (row = rowIter.Next()); rowIdx++) { 1.333 + if (nsAccUtils::IsARIASelected(row)) { 1.334 + aRows->AppendElement(rowIdx); 1.335 + continue; 1.336 + } 1.337 + 1.338 + AccIterator cellIter(row, filters::GetCell); 1.339 + Accessible* cell = cellIter.Next(); 1.340 + if (!cell) 1.341 + continue; 1.342 + 1.343 + bool isRowSelected = true; 1.344 + do { 1.345 + if (!nsAccUtils::IsARIASelected(cell)) { 1.346 + isRowSelected = false; 1.347 + break; 1.348 + } 1.349 + } while ((cell = cellIter.Next())); 1.350 + 1.351 + if (isRowSelected) 1.352 + aRows->AppendElement(rowIdx); 1.353 + } 1.354 +} 1.355 + 1.356 +void 1.357 +ARIAGridAccessible::SelectRow(uint32_t aRowIdx) 1.358 +{ 1.359 + AccIterator rowIter(this, filters::GetRow); 1.360 + 1.361 + Accessible* row = nullptr; 1.362 + for (uint32_t rowIdx = 0; (row = rowIter.Next()); rowIdx++) { 1.363 + DebugOnly<nsresult> rv = SetARIASelected(row, rowIdx == aRowIdx); 1.364 + NS_ASSERTION(NS_SUCCEEDED(rv), "SetARIASelected() Shouldn't fail!"); 1.365 + } 1.366 +} 1.367 + 1.368 +void 1.369 +ARIAGridAccessible::SelectCol(uint32_t aColIdx) 1.370 +{ 1.371 + AccIterator rowIter(this, filters::GetRow); 1.372 + 1.373 + Accessible* row = nullptr; 1.374 + while ((row = rowIter.Next())) { 1.375 + // Unselect all cells in the row. 1.376 + DebugOnly<nsresult> rv = SetARIASelected(row, false); 1.377 + NS_ASSERTION(NS_SUCCEEDED(rv), "SetARIASelected() Shouldn't fail!"); 1.378 + 1.379 + // Select cell at the column index. 1.380 + Accessible* cell = GetCellInRowAt(row, aColIdx); 1.381 + if (cell) 1.382 + SetARIASelected(cell, true); 1.383 + } 1.384 +} 1.385 + 1.386 +void 1.387 +ARIAGridAccessible::UnselectRow(uint32_t aRowIdx) 1.388 +{ 1.389 + Accessible* row = GetRowAt(aRowIdx); 1.390 + 1.391 + if (row) 1.392 + SetARIASelected(row, false); 1.393 +} 1.394 + 1.395 +void 1.396 +ARIAGridAccessible::UnselectCol(uint32_t aColIdx) 1.397 +{ 1.398 + AccIterator rowIter(this, filters::GetRow); 1.399 + 1.400 + Accessible* row = nullptr; 1.401 + while ((row = rowIter.Next())) { 1.402 + Accessible* cell = GetCellInRowAt(row, aColIdx); 1.403 + if (cell) 1.404 + SetARIASelected(cell, false); 1.405 + } 1.406 +} 1.407 + 1.408 +//////////////////////////////////////////////////////////////////////////////// 1.409 +// Protected 1.410 + 1.411 +bool 1.412 +ARIAGridAccessible::IsValidRow(int32_t aRow) 1.413 +{ 1.414 + if (aRow < 0) 1.415 + return false; 1.416 + 1.417 + int32_t rowCount = 0; 1.418 + GetRowCount(&rowCount); 1.419 + return aRow < rowCount; 1.420 +} 1.421 + 1.422 +bool 1.423 +ARIAGridAccessible::IsValidColumn(int32_t aColumn) 1.424 +{ 1.425 + if (aColumn < 0) 1.426 + return false; 1.427 + 1.428 + int32_t colCount = 0; 1.429 + GetColumnCount(&colCount); 1.430 + return aColumn < colCount; 1.431 +} 1.432 + 1.433 +Accessible* 1.434 +ARIAGridAccessible::GetRowAt(int32_t aRow) 1.435 +{ 1.436 + int32_t rowIdx = aRow; 1.437 + 1.438 + AccIterator rowIter(this, filters::GetRow); 1.439 + 1.440 + Accessible* row = rowIter.Next(); 1.441 + while (rowIdx != 0 && (row = rowIter.Next())) 1.442 + rowIdx--; 1.443 + 1.444 + return row; 1.445 +} 1.446 + 1.447 +Accessible* 1.448 +ARIAGridAccessible::GetCellInRowAt(Accessible* aRow, int32_t aColumn) 1.449 +{ 1.450 + int32_t colIdx = aColumn; 1.451 + 1.452 + AccIterator cellIter(aRow, filters::GetCell); 1.453 + Accessible* cell = cellIter.Next(); 1.454 + while (colIdx != 0 && (cell = cellIter.Next())) 1.455 + colIdx--; 1.456 + 1.457 + return cell; 1.458 +} 1.459 + 1.460 +nsresult 1.461 +ARIAGridAccessible::SetARIASelected(Accessible* aAccessible, 1.462 + bool aIsSelected, bool aNotify) 1.463 +{ 1.464 + nsIContent *content = aAccessible->GetContent(); 1.465 + NS_ENSURE_STATE(content); 1.466 + 1.467 + nsresult rv = NS_OK; 1.468 + if (aIsSelected) 1.469 + rv = content->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected, 1.470 + NS_LITERAL_STRING("true"), aNotify); 1.471 + else 1.472 + rv = content->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected, 1.473 + NS_LITERAL_STRING("false"), aNotify); 1.474 + 1.475 + NS_ENSURE_SUCCESS(rv, rv); 1.476 + 1.477 + // No "smart" select/unselect for internal call. 1.478 + if (!aNotify) 1.479 + return NS_OK; 1.480 + 1.481 + // If row or cell accessible was selected then we're able to not bother about 1.482 + // selection of its cells or its row because our algorithm is row oriented, 1.483 + // i.e. we check selection on row firstly and then on cells. 1.484 + if (aIsSelected) 1.485 + return NS_OK; 1.486 + 1.487 + roles::Role role = aAccessible->Role(); 1.488 + 1.489 + // If the given accessible is row that was unselected then remove 1.490 + // aria-selected from cell accessible. 1.491 + if (role == roles::ROW) { 1.492 + AccIterator cellIter(aAccessible, filters::GetCell); 1.493 + Accessible* cell = nullptr; 1.494 + 1.495 + while ((cell = cellIter.Next())) { 1.496 + rv = SetARIASelected(cell, false, false); 1.497 + NS_ENSURE_SUCCESS(rv, rv); 1.498 + } 1.499 + return NS_OK; 1.500 + } 1.501 + 1.502 + // If the given accessible is cell that was unselected and its row is selected 1.503 + // then remove aria-selected from row and put aria-selected on 1.504 + // siblings cells. 1.505 + if (role == roles::GRID_CELL || role == roles::ROWHEADER || 1.506 + role == roles::COLUMNHEADER) { 1.507 + Accessible* row = aAccessible->Parent(); 1.508 + 1.509 + if (row && row->Role() == roles::ROW && 1.510 + nsAccUtils::IsARIASelected(row)) { 1.511 + rv = SetARIASelected(row, false, false); 1.512 + NS_ENSURE_SUCCESS(rv, rv); 1.513 + 1.514 + AccIterator cellIter(row, filters::GetCell); 1.515 + Accessible* cell = nullptr; 1.516 + while ((cell = cellIter.Next())) { 1.517 + if (cell != aAccessible) { 1.518 + rv = SetARIASelected(cell, true, false); 1.519 + NS_ENSURE_SUCCESS(rv, rv); 1.520 + } 1.521 + } 1.522 + } 1.523 + } 1.524 + 1.525 + return NS_OK; 1.526 +} 1.527 + 1.528 +//////////////////////////////////////////////////////////////////////////////// 1.529 +// ARIAGridCellAccessible 1.530 +//////////////////////////////////////////////////////////////////////////////// 1.531 + 1.532 + 1.533 +//////////////////////////////////////////////////////////////////////////////// 1.534 +// Constructor 1.535 + 1.536 +ARIAGridCellAccessible:: 1.537 + ARIAGridCellAccessible(nsIContent* aContent, DocAccessible* aDoc) : 1.538 + HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this) 1.539 +{ 1.540 + mGenericTypes |= eTableCell; 1.541 +} 1.542 + 1.543 +//////////////////////////////////////////////////////////////////////////////// 1.544 +// nsISupports 1.545 + 1.546 +NS_IMPL_ISUPPORTS_INHERITED(ARIAGridCellAccessible, 1.547 + HyperTextAccessible, 1.548 + nsIAccessibleTableCell) 1.549 + 1.550 +//////////////////////////////////////////////////////////////////////////////// 1.551 +// nsIAccessibleTableCell 1.552 + 1.553 +TableAccessible* 1.554 +ARIAGridCellAccessible::Table() const 1.555 +{ 1.556 + Accessible* table = TableFor(Row()); 1.557 + return table ? table->AsTable() : nullptr; 1.558 +} 1.559 + 1.560 +uint32_t 1.561 +ARIAGridCellAccessible::ColIdx() const 1.562 +{ 1.563 + Accessible* row = Row(); 1.564 + if (!row) 1.565 + return 0; 1.566 + 1.567 + int32_t indexInRow = IndexInParent(); 1.568 + uint32_t colIdx = 0; 1.569 + for (int32_t idx = 0; idx < indexInRow; idx++) { 1.570 + Accessible* cell = row->GetChildAt(idx); 1.571 + roles::Role role = cell->Role(); 1.572 + if (role == roles::GRID_CELL || role == roles::ROWHEADER || 1.573 + role == roles::COLUMNHEADER) 1.574 + colIdx++; 1.575 + } 1.576 + 1.577 + return colIdx; 1.578 +} 1.579 + 1.580 +uint32_t 1.581 +ARIAGridCellAccessible::RowIdx() const 1.582 +{ 1.583 + return RowIndexFor(Row()); 1.584 +} 1.585 + 1.586 +bool 1.587 +ARIAGridCellAccessible::Selected() 1.588 +{ 1.589 + Accessible* row = Row(); 1.590 + if (!row) 1.591 + return false; 1.592 + 1.593 + return nsAccUtils::IsARIASelected(row) || nsAccUtils::IsARIASelected(this); 1.594 +} 1.595 + 1.596 +//////////////////////////////////////////////////////////////////////////////// 1.597 +// Accessible 1.598 + 1.599 +void 1.600 +ARIAGridCellAccessible::ApplyARIAState(uint64_t* aState) const 1.601 +{ 1.602 + HyperTextAccessibleWrap::ApplyARIAState(aState); 1.603 + 1.604 + // Return if the gridcell has aria-selected="true". 1.605 + if (*aState & states::SELECTED) 1.606 + return; 1.607 + 1.608 + // Check aria-selected="true" on the row. 1.609 + Accessible* row = Parent(); 1.610 + if (!row || row->Role() != roles::ROW) 1.611 + return; 1.612 + 1.613 + nsIContent *rowContent = row->GetContent(); 1.614 + if (nsAccUtils::HasDefinedARIAToken(rowContent, 1.615 + nsGkAtoms::aria_selected) && 1.616 + !rowContent->AttrValueIs(kNameSpaceID_None, 1.617 + nsGkAtoms::aria_selected, 1.618 + nsGkAtoms::_false, eCaseMatters)) 1.619 + *aState |= states::SELECTABLE | states::SELECTED; 1.620 +} 1.621 + 1.622 +already_AddRefed<nsIPersistentProperties> 1.623 +ARIAGridCellAccessible::NativeAttributes() 1.624 +{ 1.625 + nsCOMPtr<nsIPersistentProperties> attributes = 1.626 + HyperTextAccessibleWrap::NativeAttributes(); 1.627 + 1.628 + // Expose "table-cell-index" attribute. 1.629 + Accessible* thisRow = Row(); 1.630 + if (!thisRow) 1.631 + return attributes.forget(); 1.632 + 1.633 + int32_t colIdx = 0, colCount = 0; 1.634 + uint32_t childCount = thisRow->ChildCount(); 1.635 + for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) { 1.636 + Accessible* child = thisRow->GetChildAt(childIdx); 1.637 + if (child == this) 1.638 + colIdx = colCount; 1.639 + 1.640 + roles::Role role = child->Role(); 1.641 + if (role == roles::GRID_CELL || role == roles::ROWHEADER || 1.642 + role == roles::COLUMNHEADER) 1.643 + colCount++; 1.644 + } 1.645 + 1.646 + int32_t rowIdx = RowIndexFor(thisRow); 1.647 + 1.648 + nsAutoString stringIdx; 1.649 + stringIdx.AppendInt(rowIdx * colCount + colIdx); 1.650 + nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx); 1.651 + 1.652 + return attributes.forget(); 1.653 +} 1.654 + 1.655 +void 1.656 +ARIAGridCellAccessible::Shutdown() 1.657 +{ 1.658 + mTableCell = nullptr; 1.659 + HyperTextAccessibleWrap::Shutdown(); 1.660 +}