XULSelectControlAccessible.cpp (8145B)
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/. */ 6 7 #include "XULSelectControlAccessible.h" 8 9 #include "nsAccessibilityService.h" 10 #include "DocAccessible.h" 11 12 #include "nsIDOMXULSelectCntrlItemEl.h" 13 #include "nsIDOMXULMultSelectCntrlEl.h" 14 15 #include "mozilla/dom/Element.h" 16 #include "mozilla/dom/KeyboardEventBinding.h" 17 18 using namespace mozilla; 19 using namespace mozilla::a11y; 20 21 //////////////////////////////////////////////////////////////////////////////// 22 // XULSelectControlAccessible 23 //////////////////////////////////////////////////////////////////////////////// 24 25 XULSelectControlAccessible::XULSelectControlAccessible(nsIContent* aContent, 26 DocAccessible* aDoc) 27 : AccessibleWrap(aContent, aDoc) { 28 mGenericTypes |= eSelect; 29 mSelectControl = aContent->AsElement(); 30 } 31 32 //////////////////////////////////////////////////////////////////////////////// 33 // XULSelectControlAccessible: LocalAccessible 34 35 void XULSelectControlAccessible::Shutdown() { 36 mSelectControl = nullptr; 37 AccessibleWrap::Shutdown(); 38 } 39 40 //////////////////////////////////////////////////////////////////////////////// 41 // XULSelectControlAccessible: SelectAccessible 42 43 void XULSelectControlAccessible::SelectedItems(nsTArray<Accessible*>* aItems) { 44 // For XUL multi-select control 45 nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect = 46 mSelectControl->AsXULMultiSelectControl(); 47 if (xulMultiSelect) { 48 int32_t length = 0; 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); 55 } 56 } else { // Single select? 57 nsCOMPtr<nsIDOMXULSelectControlElement> selectControl = 58 mSelectControl->AsXULSelectControl(); 59 RefPtr<dom::Element> element; 60 selectControl->GetSelectedItem(getter_AddRefs(element)); 61 if (element) { 62 LocalAccessible* item = mDoc->GetAccessible(element); 63 if (item) aItems->AppendElement(item); 64 } 65 } 66 } 67 68 Accessible* XULSelectControlAccessible::GetSelectedItem(uint32_t aIndex) { 69 nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl = 70 mSelectControl->AsXULMultiSelectControl(); 71 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(); 78 if (selectControl) { 79 selectControl->GetSelectedItem(getter_AddRefs(element)); 80 } 81 } 82 83 return element && mDoc ? mDoc->GetAccessible(element) : nullptr; 84 } 85 86 uint32_t XULSelectControlAccessible::SelectedItemCount() { 87 // For XUL multi-select control 88 nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl = 89 mSelectControl->AsXULMultiSelectControl(); 90 if (multiSelectControl) { 91 int32_t count = 0; 92 multiSelectControl->GetSelectedCount(&count); 93 return count; 94 } 95 96 // For XUL single-select control/menulist 97 nsCOMPtr<nsIDOMXULSelectControlElement> selectControl = 98 mSelectControl->AsXULSelectControl(); 99 if (selectControl) { 100 int32_t index = -1; 101 selectControl->GetSelectedIndex(&index); 102 return (index >= 0) ? 1 : 0; 103 } 104 105 return 0; 106 } 107 108 bool XULSelectControlAccessible::AddItemToSelection(uint32_t aIndex) { 109 LocalAccessible* item = LocalChildAt(aIndex); 110 if (!item || !item->GetContent()) return false; 111 112 nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm = 113 item->GetContent()->AsElement()->AsXULSelectControlItem(); 114 if (!itemElm) return false; 115 116 bool isItemSelected = false; 117 itemElm->GetSelected(&isItemSelected); 118 if (isItemSelected) return true; 119 120 nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl = 121 mSelectControl->AsXULMultiSelectControl(); 122 123 if (multiSelectControl) { 124 multiSelectControl->AddItemToSelection(itemElm); 125 } else { 126 nsCOMPtr<nsIDOMXULSelectControlElement> selectControl = 127 mSelectControl->AsXULSelectControl(); 128 if (selectControl) { 129 selectControl->SetSelectedItem(item->Elm()); 130 } 131 } 132 133 return true; 134 } 135 136 bool XULSelectControlAccessible::RemoveItemFromSelection(uint32_t aIndex) { 137 LocalAccessible* item = LocalChildAt(aIndex); 138 if (!item || !item->GetContent()) return false; 139 140 nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm = 141 item->GetContent()->AsElement()->AsXULSelectControlItem(); 142 if (!itemElm) return false; 143 144 bool isItemSelected = false; 145 itemElm->GetSelected(&isItemSelected); 146 if (!isItemSelected) return true; 147 148 nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl = 149 mSelectControl->AsXULMultiSelectControl(); 150 151 if (multiSelectControl) { 152 multiSelectControl->RemoveItemFromSelection(itemElm); 153 } else { 154 nsCOMPtr<nsIDOMXULSelectControlElement> selectControl = 155 mSelectControl->AsXULSelectControl(); 156 if (selectControl) { 157 selectControl->SetSelectedItem(nullptr); 158 } 159 } 160 161 return true; 162 } 163 164 bool XULSelectControlAccessible::IsItemSelected(uint32_t aIndex) { 165 LocalAccessible* item = LocalChildAt(aIndex); 166 if (!item || !item->GetContent()) return false; 167 168 nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm = 169 item->GetContent()->AsElement()->AsXULSelectControlItem(); 170 if (!itemElm) return false; 171 172 bool isItemSelected = false; 173 itemElm->GetSelected(&isItemSelected); 174 return isItemSelected; 175 } 176 177 bool XULSelectControlAccessible::UnselectAll() { 178 nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl = 179 mSelectControl->AsXULMultiSelectControl(); 180 if (multiSelectControl) { 181 multiSelectControl->ClearSelection(); 182 } else { 183 nsCOMPtr<nsIDOMXULSelectControlElement> selectControl = 184 mSelectControl->AsXULSelectControl(); 185 if (selectControl) { 186 selectControl->SetSelectedIndex(-1); 187 } 188 } 189 190 return true; 191 } 192 193 bool XULSelectControlAccessible::SelectAll() { 194 nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl = 195 mSelectControl->AsXULMultiSelectControl(); 196 if (multiSelectControl) { 197 multiSelectControl->SelectAll(); 198 return true; 199 } 200 201 // otherwise, don't support this method 202 return false; 203 } 204 205 //////////////////////////////////////////////////////////////////////////////// 206 // XULSelectControlAccessible: Widgets 207 208 LocalAccessible* XULSelectControlAccessible::CurrentItem() const { 209 // aria-activedescendant should override. 210 LocalAccessible* current = AccessibleWrap::CurrentItem(); 211 if (current) { 212 return current; 213 } 214 215 if (!mSelectControl) return nullptr; 216 217 RefPtr<dom::Element> currentItemElm; 218 nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl = 219 mSelectControl->AsXULMultiSelectControl(); 220 if (multiSelectControl) { 221 multiSelectControl->GetCurrentItem(getter_AddRefs(currentItemElm)); 222 } else { 223 nsCOMPtr<nsIDOMXULSelectControlElement> selectControl = 224 mSelectControl->AsXULSelectControl(); 225 if (selectControl) { 226 selectControl->GetSelectedItem(getter_AddRefs(currentItemElm)); 227 } 228 } 229 230 if (currentItemElm) { 231 DocAccessible* document = Document(); 232 if (document) return document->GetAccessible(currentItemElm); 233 } 234 235 return nullptr; 236 } 237 238 void XULSelectControlAccessible::SetCurrentItem(const LocalAccessible* aItem) { 239 if (!mSelectControl) return; 240 241 nsCOMPtr<dom::Element> itemElm = aItem->Elm(); 242 nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl = 243 itemElm->AsXULMultiSelectControl(); 244 if (multiSelectControl) { 245 multiSelectControl->SetCurrentItem(itemElm); 246 } else { 247 nsCOMPtr<nsIDOMXULSelectControlElement> selectControl = 248 mSelectControl->AsXULSelectControl(); 249 if (selectControl) { 250 selectControl->SetSelectedItem(itemElm); 251 } 252 } 253 }