Bug 1889091 - Part 3: Specialize calls to native functions with variadic parameters...
[gecko.git] / accessible / xul / XULTreeGridAccessible.cpp
blob9b2e0cec33eee6cbc7c00733c0540c9c82467796
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/. */
6 #include "XULTreeGridAccessible.h"
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"
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"
30 using namespace mozilla::a11y;
31 using namespace mozilla;
33 XULTreeGridAccessible::~XULTreeGridAccessible() {}
35 ////////////////////////////////////////////////////////////////////////////////
36 // XULTreeGridAccessible: Table
38 uint32_t XULTreeGridAccessible::ColCount() const {
39 return nsCoreUtils::GetSensibleColumnCount(mTree);
42 uint32_t XULTreeGridAccessible::RowCount() {
43 if (!mTreeView) return 0;
45 int32_t rowCount = 0;
46 mTreeView->GetRowCount(&rowCount);
47 return rowCount >= 0 ? rowCount : 0;
50 uint32_t XULTreeGridAccessible::SelectedCellCount() {
51 return SelectedRowCount() * ColCount();
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.
58 uint32_t selectedRowCount = SelectedItemCount();
59 return selectedRowCount > 0 && selectedRowCount == RowCount() ? ColCount()
60 : 0;
63 uint32_t XULTreeGridAccessible::SelectedRowCount() {
64 return SelectedItemCount();
67 void XULTreeGridAccessible::SelectedCells(nsTArray<Accessible*>* aCells) {
68 uint32_t colCount = ColCount(), rowCount = RowCount();
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);
80 void XULTreeGridAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells) {
81 uint32_t colCount = ColCount(), rowCount = RowCount();
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);
92 void XULTreeGridAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols) {
93 if (RowCount() != SelectedRowCount()) return;
95 uint32_t colCount = ColCount();
96 aCols->SetCapacity(colCount);
97 for (uint32_t colIdx = 0; colIdx < colCount; colIdx++) {
98 aCols->AppendElement(colIdx);
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);
109 LocalAccessible* XULTreeGridAccessible::CellAt(uint32_t aRowIndex,
110 uint32_t aColumnIndex) {
111 XULTreeItemAccessibleBase* rowAcc = GetTreeItemAccessible(aRowIndex);
112 if (!rowAcc) return nullptr;
114 RefPtr<nsTreeColumn> column =
115 nsCoreUtils::GetSensibleColumnAt(mTree, aColumnIndex);
116 if (!column) return nullptr;
118 return rowAcc->GetCellAccessible(column);
121 void XULTreeGridAccessible::ColDescription(uint32_t aColIdx,
122 nsString& aDescription) {
123 aDescription.Truncate();
125 LocalAccessible* treeColumns = LocalAccessible::LocalChildAt(0);
126 if (treeColumns) {
127 LocalAccessible* treeColumnItem = treeColumns->LocalChildAt(aColIdx);
128 if (treeColumnItem) treeColumnItem->Name(aDescription);
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();
138 bool XULTreeGridAccessible::IsRowSelected(uint32_t aRowIdx) {
139 if (!mTreeView) return false;
141 nsCOMPtr<nsITreeSelection> selection;
142 nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection));
143 NS_ENSURE_SUCCESS(rv, false);
145 bool isSelected = false;
146 selection->IsSelected(aRowIdx, &isSelected);
147 return isSelected;
150 bool XULTreeGridAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx) {
151 return IsRowSelected(aRowIdx);
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.
160 return static_cast<int32_t>(aCellIdx % colCount);
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.
169 return static_cast<int32_t>(aCellIdx / colCount);
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.
182 *aRowIdx = static_cast<int32_t>(aCellIdx / colCount);
183 *aColIdx = static_cast<int32_t>(aCellIdx % colCount);
186 ////////////////////////////////////////////////////////////////////////////////
187 // XULTreeGridAccessible: LocalAccessible implementation
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;
196 nsTreeColumn* primaryColumn = treeColumns->GetPrimaryColumn();
198 return primaryColumn ? roles::TREE_TABLE : roles::TABLE;
201 ////////////////////////////////////////////////////////////////////////////////
202 // XULTreeGridAccessible: XULTreeAccessible implementation
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);
210 return accessible.forget();
213 ////////////////////////////////////////////////////////////////////////////////
214 // XULTreeGridRowAccessible
215 ////////////////////////////////////////////////////////////////////////////////
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;
227 XULTreeGridRowAccessible::~XULTreeGridRowAccessible() {}
229 ////////////////////////////////////////////////////////////////////////////////
230 // XULTreeGridRowAccessible: nsISupports and cycle collection implementation
232 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridRowAccessible,
233 XULTreeItemAccessibleBase, mAccessibleCache)
235 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XULTreeGridRowAccessible)
236 NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase)
238 NS_IMPL_ADDREF_INHERITED(XULTreeGridRowAccessible, XULTreeItemAccessibleBase)
239 NS_IMPL_RELEASE_INHERITED(XULTreeGridRowAccessible, XULTreeItemAccessibleBase)
241 ////////////////////////////////////////////////////////////////////////////////
242 // XULTreeGridRowAccessible: LocalAccessible implementation
244 void XULTreeGridRowAccessible::Shutdown() {
245 if (mDoc && !mDoc->IsDefunct()) {
246 UnbindCacheEntriesFromDocument(mAccessibleCache);
249 XULTreeItemAccessibleBase::Shutdown();
252 role XULTreeGridRowAccessible::NativeRole() const { return roles::ROW; }
254 ENameValueFlag XULTreeGridRowAccessible::Name(nsString& aName) const {
255 aName.Truncate();
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(' ');
262 nsAutoString cellName;
263 GetCellName(column, cellName);
264 aName.Append(cellName);
266 column = nsCoreUtils::GetNextSensibleColumn(column);
269 return eNameOK;
272 LocalAccessible* XULTreeGridRowAccessible::LocalChildAtPoint(
273 int32_t aX, int32_t aY, EWhichChildAtPoint aWhichChild) {
274 nsIFrame* frame = GetFrame();
275 if (!frame) return nullptr;
277 nsPresContext* presContext = frame->PresContext();
278 PresShell* presShell = presContext->PresShell();
280 nsIFrame* rootFrame = presShell->GetRootFrame();
281 NS_ENSURE_TRUE(rootFrame, nullptr);
283 CSSIntRect rootRect = rootFrame->GetScreenRect();
285 int32_t clientX = presContext->DevPixelsToIntCSSPixels(aX) - rootRect.X();
286 int32_t clientY = presContext->DevPixelsToIntCSSPixels(aY) - rootRect.Y();
288 ErrorResult rv;
289 dom::TreeCellInfo cellInfo;
290 mTree->GetCellAt(clientX, clientY, cellInfo, rv);
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;
295 return GetCellAccessible(cellInfo.mCol);
298 LocalAccessible* XULTreeGridRowAccessible::LocalChildAt(uint32_t aIndex) const {
299 if (IsDefunct()) return nullptr;
301 RefPtr<nsTreeColumn> column = nsCoreUtils::GetSensibleColumnAt(mTree, aIndex);
302 if (!column) return nullptr;
304 return GetCellAccessible(column);
307 uint32_t XULTreeGridRowAccessible::ChildCount() const {
308 return nsCoreUtils::GetSensibleColumnCount(mTree);
311 ////////////////////////////////////////////////////////////////////////////////
312 // XULTreeGridRowAccessible: XULTreeItemAccessibleBase implementation
314 XULTreeGridCellAccessible* XULTreeGridRowAccessible::GetCellAccessible(
315 nsTreeColumn* aColumn) const {
316 MOZ_ASSERT(aColumn, "No tree column!");
318 void* key = static_cast<void*>(aColumn);
319 XULTreeGridCellAccessible* cachedCell = mAccessibleCache.GetWeak(key);
320 if (cachedCell) return cachedCell;
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;
330 void XULTreeGridRowAccessible::RowInvalidated(int32_t aStartColIdx,
331 int32_t aEndColIdx) {
332 RefPtr<nsTreeColumns> treeColumns = mTree->GetColumns(FlushType::None);
333 if (!treeColumns) return;
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();
344 if (nameChanged) {
345 nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
349 ////////////////////////////////////////////////////////////////////////////////
350 // XULTreeGridCellAccessible
351 ////////////////////////////////////////////////////////////////////////////////
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;
366 NS_ASSERTION(mTreeView, "mTreeView is null");
368 if (mColumn->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX) {
369 mTreeView->GetCellValue(mRow, mColumn, mCachedTextEquiv);
370 } else {
371 mTreeView->GetCellText(mRow, mColumn, mCachedTextEquiv);
375 XULTreeGridCellAccessible::~XULTreeGridCellAccessible() {}
377 ////////////////////////////////////////////////////////////////////////////////
378 // XULTreeGridCellAccessible: nsISupports implementation
380 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible, LeafAccessible,
381 mTree, mColumn)
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)
388 ////////////////////////////////////////////////////////////////////////////////
389 // XULTreeGridCellAccessible: LocalAccessible
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
398 LeafAccessible::Shutdown();
401 Accessible* XULTreeGridCellAccessible::FocusedChild() { return nullptr; }
403 ENameValueFlag XULTreeGridCellAccessible::Name(nsString& aName) const {
404 aName.Truncate();
406 if (!mTreeView) return eNameOK;
408 mTreeView->GetCellText(mRow, mColumn, aName);
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);
418 return eNameOK;
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();
430 RefPtr<dom::Element> bodyElement = mTree->GetTreeBody();
431 if (!bodyElement || !bodyElement->IsXULElement()) {
432 return nsIntRect();
435 nsIFrame* bodyFrame = bodyElement->GetPrimaryFrame();
436 if (!bodyFrame) {
437 return nsIntRect();
440 CSSIntRect screenRect = bodyFrame->GetScreenRect();
441 rect.x += screenRect.x;
442 rect.y += screenRect.y;
443 return rect;
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()));
455 bool XULTreeGridCellAccessible::HasPrimaryAction() const {
456 return mColumn->Cycler() ||
457 (mColumn->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX &&
458 IsEditable());
461 void XULTreeGridCellAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) {
462 aName.Truncate();
464 if (aIndex != eAction_Click || !mTreeView) return;
466 if (mColumn->Cycler()) {
467 aName.AssignLiteral("cycle");
468 return;
471 if (mColumn->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX &&
472 IsEditable()) {
473 nsAutoString value;
474 mTreeView->GetCellValue(mRow, mColumn, value);
475 if (value.EqualsLiteral("true")) {
476 aName.AssignLiteral("uncheck");
477 } else {
478 aName.AssignLiteral("check");
483 ////////////////////////////////////////////////////////////////////////////////
484 // XULTreeGridCellAccessible: TableCell
486 TableAccessible* XULTreeGridCellAccessible::Table() const {
487 LocalAccessible* grandParent = mParent->LocalParent();
488 if (grandParent) return grandParent->AsTable();
490 return nullptr;
493 uint32_t XULTreeGridCellAccessible::ColIdx() const {
494 uint32_t colIdx = 0;
495 RefPtr<nsTreeColumn> column = mColumn;
496 while ((column = nsCoreUtils::GetPreviousSensibleColumn(column))) colIdx++;
498 return colIdx;
501 uint32_t XULTreeGridCellAccessible::RowIdx() const { return mRow; }
503 void XULTreeGridCellAccessible::ColHeaderCells(
504 nsTArray<Accessible*>* aHeaderCells) {
505 dom::Element* columnElm = mColumn->Element();
507 LocalAccessible* headerCell = mDoc->GetAccessible(columnElm);
508 if (headerCell) aHeaderCells->AppendElement(headerCell);
511 bool XULTreeGridCellAccessible::Selected() {
512 nsCOMPtr<nsITreeSelection> selection;
513 nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection));
514 NS_ENSURE_SUCCESS(rv, false);
516 bool selected = false;
517 selection->IsSelected(mRow, &selected);
518 return selected;
521 ////////////////////////////////////////////////////////////////////////////////
522 // XULTreeGridCellAccessible: LocalAccessible public implementation
524 already_AddRefed<AccAttributes> XULTreeGridCellAccessible::NativeAttributes() {
525 RefPtr<AccAttributes> attributes = new AccAttributes();
527 // "table-cell-index" attribute
528 TableAccessible* table = Table();
529 if (!table) return attributes.forget();
531 attributes->SetAttribute(nsGkAtoms::tableCellIndex,
532 table->CellIndexAt(mRow, ColIdx()));
534 // "cycles" attribute
535 if (mColumn->Cycler()) {
536 attributes->SetAttribute(nsGkAtoms::cycles, true);
539 return attributes.forget();
542 role XULTreeGridCellAccessible::NativeRole() const { return roles::GRID_CELL; }
544 uint64_t XULTreeGridCellAccessible::NativeState() const {
545 if (!mTreeView) return states::DEFUNCT;
547 // selectable/selected state
548 uint64_t states =
549 states::SELECTABLE; // keep in sync with NativeInteractiveState
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;
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;
567 return states;
570 uint64_t XULTreeGridCellAccessible::NativeInteractiveState() const {
571 return states::SELECTABLE;
574 int32_t XULTreeGridCellAccessible::IndexInParent() const { return ColIdx(); }
576 Relation XULTreeGridCellAccessible::RelationByType(RelationType aType) const {
577 return Relation();
580 ////////////////////////////////////////////////////////////////////////////////
581 // XULTreeGridCellAccessible: public implementation
583 bool XULTreeGridCellAccessible::CellInvalidated() {
584 nsAutoString textEquiv;
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);
594 mCachedTextEquiv = textEquiv;
595 return true;
598 return false;
601 mTreeView->GetCellText(mRow, mColumn, textEquiv);
602 if (mCachedTextEquiv != textEquiv) {
603 nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
604 mCachedTextEquiv = textEquiv;
605 return true;
608 return false;
611 ////////////////////////////////////////////////////////////////////////////////
612 // XULTreeGridCellAccessible: LocalAccessible protected implementation
614 LocalAccessible* XULTreeGridCellAccessible::GetSiblingAtOffset(
615 int32_t aOffset, nsresult* aError) const {
616 if (aError) *aError = NS_OK; // fail peacefully
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);
624 } else {
625 for (int32_t index = aOffset; index > 0 && columnAtOffset; index--) {
626 column = nsCoreUtils::GetNextSensibleColumn(columnAtOffset);
627 column.swap(columnAtOffset);
631 if (!columnAtOffset) return nullptr;
633 XULTreeItemAccessibleBase* rowAcc =
634 static_cast<XULTreeItemAccessibleBase*>(LocalParent());
635 return rowAcc->GetCellAccessible(columnAtOffset);
638 void XULTreeGridCellAccessible::DispatchClickEvent(
639 nsIContent* aContent, uint32_t aActionIndex) const {
640 if (IsDefunct()) return;
642 RefPtr<dom::XULTreeElement> tree = mTree;
643 RefPtr<nsTreeColumn> column = mColumn;
644 nsCoreUtils::DispatchClickEvent(tree, mRow, column);
647 ////////////////////////////////////////////////////////////////////////////////
648 // XULTreeGridCellAccessible: protected implementation
650 bool XULTreeGridCellAccessible::IsEditable() 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;
657 dom::Element* columnElm = mColumn->Element();
659 if (!columnElm->AttrValueIs(kNameSpaceID_None, nsGkAtoms::editable,
660 nsGkAtoms::_true, eCaseMatters)) {
661 return false;
664 return mContent->AsElement()->AttrValueIs(
665 kNameSpaceID_None, nsGkAtoms::editable, nsGkAtoms::_true, eCaseMatters);