Bug 363955. Combobox doesn't have good mechanism to provide the selected item. Editable menulist without dropdown button should be expose as textbox. r=surkov, r=nian.liu, r=mano

This commit is contained in:
aaronleventhal%moonset.net 2007-02-09 02:03:08 +00:00
Родитель 4d83243744
Коммит b59f3bb4be
10 изменённых файлов: 361 добавлений и 334 удалений

Просмотреть файл

@ -146,6 +146,7 @@ ACCESSIBILITY_ATOM(alt, "alt")
ACCESSIBILITY_ATOM(control, "control")
ACCESSIBILITY_ATOM(data, "data")
ACCESSIBILITY_ATOM(disabled, "disabled")
ACCESSIBILITY_ATOM(editable, "editable")
ACCESSIBILITY_ATOM(_for, "for")
ACCESSIBILITY_ATOM(href, "href")
ACCESSIBILITY_ATOM(id, "id")
@ -164,6 +165,7 @@ ACCESSIBILITY_ATOM(value, "value")
// DHTML accessibility attributes
ACCESSIBILITY_ATOM(checked, "checked")
ACCESSIBILITY_ATOM(droppable, "droppable")
ACCESSIBILITY_ATOM(expanded, "expanded")
ACCESSIBILITY_ATOM(invalid, "invalid")
ACCESSIBILITY_ATOM(level, "level")

Просмотреть файл

@ -801,7 +801,7 @@ NS_IMETHODIMP nsHTMLSelectOptGroupAccessible::GetNumActions(PRUint8 *_retval)
/** ----- nsHTMLComboboxAccessible ----- */
nsHTMLComboboxAccessible::nsHTMLComboboxAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
nsHTMLSelectableAccessible(aDOMNode, aShell)
nsAccessibleWrap(aDOMNode, aShell)
{
}

Просмотреть файл

