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(
44 nsTArray
<LocalAccessible
*>* aItems
) {
45 // For XUL multi-select control
46 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> xulMultiSelect
=
47 mSelectControl
->AsXULMultiSelectControl();
50 xulMultiSelect
->GetSelectedCount(&length
);
51 for (int32_t index
= 0; index
< length
; index
++) {
52 RefPtr
<dom::Element
> element
;
53 xulMultiSelect
->MultiGetSelectedItem(index
, getter_AddRefs(element
));
54 LocalAccessible
* item
= mDoc
->GetAccessible(element
);
55 if (item
) aItems
->AppendElement(item
);
57 } else { // Single select?
58 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
59 mSelectControl
->AsXULSelectControl();
60 RefPtr
<dom::Element
> element
;
61 selectControl
->GetSelectedItem(getter_AddRefs(element
));
63 LocalAccessible
* item
= mDoc
->GetAccessible(element
);
64 if (item
) aItems
->AppendElement(item
);
69 LocalAccessible
* XULSelectControlAccessible::GetSelectedItem(uint32_t aIndex
) {
70 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
71 mSelectControl
->AsXULMultiSelectControl();
73 RefPtr
<dom::Element
> element
;
74 if (multiSelectControl
) {
75 multiSelectControl
->MultiGetSelectedItem(aIndex
, getter_AddRefs(element
));
76 } else if (aIndex
== 0) {
77 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
78 mSelectControl
->AsXULSelectControl();
80 selectControl
->GetSelectedItem(getter_AddRefs(element
));
84 return element
&& mDoc
? mDoc
->GetAccessible(element
) : nullptr;
87 uint32_t XULSelectControlAccessible::SelectedItemCount() {
88 // For XUL multi-select control
89 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
90 mSelectControl
->AsXULMultiSelectControl();
91 if (multiSelectControl
) {
93 multiSelectControl
->GetSelectedCount(&count
);
97 // For XUL single-select control/menulist
98 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
99 mSelectControl
->AsXULSelectControl();
102 selectControl
->GetSelectedIndex(&index
);
103 return (index
>= 0) ? 1 : 0;
109 bool XULSelectControlAccessible::AddItemToSelection(uint32_t aIndex
) {
110 LocalAccessible
* item
= LocalChildAt(aIndex
);
111 if (!item
|| !item
->GetContent()) return false;
113 nsCOMPtr
<nsIDOMXULSelectControlItemElement
> itemElm
=
114 item
->GetContent()->AsElement()->AsXULSelectControlItem();
115 if (!itemElm
) return false;
117 bool isItemSelected
= false;
118 itemElm
->GetSelected(&isItemSelected
);
119 if (isItemSelected
) return true;
121 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
122 mSelectControl
->AsXULMultiSelectControl();
124 if (multiSelectControl
) {
125 multiSelectControl
->AddItemToSelection(itemElm
);
127 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
128 mSelectControl
->AsXULSelectControl();
130 selectControl
->SetSelectedItem(item
->Elm());
137 bool XULSelectControlAccessible::RemoveItemFromSelection(uint32_t aIndex
) {
138 LocalAccessible
* item
= LocalChildAt(aIndex
);
139 if (!item
|| !item
->GetContent()) return false;
141 nsCOMPtr
<nsIDOMXULSelectControlItemElement
> itemElm
=
142 item
->GetContent()->AsElement()->AsXULSelectControlItem();
143 if (!itemElm
) return false;
145 bool isItemSelected
= false;
146 itemElm
->GetSelected(&isItemSelected
);
147 if (!isItemSelected
) return true;
149 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
150 mSelectControl
->AsXULMultiSelectControl();
152 if (multiSelectControl
) {
153 multiSelectControl
->RemoveItemFromSelection(itemElm
);
155 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
156 mSelectControl
->AsXULSelectControl();
158 selectControl
->SetSelectedItem(nullptr);
165 bool XULSelectControlAccessible::IsItemSelected(uint32_t aIndex
) {
166 LocalAccessible
* item
= LocalChildAt(aIndex
);
167 if (!item
|| !item
->GetContent()) return false;
169 nsCOMPtr
<nsIDOMXULSelectControlItemElement
> itemElm
=
170 item
->GetContent()->AsElement()->AsXULSelectControlItem();
171 if (!itemElm
) return false;
173 bool isItemSelected
= false;
174 itemElm
->GetSelected(&isItemSelected
);
175 return isItemSelected
;
178 bool XULSelectControlAccessible::UnselectAll() {
179 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
180 mSelectControl
->AsXULMultiSelectControl();
181 if (multiSelectControl
) {
182 multiSelectControl
->ClearSelection();
184 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
185 mSelectControl
->AsXULSelectControl();
187 selectControl
->SetSelectedIndex(-1);
194 bool XULSelectControlAccessible::SelectAll() {
195 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
196 mSelectControl
->AsXULMultiSelectControl();
197 if (multiSelectControl
) {
198 multiSelectControl
->SelectAll();
202 // otherwise, don't support this method
206 ////////////////////////////////////////////////////////////////////////////////
207 // XULSelectControlAccessible: Widgets
209 LocalAccessible
* XULSelectControlAccessible::CurrentItem() const {
210 // aria-activedescendant should override.
211 LocalAccessible
* current
= AccessibleWrap::CurrentItem();
216 if (!mSelectControl
) return nullptr;
218 RefPtr
<dom::Element
> currentItemElm
;
219 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
220 mSelectControl
->AsXULMultiSelectControl();
221 if (multiSelectControl
) {
222 multiSelectControl
->GetCurrentItem(getter_AddRefs(currentItemElm
));
224 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
225 mSelectControl
->AsXULSelectControl();
227 selectControl
->GetSelectedItem(getter_AddRefs(currentItemElm
));
231 if (currentItemElm
) {
232 DocAccessible
* document
= Document();
233 if (document
) return document
->GetAccessible(currentItemElm
);
239 void XULSelectControlAccessible::SetCurrentItem(const LocalAccessible
* aItem
) {
240 if (!mSelectControl
) return;
242 nsCOMPtr
<dom::Element
> itemElm
= aItem
->Elm();
243 nsCOMPtr
<nsIDOMXULMultiSelectControlElement
> multiSelectControl
=
244 itemElm
->AsXULMultiSelectControl();
245 if (multiSelectControl
) {
246 multiSelectControl
->SetCurrentItem(itemElm
);
248 nsCOMPtr
<nsIDOMXULSelectControlElement
> selectControl
=
249 mSelectControl
->AsXULSelectControl();
251 selectControl
->SetSelectedItem(itemElm
);