XULTreeGridAccessible.cpp (21892B)
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 "XULTreeGridAccessible.h" 7 8 #include <stdint.h> 9 #include "AccAttributes.h" 10 #include "LocalAccessible-inl.h" 11 #include "nsAccCache.h" 12 #include "nsAccessibilityService.h" 13 #include "nsAccUtils.h" 14 #include "DocAccessible.h" 15 #include "nsEventShell.h" 16 #include "Relation.h" 17 #include "mozilla/a11y/Role.h" 18 #include "States.h" 19 #include "nsQueryObject.h" 20 #include "nsTreeColumns.h" 21 22 #include "nsITreeSelection.h" 23 #include "nsComponentManagerUtils.h" 24 #include "mozilla/PresShell.h" 25 #include "mozilla/a11y/TableAccessible.h" 26 #include "mozilla/dom/Element.h" 27 #include "mozilla/dom/TreeColumnBinding.h" 28 #include "mozilla/dom/XULTreeElementBinding.h" 29 30 using namespace mozilla::a11y; 31 using namespace mozilla; 32 33 XULTreeGridAccessible::~XULTreeGridAccessible() {} 34 35 //////////////////////////////////////////////////////////////////////////////// 36 // XULTreeGridAccessible: Table 37 38 uint32_t XULTreeGridAccessible::ColCount() const { 39 return nsCoreUtils::GetSensibleColumnCount(mTree); 40 } 41 42 uint32_t XULTreeGridAccessible::RowCount() { 43 if (!mTreeView) return 0; 44 45 int32_t rowCount = 0; 46 mTreeView->GetRowCount(&rowCount); 47 return rowCount >= 0 ? rowCount : 0; 48 } 49 50 uint32_t XULTreeGridAccessible::SelectedCellCount() { 51 return SelectedRowCount() * ColCount(); 52 } 53 54 uint32_t XULTreeGridAccessible::SelectedColCount() { 55 // If all the row has been selected, then all the columns are selected, 56 // because we can't select a column alone. 57 58 uint32_t selectedRowCount = SelectedItemCount(); 59 return selectedRowCount > 0 && selectedRowCount == RowCount() ? ColCount() 60 : 0; 61 } 62 63 uint32_t XULTreeGridAccessible::SelectedRowCount() { 64 return SelectedItemCount(); 65 } 66 67 void XULTreeGridAccessible::SelectedCells(nsTArray<Accessible*>* aCells) { 68 uint32_t colCount = ColCount(), rowCount = RowCount(); 69 70 for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) { 71 if (IsRowSelected(rowIdx)) { 72 for (uint32_t colIdx = 0; colIdx < colCount; colIdx++) { 73 LocalAccessible* cell = CellAt(rowIdx, colIdx); 74 aCells->AppendElement(cell); 75 } 76 } 77 } 78 } 79 80 void XULTreeGridAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells) { 81 uint32_t colCount = ColCount(), rowCount = RowCount(); 82 83 for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) { 84 if (IsRowSelected(rowIdx)) { 85 for (uint32_t colIdx = 0; colIdx < colCount; colIdx++) { 86 aCells->AppendElement(rowIdx * colCount + colIdx); 87 } 88 } 89 } 90 } 91 92 void XULTreeGridAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols) { 93 if (RowCount() != SelectedRowCount()) return; 94 95 uint32_t colCount = ColCount(); 96 aCols->SetCapacity(colCount); 97 for (uint32_t colIdx = 0; colIdx < colCount; colIdx++) { 98 aCols->AppendElement(colIdx); 99 } 100 } 101 102 void XULTreeGridAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows) { 103 uint32_t rowCount = RowCount(); 104 for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) { 105 if (IsRowSelected(rowIdx)) aRows->AppendElement(rowIdx); 106 } 107 } 108 109 LocalAccessible* XULTreeGridAccessible::CellAt(uint32_t aRowIndex, 110 uint32_t aColumnIndex) { 111 XULTreeItemAccessibleBase* rowAcc = GetTreeItemAccessible(aRowIndex); 112 if (!rowAcc) return nullptr; 113 114 RefPtr<nsTreeColumn> column = 115 nsCoreUtils::GetSensibleColumnAt(mTree, aColumnIndex); 116 if (!column) return nullptr; 117 118 return rowAcc->GetCellAccessible(column); 119 } 120 121 void XULTreeGridAccessible::ColDescription(uint32_t aColIdx, 122 nsString& aDescription) { 123 aDescription.Truncate(); 124 125 LocalAccessible* treeColumns = LocalAccessible::LocalChildAt(0); 126 if (treeColumns) { 127 LocalAccessible* treeColumnItem = treeColumns->LocalChildAt(aColIdx); 128 if (treeColumnItem) treeColumnItem->Name(aDescription); 129 } 130 } 131 132 bool XULTreeGridAccessible::IsColSelected(uint32_t aColIdx) { 133 // If all the row has been selected, then all the columns are selected. 134 // Because we can't select a column alone. 135 return SelectedItemCount() == RowCount(); 136 } 137 138 bool XULTreeGridAccessible::IsRowSelected(uint32_t aRowIdx) { 139 if (!mTreeView) return false; 140 141 nsCOMPtr<nsITreeSelection> selection; 142 nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection)); 143 NS_ENSURE_SUCCESS(rv, false); 144 145 bool isSelected = false; 146 selection->IsSelected(aRowIdx, &isSelected); 147 return isSelected; 148 } 149 150 bool XULTreeGridAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx) { 151 return IsRowSelected(aRowIdx); 152 } 153 154 int32_t XULTreeGridAccessible::ColIndexAt(uint32_t aCellIdx) { 155 uint32_t colCount = ColCount(); 156 if (colCount < 1 || aCellIdx >= colCount * RowCount()) { 157 return -1; // Error: column count is 0 or index out of bounds. 158 } 159 160 return static_cast<int32_t>(aCellIdx % colCount); 161 } 162 163 int32_t XULTreeGridAccessible::RowIndexAt(uint32_t aCellIdx) { 164 uint32_t colCount = ColCount(); 165 if (colCount < 1 || aCellIdx >= colCount * RowCount()) { 166 return -1; // Error: column count is 0 or index out of bounds. 167 } 168 169 return static_cast<int32_t>(aCellIdx / colCount); 170 } 171 172 void XULTreeGridAccessible::RowAndColIndicesAt(uint32_t aCellIdx, 173 int32_t* aRowIdx, 174 int32_t* aColIdx) { 175 uint32_t colCount = ColCount(); 176 if (colCount < 1 || aCellIdx >= colCount * RowCount()) { 177 *aRowIdx = -1; 178 *aColIdx = -1; 179 return; // Error: column count is 0 or index out of bounds. 180 } 181 182 *aRowIdx = static_cast<int32_t>(aCellIdx / colCount); 183 *aColIdx = static_cast<int32_t>(aCellIdx % colCount); 184 } 185 186 //////////////////////////////////////////////////////////////////////////////// 187 // XULTreeGridAccessible: LocalAccessible implementation 188 189 role XULTreeGridAccessible::NativeRole() const { 190 RefPtr<nsTreeColumns> treeColumns = mTree->GetColumns(FlushType::None); 191 if (!treeColumns) { 192 NS_ERROR("No treecolumns object for tree!"); 193 return roles::NOTHING; 194 } 195 196 nsTreeColumn* primaryColumn = treeColumns->GetPrimaryColumn(); 197 198 return primaryColumn ? roles::TREE_TABLE : roles::TABLE; 199 } 200 201 //////////////////////////////////////////////////////////////////////////////// 202 // XULTreeGridAccessible: XULTreeAccessible implementation 203 204 already_AddRefed<XULTreeItemAccessibleBase> 205 XULTreeGridAccessible::CreateTreeItemAccessible(int32_t aRow) const { 206 RefPtr<XULTreeItemAccessibleBase> accessible = new XULTreeGridRowAccessible( 207 mContent, mDoc, const_cast<XULTreeGridAccessible*>(this), mTree, 208 mTreeView, aRow); 209 210 return accessible.forget(); 211 } 212 213 //////////////////////////////////////////////////////////////////////////////// 214 // XULTreeGridRowAccessible 215 //////////////////////////////////////////////////////////////////////////////// 216 217 XULTreeGridRowAccessible::XULTreeGridRowAccessible( 218 nsIContent* aContent, DocAccessible* aDoc, LocalAccessible* aTreeAcc, 219 dom::XULTreeElement* aTree, nsITreeView* aTreeView, int32_t aRow) 220 : XULTreeItemAccessibleBase(aContent, aDoc, aTreeAcc, aTree, aTreeView, 221 aRow), 222 mAccessibleCache(kDefaultTreeCacheLength) { 223 mGenericTypes |= eTableRow; 224 mStateFlags |= eNoKidsFromDOM; 225 } 226 227 XULTreeGridRowAccessible::~XULTreeGridRowAccessible() {} 228 229 //////////////////////////////////////////////////////////////////////////////// 230 // XULTreeGridRowAccessible: nsISupports and cycle collection implementation 231 232 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridRowAccessible, 233 XULTreeItemAccessibleBase, mAccessibleCache) 234 235 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XULTreeGridRowAccessible) 236 NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase) 237 238 NS_IMPL_ADDREF_INHERITED(XULTreeGridRowAccessible, XULTreeItemAccessibleBase) 239 NS_IMPL_RELEASE_INHERITED(XULTreeGridRowAccessible, XULTreeItemAccessibleBase) 240 241 //////////////////////////////////////////////////////////////////////////////// 242 // XULTreeGridRowAccessible: LocalAccessible implementation 243 244 void XULTreeGridRowAccessible::Shutdown() { 245 if (mDoc && !mDoc->IsDefunct()) { 246 UnbindCacheEntriesFromDocument(mAccessibleCache); 247 } 248 249 XULTreeItemAccessibleBase::Shutdown(); 250 } 251 252 role XULTreeGridRowAccessible::NativeRole() const { return roles::ROW; } 253 254 ENameValueFlag XULTreeGridRowAccessible::DirectName(nsString& aName) const { 255 aName.Truncate(); 256 257 // XXX: the row name sholdn't be a concatenation of cell names (bug 664384). 258 RefPtr<nsTreeColumn> column = nsCoreUtils::GetFirstSensibleColumn(mTree); 259 while (column) { 260 if (!aName.IsEmpty()) aName.Append(' '); 261 262 nsAutoString cellName; 263 GetCellName(column, cellName); 264 aName.Append(cellName); 265 266 column = nsCoreUtils::GetNextSensibleColumn(column); 267 } 268 269 return eNameOK; 270 } 271 272 LocalAccessible* XULTreeGridRowAccessible::LocalChildAtPoint( 273 int32_t aX, int32_t aY, EWhichChildAtPoint aWhichChild) { 274 nsIFrame* frame = GetFrame(); 275 if (!frame) return nullptr; 276 277 nsPresContext* presContext = frame->PresContext(); 278 PresShell* presShell = presContext->PresShell(); 279 280 nsIFrame* rootFrame = presShell->GetRootFrame(); 281 NS_ENSURE_TRUE(rootFrame, nullptr); 282 283 CSSIntRect rootRect = rootFrame->GetScreenRect(); 284 285 int32_t clientX = presContext->DevPixelsToIntCSSPixels(aX) - rootRect.X(); 286 int32_t clientY = presContext->DevPixelsToIntCSSPixels(aY) - rootRect.Y(); 287 288 ErrorResult rv; 289 dom::TreeCellInfo cellInfo; 290 mTree->GetCellAt(clientX, clientY, cellInfo, rv); 291 292 // Return if we failed to find tree cell in the row for the given point. 293 if (cellInfo.mRow != mRow || !cellInfo.mCol) return nullptr; 294 295 return GetCellAccessible(cellInfo.mCol); 296 } 297 298 LocalAccessible* XULTreeGridRowAccessible::LocalChildAt(uint32_t aIndex) const { 299 if (IsDefunct()) return nullptr; 300 301 RefPtr<nsTreeColumn> column = nsCoreUtils::GetSensibleColumnAt(mTree, aIndex); 302 if (!column) return nullptr; 303 304 return GetCellAccessible(column); 305 } 306 307 uint32_t XULTreeGridRowAccessible::ChildCount() const { 308 return nsCoreUtils::GetSensibleColumnCount(mTree); 309 } 310 311 //////////////////////////////////////////////////////////////////////////////// 312 // XULTreeGridRowAccessible: XULTreeItemAccessibleBase implementation 313 314 XULTreeGridCellAccessible* XULTreeGridRowAccessible::GetCellAccessible( 315 nsTreeColumn* aColumn) const { 316 MOZ_ASSERT(aColumn, "No tree column!"); 317 318 void* key = static_cast<void*>(aColumn); 319 XULTreeGridCellAccessible* cachedCell = mAccessibleCache.GetWeak(key); 320 if (cachedCell) return cachedCell; 321 322 RefPtr<XULTreeGridCellAccessible> cell = new XULTreeGridCellAccessible( 323 mContent, mDoc, const_cast<XULTreeGridRowAccessible*>(this), mTree, 324 mTreeView, mRow, aColumn); 325 mAccessibleCache.InsertOrUpdate(key, RefPtr{cell}); 326 Document()->BindToDocument(cell, nullptr); 327 return cell; 328 } 329 330 void XULTreeGridRowAccessible::RowInvalidated(int32_t aStartColIdx, 331 int32_t aEndColIdx) { 332 RefPtr<nsTreeColumns> treeColumns = mTree->GetColumns(FlushType::None); 333 if (!treeColumns) return; 334 335 bool nameChanged = false; 336 for (int32_t colIdx = aStartColIdx; colIdx <= aEndColIdx; ++colIdx) { 337 nsTreeColumn* column = treeColumns->GetColumnAt(colIdx); 338 if (column && !nsCoreUtils::IsColumnHidden(column)) { 339 XULTreeGridCellAccessible* cell = GetCellAccessible(column); 340 if (cell) nameChanged |= cell->CellInvalidated(); 341 } 342 } 343 344 if (nameChanged) { 345 nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this); 346 } 347 } 348 349 //////////////////////////////////////////////////////////////////////////////// 350 // XULTreeGridCellAccessible 351 //////////////////////////////////////////////////////////////////////////////// 352 353 XULTreeGridCellAccessible::XULTreeGridCellAccessible( 354 nsIContent* aContent, DocAccessible* aDoc, 355 XULTreeGridRowAccessible* aRowAcc, dom::XULTreeElement* aTree, 356 nsITreeView* aTreeView, int32_t aRow, nsTreeColumn* aColumn) 357 : LeafAccessible(aContent, aDoc), 358 mTree(aTree), 359 mTreeView(aTreeView), 360 mRow(aRow), 361 mColumn(aColumn) { 362 mParent = aRowAcc; 363 mStateFlags |= eSharedNode; 364 mGenericTypes |= eTableCell; 365 366 NS_ASSERTION(mTreeView, "mTreeView is null"); 367 368 if (mColumn->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX) { 369 mTreeView->GetCellValue(mRow, mColumn, mCachedTextEquiv); 370 } else { 371 mTreeView->GetCellText(mRow, mColumn, mCachedTextEquiv); 372 } 373 } 374 375 XULTreeGridCellAccessible::~XULTreeGridCellAccessible() {} 376 377 //////////////////////////////////////////////////////////////////////////////// 378 // XULTreeGridCellAccessible: nsISupports implementation 379 380 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible, LeafAccessible, 381 mTree, mColumn) 382 383 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XULTreeGridCellAccessible) 384 NS_INTERFACE_MAP_END_INHERITING(LeafAccessible) 385 NS_IMPL_ADDREF_INHERITED(XULTreeGridCellAccessible, LeafAccessible) 386 NS_IMPL_RELEASE_INHERITED(XULTreeGridCellAccessible, LeafAccessible) 387 388 //////////////////////////////////////////////////////////////////////////////// 389 // XULTreeGridCellAccessible: LocalAccessible 390 391 void XULTreeGridCellAccessible::Shutdown() { 392 mTree = nullptr; 393 mTreeView = nullptr; 394 mRow = -1; 395 mColumn = nullptr; 396 mParent = nullptr; // null-out to prevent base class's shutdown ops 397 398 LeafAccessible::Shutdown(); 399 } 400 401 Accessible* XULTreeGridCellAccessible::FocusedChild() { return nullptr; } 402 403 ENameValueFlag XULTreeGridCellAccessible::DirectName(nsString& aName) const { 404 aName.Truncate(); 405 406 if (!mTreeView) return eNameOK; 407 408 mTreeView->GetCellText(mRow, mColumn, aName); 409 410 // If there is still no name try the cell value: 411 // This is for graphical cells. We need tree/table view implementors to 412 // implement FooView::GetCellValue to return a meaningful string for cases 413 // where there is something shown in the cell (non-text) such as a star icon; 414 // in which case GetCellValue for that cell would return "starred" or 415 // "flagged" for example. 416 if (aName.IsEmpty()) mTreeView->GetCellValue(mRow, mColumn, aName); 417 418 return eNameOK; 419 } 420 421 nsIntRect XULTreeGridCellAccessible::BoundsInCSSPixels() const { 422 // Get bounds for tree cell and add x and y of treechildren element to 423 // x and y of the cell. 424 nsresult rv; 425 nsIntRect rect = mTree->GetCoordsForCellItem(mRow, mColumn, u"cell"_ns, rv); 426 if (NS_FAILED(rv)) { 427 return nsIntRect(); 428 } 429 430 RefPtr<dom::Element> bodyElement = mTree->GetTreeBody(); 431 if (!bodyElement || !bodyElement->IsXULElement()) { 432 return nsIntRect(); 433 } 434 435 nsIFrame* bodyFrame = bodyElement->GetPrimaryFrame(); 436 if (!bodyFrame) { 437 return nsIntRect(); 438 } 439 440 CSSIntRect screenRect = bodyFrame->GetScreenRect(); 441 rect.x += screenRect.x; 442 rect.y += screenRect.y; 443 return rect; 444 } 445 446 nsRect XULTreeGridCellAccessible::BoundsInAppUnits() const { 447 nsIntRect bounds = BoundsInCSSPixels(); 448 nsPresContext* presContext = mDoc->PresContext(); 449 return nsRect(presContext->CSSPixelsToAppUnits(bounds.X()), 450 presContext->CSSPixelsToAppUnits(bounds.Y()), 451 presContext->CSSPixelsToAppUnits(bounds.Width()), 452 presContext->CSSPixelsToAppUnits(bounds.Height())); 453 } 454 455 bool XULTreeGridCellAccessible::HasPrimaryAction() const { 456 return mColumn->Cycler() || 457 (mColumn->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX && 458 IsEditableCell()); 459 } 460 461 void XULTreeGridCellAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) { 462 aName.Truncate(); 463 464 if (aIndex != eAction_Click || !mTreeView) return; 465 466 if (mColumn->Cycler()) { 467 aName.AssignLiteral("cycle"); 468 return; 469 } 470 471 if (mColumn->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX && 472 IsEditableCell()) { 473 nsAutoString value; 474 mTreeView->GetCellValue(mRow, mColumn, value); 475 if (value.EqualsLiteral("true")) { 476 aName.AssignLiteral("uncheck"); 477 } else { 478 aName.AssignLiteral("check"); 479 } 480 } 481 } 482 483 //////////////////////////////////////////////////////////////////////////////// 484 // XULTreeGridCellAccessible: TableCell 485 486 TableAccessible* XULTreeGridCellAccessible::Table() const { 487 LocalAccessible* grandParent = mParent->LocalParent(); 488 if (grandParent) return grandParent->AsTable(); 489 490 return nullptr; 491 } 492 493 uint32_t XULTreeGridCellAccessible::ColIdx() const { 494 uint32_t colIdx = 0; 495 RefPtr<nsTreeColumn> column = mColumn; 496 while ((column = nsCoreUtils::GetPreviousSensibleColumn(column))) colIdx++; 497 498 return colIdx; 499 } 500 501 uint32_t XULTreeGridCellAccessible::RowIdx() const { return mRow; } 502 503 void XULTreeGridCellAccessible::ColHeaderCells( 504 nsTArray<Accessible*>* aHeaderCells) { 505 dom::Element* columnElm = mColumn->Element(); 506 507 LocalAccessible* headerCell = mDoc->GetAccessible(columnElm); 508 if (headerCell) aHeaderCells->AppendElement(headerCell); 509 } 510 511 bool XULTreeGridCellAccessible::Selected() { 512 nsCOMPtr<nsITreeSelection> selection; 513 nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection)); 514 NS_ENSURE_SUCCESS(rv, false); 515 516 bool selected = false; 517 selection->IsSelected(mRow, &selected); 518 return selected; 519 } 520 521 //////////////////////////////////////////////////////////////////////////////// 522 // XULTreeGridCellAccessible: LocalAccessible public implementation 523 524 already_AddRefed<AccAttributes> XULTreeGridCellAccessible::NativeAttributes() { 525 RefPtr<AccAttributes> attributes = new AccAttributes(); 526 527 // "table-cell-index" attribute 528 TableAccessible* table = Table(); 529 if (!table) return attributes.forget(); 530 531 attributes->SetAttribute(nsGkAtoms::tableCellIndex, 532 table->CellIndexAt(mRow, ColIdx())); 533 534 // "cycles" attribute 535 if (mColumn->Cycler()) { 536 attributes->SetAttribute(nsGkAtoms::cycles, true); 537 } 538 539 return attributes.forget(); 540 } 541 542 role XULTreeGridCellAccessible::NativeRole() const { return roles::GRID_CELL; } 543 544 uint64_t XULTreeGridCellAccessible::NativeState() const { 545 if (!mTreeView) return states::DEFUNCT; 546 547 // selectable/selected state 548 uint64_t states = 549 states::SELECTABLE; // keep in sync with NativeInteractiveState 550 551 nsCOMPtr<nsITreeSelection> selection; 552 mTreeView->GetSelection(getter_AddRefs(selection)); 553 if (selection) { 554 bool isSelected = false; 555 selection->IsSelected(mRow, &isSelected); 556 if (isSelected) states |= states::SELECTED; 557 } 558 559 // checked state 560 if (mColumn->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX) { 561 states |= states::CHECKABLE; 562 nsAutoString checked; 563 mTreeView->GetCellValue(mRow, mColumn, checked); 564 if (checked.EqualsIgnoreCase("true")) states |= states::CHECKED; 565 } 566 567 return states; 568 } 569 570 uint64_t XULTreeGridCellAccessible::NativeInteractiveState() const { 571 return states::SELECTABLE; 572 } 573 574 int32_t XULTreeGridCellAccessible::IndexInParent() const { return ColIdx(); } 575 576 Relation XULTreeGridCellAccessible::RelationByType(RelationType aType) const { 577 return Relation(); 578 } 579 580 //////////////////////////////////////////////////////////////////////////////// 581 // XULTreeGridCellAccessible: public implementation 582 583 bool XULTreeGridCellAccessible::CellInvalidated() { 584 nsAutoString textEquiv; 585 586 if (mColumn->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX) { 587 mTreeView->GetCellValue(mRow, mColumn, textEquiv); 588 if (mCachedTextEquiv != textEquiv) { 589 bool isEnabled = textEquiv.EqualsLiteral("true"); 590 RefPtr<AccEvent> accEvent = 591 new AccStateChangeEvent(this, states::CHECKED, isEnabled); 592 nsEventShell::FireEvent(accEvent); 593 594 mCachedTextEquiv = textEquiv; 595 return true; 596 } 597 598 return false; 599 } 600 601 mTreeView->GetCellText(mRow, mColumn, textEquiv); 602 if (mCachedTextEquiv != textEquiv) { 603 nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this); 604 mCachedTextEquiv = textEquiv; 605 return true; 606 } 607 608 return false; 609 } 610 611 //////////////////////////////////////////////////////////////////////////////// 612 // XULTreeGridCellAccessible: LocalAccessible protected implementation 613 614 LocalAccessible* XULTreeGridCellAccessible::GetSiblingAtOffset( 615 int32_t aOffset, nsresult* aError) const { 616 if (aError) *aError = NS_OK; // fail peacefully 617 618 RefPtr<nsTreeColumn> columnAtOffset(mColumn), column; 619 if (aOffset < 0) { 620 for (int32_t index = aOffset; index < 0 && columnAtOffset; index++) { 621 column = nsCoreUtils::GetPreviousSensibleColumn(columnAtOffset); 622 column.swap(columnAtOffset); 623 } 624 } else { 625 for (int32_t index = aOffset; index > 0 && columnAtOffset; index--) { 626 column = nsCoreUtils::GetNextSensibleColumn(columnAtOffset); 627 column.swap(columnAtOffset); 628 } 629 } 630 631 if (!columnAtOffset) return nullptr; 632 633 XULTreeItemAccessibleBase* rowAcc = 634 static_cast<XULTreeItemAccessibleBase*>(LocalParent()); 635 return rowAcc->GetCellAccessible(columnAtOffset); 636 } 637 638 void XULTreeGridCellAccessible::DispatchClickEvent( 639 uint32_t aActionIndex) const { 640 if (IsDefunct()) return; 641 642 RefPtr<dom::XULTreeElement> tree = mTree; 643 RefPtr<nsTreeColumn> column = mColumn; 644 nsCoreUtils::DispatchClickEvent(tree, mRow, column); 645 } 646 647 //////////////////////////////////////////////////////////////////////////////// 648 // XULTreeGridCellAccessible: protected implementation 649 650 bool XULTreeGridCellAccessible::IsEditableCell() const { 651 // XXX: logic corresponds to tree.xml, it's preferable to have interface 652 // method to check it. 653 bool isEditable = false; 654 nsresult rv = mTreeView->IsEditable(mRow, mColumn, &isEditable); 655 if (NS_FAILED(rv) || !isEditable) return false; 656 657 dom::Element* columnElm = mColumn->Element(); 658 659 if (!columnElm->AttrValueIs(kNameSpaceID_None, nsGkAtoms::editable, 660 nsGkAtoms::_true, eCaseMatters)) { 661 return false; 662 } 663 664 return mContent->AsElement()->AttrValueIs( 665 kNameSpaceID_None, nsGkAtoms::editable, nsGkAtoms::_true, eCaseMatters); 666 }