XULTreeGridAccessible.cpp 22 KB

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