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 "XULSelectControlAccessible.h"
9 #include "nsAccessibilityService.h"
10 #include "DocAccessible.h"
12 #include "nsIDOMXULSelectCntrlItemEl.h"
13 #include "nsIDOMXULMultSelectCntrlEl.h"
15 #include "mozilla/dom/Element.h"
16 #include "mozilla/dom/KeyboardEventBinding.h"
18 using namespace mozilla
;
19 using namespace mozilla::a11y
;
21 ////////////////////////////////////////////////////////////////////////////////
22 // XULSelectControlAccessible
23 ////////////////////////////////////////////////////////////////////////////////
25 XULSelectControlAccessible::XULSelectControlAccessible(nsIContent
* aContent
,
27 : AccessibleWrap(aContent
, aDoc
) {
28 mGenericTypes
|= eSelect
;
29 mSelectControl
= aContent
->AsElement();
32 ////////////////////////////////////////////////////////////////////////////////
33 // XULSelectControlAccessible: LocalAccessible
35 void XULSelectControlAccessible::Shutdown() {
36 mSelectControl
= nullptr;
37 AccessibleWrap::Shutdown();
40 ////////////////////////////////////////////////////////////////////////////////
41 // XULSelectControlAccessible: SelectAccessible
43 void XULSelectControlAccessible::SelectedItems(nsTArray
<Accessible
*>* aItems
) {
44 // For XUL multi-select control
45 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> xulMultiSelect
=
46 mSelectControl
->AsXULMultiSelectControl();
49 xulMultiSelect
->GetSelectedCount(&length
);
50 for (int32_t index
= 0; index
< length
; index
++) {
51 RefPtr
<dom::Element
> element
;
52 xulMultiSelect
->MultiGetSelectedItem(index
, getter_AddRefs(element
));
53 LocalAccessible
* item
= mDoc
->GetAccessible(element
);
54 if (item
) aItems
->AppendElement(item
);
56 } else { // Single select?
57 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
58 mSelectControl
->AsXULSelectControl();
59 RefPtr
<dom::Element
> element
;
60 selectControl
->GetSelectedItem(getter_AddRefs(element
));
62 LocalAccessible
* item
= mDoc
->GetAccessible(element
);
63 if (item
) aItems
->AppendElement(item
);
68 Accessible
* XULSelectControlAccessible::GetSelectedItem(uint32_t aIndex
) {
69 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
70 mSelectControl
->AsXULMultiSelectControl();
72 RefPtr
<dom::Element
> element
;
73 if (multiSelectControl
) {
74 multiSelectControl
->MultiGetSelectedItem(aIndex
, getter_AddRefs(element
));
75 } else if (aIndex
== 0) {
76 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
77 mSelectControl
->AsXULSelectControl();
79 selectControl
->GetSelectedItem(getter_AddRefs(element
));
83 return element
&& mDoc
? mDoc
->GetAccessible(element
) : nullptr;
86 uint32_t XULSelectControlAccessible::SelectedItemCount() {
87 // For XUL multi-select control
88 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
89 mSelectControl
->AsXULMultiSelectControl();
90 if (multiSelectControl
) {
92 multiSelectControl
->GetSelectedCount(&count
);
96 // For XUL single-select control/menulist
97 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
98 mSelectControl
->AsXULSelectControl();
101 selectControl
->GetSelectedIndex(&index
);
102 return (index
>= 0) ? 1 : 0;
108 bool XULSelectControlAccessible::AddItemToSelection(uint32_t aIndex
) {
109 LocalAccessible
* item
= LocalChildAt(aIndex
);
110 if (!item
|| !item
->GetContent()) return false;
112 nsCOMPtr
<nsIDOMXULSelectControlItemElement
> itemElm
=
113 item
->GetContent()->AsElement()->AsXULSelectControlItem();
114 if (!itemElm
) return false;
116 bool isItemSelected
= false;
117 itemElm
->GetSelected(&isItemSelected
);
118 if (isItemSelected
) return true;
120 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
121 mSelectControl
->AsXULMultiSelectControl();
123 if (multiSelectControl
) {
124 multiSelectControl
->AddItemToSelection(itemElm
);
126 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
127 mSelectControl
->AsXULSelectControl();
129 selectControl
->SetSelectedItem(item
->Elm());
136 bool XULSelectControlAccessible::RemoveItemFromSelection(uint32_t aIndex
) {
137 LocalAccessible
* item
= LocalChildAt(aIndex
);
138 if (!item
|| !item
->GetContent()) return false;
140 nsCOMPtr
<nsIDOMXULSelectControlItemElement
> itemElm
=
141 item
->GetContent()->AsElement()->AsXULSelectControlItem();
142 if (!itemElm
) return false;
144 bool isItemSelected
= false;
145 itemElm
->GetSelected(&isItemSelected
);
146 if (!isItemSelected
) return true;
148 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
149 mSelectControl
->AsXULMultiSelectControl();
151 if (multiSelectControl
) {
152 multiSelectControl
->RemoveItemFromSelection(itemElm
);
154 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
155 mSelectControl
->AsXULSelectControl();
157 selectControl
->SetSelectedItem(nullptr);
164 bool XULSelectControlAccessible::IsItemSelected(uint32_t aIndex
) {
165 LocalAccessible
* item
= LocalChildAt(aIndex
);
166 if (!item
|| !item
->GetContent()) return false;
168 nsCOMPtr
<nsIDOMXULSelectControlItemElement
> itemElm
=
169 item
->GetContent()->AsElement()->AsXULSelectControlItem();
170 if (!itemElm
) return false;
172 bool isItemSelected
= false;
173 itemElm
->GetSelected(&isItemSelected
);
174 return isItemSelected
;
177 bool XULSelectControlAccessible::UnselectAll() {
178 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
179 mSelectControl
->AsXULMultiSelectControl();
180 if (multiSelectControl
) {
181 multiSelectControl
->ClearSelection();
183 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
184 mSelectControl
->AsXULSelectControl();
186 selectControl
->SetSelectedIndex(-1);
193 bool XULSelectControlAccessible::SelectAll() {
194 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
195 mSelectControl
->AsXULMultiSelectControl();
196 if (multiSelectControl
) {
197 multiSelectControl
->SelectAll();
201 // otherwise, don't support this method
205 ////////////////////////////////////////////////////////////////////////////////
206 // XULSelectControlAccessible: Widgets
208 LocalAccessible
* XULSelectControlAccessible::CurrentItem() const {
209 // aria-activedescendant should override.
210 LocalAccessible
* current
= AccessibleWrap::CurrentItem();
215 if (!mSelectControl
) return nullptr;
217 RefPtr
<dom::Element
> currentItemElm
;
218 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
219 mSelectControl
->AsXULMultiSelectControl();
220 if (multiSelectControl
) {
221 multiSelectControl
->GetCurrentItem(getter_AddRefs(currentItemElm
));
223 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
224 mSelectControl
->AsXULSelectControl();
226 selectControl
->GetSelectedItem(getter_AddRefs(currentItemElm
));
230 if (currentItemElm
) {
231 DocAccessible
* document
= Document();
232 if (document
) return document
->GetAccessible(currentItemElm
);
238 void XULSelectControlAccessible::SetCurrentItem(const LocalAccessible
* aItem
) {
239 if (!mSelectControl
) return;
241 nsCOMPtr
<dom::Element
> itemElm
= aItem
->Elm();
242 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
243 itemElm
->AsXULMultiSelectControl();
244 if (multiSelectControl
) {
245 multiSelectControl
->SetCurrentItem(itemElm
);
247 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
248 mSelectControl
->AsXULSelectControl();
250 selectControl
->SetSelectedItem(itemElm
);