@ -193,7 +193,7 @@ public:
/*
* A class the represents the HTML Combobox widget.
*/
class nsHTMLComboboxAccessible : public nsHTMLSelectableAccessible
class nsHTMLComboboxAccessible : public nsAccessibleWrap
{
public:
enum { eAction_Click = 0 };

Просмотреть файл

@ -42,6 +42,7 @@
#include "nsHTMLFormControlAccessible.h"
#include "nsAccessibilityAtoms.h"
#include "nsAccessibleTreeWalker.h"
#include "nsXULMenuAccessible.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMNSEditableElement.h"
#include "nsIDOMXULButtonElement.h"
@ -662,6 +663,10 @@ NS_IMETHODIMP nsXULTextFieldAccessible::GetValue(nsAString& aValue)
if (textBox) {
return textBox->GetValue(aValue);
}
nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mDOMNode));
if (menuList) {
return menuList->GetLabel(aValue);
}
return NS_ERROR_FAILURE;
}
@ -687,16 +692,30 @@ NS_IMETHODIMP nsXULTextFieldAccessible::GetExtState(PRUint32 *aExtState)
return NS_OK;
}
already_AddRefed<nsIDOMNode> nsXULTextFieldAccessible::GetInputField()
{
nsIDOMNode *inputField = nsnull;
nsCOMPtr<nsIDOMXULTextBoxElement> textBox = do_QueryInterface(mDOMNode);
if (textBox) {
textBox->GetInputField(&inputField);
return inputField;
}
nsCOMPtr<nsIDOMXULMenuListElement> menuList = do_QueryInterface(mDOMNode);
if (menuList) { // <xul:menulist droppable="false">
menuList->GetInputField(&inputField);
}
NS_ASSERTION(inputField, "No input field for nsXULTextFieldAccessible");
return inputField;
}
NS_IMETHODIMP nsXULTextFieldAccessible::GetState(PRUint32 *aState)
{
nsCOMPtr<nsIDOMXULTextBoxElement> textBox(do_QueryInterface(mDOMNode));
if (!textBox) {
if (!mDOMNode) {
return NS_ERROR_FAILURE;
}
nsHyperTextAccessible::GetState(aState);
nsCOMPtr<nsIDOMNode> inputField;
textBox->GetInputField(getter_AddRefs(inputField));
nsCOMPtr<nsIDOMNode> inputField = GetInputField();
if (!inputField) {
return NS_ERROR_FAILURE;
}
@ -710,15 +729,26 @@ NS_IMETHODIMP nsXULTextFieldAccessible::GetState(PRUint32 *aState)
}
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
NS_ASSERTION(content, "Not possible since we are a nsIDOMXULTextBoxElement");
if (content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::type,
nsAccessibilityAtoms::password, eIgnoreCase)) {
*aState |= STATE_PROTECTED;
}
NS_ASSERTION(content, "Not possible since we have an mDOMNode");
if (content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::readonly,
nsAccessibilityAtoms::_true, eIgnoreCase)) {
*aState |= STATE_READONLY;
nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mDOMNode));
if (menuList) {
// <xul:menulist droppable="false">
if (!content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::editable,
nsAccessibilityAtoms::_true, eIgnoreCase)) {
*aState |= STATE_READONLY;
}
}
else {
// <xul:textbox>
if (content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::type,
nsAccessibilityAtoms::password, eIgnoreCase)) {
*aState |= STATE_PROTECTED;
}
if (content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::readonly,
nsAccessibilityAtoms::_true, eIgnoreCase)) {
*aState |= STATE_READONLY;
}
}
return rv;
@ -791,17 +821,7 @@ void nsXULTextFieldAccessible::SetEditor(nsIEditor* aEditor)
void nsXULTextFieldAccessible::CheckForEditor()
{
nsCOMPtr<nsIDOMXULTextBoxElement> textBox(do_QueryInterface(mDOMNode));
if (!textBox) {
return;
}
nsCOMPtr<nsIDOMNode> inputField;
textBox->GetInputField(getter_AddRefs(inputField));
if (!inputField) {
return;
}
nsCOMPtr<nsIDOMNode> inputField = GetInputField();
nsCOMPtr<nsIDOMNSEditableElement> editableElt(do_QueryInterface(inputField));
if (!editableElt) {
return;

Просмотреть файл

@ -169,6 +169,8 @@ public:
NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
protected:
already_AddRefed<nsIDOMNode> GetInputField();
// Editor helpers, subclasses of nsHyperTextAccessible may have editor
virtual void SetEditor(nsIEditor *aEditor);
virtual already_AddRefed<nsIEditor> GetEditor() { nsIEditor *editor = mEditor; NS_IF_ADDREF(editor); return editor; }

Просмотреть файл

@ -39,7 +39,9 @@
#include "nsXULMenuAccessible.h"
#include "nsIDOMElement.h"
#include "nsIDOMXULElement.h"
#include "nsIMutableArray.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsIDOMXULMultSelectCntrlEl.h"
#include "nsIDOMKeyEvent.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
@ -49,6 +51,211 @@
#include "nsGUIEvent.h"
#include "nsXULFormControlAccessible.h"
/** ------------------------------------------------------ */
/** Impl. of nsXULSelectableAccessible */
/** ------------------------------------------------------ */
// Helper methos
nsXULSelectableAccessible::nsXULSelectableAccessible(nsIDOMNode* aDOMNode,
nsIWeakReference* aShell):
nsAccessibleWrap(aDOMNode, aShell)
{
mSelectControl = do_QueryInterface(aDOMNode);
}
NS_IMPL_ISUPPORTS_INHERITED1(nsXULSelectableAccessible, nsAccessible, nsIAccessibleSelectable)
NS_IMETHODIMP nsXULSelectableAccessible::Shutdown()
{
mSelectControl = nsnull;
return nsAccessibleWrap::Shutdown();
}
nsresult nsXULSelectableAccessible::ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState)
{
*aSelState = PR_FALSE;
if (!mSelectControl) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIAccessible> childAcc;
GetChildAt(aIndex, getter_AddRefs(childAcc));
nsCOMPtr<nsIAccessNode> accNode = do_QueryInterface(childAcc);
NS_ENSURE_TRUE(accNode, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMNode> childNode;
accNode->GetDOMNode(getter_AddRefs(childNode));
nsCOMPtr<nsIDOMXULSelectControlItemElement> item(do_QueryInterface(childNode));
NS_ENSURE_TRUE(item, NS_ERROR_FAILURE);
item->GetSelected(aSelState);
if (eSelection_GetState == aMethod) {
return NS_OK;
}
nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect =
do_QueryInterface(mSelectControl);
if (eSelection_Add == aMethod && !(*aSelState)) {
return xulMultiSelect ? xulMultiSelect->AddItemToSelection(item) :
mSelectControl->SetSelectedItem(item);
}
if (eSelection_Remove == aMethod && (*aSelState)) {
return xulMultiSelect ? xulMultiSelect->RemoveItemFromSelection(item) :
mSelectControl->SetSelectedItem(nsnull);
}
return NS_ERROR_FAILURE;
}
// Interface methods
NS_IMETHODIMP nsXULSelectableAccessible::GetSelectedChildren(nsIArray **aChildren)
{
*aChildren = nsnull;
if (!mSelectControl) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIAccessibilityService> accService = GetAccService();
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
nsCOMPtr<nsIMutableArray> selectedAccessibles =
do_CreateInstance(NS_ARRAY_CONTRACTID);
NS_ENSURE_STATE(selectedAccessibles);
// For XUL multi-select control
nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect =
do_QueryInterface(mSelectControl);
nsCOMPtr<nsIAccessible> selectedAccessible;
if (xulMultiSelect) {
PRInt32 length = 0;
xulMultiSelect->GetSelectedCount(&length);
for (PRInt32 index = 0; index < length; index++) {
nsCOMPtr<nsIDOMXULSelectControlItemElement> selectedItem;
xulMultiSelect->GetSelectedItem(index, getter_AddRefs(selectedItem));
nsCOMPtr<nsIDOMNode> selectedNode(do_QueryInterface(selectedItem));
accService->GetAccessibleInWeakShell(selectedNode, mWeakShell,
getter_AddRefs(selectedAccessible));
if (selectedAccessible)
selectedAccessibles->AppendElement(selectedAccessible, PR_FALSE);
}
}
else { // Single select?
nsCOMPtr<nsIDOMXULSelectControlItemElement> selectedItem;
mSelectControl->GetSelectedItem(getter_AddRefs(selectedItem));
nsCOMPtr<nsIDOMNode> selectedNode(do_QueryInterface(selectedItem));
if(selectedNode) {
accService->GetAccessibleInWeakShell(selectedNode, mWeakShell,
getter_AddRefs(selectedAccessible));
if (selectedAccessible)
selectedAccessibles->AppendElement(selectedAccessible, PR_FALSE);
}
}
PRUint32 uLength = 0;
selectedAccessibles->GetLength(&uLength);
if (uLength != 0) { // length of nsIArray containing selected options
NS_ADDREF(*aChildren = selectedAccessibles);
}
return NS_OK;
}
// return the nth selected child's nsIAccessible object
NS_IMETHODIMP nsXULSelectableAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **aAccessible)
{
*aAccessible = nsnull;
if (!mSelectControl) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMXULSelectControlItemElement> selectedItem;
nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect =
do_QueryInterface(mSelectControl);
if (xulMultiSelect)
xulMultiSelect->GetSelectedItem(aIndex, getter_AddRefs(selectedItem));
if (aIndex == 0)
mSelectControl->GetSelectedItem(getter_AddRefs(selectedItem));
if (selectedItem) {
nsCOMPtr<nsIAccessibilityService> accService = GetAccService();
if (accService) {
accService->GetAccessibleInWeakShell(selectedItem, mWeakShell, aAccessible);
if (*aAccessible) {
NS_ADDREF(*aAccessible);
return NS_OK;
}
}
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsXULSelectableAccessible::GetSelectionCount(PRInt32 *aSelectionCount)
{
*aSelectionCount = 0;
if (!mSelectControl) {
return NS_ERROR_FAILURE;
}
// For XUL multi-select control
nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect =
do_QueryInterface(mSelectControl);
if (xulMultiSelect)
return xulMultiSelect->GetSelectedCount(aSelectionCount);
// For XUL single-select control/menulist
PRInt32 index;
mSelectControl->GetSelectedIndex(&index);
if (index >= 0)
*aSelectionCount = 1;
return NS_OK;
}
NS_IMETHODIMP nsXULSelectableAccessible::AddChildToSelection(PRInt32 aIndex)
{
PRBool isSelected;
return ChangeSelection(aIndex, eSelection_Add, &isSelected);
}
NS_IMETHODIMP nsXULSelectableAccessible::RemoveChildFromSelection(PRInt32 aIndex)
{
PRBool isSelected;
return ChangeSelection(aIndex, eSelection_Remove, &isSelected);
}
NS_IMETHODIMP nsXULSelectableAccessible::IsChildSelected(PRInt32 aIndex, PRBool *aIsSelected)
{
*aIsSelected = PR_FALSE;
return ChangeSelection(aIndex, eSelection_GetState, aIsSelected);
}
NS_IMETHODIMP nsXULSelectableAccessible::ClearSelection()
{
if (!mSelectControl) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect =
do_QueryInterface(mSelectControl);
return xulMultiSelect ? xulMultiSelect->ClearSelection() : mSelectControl->SetSelectedIndex(-1);
}
NS_IMETHODIMP nsXULSelectableAccessible::SelectAllSelection(PRBool *aSucceeded)
{
*aSucceeded = PR_TRUE;
nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect =
do_QueryInterface(mSelectControl);
if (xulMultiSelect)
return xulMultiSelect->SelectAll();
// otherwise, don't support this method
*aSucceeded = PR_FALSE;
return NS_ERROR_NOT_IMPLEMENTED;
}
// ------------------------ Menu Item -----------------------------
nsXULMenuitemAccessible::nsXULMenuitemAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
@ -56,6 +263,13 @@ nsAccessibleWrap(aDOMNode, aShell)
{
}
NS_IMETHODIMP nsXULMenuitemAccessible::Init()
{
nsresult rv = nsAccessibleWrap::Init();
nsXULMenupopupAccessible::GenerateMenu(mDOMNode);
return rv;
}
NS_IMETHODIMP nsXULMenuitemAccessible::GetState(PRUint32 *_retval)
{
nsAccessible::GetState(_retval);
@ -216,47 +430,6 @@ NS_IMETHODIMP nsXULMenuitemAccessible::GetRole(PRUint32 *aRole)
return NS_OK;
}
void nsXULMenuitemAccessible::CacheChildren()
{
if (!mWeakShell) {
// This node has been shut down
mAccChildCount = eChildCountUninitialized;
return;
}
if (mAccChildCount != eChildCountUninitialized) {
return;
}
// Set menugenerated="true" on the menupopup node to generate the
// sub-menu items if they have not been generated
PRUint32 childIndex, numChildren = 0;
nsCOMPtr<nsIDOMNode> childNode;
nsCOMPtr<nsIDOMNodeList> nodeList;
mDOMNode->GetChildNodes(getter_AddRefs(nodeList));
if (nodeList && NS_OK == nodeList->GetLength(&numChildren)) {
for (childIndex = 0; childIndex < numChildren; childIndex++) {
nodeList->Item(childIndex, getter_AddRefs(childNode));
nsCOMPtr<nsIContent> content = do_QueryInterface(childNode);
if (content->NodeInfo()->Equals(nsAccessibilityAtoms::menupopup, kNameSpaceID_XUL)) {
break;
}
}
if (childIndex < numChildren) {
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(childNode));
if (element) {
nsAutoString attr;
element->GetAttribute(NS_LITERAL_STRING("menugenerated"), attr);
if (!attr.EqualsLiteral("true")) {
element->SetAttribute(NS_LITERAL_STRING("menugenerated"), NS_LITERAL_STRING("true"));
}
}
}
}
nsAccessibleWrap::CacheChildren();
}
NS_IMETHODIMP
nsXULMenuitemAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
{
@ -337,8 +510,12 @@ NS_IMETHODIMP nsXULMenuSeparatorAccessible::GetNumActions(PRUint8 *_retval)
// ------------------------ Menu Popup -----------------------------
nsXULMenupopupAccessible::nsXULMenupopupAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
nsAccessibleWrap(aDOMNode, aShell)
nsXULSelectableAccessible(aDOMNode, aShell)
{
// May be the anonymous <menupopup> inside <menulist> (a combobox)
nsCOMPtr<nsIDOMNode> parentNode;
aDOMNode->GetParentNode(getter_AddRefs(parentNode));
mSelectControl = do_QueryInterface(parentNode);
}
NS_IMETHODIMP nsXULMenupopupAccessible::GetState(PRUint32 *_retval)
@ -366,6 +543,46 @@ NS_IMETHODIMP nsXULMenupopupAccessible::GetState(PRUint32 *_retval)
return NS_OK;
}
already_AddRefed<nsIDOMNode>
nsXULMenupopupAccessible::FindInNodeList(nsIDOMNodeList *aNodeList,
nsIAtom *aAtom, PRUint32 aNameSpaceID)
{
PRUint32 numChildren;
if (!aNodeList || NS_FAILED(aNodeList->GetLength(&numChildren))) {
return nsnull;
}
nsCOMPtr<nsIDOMNode> childNode;
for (PRUint32 childIndex = 0; childIndex < numChildren; childIndex++) {
aNodeList->Item(childIndex, getter_AddRefs(childNode));
nsCOMPtr<nsIContent> content = do_QueryInterface(childNode);
if (content && content->NodeInfo()->Equals(aAtom, kNameSpaceID_XUL)) {
nsIDOMNode *matchNode = childNode;
NS_ADDREF(matchNode);
return matchNode;
}
}
return nsnull;
}
void nsXULMenupopupAccessible::GenerateMenu(nsIDOMNode *aNode)
{
// Set menugenerated="true" on the menupopup node to generate the
// sub-menu items if they have not been generated
nsCOMPtr<nsIDOMNodeList> nodeList;
aNode->GetChildNodes(getter_AddRefs(nodeList));
nsCOMPtr<nsIDOMNode> menuPopup = FindInNodeList(nodeList, nsAccessibilityAtoms::menupopup,
kNameSpaceID_XUL);
nsCOMPtr<nsIDOMElement> popupElement(do_QueryInterface(menuPopup));
if (popupElement) {
nsAutoString attr;
popupElement->GetAttribute(NS_LITERAL_STRING("menugenerated"), attr);
if (!attr.EqualsLiteral("true")) {
popupElement->SetAttribute(NS_LITERAL_STRING("menugenerated"), NS_LITERAL_STRING("true"));
}
}
}
NS_IMETHODIMP nsXULMenupopupAccessible::GetName(nsAString& _retval)
{
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));

Просмотреть файл

@ -41,6 +41,31 @@
#include "nsAccessibleWrap.h"
#include "nsAccessibleTreeWalker.h"
#include "nsIAccessibleSelectable.h"
#include "nsIDOMXULSelectCntrlEl.h"
/*
* The basic implemetation of nsIAccessibleSelectable.
*/
class nsXULSelectableAccessible : public nsAccessibleWrap
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIACCESSIBLESELECTABLE
nsXULSelectableAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
virtual ~nsXULSelectableAccessible() {}
NS_IMETHOD Shutdown();
protected:
nsresult ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState);
nsresult AppendFlatStringFromSubtree(nsIContent *aContent, nsAString *aFlatString)
{ return NS_OK; } // Overrides base impl in nsAccessible
// nsIDOMXULMultiSelectControlElement inherits from this, so we'll always have
// one of these if the widget is valid and not defunct
nsCOMPtr<nsIDOMXULSelectControlElement> mSelectControl;
};
/* Accessible for supporting XUL menus
*/
@ -51,6 +76,7 @@ public:
enum { eAction_Click = 0 };
nsXULMenuitemAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
NS_IMETHOD Init();
NS_IMETHOD GetName(nsAString& _retval);
NS_IMETHOD GetDescription(nsAString& aDescription);
NS_IMETHOD GetKeyboardShortcut(nsAString& _retval);
@ -61,7 +87,6 @@ public:
NS_IMETHOD GetActionName(PRUint8 index, nsAString& _retval);
NS_IMETHOD GetNumActions(PRUint8 *_retval);
NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
void CacheChildren();
};
class nsXULMenuSeparatorAccessible : public nsXULMenuitemAccessible
@ -76,13 +101,16 @@ public:
NS_IMETHOD GetNumActions(PRUint8 *_retval);
};
class nsXULMenupopupAccessible : public nsAccessibleWrap
class nsXULMenupopupAccessible : public nsXULSelectableAccessible
{
public:
nsXULMenupopupAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
NS_IMETHOD GetName(nsAString& _retval);
NS_IMETHOD GetState(PRUint32 *_retval);
NS_IMETHOD GetRole(PRUint32 *_retval);
static already_AddRefed<nsIDOMNode> FindInNodeList(nsIDOMNodeList *aNodeList,
nsIAtom *aAtom, PRUint32 aNameSpaceID);
static void GenerateMenu(nsIDOMNode *aNode);
};
class nsXULMenubarAccessible : public nsAccessibleWrap

