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 "AccAttributes.h"
9 #include "LocalAccessible-inl.h"
10 #include "nsAccCache.h"
11 #include "nsAccessibilityService.h"
12 #include "nsAccUtils.h"
13 #include "DocAccessible.h"
14 #include "nsEventShell.h"
18 #include "nsQueryObject.h"
19 #include "nsTreeColumns.h"
21 #include "nsITreeSelection.h"
22 #include "nsComponentManagerUtils.h"
23 #include "mozilla/PresShell.h"
24 #include "mozilla/dom/Element.h"
25 #include "mozilla/dom/TreeColumnBinding.h"
26 #include "mozilla/dom/XULTreeElementBinding.h"
28 using namespace mozilla::a11y
;
29 using namespace mozilla
;
31 XULTreeGridAccessible::~XULTreeGridAccessible() {}
33 ////////////////////////////////////////////////////////////////////////////////
34 // XULTreeGridAccessible: Table
36 uint32_t XULTreeGridAccessible::ColCount() const {
37 return nsCoreUtils::GetSensibleColumnCount(mTree
);
40 uint32_t XULTreeGridAccessible::RowCount() {
41 if (!mTreeView
) return 0;
44 mTreeView
->GetRowCount(&rowCount
);
45 return rowCount
>= 0 ? rowCount
: 0;
48 uint32_t XULTreeGridAccessible::SelectedCellCount() {
49 return SelectedRowCount() * ColCount();
52 uint32_t XULTreeGridAccessible::SelectedColCount() {
53 // If all the row has been selected, then all the columns are selected,
54 // because we can't select a column alone.
56 uint32_t selectedRowCount
= SelectedItemCount();
57 return selectedRowCount
> 0 && selectedRowCount
== RowCount() ? ColCount()
61 uint32_t XULTreeGridAccessible::SelectedRowCount() {
62 return SelectedItemCount();
65 void XULTreeGridAccessible::SelectedCells(nsTArray
<Accessible
*>* aCells
) {
66 uint32_t colCount
= ColCount(), rowCount
= RowCount();
68 for (uint32_t rowIdx
= 0; rowIdx
< rowCount
; rowIdx
++) {
69 if (IsRowSelected(rowIdx
)) {
70 for (uint32_t colIdx
= 0; colIdx
< colCount
; colIdx
++) {
71 LocalAccessible
* cell
= CellAt(rowIdx
, colIdx
);
72 aCells
->AppendElement(cell
);
78 void XULTreeGridAccessible::SelectedCellIndices(nsTArray
<uint32_t>* aCells
) {
79 uint32_t colCount
= ColCount(), rowCount
= RowCount();
81 for (uint32_t rowIdx
= 0; rowIdx
< rowCount
; rowIdx
++) {
82 if (IsRowSelected(rowIdx
)) {
83 for (uint32_t colIdx
= 0; colIdx
< colCount
; colIdx
++) {
84 aCells
->AppendElement(rowIdx
* colCount
+ colIdx
);
90 void XULTreeGridAccessible::SelectedColIndices(nsTArray
<uint32_t>* aCols
) {
91 if (RowCount() != SelectedRowCount()) return;
93 uint32_t colCount
= ColCount();
94 aCols
->SetCapacity(colCount
);
95 for (uint32_t colIdx
= 0; colIdx
< colCount
; colIdx
++) {
96 aCols
->AppendElement(colIdx
);
100 void XULTreeGridAccessible::SelectedRowIndices(nsTArray
<uint32_t>* aRows
) {
101 uint32_t rowCount
= RowCount();
102 for (uint32_t rowIdx
= 0; rowIdx
< rowCount
; rowIdx
++) {
103 if (IsRowSelected(rowIdx
)) aRows
->AppendElement(rowIdx
);
107 LocalAccessible
* XULTreeGridAccessible::CellAt(uint32_t aRowIndex
,
108 uint32_t aColumnIndex
) {
109 XULTreeItemAccessibleBase
* rowAcc
= GetTreeItemAccessible(aRowIndex
);
110 if (!rowAcc
) return nullptr;
112 RefPtr
<nsTreeColumn
> column
=
113 nsCoreUtils::GetSensibleColumnAt(mTree
, aColumnIndex
);
114 if (!column
) return nullptr;
116 return rowAcc
->GetCellAccessible(column
);
119 void XULTreeGridAccessible::ColDescription(uint32_t aColIdx
,
120 nsString
& aDescription
) {
121 aDescription
.Truncate();
123 LocalAccessible
* treeColumns
= LocalAccessible::LocalChildAt(0);
125 LocalAccessible
* treeColumnItem
= treeColumns
->LocalChildAt(aColIdx
);
126 if (treeColumnItem
) treeColumnItem
->Name(aDescription
);
130 bool XULTreeGridAccessible::IsColSelected(uint32_t aColIdx
) {
131 // If all the row has been selected, then all the columns are selected.
132 // Because we can't select a column alone.
133 return SelectedItemCount() == RowCount();
136 bool XULTreeGridAccessible::IsRowSelected(uint32_t aRowIdx
) {
137 if (!mTreeView
) return false;
139 nsCOMPtr
<nsITreeSelection
> selection
;
140 nsresult rv
= mTreeView
->GetSelection(getter_AddRefs(selection
));
141 NS_ENSURE_SUCCESS(rv
, false);
143 bool isSelected
= false;
144 selection
->IsSelected(aRowIdx
, &isSelected
);
148 bool XULTreeGridAccessible::IsCellSelected(uint32_t aRowIdx
, uint32_t aColIdx
) {
149 return IsRowSelected(aRowIdx
);
152 void XULTreeGridAccessible::SelectRow(uint32_t aRowIdx
) {
153 if (!mTreeView
) return;
155 nsCOMPtr
<nsITreeSelection
> selection
;
156 mTreeView
->GetSelection(getter_AddRefs(selection
));
157 NS_ASSERTION(selection
, "GetSelection() Shouldn't fail!");
159 selection
->Select(aRowIdx
);
162 void XULTreeGridAccessible::UnselectRow(uint32_t aRowIdx
) {
163 if (!mTreeView
) return;
165 nsCOMPtr
<nsITreeSelection
> selection
;
166 mTreeView
->GetSelection(getter_AddRefs(selection
));
168 if (selection
) selection
->ClearRange(aRowIdx
, aRowIdx
);
171 ////////////////////////////////////////////////////////////////////////////////
172 // XULTreeGridAccessible: LocalAccessible implementation
174 role
XULTreeGridAccessible::NativeRole() const {
175 RefPtr
<nsTreeColumns
> treeColumns
= mTree
->GetColumns(FlushType::None
);
177 NS_ERROR("No treecolumns object for tree!");
178 return roles::NOTHING
;
181 nsTreeColumn
* primaryColumn
= treeColumns
->GetPrimaryColumn();
183 return primaryColumn
? roles::TREE_TABLE
: roles::TABLE
;
186 ////////////////////////////////////////////////////////////////////////////////
187 // XULTreeGridAccessible: XULTreeAccessible implementation
189 already_AddRefed
<XULTreeItemAccessibleBase
>
190 XULTreeGridAccessible::CreateTreeItemAccessible(int32_t aRow
) const {
191 RefPtr
<XULTreeItemAccessibleBase
> accessible
= new XULTreeGridRowAccessible(
192 mContent
, mDoc
, const_cast<XULTreeGridAccessible
*>(this), mTree
,
195 return accessible
.forget();
198 ////////////////////////////////////////////////////////////////////////////////
199 // XULTreeGridRowAccessible
200 ////////////////////////////////////////////////////////////////////////////////
202 XULTreeGridRowAccessible::XULTreeGridRowAccessible(
203 nsIContent
* aContent
, DocAccessible
* aDoc
, LocalAccessible
* aTreeAcc
,
204 dom::XULTreeElement
* aTree
, nsITreeView
* aTreeView
, int32_t aRow
)
205 : XULTreeItemAccessibleBase(aContent
, aDoc
, aTreeAcc
, aTree
, aTreeView
,
207 mAccessibleCache(kDefaultTreeCacheLength
) {
208 mGenericTypes
|= eTableRow
;
209 mStateFlags
|= eNoKidsFromDOM
;
212 XULTreeGridRowAccessible::~XULTreeGridRowAccessible() {}
214 ////////////////////////////////////////////////////////////////////////////////
215 // XULTreeGridRowAccessible: nsISupports and cycle collection implementation
217 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridRowAccessible
,
218 XULTreeItemAccessibleBase
, mAccessibleCache
)
220 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XULTreeGridRowAccessible
)
221 NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase
)
223 NS_IMPL_ADDREF_INHERITED(XULTreeGridRowAccessible
, XULTreeItemAccessibleBase
)
224 NS_IMPL_RELEASE_INHERITED(XULTreeGridRowAccessible
, XULTreeItemAccessibleBase
)
226 ////////////////////////////////////////////////////////////////////////////////
227 // XULTreeGridRowAccessible: LocalAccessible implementation
229 void XULTreeGridRowAccessible::Shutdown() {
230 if (mDoc
&& !mDoc
->IsDefunct()) {
231 UnbindCacheEntriesFromDocument(mAccessibleCache
);
234 XULTreeItemAccessibleBase::Shutdown();
237 role
XULTreeGridRowAccessible::NativeRole() const { return roles::ROW
; }
239 ENameValueFlag
XULTreeGridRowAccessible::Name(nsString
& aName
) const {
242 // XXX: the row name sholdn't be a concatenation of cell names (bug 664384).
243 RefPtr
<nsTreeColumn
> column
= nsCoreUtils::GetFirstSensibleColumn(mTree
);
245 if (!aName
.IsEmpty()) aName
.Append(' ');
247 nsAutoString cellName
;
248 GetCellName(column
, cellName
);
249 aName
.Append(cellName
);
251 column
= nsCoreUtils::GetNextSensibleColumn(column
);
257 LocalAccessible
* XULTreeGridRowAccessible::LocalChildAtPoint(
258 int32_t aX
, int32_t aY
, EWhichChildAtPoint aWhichChild
) {
259 nsIFrame
* frame
= GetFrame();
260 if (!frame
) return nullptr;
262 nsPresContext
* presContext
= frame
->PresContext();
263 PresShell
* presShell
= presContext
->PresShell();
265 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
266 NS_ENSURE_TRUE(rootFrame
, nullptr);
268 CSSIntRect rootRect
= rootFrame
->GetScreenRect();
270 int32_t clientX
= presContext
->DevPixelsToIntCSSPixels(aX
) - rootRect
.X();
271 int32_t clientY
= presContext
->DevPixelsToIntCSSPixels(aY
) - rootRect
.Y();
274 dom::TreeCellInfo cellInfo
;
275 mTree
->GetCellAt(clientX
, clientY
, cellInfo
, rv
);
277 // Return if we failed to find tree cell in the row for the given point.
278 if (cellInfo
.mRow
!= mRow
|| !cellInfo
.mCol
) return nullptr;
280 return GetCellAccessible(cellInfo
.mCol
);
283 LocalAccessible
* XULTreeGridRowAccessible::LocalChildAt(uint32_t aIndex
) const {
284 if (IsDefunct()) return nullptr;
286 RefPtr
<nsTreeColumn
> column
= nsCoreUtils::GetSensibleColumnAt(mTree
, aIndex
);
287 if (!column
) return nullptr;
289 return GetCellAccessible(column
);
292 uint32_t XULTreeGridRowAccessible::ChildCount() const {
293 return nsCoreUtils::GetSensibleColumnCount(mTree
);
296 ////////////////////////////////////////////////////////////////////////////////
297 // XULTreeGridRowAccessible: XULTreeItemAccessibleBase implementation
299 XULTreeGridCellAccessible
* XULTreeGridRowAccessible::GetCellAccessible(
300 nsTreeColumn
* aColumn
) const {
301 MOZ_ASSERT(aColumn
, "No tree column!");
303 void* key
= static_cast<void*>(aColumn
);
304 XULTreeGridCellAccessible
* cachedCell
= mAccessibleCache
.GetWeak(key
);
305 if (cachedCell
) return cachedCell
;
307 RefPtr
<XULTreeGridCellAccessible
> cell
= new XULTreeGridCellAccessible(
308 mContent
, mDoc
, const_cast<XULTreeGridRowAccessible
*>(this), mTree
,
309 mTreeView
, mRow
, aColumn
);
310 mAccessibleCache
.InsertOrUpdate(key
, RefPtr
{cell
});
311 Document()->BindToDocument(cell
, nullptr);
315 void XULTreeGridRowAccessible::RowInvalidated(int32_t aStartColIdx
,
316 int32_t aEndColIdx
) {
317 RefPtr
<nsTreeColumns
> treeColumns
= mTree
->GetColumns(FlushType::None
);
318 if (!treeColumns
) return;
320 bool nameChanged
= false;
321 for (int32_t colIdx
= aStartColIdx
; colIdx
<= aEndColIdx
; ++colIdx
) {
322 nsTreeColumn
* column
= treeColumns
->GetColumnAt(colIdx
);
323 if (column
&& !nsCoreUtils::IsColumnHidden(column
)) {
324 XULTreeGridCellAccessible
* cell
= GetCellAccessible(column
);
325 if (cell
) nameChanged
|= cell
->CellInvalidated();
330 nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE
, this);
334 ////////////////////////////////////////////////////////////////////////////////
335 // XULTreeGridCellAccessible
336 ////////////////////////////////////////////////////////////////////////////////
338 XULTreeGridCellAccessible::XULTreeGridCellAccessible(
339 nsIContent
* aContent
, DocAccessible
* aDoc
,
340 XULTreeGridRowAccessible
* aRowAcc
, dom::XULTreeElement
* aTree
,
341 nsITreeView
* aTreeView
, int32_t aRow
, nsTreeColumn
* aColumn
)
342 : LeafAccessible(aContent
, aDoc
),
344 mTreeView(aTreeView
),
348 mStateFlags
|= eSharedNode
;
349 mGenericTypes
|= eTableCell
;
351 NS_ASSERTION(mTreeView
, "mTreeView is null");
353 if (mColumn
->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX
) {
354 mTreeView
->GetCellValue(mRow
, mColumn
, mCachedTextEquiv
);
356 mTreeView
->GetCellText(mRow
, mColumn
, mCachedTextEquiv
);
360 XULTreeGridCellAccessible::~XULTreeGridCellAccessible() {}
362 ////////////////////////////////////////////////////////////////////////////////
363 // XULTreeGridCellAccessible: nsISupports implementation
365 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible
, LeafAccessible
,
368 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XULTreeGridCellAccessible
)
369 NS_INTERFACE_MAP_END_INHERITING(LeafAccessible
)
370 NS_IMPL_ADDREF_INHERITED(XULTreeGridCellAccessible
, LeafAccessible
)
371 NS_IMPL_RELEASE_INHERITED(XULTreeGridCellAccessible
, LeafAccessible
)
373 ////////////////////////////////////////////////////////////////////////////////
374 // XULTreeGridCellAccessible: LocalAccessible
376 void XULTreeGridCellAccessible::Shutdown() {
381 mParent
= nullptr; // null-out to prevent base class's shutdown ops
383 LeafAccessible::Shutdown();
386 Accessible
* XULTreeGridCellAccessible::FocusedChild() { return nullptr; }
388 ENameValueFlag
XULTreeGridCellAccessible::Name(nsString
& aName
) const {
391 if (!mTreeView
) return eNameOK
;
393 mTreeView
->GetCellText(mRow
, mColumn
, aName
);
395 // If there is still no name try the cell value:
396 // This is for graphical cells. We need tree/table view implementors to
397 // implement FooView::GetCellValue to return a meaningful string for cases
398 // where there is something shown in the cell (non-text) such as a star icon;
399 // in which case GetCellValue for that cell would return "starred" or
400 // "flagged" for example.
401 if (aName
.IsEmpty()) mTreeView
->GetCellValue(mRow
, mColumn
, aName
);
406 nsIntRect
XULTreeGridCellAccessible::BoundsInCSSPixels() const {
407 // Get bounds for tree cell and add x and y of treechildren element to
408 // x and y of the cell.
410 nsIntRect rect
= mTree
->GetCoordsForCellItem(mRow
, mColumn
, u
"cell"_ns
, rv
);
415 RefPtr
<dom::Element
> bodyElement
= mTree
->GetTreeBody();
416 if (!bodyElement
|| !bodyElement
->IsXULElement()) {
420 nsIFrame
* bodyFrame
= bodyElement
->GetPrimaryFrame();
425 CSSIntRect screenRect
= bodyFrame
->GetScreenRect();
426 rect
.x
+= screenRect
.x
;
427 rect
.y
+= screenRect
.y
;
431 nsRect
XULTreeGridCellAccessible::BoundsInAppUnits() const {
432 nsIntRect bounds
= BoundsInCSSPixels();
433 nsPresContext
* presContext
= mDoc
->PresContext();
434 return nsRect(presContext
->CSSPixelsToAppUnits(bounds
.X()),
435 presContext
->CSSPixelsToAppUnits(bounds
.Y()),
436 presContext
->CSSPixelsToAppUnits(bounds
.Width()),
437 presContext
->CSSPixelsToAppUnits(bounds
.Height()));
440 bool XULTreeGridCellAccessible::HasPrimaryAction() const {
441 return mColumn
->Cycler() ||
442 (mColumn
->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX
&&
446 void XULTreeGridCellAccessible::ActionNameAt(uint8_t aIndex
, nsAString
& aName
) {
449 if (aIndex
!= eAction_Click
|| !mTreeView
) return;
451 if (mColumn
->Cycler()) {
452 aName
.AssignLiteral("cycle");
456 if (mColumn
->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX
&&
459 mTreeView
->GetCellValue(mRow
, mColumn
, value
);
460 if (value
.EqualsLiteral("true")) {
461 aName
.AssignLiteral("uncheck");
463 aName
.AssignLiteral("check");
468 ////////////////////////////////////////////////////////////////////////////////
469 // XULTreeGridCellAccessible: TableCell
471 TableAccessible
* XULTreeGridCellAccessible::Table() const {
472 LocalAccessible
* grandParent
= mParent
->LocalParent();
473 if (grandParent
) return grandParent
->AsTable();
478 uint32_t XULTreeGridCellAccessible::ColIdx() const {
480 RefPtr
<nsTreeColumn
> column
= mColumn
;
481 while ((column
= nsCoreUtils::GetPreviousSensibleColumn(column
))) colIdx
++;
486 uint32_t XULTreeGridCellAccessible::RowIdx() const { return mRow
; }
488 void XULTreeGridCellAccessible::ColHeaderCells(
489 nsTArray
<Accessible
*>* aHeaderCells
) {
490 dom::Element
* columnElm
= mColumn
->Element();
492 LocalAccessible
* headerCell
= mDoc
->GetAccessible(columnElm
);
493 if (headerCell
) aHeaderCells
->AppendElement(headerCell
);
496 bool XULTreeGridCellAccessible::Selected() {
497 nsCOMPtr
<nsITreeSelection
> selection
;
498 nsresult rv
= mTreeView
->GetSelection(getter_AddRefs(selection
));
499 NS_ENSURE_SUCCESS(rv
, false);
501 bool selected
= false;
502 selection
->IsSelected(mRow
, &selected
);
506 ////////////////////////////////////////////////////////////////////////////////
507 // XULTreeGridCellAccessible: LocalAccessible public implementation
509 already_AddRefed
<AccAttributes
> XULTreeGridCellAccessible::NativeAttributes() {
510 RefPtr
<AccAttributes
> attributes
= new AccAttributes();
512 // "table-cell-index" attribute
513 TableAccessible
* table
= Table();
514 if (!table
) return attributes
.forget();
516 attributes
->SetAttribute(nsGkAtoms::tableCellIndex
,
517 table
->CellIndexAt(mRow
, ColIdx()));
519 // "cycles" attribute
520 if (mColumn
->Cycler()) {
521 attributes
->SetAttribute(nsGkAtoms::cycles
, true);
524 return attributes
.forget();
527 role
XULTreeGridCellAccessible::NativeRole() const { return roles::GRID_CELL
; }
529 uint64_t XULTreeGridCellAccessible::NativeState() const {
530 if (!mTreeView
) return states::DEFUNCT
;
532 // selectable/selected state
534 states::SELECTABLE
; // keep in sync with NativeInteractiveState
536 nsCOMPtr
<nsITreeSelection
> selection
;
537 mTreeView
->GetSelection(getter_AddRefs(selection
));
539 bool isSelected
= false;
540 selection
->IsSelected(mRow
, &isSelected
);
541 if (isSelected
) states
|= states::SELECTED
;
545 if (mColumn
->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX
) {
546 states
|= states::CHECKABLE
;
547 nsAutoString checked
;
548 mTreeView
->GetCellValue(mRow
, mColumn
, checked
);
549 if (checked
.EqualsIgnoreCase("true")) states
|= states::CHECKED
;
555 uint64_t XULTreeGridCellAccessible::NativeInteractiveState() const {
556 return states::SELECTABLE
;
559 int32_t XULTreeGridCellAccessible::IndexInParent() const { return ColIdx(); }
561 Relation
XULTreeGridCellAccessible::RelationByType(RelationType aType
) const {
565 ////////////////////////////////////////////////////////////////////////////////
566 // XULTreeGridCellAccessible: public implementation
568 bool XULTreeGridCellAccessible::CellInvalidated() {
569 nsAutoString textEquiv
;
571 if (mColumn
->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX
) {
572 mTreeView
->GetCellValue(mRow
, mColumn
, textEquiv
);
573 if (mCachedTextEquiv
!= textEquiv
) {
574 bool isEnabled
= textEquiv
.EqualsLiteral("true");
575 RefPtr
<AccEvent
> accEvent
=
576 new AccStateChangeEvent(this, states::CHECKED
, isEnabled
);
577 nsEventShell::FireEvent(accEvent
);
579 mCachedTextEquiv
= textEquiv
;
586 mTreeView
->GetCellText(mRow
, mColumn
, textEquiv
);
587 if (mCachedTextEquiv
!= textEquiv
) {
588 nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE
, this);
589 mCachedTextEquiv
= textEquiv
;
596 ////////////////////////////////////////////////////////////////////////////////
597 // XULTreeGridCellAccessible: LocalAccessible protected implementation
599 LocalAccessible
* XULTreeGridCellAccessible::GetSiblingAtOffset(
600 int32_t aOffset
, nsresult
* aError
) const {
601 if (aError
) *aError
= NS_OK
; // fail peacefully
603 RefPtr
<nsTreeColumn
> columnAtOffset(mColumn
), column
;
605 for (int32_t index
= aOffset
; index
< 0 && columnAtOffset
; index
++) {
606 column
= nsCoreUtils::GetPreviousSensibleColumn(columnAtOffset
);
607 column
.swap(columnAtOffset
);
610 for (int32_t index
= aOffset
; index
> 0 && columnAtOffset
; index
--) {
611 column
= nsCoreUtils::GetNextSensibleColumn(columnAtOffset
);
612 column
.swap(columnAtOffset
);
616 if (!columnAtOffset
) return nullptr;
618 XULTreeItemAccessibleBase
* rowAcc
=
619 static_cast<XULTreeItemAccessibleBase
*>(LocalParent());
620 return rowAcc
->GetCellAccessible(columnAtOffset
);
623 void XULTreeGridCellAccessible::DispatchClickEvent(
624 nsIContent
* aContent
, uint32_t aActionIndex
) const {
625 if (IsDefunct()) return;
627 RefPtr
<dom::XULTreeElement
> tree
= mTree
;
628 RefPtr
<nsTreeColumn
> column
= mColumn
;
629 nsCoreUtils::DispatchClickEvent(tree
, mRow
, column
);
632 ////////////////////////////////////////////////////////////////////////////////
633 // XULTreeGridCellAccessible: protected implementation
635 bool XULTreeGridCellAccessible::IsEditable() const {
636 // XXX: logic corresponds to tree.xml, it's preferable to have interface
637 // method to check it.
638 bool isEditable
= false;
639 nsresult rv
= mTreeView
->IsEditable(mRow
, mColumn
, &isEditable
);
640 if (NS_FAILED(rv
) || !isEditable
) return false;
642 dom::Element
* columnElm
= mColumn
->Element();
644 if (!columnElm
->AttrValueIs(kNameSpaceID_None
, nsGkAtoms::editable
,
645 nsGkAtoms::_true
, eCaseMatters
)) {
649 return mContent
->AsElement()->AttrValueIs(
650 kNameSpaceID_None
, nsGkAtoms::editable
, nsGkAtoms::_true
, eCaseMatters
);