1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "XULTreeAccessible.h"
9 #include "Accessible-inl.h"
10 #include "DocAccessible-inl.h"
11 #include "nsAccCache.h"
12 #include "nsAccUtils.h"
13 #include "nsCoreUtils.h"
14 #include "nsEventShell.h"
15 #include "DocAccessible.h"
19 #include "XULTreeGridAccessible.h"
21 #include "nsComponentManagerUtils.h"
22 #include "nsIAccessibleRelation.h"
23 #include "nsIAutoCompleteInput.h"
24 #include "nsIAutoCompletePopup.h"
25 #include "nsIBoxObject.h"
26 #include "nsIDOMXULElement.h"
27 #include "nsIDOMXULMenuListElement.h"
28 #include "nsIDOMXULMultSelectCntrlEl.h"
29 #include "nsIDOMXULTreeElement.h"
30 #include "nsITreeSelection.h"
31 #include "nsIMutableArray.h"
32 #include "nsTreeBodyFrame.h"
33 #include "nsTreeColumns.h"
34 #include "nsTreeUtils.h"
36 using namespace mozilla::a11y
;
38 ////////////////////////////////////////////////////////////////////////////////
40 ////////////////////////////////////////////////////////////////////////////////
43 XULTreeAccessible(nsIContent
* aContent
, DocAccessible
* aDoc
,
44 nsTreeBodyFrame
* aTreeFrame
) :
45 AccessibleWrap(aContent
, aDoc
),
46 mAccessibleCache(kDefaultTreeCacheLength
)
49 mGenericTypes
|= eSelect
;
51 nsCOMPtr
<nsITreeView
> view
= aTreeFrame
->GetExistingView();
54 mTree
= nsCoreUtils::GetTreeBoxObject(aContent
);
55 NS_ASSERTION(mTree
, "Can't get mTree!\n");
57 nsIContent
* parentContent
= mContent
->GetParent();
59 nsCOMPtr
<nsIAutoCompletePopup
> autoCompletePopupElm
=
60 do_QueryInterface(parentContent
);
61 if (autoCompletePopupElm
)
62 mGenericTypes
|= eAutoCompletePopup
;
66 XULTreeAccessible::~XULTreeAccessible()
70 ////////////////////////////////////////////////////////////////////////////////
71 // XULTreeAccessible: nsISupports and cycle collection implementation
73 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeAccessible
, Accessible
,
74 mTree
, mAccessibleCache
)
76 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeAccessible
)
77 NS_INTERFACE_MAP_END_INHERITING(Accessible
)
79 NS_IMPL_ADDREF_INHERITED(XULTreeAccessible
, Accessible
)
80 NS_IMPL_RELEASE_INHERITED(XULTreeAccessible
, Accessible
)
82 ////////////////////////////////////////////////////////////////////////////////
83 // XULTreeAccessible: Accessible implementation
86 XULTreeAccessible::NativeState()
88 // Get focus status from base class.
89 uint64_t state
= Accessible::NativeState();
92 state
|= states::READONLY
;
94 // multiselectable state.
98 nsCOMPtr
<nsITreeSelection
> selection
;
99 mTreeView
->GetSelection(getter_AddRefs(selection
));
100 NS_ENSURE_TRUE(selection
, state
);
102 bool isSingle
= false;
103 nsresult rv
= selection
->GetSingle(&isSingle
);
104 NS_ENSURE_SUCCESS(rv
, state
);
107 state
|= states::MULTISELECTABLE
;
113 XULTreeAccessible::Value(nsString
& aValue
)
119 // Return the value is the first selected child.
120 nsCOMPtr
<nsITreeSelection
> selection
;
121 mTreeView
->GetSelection(getter_AddRefs(selection
));
125 int32_t currentIndex
;
126 nsCOMPtr
<nsIDOMElement
> selectItem
;
127 selection
->GetCurrentIndex(¤tIndex
);
128 if (currentIndex
>= 0) {
129 nsCOMPtr
<nsITreeColumn
> keyCol
;
131 nsCOMPtr
<nsITreeColumns
> cols
;
132 mTree
->GetColumns(getter_AddRefs(cols
));
134 cols
->GetKeyColumn(getter_AddRefs(keyCol
));
136 mTreeView
->GetCellText(currentIndex
, keyCol
, aValue
);
141 ////////////////////////////////////////////////////////////////////////////////
142 // XULTreeAccessible: Accessible implementation
145 XULTreeAccessible::Shutdown()
147 // XXX: we don't remove accessible from document cache if shutdown wasn't
148 // initiated by document destroying. Note, we can't remove accessible from
149 // document cache here while document is going to be shutdown. Note, this is
150 // not unique place where we have similar problem.
151 ClearCache(mAccessibleCache
);
156 AccessibleWrap::Shutdown();
160 XULTreeAccessible::NativeRole()
162 // No primary column means we're in a list. In fact, history and mail turn off
163 // the primary flag when switching to a flat view.
165 nsIContent
* child
= nsTreeUtils::GetDescendantChild(mContent
, nsGkAtoms::treechildren
);
166 NS_ASSERTION(child
, "tree without treechildren!");
167 nsTreeBodyFrame
* treeFrame
= do_QueryFrame(child
->GetPrimaryFrame());
168 NS_ASSERTION(treeFrame
, "xul tree accessible for tree without a frame!");
172 nsRefPtr
<nsTreeColumns
> cols
= treeFrame
->Columns();
173 nsCOMPtr
<nsITreeColumn
> primaryCol
;
174 cols
->GetPrimaryColumn(getter_AddRefs(primaryCol
));
176 return primaryCol
? roles::OUTLINE
: roles::LIST
;
179 ////////////////////////////////////////////////////////////////////////////////
180 // XULTreeAccessible: Accessible implementation (DON'T put methods here)
183 XULTreeAccessible::ChildAtPoint(int32_t aX
, int32_t aY
,
184 EWhichChildAtPoint aWhichChild
)
186 nsIFrame
*frame
= GetFrame();
190 nsPresContext
*presContext
= frame
->PresContext();
191 nsIPresShell
* presShell
= presContext
->PresShell();
193 nsIFrame
*rootFrame
= presShell
->GetRootFrame();
194 NS_ENSURE_TRUE(rootFrame
, nullptr);
196 nsIntRect rootRect
= rootFrame
->GetScreenRect();
198 int32_t clientX
= presContext
->DevPixelsToIntCSSPixels(aX
) - rootRect
.x
;
199 int32_t clientY
= presContext
->DevPixelsToIntCSSPixels(aY
) - rootRect
.y
;
202 nsCOMPtr
<nsITreeColumn
> column
;
203 nsAutoString childEltUnused
;
204 mTree
->GetCellAt(clientX
, clientY
, &row
, getter_AddRefs(column
),
207 // If we failed to find tree cell for the given point then it might be
209 if (row
== -1 || !column
)
210 return AccessibleWrap::ChildAtPoint(aX
, aY
, aWhichChild
);
212 Accessible
* child
= GetTreeItemAccessible(row
);
213 if (aWhichChild
== eDeepestChild
&& child
) {
214 // Look for accessible cell for the found item accessible.
215 nsRefPtr
<XULTreeItemAccessibleBase
> treeitem
= do_QueryObject(child
);
217 Accessible
* cell
= treeitem
->GetCellAccessible(column
);
225 ////////////////////////////////////////////////////////////////////////////////
226 // XULTreeAccessible: SelectAccessible
229 XULTreeAccessible::CurrentItem()
234 nsCOMPtr
<nsITreeSelection
> selection
;
235 mTreeView
->GetSelection(getter_AddRefs(selection
));
237 int32_t currentIndex
= -1;
238 selection
->GetCurrentIndex(¤tIndex
);
239 if (currentIndex
>= 0)
240 return GetTreeItemAccessible(currentIndex
);
247 XULTreeAccessible::SetCurrentItem(Accessible
* aItem
)
249 NS_ERROR("XULTreeAccessible::SetCurrentItem not implemented");
253 XULTreeAccessible::SelectedItems(nsTArray
<Accessible
*>* aItems
)
258 nsCOMPtr
<nsITreeSelection
> selection
;
259 mTreeView
->GetSelection(getter_AddRefs(selection
));
263 int32_t rangeCount
= 0;
264 selection
->GetRangeCount(&rangeCount
);
265 for (int32_t rangeIdx
= 0; rangeIdx
< rangeCount
; rangeIdx
++) {
266 int32_t firstIdx
= 0, lastIdx
= -1;
267 selection
->GetRangeAt(rangeIdx
, &firstIdx
, &lastIdx
);
268 for (int32_t rowIdx
= firstIdx
; rowIdx
<= lastIdx
; rowIdx
++) {
269 Accessible
* item
= GetTreeItemAccessible(rowIdx
);
271 aItems
->AppendElement(item
);
277 XULTreeAccessible::SelectedItemCount()
282 nsCOMPtr
<nsITreeSelection
> selection
;
283 mTreeView
->GetSelection(getter_AddRefs(selection
));
286 selection
->GetCount(&count
);
294 XULTreeAccessible::AddItemToSelection(uint32_t aIndex
)
299 nsCOMPtr
<nsITreeSelection
> selection
;
300 mTreeView
->GetSelection(getter_AddRefs(selection
));
302 bool isSelected
= false;
303 selection
->IsSelected(aIndex
, &isSelected
);
305 selection
->ToggleSelect(aIndex
);
313 XULTreeAccessible::RemoveItemFromSelection(uint32_t aIndex
)
318 nsCOMPtr
<nsITreeSelection
> selection
;
319 mTreeView
->GetSelection(getter_AddRefs(selection
));
321 bool isSelected
= false;
322 selection
->IsSelected(aIndex
, &isSelected
);
324 selection
->ToggleSelect(aIndex
);
332 XULTreeAccessible::IsItemSelected(uint32_t aIndex
)
337 nsCOMPtr
<nsITreeSelection
> selection
;
338 mTreeView
->GetSelection(getter_AddRefs(selection
));
340 bool isSelected
= false;
341 selection
->IsSelected(aIndex
, &isSelected
);
348 XULTreeAccessible::UnselectAll()
353 nsCOMPtr
<nsITreeSelection
> selection
;
354 mTreeView
->GetSelection(getter_AddRefs(selection
));
358 selection
->ClearSelection();
363 XULTreeAccessible::GetSelectedItem(uint32_t aIndex
)
368 nsCOMPtr
<nsITreeSelection
> selection
;
369 mTreeView
->GetSelection(getter_AddRefs(selection
));
373 uint32_t selCount
= 0;
374 int32_t rangeCount
= 0;
375 selection
->GetRangeCount(&rangeCount
);
376 for (int32_t rangeIdx
= 0; rangeIdx
< rangeCount
; rangeIdx
++) {
377 int32_t firstIdx
= 0, lastIdx
= -1;
378 selection
->GetRangeAt(rangeIdx
, &firstIdx
, &lastIdx
);
379 for (int32_t rowIdx
= firstIdx
; rowIdx
<= lastIdx
; rowIdx
++) {
380 if (selCount
== aIndex
)
381 return GetTreeItemAccessible(rowIdx
);
391 XULTreeAccessible::SelectAll()
393 // see if we are multiple select if so set ourselves as such
397 nsCOMPtr
<nsITreeSelection
> selection
;
398 mTreeView
->GetSelection(getter_AddRefs(selection
));
401 selection
->GetSingle(&single
);
403 selection
->SelectAll();
411 ////////////////////////////////////////////////////////////////////////////////
412 // XULTreeAccessible: Accessible implementation
415 XULTreeAccessible::GetChildAt(uint32_t aIndex
) const
417 uint32_t childCount
= Accessible::ChildCount();
418 if (aIndex
< childCount
)
419 return Accessible::GetChildAt(aIndex
);
421 return GetTreeItemAccessible(aIndex
- childCount
);
425 XULTreeAccessible::ChildCount() const
427 // Tree's children count is row count + treecols count.
428 uint32_t childCount
= Accessible::ChildCount();
432 int32_t rowCount
= 0;
433 mTreeView
->GetRowCount(&rowCount
);
434 childCount
+= rowCount
;
440 XULTreeAccessible::RelationByType(RelationType aType
)
442 if (aType
== RelationType::NODE_PARENT_OF
) {
444 return Relation(new XULTreeItemIterator(this, mTreeView
, -1));
449 return Accessible::RelationByType(aType
);
452 ////////////////////////////////////////////////////////////////////////////////
453 // XULTreeAccessible: Widgets
456 XULTreeAccessible::IsWidget() const
462 XULTreeAccessible::IsActiveWidget() const
464 if (IsAutoCompletePopup()) {
465 nsCOMPtr
<nsIAutoCompletePopup
> autoCompletePopupElm
=
466 do_QueryInterface(mContent
->GetParent());
468 if (autoCompletePopupElm
) {
470 autoCompletePopupElm
->GetPopupOpen(&isOpen
);
474 return FocusMgr()->HasDOMFocus(mContent
);
478 XULTreeAccessible::AreItemsOperable() const
480 if (IsAutoCompletePopup()) {
481 nsCOMPtr
<nsIAutoCompletePopup
> autoCompletePopupElm
=
482 do_QueryInterface(mContent
->GetParent());
484 if (autoCompletePopupElm
) {
486 autoCompletePopupElm
->GetPopupOpen(&isOpen
);
494 XULTreeAccessible::ContainerWidget() const
496 if (IsAutoCompletePopup()) {
497 // This works for XUL autocompletes. It doesn't work for HTML forms
498 // autocomplete because of potential crossprocess calls (when autocomplete
499 // lives in content process while popup lives in chrome process). If that's
500 // a problem then rethink Widgets interface.
501 nsCOMPtr
<nsIDOMXULMenuListElement
> menuListElm
=
502 do_QueryInterface(mContent
->GetParent());
504 nsCOMPtr
<nsIDOMNode
> inputElm
;
505 menuListElm
->GetInputField(getter_AddRefs(inputElm
));
507 nsCOMPtr
<nsINode
> inputNode
= do_QueryInterface(inputElm
);
510 mDoc
->GetAccessible(inputNode
);
511 return input
? input
->ContainerWidget() : nullptr;
519 ////////////////////////////////////////////////////////////////////////////////
520 // XULTreeAccessible: public implementation
523 XULTreeAccessible::GetTreeItemAccessible(int32_t aRow
) const
525 if (aRow
< 0 || IsDefunct() || !mTreeView
)
528 int32_t rowCount
= 0;
529 nsresult rv
= mTreeView
->GetRowCount(&rowCount
);
530 if (NS_FAILED(rv
) || aRow
>= rowCount
)
533 void *key
= reinterpret_cast<void*>(aRow
);
534 Accessible
* cachedTreeItem
= mAccessibleCache
.GetWeak(key
);
536 return cachedTreeItem
;
538 nsRefPtr
<Accessible
> treeItem
= CreateTreeItemAccessible(aRow
);
540 mAccessibleCache
.Put(key
, treeItem
);
541 Document()->BindToDocument(treeItem
, nullptr);
549 XULTreeAccessible::InvalidateCache(int32_t aRow
, int32_t aCount
)
555 ClearCache(mAccessibleCache
);
559 // Do not invalidate the cache if rows have been inserted.
563 DocAccessible
* document
= Document();
565 // Fire destroy event for removed tree items and delete them from caches.
566 for (int32_t rowIdx
= aRow
; rowIdx
< aRow
- aCount
; rowIdx
++) {
568 void* key
= reinterpret_cast<void*>(rowIdx
);
569 Accessible
* treeItem
= mAccessibleCache
.GetWeak(key
);
572 nsRefPtr
<AccEvent
> event
=
573 new AccEvent(nsIAccessibleEvent::EVENT_HIDE
, treeItem
);
574 nsEventShell::FireEvent(event
);
576 // Unbind from document, shutdown and remove from tree cache.
577 document
->UnbindFromDocument(treeItem
);
578 mAccessibleCache
.Remove(key
);
582 // We dealt with removed tree items already however we may keep tree items
583 // having row indexes greater than row count. We should remove these dead tree
584 // items silently from caches.
585 int32_t newRowCount
= 0;
586 nsresult rv
= mTreeView
->GetRowCount(&newRowCount
);
590 int32_t oldRowCount
= newRowCount
- aCount
;
592 for (int32_t rowIdx
= newRowCount
; rowIdx
< oldRowCount
; ++rowIdx
) {
594 void *key
= reinterpret_cast<void*>(rowIdx
);
595 Accessible
* treeItem
= mAccessibleCache
.GetWeak(key
);
598 // Unbind from document, shutdown and remove from tree cache.
599 document
->UnbindFromDocument(treeItem
);
600 mAccessibleCache
.Remove(key
);
606 XULTreeAccessible::TreeViewInvalidated(int32_t aStartRow
, int32_t aEndRow
,
607 int32_t aStartCol
, int32_t aEndCol
)
613 ClearCache(mAccessibleCache
);
617 int32_t endRow
= aEndRow
;
621 int32_t rowCount
= 0;
622 rv
= mTreeView
->GetRowCount(&rowCount
);
626 endRow
= rowCount
- 1;
629 nsCOMPtr
<nsITreeColumns
> treeColumns
;
630 mTree
->GetColumns(getter_AddRefs(treeColumns
));
634 int32_t endCol
= aEndCol
;
637 int32_t colCount
= 0;
638 rv
= treeColumns
->GetCount(&colCount
);
642 endCol
= colCount
- 1;
645 for (int32_t rowIdx
= aStartRow
; rowIdx
<= endRow
; ++rowIdx
) {
647 void *key
= reinterpret_cast<void*>(rowIdx
);
648 Accessible
* accessible
= mAccessibleCache
.GetWeak(key
);
651 nsRefPtr
<XULTreeItemAccessibleBase
> treeitemAcc
= do_QueryObject(accessible
);
652 NS_ASSERTION(treeitemAcc
, "Wrong accessible at the given key!");
654 treeitemAcc
->RowInvalidated(aStartCol
, endCol
);
660 XULTreeAccessible::TreeViewChanged(nsITreeView
* aView
)
665 // Fire reorder event on tree accessible on accessible tree (do not fire
666 // show/hide events on tree items because it can be expensive to fire them for
668 nsRefPtr
<AccReorderEvent
> reorderEvent
= new AccReorderEvent(this);
669 Document()->FireDelayedEvent(reorderEvent
);
672 ClearCache(mAccessibleCache
);
676 ////////////////////////////////////////////////////////////////////////////////
677 // XULTreeAccessible: protected implementation
679 already_AddRefed
<Accessible
>
680 XULTreeAccessible::CreateTreeItemAccessible(int32_t aRow
) const
682 nsRefPtr
<Accessible
> accessible
=
683 new XULTreeItemAccessible(mContent
, mDoc
, const_cast<XULTreeAccessible
*>(this),
684 mTree
, mTreeView
, aRow
);
686 return accessible
.forget();
689 ////////////////////////////////////////////////////////////////////////////////
690 // XULTreeItemAccessibleBase
691 ////////////////////////////////////////////////////////////////////////////////
693 XULTreeItemAccessibleBase::
694 XULTreeItemAccessibleBase(nsIContent
* aContent
, DocAccessible
* aDoc
,
695 Accessible
* aParent
, nsITreeBoxObject
* aTree
,
696 nsITreeView
* aTreeView
, int32_t aRow
) :
697 AccessibleWrap(aContent
, aDoc
),
698 mTree(aTree
), mTreeView(aTreeView
), mRow(aRow
)
701 mStateFlags
|= eSharedNode
;
704 XULTreeItemAccessibleBase::~XULTreeItemAccessibleBase()
708 ////////////////////////////////////////////////////////////////////////////////
709 // XULTreeItemAccessibleBase: nsISupports implementation
711 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessibleBase
, Accessible
,
714 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessibleBase
)
715 NS_INTERFACE_TABLE_INHERITED(XULTreeItemAccessibleBase
,
716 XULTreeItemAccessibleBase
)
717 NS_INTERFACE_TABLE_TAIL_INHERITING(Accessible
)
718 NS_IMPL_ADDREF_INHERITED(XULTreeItemAccessibleBase
, Accessible
)
719 NS_IMPL_RELEASE_INHERITED(XULTreeItemAccessibleBase
, Accessible
)
721 ////////////////////////////////////////////////////////////////////////////////
722 // XULTreeItemAccessibleBase: Accessible
725 XULTreeItemAccessibleBase::FocusedChild()
727 return FocusMgr()->FocusedAccessible() == this ? this : nullptr;
731 XULTreeItemAccessibleBase::Bounds() const
733 // Get x coordinate and width from treechildren element, get y coordinate and
734 // height from tree cell.
736 nsCOMPtr
<nsIBoxObject
> boxObj
= nsCoreUtils::GetTreeBodyBoxObject(mTree
);
740 nsCOMPtr
<nsITreeColumn
> column
= nsCoreUtils::GetFirstSensibleColumn(mTree
);
742 int32_t x
= 0, y
= 0, width
= 0, height
= 0;
743 nsresult rv
= mTree
->GetCoordsForCellItem(mRow
, column
, EmptyString(),
744 &x
, &y
, &width
, &height
);
748 boxObj
->GetWidth(&width
);
750 int32_t tcX
= 0, tcY
= 0;
751 boxObj
->GetScreenX(&tcX
);
752 boxObj
->GetScreenY(&tcY
);
757 nsPresContext
* presContext
= mDoc
->PresContext();
758 return nsIntRect(presContext
->CSSPixelsToDevPixels(x
),
759 presContext
->CSSPixelsToDevPixels(y
),
760 presContext
->CSSPixelsToDevPixels(width
),
761 presContext
->CSSPixelsToDevPixels(height
));
765 XULTreeItemAccessibleBase::SetSelected(bool aSelect
)
767 nsCOMPtr
<nsITreeSelection
> selection
;
768 mTreeView
->GetSelection(getter_AddRefs(selection
));
770 bool isSelected
= false;
771 selection
->IsSelected(mRow
, &isSelected
);
772 if (isSelected
!= aSelect
)
773 selection
->ToggleSelect(mRow
);
778 XULTreeItemAccessibleBase::TakeFocus()
780 nsCOMPtr
<nsITreeSelection
> selection
;
781 mTreeView
->GetSelection(getter_AddRefs(selection
));
783 selection
->SetCurrentIndex(mRow
);
785 // focus event will be fired here
786 Accessible::TakeFocus();
790 XULTreeItemAccessibleBase::RelationByType(RelationType aType
)
794 case RelationType::NODE_CHILD_OF
: {
795 int32_t parentIndex
= -1;
796 if (!NS_SUCCEEDED(mTreeView
->GetParentIndex(mRow
, &parentIndex
)))
799 if (parentIndex
== -1)
800 return Relation(mParent
);
802 XULTreeAccessible
* treeAcc
= mParent
->AsXULTree();
803 return Relation(treeAcc
->GetTreeItemAccessible(parentIndex
));
806 case RelationType::NODE_PARENT_OF
: {
808 if (NS_FAILED(mTreeView
->IsContainerEmpty(mRow
, &isTrue
)) || isTrue
)
811 if (NS_FAILED(mTreeView
->IsContainerOpen(mRow
, &isTrue
)) || !isTrue
)
814 XULTreeAccessible
* tree
= mParent
->AsXULTree();
815 return Relation(new XULTreeItemIterator(tree
, mTreeView
, mRow
));
824 XULTreeItemAccessibleBase::ActionCount()
826 // "activate" action is available for all treeitems, "expand/collapse" action
827 // is avaible for treeitem which is container.
828 return IsExpandable() ? 2 : 1;
832 XULTreeItemAccessibleBase::ActionNameAt(uint8_t aIndex
, nsAString
& aName
)
834 if (aIndex
== eAction_Click
) {
835 aName
.AssignLiteral("activate");
839 if (aIndex
== eAction_Expand
&& IsExpandable()) {
840 bool isContainerOpen
= false;
841 mTreeView
->IsContainerOpen(mRow
, &isContainerOpen
);
843 aName
.AssignLiteral("collapse");
845 aName
.AssignLiteral("expand");
850 XULTreeItemAccessibleBase::DoAction(uint8_t aIndex
)
852 if (aIndex
!= eAction_Click
&&
853 (aIndex
!= eAction_Expand
|| !IsExpandable()))
856 DoCommand(nullptr, aIndex
);
860 ////////////////////////////////////////////////////////////////////////////////
861 // XULTreeItemAccessibleBase: Accessible implementation
864 XULTreeItemAccessibleBase::Shutdown()
870 AccessibleWrap::Shutdown();
874 XULTreeItemAccessibleBase::GroupPosition()
879 nsresult rv
= mTreeView
->GetLevel(mRow
, &level
);
880 NS_ENSURE_SUCCESS(rv
, groupPos
);
882 int32_t topCount
= 1;
883 for (int32_t index
= mRow
- 1; index
>= 0; index
--) {
885 if (NS_SUCCEEDED(mTreeView
->GetLevel(index
, &lvl
))) {
894 int32_t rowCount
= 0;
895 rv
= mTreeView
->GetRowCount(&rowCount
);
896 NS_ENSURE_SUCCESS(rv
, groupPos
);
898 int32_t bottomCount
= 0;
899 for (int32_t index
= mRow
+ 1; index
< rowCount
; index
++) {
901 if (NS_SUCCEEDED(mTreeView
->GetLevel(index
, &lvl
))) {
910 groupPos
.level
= level
+ 1;
911 groupPos
.setSize
= topCount
+ bottomCount
;
912 groupPos
.posInSet
= topCount
;
918 XULTreeItemAccessibleBase::NativeState()
921 // focusable and selectable states
922 uint64_t state
= NativeInteractiveState();
924 // expanded/collapsed state
925 if (IsExpandable()) {
926 bool isContainerOpen
;
927 mTreeView
->IsContainerOpen(mRow
, &isContainerOpen
);
928 state
|= isContainerOpen
? states::EXPANDED
: states::COLLAPSED
;
932 nsCOMPtr
<nsITreeSelection
> selection
;
933 mTreeView
->GetSelection(getter_AddRefs(selection
));
936 selection
->IsSelected(mRow
, &isSelected
);
938 state
|= states::SELECTED
;
942 if (FocusMgr()->IsFocused(this))
943 state
|= states::FOCUSED
;
946 int32_t firstVisibleRow
, lastVisibleRow
;
947 mTree
->GetFirstVisibleRow(&firstVisibleRow
);
948 mTree
->GetLastVisibleRow(&lastVisibleRow
);
949 if (mRow
< firstVisibleRow
|| mRow
> lastVisibleRow
)
950 state
|= states::INVISIBLE
;
956 XULTreeItemAccessibleBase::NativeInteractiveState() const
958 return states::FOCUSABLE
| states::SELECTABLE
;
962 XULTreeItemAccessibleBase::IndexInParent() const
964 return mParent
? mParent
->ContentChildCount() + mRow
: -1;
967 ////////////////////////////////////////////////////////////////////////////////
968 // XULTreeItemAccessibleBase: Widgets
971 XULTreeItemAccessibleBase::ContainerWidget() const
976 ////////////////////////////////////////////////////////////////////////////////
977 // XULTreeItemAccessibleBase: Accessible protected methods
980 XULTreeItemAccessibleBase::DispatchClickEvent(nsIContent
* aContent
,
981 uint32_t aActionIndex
)
986 nsCOMPtr
<nsITreeColumns
> columns
;
987 mTree
->GetColumns(getter_AddRefs(columns
));
991 // Get column and pseudo element.
992 nsCOMPtr
<nsITreeColumn
> column
;
993 nsAutoString pseudoElm
;
995 if (aActionIndex
== eAction_Click
) {
996 // Key column is visible and clickable.
997 columns
->GetKeyColumn(getter_AddRefs(column
));
999 // Primary column contains a twisty we should click on.
1000 columns
->GetPrimaryColumn(getter_AddRefs(column
));
1001 pseudoElm
= NS_LITERAL_STRING("twisty");
1005 nsCoreUtils::DispatchClickEvent(mTree
, mRow
, column
, pseudoElm
);
1009 XULTreeItemAccessibleBase::GetSiblingAtOffset(int32_t aOffset
,
1010 nsresult
* aError
) const
1013 *aError
= NS_OK
; // fail peacefully
1015 return mParent
->GetChildAt(IndexInParent() + aOffset
);
1018 ////////////////////////////////////////////////////////////////////////////////
1019 // XULTreeItemAccessibleBase: protected implementation
1022 XULTreeItemAccessibleBase::IsExpandable()
1025 bool isContainer
= false;
1026 mTreeView
->IsContainer(mRow
, &isContainer
);
1028 bool isEmpty
= false;
1029 mTreeView
->IsContainerEmpty(mRow
, &isEmpty
);
1031 nsCOMPtr
<nsITreeColumns
> columns
;
1032 mTree
->GetColumns(getter_AddRefs(columns
));
1033 nsCOMPtr
<nsITreeColumn
> primaryColumn
;
1035 columns
->GetPrimaryColumn(getter_AddRefs(primaryColumn
));
1036 if (primaryColumn
&&
1037 !nsCoreUtils::IsColumnHidden(primaryColumn
))
1047 XULTreeItemAccessibleBase::GetCellName(nsITreeColumn
* aColumn
, nsAString
& aName
)
1050 mTreeView
->GetCellText(mRow
, aColumn
, aName
);
1052 // If there is still no name try the cell value:
1053 // This is for graphical cells. We need tree/table view implementors to
1054 // implement FooView::GetCellValue to return a meaningful string for cases
1055 // where there is something shown in the cell (non-text) such as a star icon;
1056 // in which case GetCellValue for that cell would return "starred" or
1057 // "flagged" for example.
1058 if (aName
.IsEmpty())
1059 mTreeView
->GetCellValue(mRow
, aColumn
, aName
);
1063 ////////////////////////////////////////////////////////////////////////////////
1064 // XULTreeItemAccessible
1065 ////////////////////////////////////////////////////////////////////////////////
1067 XULTreeItemAccessible::
1068 XULTreeItemAccessible(nsIContent
* aContent
, DocAccessible
* aDoc
,
1069 Accessible
* aParent
, nsITreeBoxObject
* aTree
,
1070 nsITreeView
* aTreeView
, int32_t aRow
) :
1071 XULTreeItemAccessibleBase(aContent
, aDoc
, aParent
, aTree
, aTreeView
, aRow
)
1073 mColumn
= nsCoreUtils::GetFirstSensibleColumn(mTree
);
1074 GetCellName(mColumn
, mCachedName
);
1077 XULTreeItemAccessible::~XULTreeItemAccessible()
1081 ////////////////////////////////////////////////////////////////////////////////
1082 // XULTreeItemAccessible: nsISupports implementation
1084 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessible
,
1085 XULTreeItemAccessibleBase
,
1088 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessible
)
1089 NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase
)
1090 NS_IMPL_ADDREF_INHERITED(XULTreeItemAccessible
, XULTreeItemAccessibleBase
)
1091 NS_IMPL_RELEASE_INHERITED(XULTreeItemAccessible
, XULTreeItemAccessibleBase
)
1093 ////////////////////////////////////////////////////////////////////////////////
1094 // XULTreeItemAccessible: nsIAccessible implementation
1097 XULTreeItemAccessible::Name(nsString
& aName
)
1101 GetCellName(mColumn
, aName
);
1105 ////////////////////////////////////////////////////////////////////////////////
1106 // XULTreeItemAccessible: Accessible implementation
1109 XULTreeItemAccessible::Shutdown()
1112 XULTreeItemAccessibleBase::Shutdown();
1116 XULTreeItemAccessible::NativeRole()
1118 nsCOMPtr
<nsITreeColumns
> columns
;
1119 mTree
->GetColumns(getter_AddRefs(columns
));
1121 NS_ERROR("No tree columns object in the tree!");
1122 return roles::NOTHING
;
1125 nsCOMPtr
<nsITreeColumn
> primaryColumn
;
1126 columns
->GetPrimaryColumn(getter_AddRefs(primaryColumn
));
1128 return primaryColumn
? roles::OUTLINEITEM
: roles::LISTITEM
;
1131 ////////////////////////////////////////////////////////////////////////////////
1132 // XULTreeItemAccessible: XULTreeItemAccessibleBase implementation
1135 XULTreeItemAccessible::RowInvalidated(int32_t aStartColIdx
, int32_t aEndColIdx
)
1140 if (name
!= mCachedName
) {
1141 nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE
, this);
1146 ////////////////////////////////////////////////////////////////////////////////
1147 // XULTreeItemAccessible: Accessible protected implementation
1150 XULTreeItemAccessible::CacheChildren()
1155 ////////////////////////////////////////////////////////////////////////////////
1156 // XULTreeColumAccessible
1157 ////////////////////////////////////////////////////////////////////////////////
1159 XULTreeColumAccessible::
1160 XULTreeColumAccessible(nsIContent
* aContent
, DocAccessible
* aDoc
) :
1161 XULColumAccessible(aContent
, aDoc
)
1166 XULTreeColumAccessible::GetSiblingAtOffset(int32_t aOffset
,
1167 nsresult
* aError
) const
1170 return XULColumAccessible::GetSiblingAtOffset(aOffset
, aError
);
1173 *aError
= NS_OK
; // fail peacefully
1175 nsCOMPtr
<nsITreeBoxObject
> tree
= nsCoreUtils::GetTreeBoxObject(mContent
);
1177 nsCOMPtr
<nsITreeView
> treeView
;
1178 tree
->GetView(getter_AddRefs(treeView
));
1180 int32_t rowCount
= 0;
1181 treeView
->GetRowCount(&rowCount
);
1182 if (rowCount
> 0 && aOffset
<= rowCount
) {
1183 XULTreeAccessible
* treeAcc
= Parent()->AsXULTree();
1186 return treeAcc
->GetTreeItemAccessible(aOffset
- 1);