Просмотреть файл

@ -39,10 +39,8 @@
#include "nsXULSelectAccessible.h"
#include "nsAccessibilityService.h"
#include "nsIMutableArray.h"
#include "nsIContent.h"
#include "nsIDOMXULMenuListElement.h"
#include "nsIDOMXULMultSelectCntrlEl.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsIDOMXULSelectCntrlEl.h"
#include "nsIDOMXULTextboxElement.h"
@ -67,194 +65,6 @@
* - nsXULMenuitemAccessible <menuitem/>
*/
/** ------------------------------------------------------ */
/** Impl. of nsXULSelectableAccessible */
/** ------------------------------------------------------ */
// Helper methos
nsXULSelectableAccessible::nsXULSelectableAccessible(nsIDOMNode* aDOMNode,
nsIWeakReference* aShell):
nsAccessibleWrap(aDOMNode, aShell)
{
}
NS_IMETHODIMP nsXULSelectableAccessible::GetName(nsAString& aName)
{
return GetXULName(aName, PR_FALSE);
}
NS_IMPL_ISUPPORTS_INHERITED1(nsXULSelectableAccessible, nsAccessible, nsIAccessibleSelectable)
NS_IMETHODIMP nsXULSelectableAccessible::ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState)
{
nsCOMPtr<nsIAccessible> childAcc;
GetChildAt(aIndex, getter_AddRefs(childAcc));
nsCOMPtr<nsIAccessNode> accNode = do_QueryInterface(childAcc);
NS_ENSURE_TRUE(accNode, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMNode> childNode;
accNode->GetDOMNode(getter_AddRefs(childNode));
nsCOMPtr<nsIDOMXULSelectControlItemElement> item(do_QueryInterface(childNode));
NS_ENSURE_TRUE(item, NS_ERROR_FAILURE);
*aSelState = PR_FALSE;
nsCOMPtr<nsIDOMXULSelectControlElement> xulSelect(do_QueryInterface(mDOMNode));
nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect(do_QueryInterface(mDOMNode));
if (xulSelect || xulMultiSelect) {
item->GetSelected(aSelState);
if (eSelection_Add == aMethod && !(*aSelState)) {
if (xulMultiSelect)
return xulMultiSelect->AddItemToSelection(item);
else if (xulSelect)
return xulSelect->SetSelectedItem(item);
}
else if (eSelection_Remove == aMethod && (*aSelState)) {
if (xulMultiSelect)
return xulMultiSelect->RemoveItemFromSelection(item);
else if (xulSelect)
return xulSelect->SetSelectedIndex(-1);
}
}
return NS_ERROR_FAILURE;
}
// Interface methods
NS_IMETHODIMP nsXULSelectableAccessible::GetSelectedChildren(nsIArray **_retval)
{
*_retval = nsnull;
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
if (!accService)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIMutableArray> selectedAccessibles =
do_CreateInstance(NS_ARRAY_CONTRACTID);
NS_ENSURE_STATE(selectedAccessibles);
// For XUL multi-select control
nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect(do_QueryInterface(mDOMNode));
if (xulMultiSelect) {
PRInt32 length = 0;
xulMultiSelect->GetSelectedCount(&length);
for (PRInt32 index = 0; index < length; index++) {
nsCOMPtr<nsIAccessible> tempAccessible;
nsCOMPtr<nsIDOMXULSelectControlItemElement> tempNode;
xulMultiSelect->GetSelectedItem(index, getter_AddRefs(tempNode));
nsCOMPtr<nsIDOMNode> tempDOMNode (do_QueryInterface(tempNode));
accService->GetAccessibleInWeakShell(tempDOMNode, mWeakShell, getter_AddRefs(tempAccessible));
if (tempAccessible)
selectedAccessibles->AppendElement(tempAccessible, PR_FALSE);
}
}
PRUint32 uLength = 0;
selectedAccessibles->GetLength(&uLength);
if (uLength != 0) { // length of nsIArray containing selected options
*_retval = selectedAccessibles;
NS_ADDREF(*_retval);
}
return NS_OK;
}
// return the nth selected child's nsIAccessible object
NS_IMETHODIMP nsXULSelectableAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **_retval)
{
*_retval = nsnull;
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
if (!accService)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMXULSelectControlItemElement> tempDOMNode;
nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect(do_QueryInterface(mDOMNode));
if (xulMultiSelect)
xulMultiSelect->GetSelectedItem(aIndex, getter_AddRefs(tempDOMNode));
nsCOMPtr<nsIDOMXULSelectControlElement> xulSelect(do_QueryInterface(mDOMNode));
if (xulSelect && aIndex == 0)
xulSelect->GetSelectedItem(getter_AddRefs(tempDOMNode));
if (tempDOMNode) {
nsCOMPtr<nsIAccessible> tempAccess;
accService->GetAccessibleInWeakShell(tempDOMNode, mWeakShell, getter_AddRefs(tempAccess));
*_retval = tempAccess;
NS_IF_ADDREF(*_retval);
return *_retval ? NS_OK : NS_ERROR_FAILURE;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsXULSelectableAccessible::GetSelectionCount(PRInt32 *aSelectionCount)
{
*aSelectionCount = 0;
// For XUL multi-select control
nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect(do_QueryInterface(mDOMNode));
if (xulMultiSelect)
return xulMultiSelect->GetSelectedCount(aSelectionCount);
// For XUL single-select control/menulist
nsCOMPtr<nsIDOMXULSelectControlElement> xulSelect(do_QueryInterface(mDOMNode));
if (xulSelect) {
PRInt32 index;
xulSelect->GetSelectedIndex(&index);
if (index >= 0)
*aSelectionCount = 1;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsXULSelectableAccessible::AddChildToSelection(PRInt32 aIndex)
{
PRBool isSelected;
return ChangeSelection(aIndex, eSelection_Add, &isSelected);
}
NS_IMETHODIMP nsXULSelectableAccessible::RemoveChildFromSelection(PRInt32 aIndex)
{
PRBool isSelected;
return ChangeSelection(aIndex, eSelection_Remove, &isSelected);
}
NS_IMETHODIMP nsXULSelectableAccessible::IsChildSelected(PRInt32 aIndex, PRBool *_retval)
{
*_retval = PR_FALSE;
return ChangeSelection(aIndex, eSelection_GetState, _retval);
}
NS_IMETHODIMP nsXULSelectableAccessible::ClearSelection()
{
nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect(do_QueryInterface(mDOMNode));
if (xulMultiSelect)
return xulMultiSelect->ClearSelection();
nsCOMPtr<nsIDOMXULSelectControlElement> xulSelect(do_QueryInterface(mDOMNode));
if (xulSelect)
return xulSelect->SetSelectedIndex(-1);
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsXULSelectableAccessible::SelectAllSelection(PRBool *_retval)
{
*_retval = PR_TRUE;
nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect(do_QueryInterface(mDOMNode));
if (xulMultiSelect)
return xulMultiSelect->SelectAll();
// otherwise, don't support this method
*_retval = PR_FALSE;
return NS_OK;
}
/** ----- nsXULListboxAccessible ----- */
/** Constructor */
@ -402,6 +212,7 @@ NS_IMETHODIMP nsXULListitemAccessible::GetActionName(PRUint8 index, nsAString& _
}
return NS_ERROR_INVALID_ARG;
}
/** ------------------------------------------------------ */
/** Finally, the Combobox widgets */
/** ------------------------------------------------------ */
@ -410,10 +221,17 @@ NS_IMETHODIMP nsXULListitemAccessible::GetActionName(PRUint8 index, nsAString& _
/** Constructor */
nsXULComboboxAccessible::nsXULComboboxAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
nsXULSelectableAccessible(aDOMNode, aShell)
nsAccessibleWrap(aDOMNode, aShell)
{
}
NS_IMETHODIMP nsXULComboboxAccessible::Init()
{
nsresult rv = nsAccessibleWrap::Init();
nsXULMenupopupAccessible::GenerateMenu(mDOMNode);
return rv;
}
/** We are a combobox */
NS_IMETHODIMP nsXULComboboxAccessible::GetRole(PRUint32 *aRole)
{
@ -499,55 +317,17 @@ NS_IMETHODIMP nsXULComboboxAccessible::GetDescription(nsAString& aDescription)
return NS_OK;
}
void nsXULComboboxAccessible::CacheChildren()
{
if (!mWeakShell) {
// This node has been shut down
mAccChildCount = eChildCountUninitialized;
return;
}
if (mAccChildCount != eChildCountUninitialized) {
return;
}
// Set menugenerated="true" on the menupopup node to generate the
// sub-menu items if they have not been generated
PRUint32 childIndex, numChildren = 0;
nsCOMPtr<nsIDOMNode> childNode;
nsCOMPtr<nsIDOMNodeList> nodeList;
mDOMNode->GetChildNodes(getter_AddRefs(nodeList));
if (nodeList && NS_OK == nodeList->GetLength(&numChildren)) {
for (childIndex = 0; childIndex < numChildren; childIndex++) {
nodeList->Item(childIndex, getter_AddRefs(childNode));
nsCOMPtr<nsIContent> content = do_QueryInterface(childNode);
if (content->NodeInfo()->Equals(nsAccessibilityAtoms::menupopup, kNameSpaceID_XUL)) {
break;
}
}
if (childIndex < numChildren) {
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(childNode));
if (element) {
nsAutoString attr;
element->GetAttribute(NS_LITERAL_STRING("menugenerated"), attr);
if (!attr.Equals(NS_LITERAL_STRING("true"))) {
element->SetAttribute(NS_LITERAL_STRING("menugenerated"), NS_LITERAL_STRING("true"));
}
}
}
}
nsXULSelectableAccessible::CacheChildren();
}
NS_IMETHODIMP
nsXULComboboxAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
{
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
if (content->NodeInfo()->Equals(nsAccessibilityAtoms::textbox, kNameSpaceID_XUL)) {
// autocomplete textbox also uses nsXULComboboxAccessible and we need walk
// anonymous children
if (content->NodeInfo()->Equals(nsAccessibilityAtoms::textbox, kNameSpaceID_XUL) ||
content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::editable,
nsAccessibilityAtoms::_true, eIgnoreCase)) {
// Both the XUL <textbox type="autocomplete"> and <menulist editable="true"> widgets
// use nsXULComboboxAccessible. We need to walk the anonymous children for these
// so that the entry field is a child
*aAllowsAnonChildren = PR_TRUE;
} else {
// Argument of PR_FALSE indicates we don't walk anonymous children for

Просмотреть файл

@ -39,7 +39,6 @@
#define __nsXULSelectAccessible_h__
#include "nsCOMPtr.h"
#include "nsIAccessibleSelectable.h"
#include "nsXULMenuAccessible.h"
class nsIWeakReference;
@ -63,30 +62,6 @@ class nsIWeakReference;
/** First, the common widgets */
/** ------------------------------------------------------ */
/*
* The basic implemetation of nsIAccessibleSelectable.
*/
class nsXULSelectableAccessible : public nsAccessibleWrap
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIACCESSIBLESELECTABLE
nsXULSelectableAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
virtual ~nsXULSelectableAccessible() {}
NS_IMETHOD GetName(nsAString& _retval);
protected:
NS_IMETHOD ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState);
nsresult AppendFlatStringFromSubtree(nsIContent *aContent, nsAString *aFlatString)
{ return NS_ERROR_FAILURE; } // Overrides base impl in nsAccessible
};
/** ------------------------------------------------------ */
/** Secondly, the Listbox widget */
/** ------------------------------------------------------ */
/*
* A class the represents the XUL Listbox widget.
*/
@ -121,8 +96,6 @@ public:
NS_IMETHOD GetRole(PRUint32 *_retval);
NS_IMETHOD GetState(PRUint32 *_retval);
NS_IMETHOD GetActionName(PRUint8 index, nsAString& _retval);
// Don't use XUL menu's special child aggregator, this can be a rich list item
void CacheChildren() { nsAccessibleWrap::CacheChildren(); }
// Don't use XUL menuitems's description attribute
NS_IMETHOD GetDescription(nsAString& aDesc) { return nsAccessibleWrap::GetDescription(aDesc); }
@ -137,7 +110,7 @@ private:
/*
* A class the represents the XUL Combobox widget.
*/
class nsXULComboboxAccessible : public nsXULSelectableAccessible
class nsXULComboboxAccessible : public nsAccessibleWrap
{
public:
enum { eAction_Click = 0 };
@ -145,8 +118,10 @@ public:
nsXULComboboxAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
virtual ~nsXULComboboxAccessible() {}
/* ----- nsPIAccessible ---- */
NS_IMETHOD Init();
/* ----- nsIAccessible ----- */
void CacheChildren();
NS_IMETHOD GetRole(PRUint32 *_retval);
NS_IMETHOD GetState(PRUint32 *_retval);
NS_IMETHOD GetValue(nsAString& _retval);

Просмотреть файл

@ -312,7 +312,10 @@
<property name="accessibleType" readonly="true">
<getter>
<![CDATA[
return Components.interfaces.nsIAccessibleProvider.XULCombobox;
<!-- Droppable is currently used for the Firefox bookmarks dialog only -->
return (this.getAttribute("droppable") == "false") ?
Components.interfaces.nsIAccessibleProvider.XULTextBox :
Components.interfaces.nsIAccessibleProvider.XULCombobox;
]]>
</getter>
</property>