accessible/src/generic/ARIAGridAccessible.cpp

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

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

mercurial