summaryrefslogtreecommitdiffstats
path: root/accessible/xul/XULSelectControlAccessible.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/xul/XULSelectControlAccessible.cpp')
-rw-r--r--accessible/xul/XULSelectControlAccessible.cpp253
1 files changed, 253 insertions, 0 deletions
diff --git a/accessible/xul/XULSelectControlAccessible.cpp b/accessible/xul/XULSelectControlAccessible.cpp
new file mode 100644
index 0000000000..006d1daf89
--- /dev/null
+++ b/accessible/xul/XULSelectControlAccessible.cpp
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "XULSelectControlAccessible.h"
+
+#include "nsAccessibilityService.h"
+#include "DocAccessible.h"
+
+#include "nsIDOMXULSelectCntrlItemEl.h"
+#include "nsIDOMXULMultSelectCntrlEl.h"
+
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/KeyboardEventBinding.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+////////////////////////////////////////////////////////////////////////////////
+// XULSelectControlAccessible
+////////////////////////////////////////////////////////////////////////////////
+
+XULSelectControlAccessible::XULSelectControlAccessible(nsIContent* aContent,
+ DocAccessible* aDoc)
+ : AccessibleWrap(aContent, aDoc) {
+ mGenericTypes |= eSelect;
+ mSelectControl = aContent->AsElement();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// XULSelectControlAccessible: LocalAccessible
+
+void XULSelectControlAccessible::Shutdown() {
+ mSelectControl = nullptr;
+ AccessibleWrap::Shutdown();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// XULSelectControlAccessible: SelectAccessible
+
+void XULSelectControlAccessible::SelectedItems(nsTArray<Accessible*>* aItems) {
+ // For XUL multi-select control
+ nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect =
+ mSelectControl->AsXULMultiSelectControl();
+ if (xulMultiSelect) {
+ int32_t length = 0;
+ xulMultiSelect->GetSelectedCount(&length);
+ for (int32_t index = 0; index < length; index++) {
+ RefPtr<dom::Element> element;
+ xulMultiSelect->MultiGetSelectedItem(index, getter_AddRefs(element));
+ LocalAccessible* item = mDoc->GetAccessible(element);
+ if (item) aItems->AppendElement(item);
+ }
+ } else { // Single select?
+ nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+ mSelectControl->AsXULSelectControl();
+ RefPtr<dom::Element> element;
+ selectControl->GetSelectedItem(getter_AddRefs(element));
+ if (element) {
+ LocalAccessible* item = mDoc->GetAccessible(element);
+ if (item) aItems->AppendElement(item);
+ }
+ }
+}
+
+Accessible* XULSelectControlAccessible::GetSelectedItem(uint32_t aIndex) {
+ nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+ mSelectControl->AsXULMultiSelectControl();
+
+ RefPtr<dom::Element> element;
+ if (multiSelectControl) {
+ multiSelectControl->MultiGetSelectedItem(aIndex, getter_AddRefs(element));
+ } else if (aIndex == 0) {
+ nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+ mSelectControl->AsXULSelectControl();
+ if (selectControl) {
+ selectControl->GetSelectedItem(getter_AddRefs(element));
+ }
+ }
+
+ return element && mDoc ? mDoc->GetAccessible(element) : nullptr;
+}
+
+uint32_t XULSelectControlAccessible::SelectedItemCount() {
+ // For XUL multi-select control
+ nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+ mSelectControl->AsXULMultiSelectControl();
+ if (multiSelectControl) {
+ int32_t count = 0;
+ multiSelectControl->GetSelectedCount(&count);
+ return count;
+ }
+
+ // For XUL single-select control/menulist
+ nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+ mSelectControl->AsXULSelectControl();
+ if (selectControl) {
+ int32_t index = -1;
+ selectControl->GetSelectedIndex(&index);
+ return (index >= 0) ? 1 : 0;
+ }
+
+ return 0;
+}
+
+bool XULSelectControlAccessible::AddItemToSelection(uint32_t aIndex) {
+ LocalAccessible* item = LocalChildAt(aIndex);
+ if (!item || !item->GetContent()) return false;
+
+ nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
+ item->GetContent()->AsElement()->AsXULSelectControlItem();
+ if (!itemElm) return false;
+
+ bool isItemSelected = false;
+ itemElm->GetSelected(&isItemSelected);
+ if (isItemSelected) return true;
+
+ nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+ mSelectControl->AsXULMultiSelectControl();
+
+ if (multiSelectControl) {
+ multiSelectControl->AddItemToSelection(itemElm);
+ } else {
+ nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+ mSelectControl->AsXULSelectControl();
+ if (selectControl) {
+ selectControl->SetSelectedItem(item->Elm());
+ }
+ }
+
+ return true;
+}
+
+bool XULSelectControlAccessible::RemoveItemFromSelection(uint32_t aIndex) {
+ LocalAccessible* item = LocalChildAt(aIndex);
+ if (!item || !item->GetContent()) return false;
+
+ nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
+ item->GetContent()->AsElement()->AsXULSelectControlItem();
+ if (!itemElm) return false;
+
+ bool isItemSelected = false;
+ itemElm->GetSelected(&isItemSelected);
+ if (!isItemSelected) return true;
+
+ nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+ mSelectControl->AsXULMultiSelectControl();
+
+ if (multiSelectControl) {
+ multiSelectControl->RemoveItemFromSelection(itemElm);
+ } else {
+ nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+ mSelectControl->AsXULSelectControl();
+ if (selectControl) {
+ selectControl->SetSelectedItem(nullptr);
+ }
+ }
+
+ return true;
+}
+
+bool XULSelectControlAccessible::IsItemSelected(uint32_t aIndex) {
+ LocalAccessible* item = LocalChildAt(aIndex);
+ if (!item || !item->GetContent()) return false;
+
+ nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
+ item->GetContent()->AsElement()->AsXULSelectControlItem();
+ if (!itemElm) return false;
+
+ bool isItemSelected = false;
+ itemElm->GetSelected(&isItemSelected);
+ return isItemSelected;
+}
+
+bool XULSelectControlAccessible::UnselectAll() {
+ nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+ mSelectControl->AsXULMultiSelectControl();
+ if (multiSelectControl) {
+ multiSelectControl->ClearSelection();
+ } else {
+ nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+ mSelectControl->AsXULSelectControl();
+ if (selectControl) {
+ selectControl->SetSelectedIndex(-1);
+ }
+ }
+
+ return true;
+}
+
+bool XULSelectControlAccessible::SelectAll() {
+ nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+ mSelectControl->AsXULMultiSelectControl();
+ if (multiSelectControl) {
+ multiSelectControl->SelectAll();
+ return true;
+ }
+
+ // otherwise, don't support this method
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// XULSelectControlAccessible: Widgets
+
+LocalAccessible* XULSelectControlAccessible::CurrentItem() const {
+ // aria-activedescendant should override.
+ LocalAccessible* current = AccessibleWrap::CurrentItem();
+ if (current) {
+ return current;
+ }
+
+ if (!mSelectControl) return nullptr;
+
+ RefPtr<dom::Element> currentItemElm;
+ nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+ mSelectControl->AsXULMultiSelectControl();
+ if (multiSelectControl) {
+ multiSelectControl->GetCurrentItem(getter_AddRefs(currentItemElm));
+ } else {
+ nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+ mSelectControl->AsXULSelectControl();
+ if (selectControl) {
+ selectControl->GetSelectedItem(getter_AddRefs(currentItemElm));
+ }
+ }
+
+ if (currentItemElm) {
+ DocAccessible* document = Document();
+ if (document) return document->GetAccessible(currentItemElm);
+ }
+
+ return nullptr;
+}
+
+void XULSelectControlAccessible::SetCurrentItem(const LocalAccessible* aItem) {
+ if (!mSelectControl) return;
+
+ nsCOMPtr<dom::Element> itemElm = aItem->Elm();
+ nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+ itemElm->AsXULMultiSelectControl();
+ if (multiSelectControl) {
+ multiSelectControl->SetCurrentItem(itemElm);
+ } else {
+ nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
+ mSelectControl->AsXULSelectControl();
+ if (selectControl) {
+ selectControl->SetSelectedItem(itemElm);
+ }
+ }
+}