diff --git a/accessible/src/atk/nsAccessibleWrap.cpp b/accessible/src/atk/nsAccessibleWrap.cpp index 84485e95593..321dff5434d 100644 --- a/accessible/src/atk/nsAccessibleWrap.cpp +++ b/accessible/src/atk/nsAccessibleWrap.cpp @@ -475,10 +475,7 @@ nsAccessibleWrap::CreateMaiInterfaces(void) } //nsIAccessibleSelection - nsCOMPtr accessInterfaceSelection; - QueryInterface(NS_GET_IID(nsIAccessibleSelectable), - getter_AddRefs(accessInterfaceSelection)); - if (accessInterfaceSelection) { + if (IsSelect()) { interfacesBits |= 1 << MAI_INTERFACE_SELECTION; } } diff --git a/accessible/src/atk/nsMaiInterfaceSelection.cpp b/accessible/src/atk/nsMaiInterfaceSelection.cpp index 38a0cd0de34..c0da303ef08 100644 --- a/accessible/src/atk/nsMaiInterfaceSelection.cpp +++ b/accessible/src/atk/nsMaiInterfaceSelection.cpp @@ -60,51 +60,34 @@ gboolean addSelectionCB(AtkSelection *aSelection, gint i) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection)); - if (!accWrap) + if (!accWrap || !accWrap->IsSelect()) return FALSE; - nsCOMPtr accSelection; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleSelectable), - getter_AddRefs(accSelection)); - NS_ENSURE_TRUE(accSelection, FALSE); - - return NS_SUCCEEDED(accSelection->AddChildToSelection(i)); + return accWrap->AddItemToSelection(i); } gboolean clearSelectionCB(AtkSelection *aSelection) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection)); - if (!accWrap) + if (!accWrap || !accWrap->IsSelect()) return FALSE; - nsCOMPtr accSelection; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleSelectable), - getter_AddRefs(accSelection)); - NS_ENSURE_TRUE(accSelection, FALSE); - - return NS_SUCCEEDED(accSelection->ClearSelection()); + return accWrap->UnselectAll(); } AtkObject * refSelectionCB(AtkSelection *aSelection, gint i) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection)); - if (!accWrap) + if (!accWrap || !accWrap->IsSelect()) return nsnull; - nsCOMPtr accSelection; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleSelectable), - getter_AddRefs(accSelection)); - NS_ENSURE_TRUE(accSelection, nsnull); - - nsCOMPtr accSelect; - accSelection->RefSelection(i, getter_AddRefs(accSelect)); - if (!accSelect) { + nsAccessible* selectedItem = accWrap->GetSelectedItem(i); + if (!selectedItem) return nsnull; - } - AtkObject *atkObj = nsAccessibleWrap::GetAtkObject(accSelect); + AtkObject* atkObj = nsAccessibleWrap::GetAtkObject(selectedItem); if (atkObj) { g_object_ref(atkObj); } @@ -115,65 +98,38 @@ gint getSelectionCountCB(AtkSelection *aSelection) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection)); - if (!accWrap) + if (!accWrap || !accWrap->IsSelect()) return -1; - nsCOMPtr accSelection; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleSelectable), - getter_AddRefs(accSelection)); - NS_ENSURE_TRUE(accSelection, -1); - - PRInt32 num = 0; - nsresult rv = accSelection->GetSelectionCount(&num); - return (NS_FAILED(rv)) ? -1 : num; + return accWrap->SelectedItemCount(); } gboolean isChildSelectedCB(AtkSelection *aSelection, gint i) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection)); - if (!accWrap) + if (!accWrap || !accWrap->IsSelect()) return FALSE; - nsCOMPtr accSelection; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleSelectable), - getter_AddRefs(accSelection)); - NS_ENSURE_TRUE(accSelection, FALSE); - - PRBool result = FALSE; - nsresult rv = accSelection->IsChildSelected(i, &result); - return (NS_FAILED(rv)) ? FALSE : result; + return accWrap->IsItemSelected(i); } gboolean removeSelectionCB(AtkSelection *aSelection, gint i) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection)); - if (!accWrap) + if (!accWrap || !accWrap->IsSelect()) return FALSE; - nsCOMPtr accSelection; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleSelectable), - getter_AddRefs(accSelection)); - NS_ENSURE_TRUE(accSelection, FALSE); - - nsresult rv = accSelection->RemoveChildFromSelection(i); - return (NS_FAILED(rv)) ? FALSE : TRUE; + return accWrap->RemoveItemFromSelection(i); } gboolean selectAllSelectionCB(AtkSelection *aSelection) { nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aSelection)); - if (!accWrap) + if (!accWrap || !accWrap->IsSelect()) return FALSE; - nsCOMPtr accSelection; - accWrap->QueryInterface(NS_GET_IID(nsIAccessibleSelectable), - getter_AddRefs(accSelection)); - NS_ENSURE_TRUE(accSelection, FALSE); - - PRBool result = FALSE; - nsresult rv = accSelection->SelectAllSelection(&result); - return (NS_FAILED(rv)) ? FALSE : result; + return accWrap->SelectAll(); } diff --git a/accessible/src/atk/nsMaiInterfaceSelection.h b/accessible/src/atk/nsMaiInterfaceSelection.h index 71d253c84c8..15390cb2c23 100644 --- a/accessible/src/atk/nsMaiInterfaceSelection.h +++ b/accessible/src/atk/nsMaiInterfaceSelection.h @@ -42,7 +42,6 @@ #define __MAI_INTERFACE_SELECTION_H__ #include "nsMai.h" -#include "nsIAccessibleSelectable.h" G_BEGIN_DECLS diff --git a/accessible/src/base/nsAccUtils.cpp b/accessible/src/base/nsAccUtils.cpp index 7bf1e34e0b8..51cfa07c762 100644 --- a/accessible/src/base/nsAccUtils.cpp +++ b/accessible/src/base/nsAccUtils.cpp @@ -376,16 +376,11 @@ nsAccUtils::GetSelectableContainer(nsAccessible *aAccessible, PRUint32 aState) if (!(aState & nsIAccessibleStates::STATE_SELECTABLE)) return nsnull; - nsCOMPtr container; - nsAccessible *parent = aAccessible; - while (!container) { - parent = parent->GetParent(); - if (!parent || Role(parent) == nsIAccessibleRole::ROLE_PANE) + nsAccessible* parent = aAccessible; + while ((parent = parent->GetParent()) && !parent->IsSelect()) { + if (Role(parent) == nsIAccessibleRole::ROLE_PANE) return nsnull; - - container = do_QueryObject(parent); } - return parent; } diff --git a/accessible/src/base/nsAccessible.cpp b/accessible/src/base/nsAccessible.cpp index 6f2ff0f83d1..8808c98aa77 100644 --- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -155,20 +155,12 @@ nsresult nsAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr) } if (aIID.Equals(NS_GET_IID(nsIAccessibleSelectable))) { - if (mRoleMapEntry && - (mRoleMapEntry->attributeMap1 == eARIAMultiSelectable || - mRoleMapEntry->attributeMap2 == eARIAMultiSelectable || - mRoleMapEntry->attributeMap3 == eARIAMultiSelectable)) { - - // If we have an ARIA role attribute present and the role allows multi - // selectable state, then we need to support nsIAccessibleSelectable. - // If either attribute (role or multiselectable) change, then we'll - // destroy this accessible so that we can follow COM identity rules. - + if (IsSelect()) { *aInstancePtr = static_cast(this); NS_ADDREF_THIS(); return NS_OK; } + return NS_ERROR_NO_INTERFACE; } if (aIID.Equals(NS_GET_IID(nsIAccessibleValue))) { @@ -2381,22 +2373,18 @@ nsAccessible::DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex) // nsIAccessibleSelectable NS_IMETHODIMP nsAccessible::GetSelectedChildren(nsIArray **aSelectedAccessibles) { + NS_ENSURE_ARG_POINTER(aSelectedAccessibles); *aSelectedAccessibles = nsnull; - nsCOMPtr selectedAccessibles = - do_CreateInstance(NS_ARRAY_CONTRACTID); - NS_ENSURE_STATE(selectedAccessibles); + if (IsDefunct() || !IsSelect()) + return NS_ERROR_FAILURE; - AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav); - nsIAccessible *selected = nsnull; - while ((selected = iter.GetNext())) - selectedAccessibles->AppendElement(selected, PR_FALSE); - - PRUint32 length = 0; - selectedAccessibles->GetLength(&length); - if (length) { // length of nsIArray containing selected options - *aSelectedAccessibles = selectedAccessibles; - NS_ADDREF(*aSelectedAccessibles); + nsCOMPtr items = SelectedItems(); + if (items) { + PRUint32 length = 0; + items->GetLength(&length); + if (length) + items.swap(*aSelectedAccessibles); } return NS_OK; @@ -2408,23 +2396,20 @@ NS_IMETHODIMP nsAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **aSelect NS_ENSURE_ARG_POINTER(aSelected); *aSelected = nsnull; + if (IsDefunct() || !IsSelect()) + return NS_ERROR_FAILURE; + if (aIndex < 0) { return NS_ERROR_INVALID_ARG; } - AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav); - nsAccessible *selected = nsnull; - - PRInt32 count = 0; - while (count ++ <= aIndex) { - selected = iter.GetNext(); - if (!selected) { - // The index is out of range. - return NS_ERROR_INVALID_ARG; - } + *aSelected = GetSelectedItem(aIndex); + if (*aSelected) { + NS_ADDREF(*aSelected); + return NS_OK; } - NS_IF_ADDREF(*aSelected = selected); - return NS_OK; + + return NS_ERROR_INVALID_ARG; } NS_IMETHODIMP nsAccessible::GetSelectionCount(PRInt32 *aSelectionCount) @@ -2432,83 +2417,65 @@ NS_IMETHODIMP nsAccessible::GetSelectionCount(PRInt32 *aSelectionCount) NS_ENSURE_ARG_POINTER(aSelectionCount); *aSelectionCount = 0; - AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav); - nsAccessible *selected = nsnull; - while ((selected = iter.GetNext())) - ++(*aSelectionCount); + if (IsDefunct() || !IsSelect()) + return NS_ERROR_FAILURE; + *aSelectionCount = SelectedItemCount(); return NS_OK; } NS_IMETHODIMP nsAccessible::AddChildToSelection(PRInt32 aIndex) { - // Tree views and other container widgets which may have grandchildren should - // implement a selection methods for their specific interfaces, because being - // able to deal with selection on a per-child basis would not be enough. + if (IsDefunct() || !IsSelect()) + return NS_ERROR_FAILURE; - NS_ENSURE_TRUE(aIndex >= 0, NS_ERROR_FAILURE); - - nsAccessible* child = GetChildAt(aIndex); - PRUint32 state = nsAccUtils::State(child); - if (!(state & nsIAccessibleStates::STATE_SELECTABLE)) { - return NS_OK; - } - - return child->SetSelected(PR_TRUE); + return aIndex >= 0 && AddItemToSelection(aIndex) ? + NS_OK : NS_ERROR_INVALID_ARG; } NS_IMETHODIMP nsAccessible::RemoveChildFromSelection(PRInt32 aIndex) { - // Tree views and other container widgets which may have grandchildren should - // implement a selection methods for their specific interfaces, because being - // able to deal with selection on a per-child basis would not be enough. + if (IsDefunct() || !IsSelect()) + return NS_ERROR_FAILURE; - NS_ENSURE_TRUE(aIndex >= 0, NS_ERROR_FAILURE); - - nsAccessible* child = GetChildAt(aIndex); - PRUint32 state = nsAccUtils::State(child); - if (!(state & nsIAccessibleStates::STATE_SELECTED)) { - return NS_OK; - } - - return child->SetSelected(PR_FALSE); + return aIndex >=0 && RemoveItemFromSelection(aIndex) ? + NS_OK : NS_ERROR_INVALID_ARG; } NS_IMETHODIMP nsAccessible::IsChildSelected(PRInt32 aIndex, PRBool *aIsSelected) { - // Tree views and other container widgets which may have grandchildren should - // implement a selection methods for their specific interfaces, because being - // able to deal with selection on a per-child basis would not be enough. - + NS_ENSURE_ARG_POINTER(aIsSelected); *aIsSelected = PR_FALSE; + + if (IsDefunct() || !IsSelect()) + return NS_ERROR_FAILURE; + NS_ENSURE_TRUE(aIndex >= 0, NS_ERROR_FAILURE); - nsAccessible* child = GetChildAt(aIndex); - PRUint32 state = nsAccUtils::State(child); - if (state & nsIAccessibleStates::STATE_SELECTED) { - *aIsSelected = PR_TRUE; - } + *aIsSelected = IsItemSelected(aIndex); return NS_OK; } NS_IMETHODIMP nsAccessible::ClearSelection() { - AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav); - nsAccessible *selected = nsnull; - while ((selected = iter.GetNext())) - selected->SetSelected(PR_FALSE); + if (IsDefunct() || !IsSelect()) + return NS_ERROR_FAILURE; + UnselectAll(); return NS_OK; } -NS_IMETHODIMP nsAccessible::SelectAllSelection(PRBool *_retval) +NS_IMETHODIMP +nsAccessible::SelectAllSelection(PRBool* aIsMultiSelect) { - AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav); - nsAccessible *selectable = nsnull; - while((selectable = iter.GetNext())) - selectable->SetSelected(PR_TRUE); + NS_ENSURE_ARG_POINTER(aIsMultiSelect); + *aIsMultiSelect = PR_FALSE; + if (IsDefunct() || !IsSelect()) + return NS_ERROR_FAILURE; + + *aIsMultiSelect = SelectAll(); return NS_OK; } @@ -3033,6 +3000,138 @@ nsAccessible::GetAnchorURI(PRUint32 aAnchorIndex) return nsnull; } + +//////////////////////////////////////////////////////////////////////////////// +// SelectAccessible + +bool +nsAccessible::IsSelect() +{ + // If we have an ARIA role attribute present and the role allows multi + // selectable state, then we need to support SelectAccessible interface. If + // either attribute (role or multiselectable) change, then we'll destroy this + // accessible so that we can follow COM identity rules. + + return mRoleMapEntry && + (mRoleMapEntry->attributeMap1 == eARIAMultiSelectable || + mRoleMapEntry->attributeMap2 == eARIAMultiSelectable || + mRoleMapEntry->attributeMap3 == eARIAMultiSelectable); +} + +already_AddRefed +nsAccessible::SelectedItems() +{ + nsCOMPtr selectedItems = do_CreateInstance(NS_ARRAY_CONTRACTID); + if (!selectedItems) + return nsnull; + + AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav); + nsIAccessible* selected = nsnull; + while ((selected = iter.GetNext())) + selectedItems->AppendElement(selected, PR_FALSE); + + nsIMutableArray* items = nsnull; + selectedItems.forget(&items); + return items; +} + +PRUint32 +nsAccessible::SelectedItemCount() +{ + PRUint32 count = 0; + AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav); + nsAccessible* selected = nsnull; + while ((selected = iter.GetNext())) + ++count; + + return count; +} + +nsAccessible* +nsAccessible::GetSelectedItem(PRUint32 aIndex) +{ + AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav); + nsAccessible* selected = nsnull; + + PRUint32 index = 0; + while ((selected = iter.GetNext()) && index < aIndex) + index++; + + return selected; +} + +bool +nsAccessible::IsItemSelected(PRUint32 aIndex) +{ + PRUint32 index = 0; + AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav); + nsAccessible* selected = nsnull; + while ((selected = iter.GetNext()) && index < aIndex) + index++; + + return selected && + nsAccUtils::State(selected) & nsIAccessibleStates::STATE_SELECTED; +} + +bool +nsAccessible::AddItemToSelection(PRUint32 aIndex) +{ + PRUint32 index = 0; + AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav); + nsAccessible* selected = nsnull; + while ((selected = iter.GetNext()) && index < aIndex) + index++; + + if (selected) + selected->SetSelected(PR_TRUE); + + return static_cast(selected); +} + +bool +nsAccessible::RemoveItemFromSelection(PRUint32 aIndex) +{ + PRUint32 index = 0; + AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav); + nsAccessible* selected = nsnull; + while ((selected = iter.GetNext()) && index < aIndex) + index++; + + if (selected) + selected->SetSelected(PR_FALSE); + + return static_cast(selected); +} + +bool +nsAccessible::SelectAll() +{ + bool success = false; + nsAccessible* selectable = nsnull; + + AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav); + while((selectable = iter.GetNext())) { + success = true; + selectable->SetSelected(PR_TRUE); + } + return success; +} + +bool +nsAccessible::UnselectAll() +{ + bool success = false; + nsAccessible* selected = nsnull; + + AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav); + while ((selected = iter.GetNext())) { + success = true; + selected->SetSelected(PR_FALSE); + } + return success; +} + + //////////////////////////////////////////////////////////////////////////////// // nsAccessible protected methods diff --git a/accessible/src/base/nsAccessible.h b/accessible/src/base/nsAccessible.h index 7e1909e485f..85a3e54d946 100644 --- a/accessible/src/base/nsAccessible.h +++ b/accessible/src/base/nsAccessible.h @@ -370,6 +370,55 @@ public: */ virtual already_AddRefed GetAnchorURI(PRUint32 aAnchorIndex); + ////////////////////////////////////////////////////////////////////////////// + // SelectAccessible + + /** + * Return true if the accessible is a select control containing selectable + * items. + */ + virtual bool IsSelect(); + + /** + * Return an array of selected items. + */ + virtual already_AddRefed SelectedItems(); + + /** + * Return the number of selected items. + */ + virtual PRUint32 SelectedItemCount(); + + /** + * Return selected item at the given index. + */ + virtual nsAccessible* GetSelectedItem(PRUint32 aIndex); + + /** + * Determine if item at the given index is selected. + */ + virtual bool IsItemSelected(PRUint32 aIndex); + + /** + * Add item at the given index the selection. Return true if success. + */ + virtual bool AddItemToSelection(PRUint32 aIndex); + + /** + * Remove item at the given index from the selection. Return if success. + */ + virtual bool RemoveItemFromSelection(PRUint32 aIndex); + + /** + * Select all items. Return true if success. + */ + virtual bool SelectAll(); + + /** + * Unselect all items. Return true if success. + */ + virtual bool UnselectAll(); + protected: ////////////////////////////////////////////////////////////////////////////// diff --git a/accessible/src/base/nsDocAccessible.cpp b/accessible/src/base/nsDocAccessible.cpp index 3187bbe981b..99ccb5f4dae 100644 --- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -1174,7 +1174,7 @@ nsDocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute) if (aAttribute == nsAccessibilityAtoms::aria_multiselectable && aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::role)) { - // This affects whether the accessible supports nsIAccessibleSelectable. + // This affects whether the accessible supports SelectAccessible. // COM says we cannot change what interfaces are supported on-the-fly, // so invalidate this object. A new one will be created on demand. InvalidateCacheSubtree(aContent, diff --git a/accessible/src/html/nsHTMLSelectAccessible.cpp b/accessible/src/html/nsHTMLSelectAccessible.cpp index 41d260e9463..2d08951cc91 100644 --- a/accessible/src/html/nsHTMLSelectAccessible.cpp +++ b/accessible/src/html/nsHTMLSelectAccessible.cpp @@ -56,252 +56,13 @@ #include "nsIServiceManager.h" #include "nsIMutableArray.h" -//////////////////////////////////////////////////////////////////////////////// -// nsHTMLSelectableAccessible -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// nsHTMLSelectableAccessible::iterator - -nsHTMLSelectableAccessible::iterator::iterator(nsHTMLSelectableAccessible *aParent, nsIWeakReference *aWeakShell): - mWeakShell(aWeakShell), mParentSelect(aParent) -{ - mLength = mIndex = 0; - mSelCount = 0; - - nsCOMPtr htmlSelect = - do_QueryInterface(mParentSelect->mContent); - if (htmlSelect) { - htmlSelect->GetOptions(getter_AddRefs(mOptions)); - if (mOptions) - mOptions->GetLength(&mLength); - } -} - -PRBool nsHTMLSelectableAccessible::iterator::Advance() -{ - if (mIndex < mLength) { - nsCOMPtr tempNode; - if (mOptions) { - mOptions->Item(mIndex, getter_AddRefs(tempNode)); - mOption = do_QueryInterface(tempNode); - } - mIndex++; - return PR_TRUE; - } - return PR_FALSE; -} - -void nsHTMLSelectableAccessible::iterator::CalcSelectionCount(PRInt32 *aSelectionCount) -{ - PRBool isSelected = PR_FALSE; - - if (mOption) - mOption->GetSelected(&isSelected); - - if (isSelected) - (*aSelectionCount)++; -} - -void -nsHTMLSelectableAccessible::iterator::AddAccessibleIfSelected(nsIMutableArray *aSelectedAccessibles, - nsPresContext *aContext) -{ - PRBool isSelected = PR_FALSE; - nsAccessible *optionAcc = nsnull; - - if (mOption) { - mOption->GetSelected(&isSelected); - if (isSelected) { - nsCOMPtr optionContent(do_QueryInterface(mOption)); - optionAcc = GetAccService()->GetAccessibleInWeakShell(optionContent, - mWeakShell); - } - } - - if (optionAcc) - aSelectedAccessibles->AppendElement(static_cast(optionAcc), - PR_FALSE); -} - -PRBool -nsHTMLSelectableAccessible::iterator::GetAccessibleIfSelected(PRInt32 aIndex, - nsPresContext *aContext, - nsIAccessible **aAccessible) -{ - PRBool isSelected = PR_FALSE; - - *aAccessible = nsnull; - - if (mOption) { - mOption->GetSelected(&isSelected); - if (isSelected) { - if (mSelCount == aIndex) { - nsCOMPtr optionContent(do_QueryInterface(mOption)); - nsAccessible *accessible = - GetAccService()->GetAccessibleInWeakShell(optionContent, mWeakShell); - NS_IF_ADDREF(*aAccessible = accessible); - - return PR_TRUE; - } - mSelCount++; - } - } - - return PR_FALSE; -} - -void nsHTMLSelectableAccessible::iterator::Select(PRBool aSelect) -{ - if (mOption) - mOption->SetSelected(aSelect); -} - -//////////////////////////////////////////////////////////////////////////////// -// nsHTMLSelectableAccessible - -nsHTMLSelectableAccessible:: - nsHTMLSelectableAccessible(nsIContent *aContent, nsIWeakReference *aShell) : - nsAccessibleWrap(aContent, aShell) -{ -} - -NS_IMPL_ISUPPORTS_INHERITED1(nsHTMLSelectableAccessible, nsAccessible, nsIAccessibleSelectable) - -// Helper methods -NS_IMETHODIMP nsHTMLSelectableAccessible::ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState) -{ - *aSelState = PR_FALSE; - - nsCOMPtr htmlSelect(do_QueryInterface(mContent)); - if (!htmlSelect) - return NS_ERROR_FAILURE; - - nsCOMPtr options; - htmlSelect->GetOptions(getter_AddRefs(options)); - if (!options) - return NS_ERROR_FAILURE; - - nsCOMPtr tempNode; - options->Item(aIndex, getter_AddRefs(tempNode)); - nsCOMPtr tempOption(do_QueryInterface(tempNode)); - if (!tempOption) - return NS_ERROR_FAILURE; - - tempOption->GetSelected(aSelState); - nsresult rv = NS_OK; - if (eSelection_Add == aMethod && !(*aSelState)) - rv = tempOption->SetSelected(PR_TRUE); - else if (eSelection_Remove == aMethod && (*aSelState)) - rv = tempOption->SetSelected(PR_FALSE); - return rv; -} - -// Interface methods -NS_IMETHODIMP nsHTMLSelectableAccessible::GetSelectedChildren(nsIArray **_retval) -{ - *_retval = nsnull; - - nsCOMPtr selectedAccessibles = - do_CreateInstance(NS_ARRAY_CONTRACTID); - NS_ENSURE_STATE(selectedAccessibles); - - nsPresContext *context = GetPresContext(); - if (!context) - return NS_ERROR_FAILURE; - - nsHTMLSelectableAccessible::iterator iter(this, mWeakShell); - while (iter.Advance()) - iter.AddAccessibleIfSelected(selectedAccessibles, context); - - 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 nsHTMLSelectableAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **_retval) -{ - *_retval = nsnull; - - nsPresContext *context = GetPresContext(); - if (!context) - return NS_ERROR_FAILURE; - - nsHTMLSelectableAccessible::iterator iter(this, mWeakShell); - while (iter.Advance()) - if (iter.GetAccessibleIfSelected(aIndex, context, _retval)) - return NS_OK; - - // No matched item found - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP nsHTMLSelectableAccessible::GetSelectionCount(PRInt32 *aSelectionCount) -{ - *aSelectionCount = 0; - - nsHTMLSelectableAccessible::iterator iter(this, mWeakShell); - while (iter.Advance()) - iter.CalcSelectionCount(aSelectionCount); - return NS_OK; -} - -NS_IMETHODIMP nsHTMLSelectableAccessible::AddChildToSelection(PRInt32 aIndex) -{ - PRBool isSelected; - return ChangeSelection(aIndex, eSelection_Add, &isSelected); -} - -NS_IMETHODIMP nsHTMLSelectableAccessible::RemoveChildFromSelection(PRInt32 aIndex) -{ - PRBool isSelected; - return ChangeSelection(aIndex, eSelection_Remove, &isSelected); -} - -NS_IMETHODIMP nsHTMLSelectableAccessible::IsChildSelected(PRInt32 aIndex, PRBool *_retval) -{ - *_retval = PR_FALSE; - return ChangeSelection(aIndex, eSelection_GetState, _retval); -} - -NS_IMETHODIMP nsHTMLSelectableAccessible::ClearSelection() -{ - nsHTMLSelectableAccessible::iterator iter(this, mWeakShell); - while (iter.Advance()) - iter.Select(PR_FALSE); - return NS_OK; -} - -NS_IMETHODIMP nsHTMLSelectableAccessible::SelectAllSelection(PRBool *_retval) -{ - *_retval = PR_FALSE; - - nsCOMPtr htmlSelect(do_QueryInterface(mContent)); - if (!htmlSelect) - return NS_ERROR_FAILURE; - - htmlSelect->GetMultiple(_retval); - if (*_retval) { - nsHTMLSelectableAccessible::iterator iter(this, mWeakShell); - while (iter.Advance()) - iter.Select(PR_TRUE); - } - return NS_OK; -} - - //////////////////////////////////////////////////////////////////////////////// // nsHTMLSelectListAccessible //////////////////////////////////////////////////////////////////////////////// nsHTMLSelectListAccessible:: nsHTMLSelectListAccessible(nsIContent *aContent, nsIWeakReference *aShell) : - nsHTMLSelectableAccessible(aContent, aShell) + nsAccessibleWrap(aContent, aShell) { } @@ -312,8 +73,7 @@ nsresult nsHTMLSelectListAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState) { - nsresult rv = nsHTMLSelectableAccessible::GetStateInternal(aState, - aExtraState); + nsresult rv = nsAccessibleWrap::GetStateInternal(aState, aExtraState); NS_ENSURE_A11Y_SUCCESS(rv, rv); // As a nsHTMLSelectListAccessible we can have the following states: @@ -352,6 +112,33 @@ nsHTMLSelectListAccessible::GetRoleInternal(PRUint32 *aRole) return NS_OK; } +//////////////////////////////////////////////////////////////////////////////// +// nsHTMLSelectListAccessible: SelectAccessible + +bool +nsHTMLSelectListAccessible::IsSelect() +{ + return true; +} + +bool +nsHTMLSelectListAccessible::SelectAll() +{ + nsCOMPtr selectElm(do_QueryInterface(mContent)); + PRBool isMultiple = PR_FALSE; + selectElm->GetMultiple(&isMultiple); + return isMultiple ? nsAccessibleWrap::SelectAll() : false; +} + +bool +nsHTMLSelectListAccessible::UnselectAll() +{ + nsCOMPtr selectElm(do_QueryInterface(mContent)); + PRBool isMultiple = PR_FALSE; + selectElm->GetMultiple(&isMultiple); + return isMultiple ? nsAccessibleWrap::UnselectAll() : false; +} + //////////////////////////////////////////////////////////////////////////////// // nsHTMLSelectListAccessible: nsAccessible protected @@ -676,6 +463,16 @@ NS_IMETHODIMP nsHTMLSelectOptionAccessible::DoAction(PRUint8 index) return NS_ERROR_INVALID_ARG; } +NS_IMETHODIMP +nsHTMLSelectOptionAccessible::SetSelected(PRBool aSelect) +{ + if (IsDefunct()) + return NS_ERROR_FAILURE; + + nsCOMPtr optionElm(do_QueryInterface(mContent)); + return optionElm->SetSelected(aSelect); +} + //////////////////////////////////////////////////////////////////////////////// // nsHTMLSelectOptionAccessible: static methods diff --git a/accessible/src/html/nsHTMLSelectAccessible.h b/accessible/src/html/nsHTMLSelectAccessible.h index 03a2134ce7d..bbf2d377461 100644 --- a/accessible/src/html/nsHTMLSelectAccessible.h +++ b/accessible/src/html/nsHTMLSelectAccessible.h @@ -39,7 +39,6 @@ #ifndef __nsHTMLSelectAccessible_h__ #define __nsHTMLSelectAccessible_h__ -#include "nsIAccessibleSelectable.h" #include "nsAccessibilityAtoms.h" #include "nsHTMLFormControlAccessible.h" #include "nsIDOMHTMLOptionsCollection.h" @@ -63,58 +62,10 @@ class nsIMutableArray; * - nsHTMLSelectOptionAccessible(s) */ -/** ------------------------------------------------------ */ -/** First, the common widgets */ -/** ------------------------------------------------------ */ - -/* - * The HTML implementation of nsIAccessibleSelectable. - */ -class nsHTMLSelectableAccessible : public nsAccessibleWrap -{ -public: - - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIACCESSIBLESELECTABLE - - nsHTMLSelectableAccessible(nsIContent *aContent, nsIWeakReference *aShell); - virtual ~nsHTMLSelectableAccessible() {} - -protected: - - NS_IMETHOD ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState); - - class iterator - { - protected: - PRUint32 mLength; - PRUint32 mIndex; - PRInt32 mSelCount; - nsCOMPtr mOptions; - nsCOMPtr mOption; - nsCOMPtr mWeakShell; - nsHTMLSelectableAccessible *mParentSelect; - - public: - iterator(nsHTMLSelectableAccessible *aParent, nsIWeakReference *aWeakShell); - - void CalcSelectionCount(PRInt32 *aSelectionCount); - void Select(PRBool aSelect); - void AddAccessibleIfSelected(nsIMutableArray *aSelectedAccessibles, - nsPresContext *aContext); - PRBool GetAccessibleIfSelected(PRInt32 aIndex, nsPresContext *aContext, - nsIAccessible **aAccessible); - - PRBool Advance(); - }; - - friend class iterator; -}; - /* * The list that contains all the options in the select. */ -class nsHTMLSelectListAccessible : public nsHTMLSelectableAccessible +class nsHTMLSelectListAccessible : public nsAccessibleWrap { public: @@ -125,6 +76,11 @@ public: virtual nsresult GetRoleInternal(PRUint32 *aRole); virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState); + // SelectAccessible + virtual bool IsSelect(); + virtual bool SelectAll(); + virtual bool UnselectAll(); + protected: // nsAccessible @@ -153,6 +109,7 @@ public: NS_IMETHOD DoAction(PRUint8 index); NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName); NS_IMETHOD GetNumActions(PRUint8 *_retval); + NS_IMETHOD SetSelected(PRBool aSelect); // nsAccessible virtual nsresult GetNameInternal(nsAString& aName); diff --git a/accessible/src/msaa/nsAccessibleWrap.cpp b/accessible/src/msaa/nsAccessibleWrap.cpp index 49f9c7fce0f..a9b949ba2d5 100644 --- a/accessible/src/msaa/nsAccessibleWrap.cpp +++ b/accessible/src/msaa/nsAccessibleWrap.cpp @@ -44,7 +44,6 @@ #include "nsRelUtils.h" #include "nsIAccessibleDocument.h" -#include "nsIAccessibleSelectable.h" #include "nsIAccessibleEvent.h" #include "nsIAccessibleWin32Object.h" @@ -697,7 +696,7 @@ __try { /** * This method is called when a client wants to know which children of a node * are selected. Note that this method can only find selected children for - * nsIAccessible object which implement nsIAccessibleSelectable. + * nsIAccessible object which implement SelectAccessible. * * The VARIANT return value arguement is expected to either contain a single IAccessible * or an IEnumVARIANT of IAccessibles. We return the IEnumVARIANT regardless of the number @@ -717,17 +716,12 @@ __try { VariantInit(pvarChildren); pvarChildren->vt = VT_EMPTY; - nsCOMPtr - select(do_QueryInterface(static_cast(this))); - - if (select) { // do we have an nsIAccessibleSelectable? - // we have an accessible that can have children selected - nsCOMPtr selectedOptions; - // gets the selected options as nsIAccessibles. - select->GetSelectedChildren(getter_AddRefs(selectedOptions)); - if (selectedOptions) { // false if the select has no children or none are selected + if (IsSelect()) { + nsCOMPtr selectedItems = SelectedItems(); + if (selectedItems) { // 1) Create and initialize the enumeration - nsRefPtr pEnum = new AccessibleEnumerator(selectedOptions); + nsRefPtr pEnum = + new AccessibleEnumerator(selectedItems); // 2) Put the enumerator in the VARIANT if (!pEnum) diff --git a/accessible/src/xforms/nsXFormsAccessible.cpp b/accessible/src/xforms/nsXFormsAccessible.cpp index 3d3e411df2c..3534e8ca452 100644 --- a/accessible/src/xforms/nsXFormsAccessible.cpp +++ b/accessible/src/xforms/nsXFormsAccessible.cpp @@ -316,12 +316,9 @@ nsXFormsEditableAccessible::GetAssociatedEditor(nsIEditor **aEditor) return sXFormsService->GetEditor(DOMNode, aEditor); } +//////////////////////////////////////////////////////////////////////////////// // nsXFormsSelectableAccessible - - -NS_IMPL_ISUPPORTS_INHERITED1(nsXFormsSelectableAccessible, - nsXFormsEditableAccessible, - nsIAccessibleSelectable) +//////////////////////////////////////////////////////////////////////////////// nsXFormsSelectableAccessible:: nsXFormsSelectableAccessible(nsIContent *aContent, nsIWeakReference *aShell) : @@ -331,265 +328,225 @@ nsXFormsSelectableAccessible:: mContent->NodeInfo()->Equals(nsAccessibilityAtoms::select1); } -NS_IMETHODIMP -nsXFormsSelectableAccessible::GetSelectedChildren(nsIArray **aAccessibles) +bool +nsXFormsSelectableAccessible::IsSelect() { - NS_ENSURE_ARG_POINTER(aAccessibles); + return true; +} - *aAccessibles = nsnull; - - nsCOMPtr accessibles = +already_AddRefed +nsXFormsSelectableAccessible::SelectedItems() +{ + nsCOMPtr selectedItems = do_CreateInstance(NS_ARRAY_CONTRACTID); - NS_ENSURE_TRUE(accessibles, NS_ERROR_OUT_OF_MEMORY); + if (!selectedItems) + return nsnull; nsresult rv; nsCOMPtr DOMNode(do_QueryInterface(mContent)); if (mIsSelect1Element) { - nsCOMPtr item; + nsCOMPtr itemDOMNode; rv = sXFormsService->GetSelectedItemForSelect1(DOMNode, - getter_AddRefs(item)); - NS_ENSURE_SUCCESS(rv, rv); - - if (!item) - return NS_OK; - - nsCOMPtr accessible; - GetAccService()->GetAccessibleFor(item, getter_AddRefs(accessible)); - NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE); - - accessibles->AppendElement(accessible, PR_FALSE); - NS_ADDREF(*aAccessibles = accessibles); - return NS_OK; - } - - nsCOMPtr items; - rv = sXFormsService->GetSelectedItemsForSelect(DOMNode, - getter_AddRefs(items)); - NS_ENSURE_SUCCESS(rv, rv); - - if (!items) - return NS_OK; - - PRUint32 length = 0; - items->GetLength(&length); - if (!length) - return NS_OK; - - for (PRUint32 index = 0; index < length; index++) { - nsCOMPtr item; - items->Item(index, getter_AddRefs(item)); - NS_ENSURE_TRUE(item, NS_ERROR_FAILURE); - - nsCOMPtr accessible; - GetAccService()->GetAccessibleFor(item, getter_AddRefs(accessible)); - NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE); - - accessibles->AppendElement(accessible, PR_FALSE); - } - - NS_ADDREF(*aAccessibles = accessibles); - return NS_OK; -} - -NS_IMETHODIMP -nsXFormsSelectableAccessible::GetSelectionCount(PRInt32 *aCount) -{ - NS_ENSURE_ARG_POINTER(aCount); - - *aCount = 0; - - nsresult rv; - nsCOMPtr DOMNode(do_QueryInterface(mContent)); - - if (mIsSelect1Element) { - nsCOMPtr item; - rv = sXFormsService->GetSelectedItemForSelect1(DOMNode, - getter_AddRefs(item)); - NS_ENSURE_SUCCESS(rv, rv); + getter_AddRefs(itemDOMNode)); + if (NS_FAILED(rv) || !itemDOMNode) + return nsnull; + nsCOMPtr itemNode(do_QueryInterface(itemDOMNode)); + nsIAccessible* item = GetAccService()->GetAccessibleInWeakShell(itemNode, + mWeakShell); if (item) - *aCount = 1; + selectedItems->AppendElement(item, PR_FALSE); - return NS_OK; + nsIMutableArray* items = nsnull; + selectedItems.forget(&items); + return items; } - nsCOMPtr items; + nsCOMPtr itemNodeList; rv = sXFormsService->GetSelectedItemsForSelect(DOMNode, - getter_AddRefs(items)); - NS_ENSURE_SUCCESS(rv, rv); - - if (!items) - return NS_OK; + getter_AddRefs(itemNodeList)); + if (NS_FAILED(rv) || !itemNodeList) + return nsnull; PRUint32 length = 0; - items->GetLength(&length); - if (length) - *aCount = length; + itemNodeList->GetLength(&length); + for (PRUint32 index = 0; index < length; index++) { + nsCOMPtr itemDOMNode; + itemNodeList->Item(index, getter_AddRefs(itemDOMNode)); + if (!itemDOMNode) + return nsnull; - return NS_OK; + nsCOMPtr itemNode(do_QueryInterface(itemDOMNode)); + nsIAccessible* item = GetAccService()->GetAccessibleInWeakShell(itemNode, + mWeakShell); + if (item) + selectedItems->AppendElement(item, PR_FALSE); + } + + nsIMutableArray* items = nsnull; + selectedItems.forget(&items); + return items; } -NS_IMETHODIMP -nsXFormsSelectableAccessible::AddChildToSelection(PRInt32 aIndex) +PRUint32 +nsXFormsSelectableAccessible::SelectedItemCount() { - nsCOMPtr item = GetItemByIndex(&aIndex); - if (!item) - return NS_OK; + nsresult rv; + nsCOMPtr DOMNode(do_QueryInterface(mContent)); + + if (mIsSelect1Element) { + nsCOMPtr item; + rv = sXFormsService->GetSelectedItemForSelect1(DOMNode, + getter_AddRefs(item)); + return NS_SUCCEEDED(rv) && item ? 1 : 0; + } + + nsCOMPtr itemNodeList; + rv = sXFormsService->GetSelectedItemsForSelect(DOMNode, + getter_AddRefs(itemNodeList)); + if (NS_FAILED(rv) || !itemNodeList) + return 0; + + PRUint32 length = 0; + itemNodeList->GetLength(&length); + return length; +} + +bool +nsXFormsSelectableAccessible::AddItemToSelection(PRUint32 aIndex) +{ + nsCOMPtr itemDOMNode(do_QueryInterface(GetItemByIndex(&aIndex))); + if (!itemDOMNode) + return false; nsCOMPtr DOMNode(do_QueryInterface(mContent)); if (mIsSelect1Element) - return sXFormsService->SetSelectedItemForSelect1(DOMNode, item); + sXFormsService->SetSelectedItemForSelect1(DOMNode, itemDOMNode); + else + sXFormsService->AddItemToSelectionForSelect(DOMNode, itemDOMNode); - return sXFormsService->AddItemToSelectionForSelect(DOMNode, item); + return true; } -NS_IMETHODIMP -nsXFormsSelectableAccessible::RemoveChildFromSelection(PRInt32 aIndex) +bool +nsXFormsSelectableAccessible::RemoveItemFromSelection(PRUint32 aIndex) { - nsCOMPtr item = GetItemByIndex(&aIndex); - if (!item) - return NS_OK; + nsCOMPtr itemDOMNode(do_QueryInterface(GetItemByIndex(&aIndex))); + if (!itemDOMNode) + return false; nsresult rv; nsCOMPtr DOMNode(do_QueryInterface(mContent)); if (mIsSelect1Element) { - nsCOMPtr selitem; - rv = sXFormsService->GetSelectedItemForSelect1(DOMNode, - getter_AddRefs(selitem)); - NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); + nsCOMPtr selItemDOMNode; + sXFormsService->GetSelectedItemForSelect1(DOMNode, + getter_AddRefs(selItemDOMNode)); + if (selItemDOMNode == itemDOMNode) + sXFormsService->SetSelectedItemForSelect1(DOMNode, nsnull); - if (selitem != item) - return NS_ERROR_FAILURE; - return sXFormsService->SetSelectedItemForSelect1(DOMNode, nsnull); + return true; } - return sXFormsService->RemoveItemFromSelectionForSelect(DOMNode, item); + sXFormsService->RemoveItemFromSelectionForSelect(DOMNode, itemDOMNode); + return true; } -NS_IMETHODIMP -nsXFormsSelectableAccessible::RefSelection(PRInt32 aIndex, - nsIAccessible **aAccessible) +nsAccessible* +nsXFormsSelectableAccessible::GetSelectedItem(PRUint32 aIndex) { - NS_ENSURE_ARG_POINTER(aAccessible); - *aAccessible = nsnull; - nsresult rv; nsCOMPtr DOMNode(do_QueryInterface(mContent)); if (mIsSelect1Element) { if (aIndex != 0) - return NS_OK; + return nsnull; - nsCOMPtr item; + nsCOMPtr itemDOMNode; rv = sXFormsService->GetSelectedItemForSelect1(DOMNode, - getter_AddRefs(item)); - NS_ENSURE_SUCCESS(rv, rv); - - if (item) - return GetAccService()->GetAccessibleFor(item, aAccessible); - return NS_OK; + getter_AddRefs(itemDOMNode)); + if (NS_SUCCEEDED(rv) && itemDOMNode) { + nsCOMPtr itemNode(do_QueryInterface(itemDOMNode)); + return GetAccService()->GetAccessibleInWeakShell(itemNode, mWeakShell); + } + return nsnull; } - nsCOMPtr items; + nsCOMPtr itemNodeList; rv = sXFormsService->GetSelectedItemsForSelect(DOMNode, - getter_AddRefs(items)); - NS_ENSURE_SUCCESS(rv, rv); + getter_AddRefs(itemNodeList)); + if (NS_FAILED(rv) || !itemNodeList) + return nsnull; - if (!items) - return NS_OK; + nsCOMPtr itemDOMNode; + itemNodeList->Item(aIndex, getter_AddRefs(itemDOMNode)); - PRUint32 length = 0; - items->GetLength(&length); - if (aIndex < 0 || PRUint32(aIndex) >= length) - return NS_OK; - - nsCOMPtr item; - items->Item(aIndex, getter_AddRefs(item)); - - nsCOMPtr accessible; - return GetAccService()->GetAccessibleFor(item, getter_AddRefs(accessible)); + nsCOMPtr itemNode(do_QueryInterface(itemDOMNode)); + return GetAccService()->GetAccessibleInWeakShell(itemNode, mWeakShell); } -NS_IMETHODIMP -nsXFormsSelectableAccessible::IsChildSelected(PRInt32 aIndex, - PRBool *aIsSelected) +bool +nsXFormsSelectableAccessible::IsItemSelected(PRUint32 aIndex) { - NS_ENSURE_ARG_POINTER(aIsSelected); - *aIsSelected = PR_FALSE; - - nsCOMPtr item = GetItemByIndex(&aIndex); - if (!item) - return NS_OK; + nsCOMPtr itemDOMNode(do_QueryInterface(GetItemByIndex(&aIndex))); + if (!itemDOMNode) + return false; nsresult rv; nsCOMPtr DOMNode(do_QueryInterface(mContent)); if (mIsSelect1Element) { - nsCOMPtr selitem; - rv = sXFormsService->GetSelectedItemForSelect1(DOMNode, - getter_AddRefs(selitem)); - NS_ENSURE_SUCCESS(rv, rv); - - if (selitem == item) - *aIsSelected = PR_TRUE; - return NS_OK; + nsCOMPtr selItemDOMNode; + sXFormsService->GetSelectedItemForSelect1(DOMNode, + getter_AddRefs(selItemDOMNode)); + return selItemDOMNode == itemDOMNode; } - return sXFormsService->IsSelectItemSelected(DOMNode, item, aIsSelected); + PRBool isSelected = PR_FALSE; + sXFormsService->IsSelectItemSelected(DOMNode, itemDOMNode, &isSelected); + return isSelected; } -NS_IMETHODIMP -nsXFormsSelectableAccessible::ClearSelection() +bool +nsXFormsSelectableAccessible::UnselectAll() { nsCOMPtr DOMNode(do_QueryInterface(mContent)); if (mIsSelect1Element) - return sXFormsService->SetSelectedItemForSelect1(DOMNode, nsnull); + sXFormsService->SetSelectedItemForSelect1(DOMNode, nsnull); - return sXFormsService->ClearSelectionForSelect(DOMNode); + sXFormsService->ClearSelectionForSelect(DOMNode); + return true; } -NS_IMETHODIMP -nsXFormsSelectableAccessible::SelectAllSelection(PRBool *aMultipleSelection) +bool +nsXFormsSelectableAccessible::SelectAll() { - NS_ENSURE_ARG_POINTER(aMultipleSelection); + if (mIsSelect1Element) + return false; - if (mIsSelect1Element) { - *aMultipleSelection = PR_FALSE; - return NS_OK; - } - - *aMultipleSelection = PR_TRUE; nsCOMPtr DOMNode(do_QueryInterface(mContent)); - return sXFormsService->SelectAllItemsForSelect(DOMNode); + sXFormsService->SelectAllItemsForSelect(DOMNode); + return true; } -already_AddRefed -nsXFormsSelectableAccessible::GetItemByIndex(PRInt32 *aIndex, - nsIAccessible *aAccessible) +nsIContent* +nsXFormsSelectableAccessible::GetItemByIndex(PRUint32* aIndex, + nsAccessible* aAccessible) { - nsRefPtr accessible(do_QueryObject(aAccessible)); - if (!accessible) - accessible = this; - + nsAccessible* accessible = aAccessible ? aAccessible : this; PRInt32 childCount = accessible->GetChildCount(); for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) { nsAccessible *child = accessible->GetChildAt(childIdx); - - nsCOMPtr childNode(child->GetDOMNode()); - nsCOMPtr childContent(do_QueryInterface(childNode)); - if (!childContent) - continue; - + nsIContent* childContent = child->GetContent(); nsINodeInfo *nodeInfo = childContent->NodeInfo(); if (nodeInfo->NamespaceEquals(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS))) { if (nodeInfo->Equals(nsAccessibilityAtoms::item)) { if (!*aIndex) - return childNode.forget(); + return childContent; --*aIndex; } else if (nodeInfo->Equals(nsAccessibilityAtoms::choices)) { - nsIDOMNode *itemNode = GetItemByIndex(aIndex, child).get(); - if (itemNode) - return itemNode; + nsIContent* itemContent = GetItemByIndex(aIndex, child); + if (itemContent) + return itemContent; } } } diff --git a/accessible/src/xforms/nsXFormsAccessible.h b/accessible/src/xforms/nsXFormsAccessible.h index addbe9d8e4e..6fe316981bb 100644 --- a/accessible/src/xforms/nsXFormsAccessible.h +++ b/accessible/src/xforms/nsXFormsAccessible.h @@ -162,12 +162,21 @@ class nsXFormsSelectableAccessible : public nsXFormsEditableAccessible public: nsXFormsSelectableAccessible(nsIContent *aContent, nsIWeakReference *aShell); - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIACCESSIBLESELECTABLE + // SelectAccessible + virtual bool IsSelect(); + virtual already_AddRefed SelectedItems(); + virtual PRUint32 SelectedItemCount(); + virtual nsAccessible* GetSelectedItem(PRUint32 aIndex); + virtual bool IsItemSelected(PRUint32 aIndex); + virtual bool AddItemToSelection(PRUint32 aIndex); + virtual bool RemoveItemFromSelection(PRUint32 aIndex); + virtual bool SelectAll(); + virtual bool UnselectAll(); protected: - already_AddRefed GetItemByIndex(PRInt32 *aIndex, - nsIAccessible *aAccessible = nsnull); + nsIContent* GetItemByIndex(PRUint32* aIndex, + nsAccessible* aAccessible = nsnull); + PRBool mIsSelect1Element; }; diff --git a/accessible/src/xul/nsXULListboxAccessible.cpp b/accessible/src/xul/nsXULListboxAccessible.cpp index 2864c2afbbd..04f7d212137 100644 --- a/accessible/src/xul/nsXULListboxAccessible.cpp +++ b/accessible/src/xul/nsXULListboxAccessible.cpp @@ -879,7 +879,6 @@ nsXULListitemAccessible:: eCaseMatters); } -/** Inherit the ISupports impl from nsAccessible, we handle nsIAccessibleSelectable */ NS_IMPL_ISUPPORTS_INHERITED0(nsXULListitemAccessible, nsAccessible) nsAccessible * diff --git a/accessible/src/xul/nsXULMenuAccessible.cpp b/accessible/src/xul/nsXULMenuAccessible.cpp index 9901d2784af..116f02a9089 100644 --- a/accessible/src/xul/nsXULMenuAccessible.cpp +++ b/accessible/src/xul/nsXULMenuAccessible.cpp @@ -65,7 +65,6 @@ static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); // nsXULSelectableAccessible //////////////////////////////////////////////////////////////////////////////// -// Helper methos nsXULSelectableAccessible:: nsXULSelectableAccessible(nsIContent *aContent, nsIWeakReference *aShell) : nsAccessibleWrap(aContent, aShell) @@ -73,7 +72,8 @@ nsXULSelectableAccessible:: mSelectControl = do_QueryInterface(aContent); } -NS_IMPL_ISUPPORTS_INHERITED1(nsXULSelectableAccessible, nsAccessible, nsIAccessibleSelectable) +//////////////////////////////////////////////////////////////////////////////// +// nsXULSelectableAccessible: nsAccessNode void nsXULSelectableAccessible::Shutdown() @@ -82,51 +82,23 @@ nsXULSelectableAccessible::Shutdown() nsAccessibleWrap::Shutdown(); } -nsresult nsXULSelectableAccessible::ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState) +//////////////////////////////////////////////////////////////////////////////// +// nsXULSelectableAccessible: SelectAccessible + +bool +nsXULSelectableAccessible::IsSelect() { - *aSelState = PR_FALSE; - - if (!mSelectControl) { - return NS_ERROR_FAILURE; - } - nsAccessible* child = GetChildAt(aIndex); - NS_ENSURE_TRUE(child, NS_ERROR_FAILURE); - - nsCOMPtr childNode; - child->GetDOMNode(getter_AddRefs(childNode)); - nsCOMPtr item(do_QueryInterface(childNode)); - NS_ENSURE_TRUE(item, NS_ERROR_FAILURE); - - item->GetSelected(aSelState); - if (eSelection_GetState == aMethod) { - return NS_OK; - } - - nsCOMPtr 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; + return !!mSelectControl; } // Interface methods -NS_IMETHODIMP nsXULSelectableAccessible::GetSelectedChildren(nsIArray **aChildren) +already_AddRefed +nsXULSelectableAccessible::SelectedItems() { - *aChildren = nsnull; - if (!mSelectControl) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr selectedAccessibles = + nsCOMPtr selectedItems = do_CreateInstance(NS_ARRAY_CONTRACTID); - NS_ENSURE_STATE(selectedAccessibles); + if (!selectedItems) + return nsnull; // For XUL multi-select control nsCOMPtr xulMultiSelect = @@ -135,129 +107,165 @@ NS_IMETHODIMP nsXULSelectableAccessible::GetSelectedChildren(nsIArray **aChildre PRInt32 length = 0; xulMultiSelect->GetSelectedCount(&length); for (PRInt32 index = 0; index < length; index++) { - nsCOMPtr selectedItem; - xulMultiSelect->GetSelectedItem(index, getter_AddRefs(selectedItem)); - nsCOMPtr selectedContent(do_QueryInterface(selectedItem)); - nsAccessible *selectedAcc = - GetAccService()->GetAccessibleInWeakShell(selectedContent, mWeakShell); - if (selectedAcc) - selectedAccessibles->AppendElement(static_cast(selectedAcc), - PR_FALSE); + nsCOMPtr itemElm; + xulMultiSelect->GetSelectedItem(index, getter_AddRefs(itemElm)); + nsCOMPtr itemNode(do_QueryInterface(itemElm)); + nsAccessible* item = + GetAccService()->GetAccessibleInWeakShell(itemNode, mWeakShell); + if (item) + selectedItems->AppendElement(static_cast(item), + PR_FALSE); } } else { // Single select? - nsCOMPtr selectedItem; - mSelectControl->GetSelectedItem(getter_AddRefs(selectedItem)); - nsCOMPtr selectedContent(do_QueryInterface(selectedItem)); - if(selectedContent) { - nsAccessible *selectedAcc = - GetAccService()->GetAccessibleInWeakShell(selectedContent, mWeakShell); - if (selectedAcc) - selectedAccessibles->AppendElement(static_cast(selectedAcc), - PR_FALSE); + nsCOMPtr itemElm; + mSelectControl->GetSelectedItem(getter_AddRefs(itemElm)); + nsCOMPtr itemNode(do_QueryInterface(itemElm)); + if(itemNode) { + nsAccessible* item = + GetAccService()->GetAccessibleInWeakShell(itemNode, mWeakShell); + if (item) + selectedItems->AppendElement(static_cast(item), + PR_FALSE); } } - PRUint32 uLength = 0; - selectedAccessibles->GetLength(&uLength); - if (uLength != 0) { // length of nsIArray containing selected options - NS_ADDREF(*aChildren = selectedAccessibles); - } - - return NS_OK; + nsIMutableArray* items = nsnull; + selectedItems.forget(&items); + return items; } -// return the nth selected child's nsIAccessible object -NS_IMETHODIMP nsXULSelectableAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **aAccessible) +nsAccessible* +nsXULSelectableAccessible::GetSelectedItem(PRUint32 aIndex) { - *aAccessible = nsnull; - if (!mSelectControl) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr selectedItem; - nsCOMPtr xulMultiSelect = + nsCOMPtr multiSelectControl = do_QueryInterface(mSelectControl); - if (xulMultiSelect) - xulMultiSelect->GetSelectedItem(aIndex, getter_AddRefs(selectedItem)); - if (aIndex == 0) - mSelectControl->GetSelectedItem(getter_AddRefs(selectedItem)); + nsCOMPtr itemElm; + if (multiSelectControl) + multiSelectControl->GetSelectedItem(aIndex, getter_AddRefs(itemElm)); + else if (aIndex == 0) + mSelectControl->GetSelectedItem(getter_AddRefs(itemElm)); - if (!selectedItem) - return NS_ERROR_FAILURE; - - nsCOMPtr selectedContent(do_QueryInterface(selectedItem)); - nsAccessible *selectedAcc = - GetAccService()->GetAccessibleInWeakShell(selectedContent, mWeakShell); - if (!selectedAcc) - return NS_ERROR_FAILURE; - - NS_ADDREF(*aAccessible = selectedAcc); - return NS_OK; + nsCOMPtr itemNode(do_QueryInterface(itemElm)); + return itemNode ? + GetAccService()->GetAccessibleInWeakShell(itemNode, mWeakShell) : nsnull; } -NS_IMETHODIMP nsXULSelectableAccessible::GetSelectionCount(PRInt32 *aSelectionCount) +PRUint32 +nsXULSelectableAccessible::SelectedItemCount() { - *aSelectionCount = 0; - if (!mSelectControl) { - return NS_ERROR_FAILURE; - } - // For XUL multi-select control - nsCOMPtr xulMultiSelect = + nsCOMPtr multiSelectControl = do_QueryInterface(mSelectControl); - if (xulMultiSelect) - return xulMultiSelect->GetSelectedCount(aSelectionCount); + if (multiSelectControl) { + PRInt32 count = 0; + multiSelectControl->GetSelectedCount(&count); + return count; + } // For XUL single-select control/menulist PRInt32 index; mSelectControl->GetSelectedIndex(&index); - if (index >= 0) - *aSelectionCount = 1; - return NS_OK; + return (index >= 0) ? 1 : 0; } -NS_IMETHODIMP nsXULSelectableAccessible::AddChildToSelection(PRInt32 aIndex) +bool +nsXULSelectableAccessible::AddItemToSelection(PRUint32 aIndex) { - PRBool isSelected; - return ChangeSelection(aIndex, eSelection_Add, &isSelected); + nsAccessible* item = GetChildAt(aIndex); + if (!item) + return false; + + nsCOMPtr itemElm = + do_QueryInterface(item->GetContent()); + if (!itemElm) + return false; + + PRBool isItemSelected = PR_FALSE; + itemElm->GetSelected(&isItemSelected); + if (isItemSelected) + return true; + + nsCOMPtr multiSelectControl = + do_QueryInterface(mSelectControl); + + if (multiSelectControl) + multiSelectControl->AddItemToSelection(itemElm); + else + mSelectControl->SetSelectedItem(itemElm); + + return true; } -NS_IMETHODIMP nsXULSelectableAccessible::RemoveChildFromSelection(PRInt32 aIndex) +bool +nsXULSelectableAccessible::RemoveItemFromSelection(PRUint32 aIndex) { - PRBool isSelected; - return ChangeSelection(aIndex, eSelection_Remove, &isSelected); + nsAccessible* item = GetChildAt(aIndex); + if (!item) + return false; + + nsCOMPtr itemElm = + do_QueryInterface(item->GetContent()); + if (!itemElm) + return false; + + PRBool isItemSelected = PR_FALSE; + itemElm->GetSelected(&isItemSelected); + if (!isItemSelected) + return true; + + nsCOMPtr multiSelectControl = + do_QueryInterface(mSelectControl); + + if (multiSelectControl) + multiSelectControl->RemoveItemFromSelection(itemElm); + else + mSelectControl->SetSelectedItem(nsnull); + + return true; } -NS_IMETHODIMP nsXULSelectableAccessible::IsChildSelected(PRInt32 aIndex, PRBool *aIsSelected) +bool +nsXULSelectableAccessible::IsItemSelected(PRUint32 aIndex) { - *aIsSelected = PR_FALSE; - return ChangeSelection(aIndex, eSelection_GetState, aIsSelected); + nsAccessible* item = GetChildAt(aIndex); + if (!item) + return false; + + nsCOMPtr itemElm = + do_QueryInterface(item->GetContent()); + if (!itemElm) + return false; + + PRBool isItemSelected = PR_FALSE; + itemElm->GetSelected(&isItemSelected); + return isItemSelected; } -NS_IMETHODIMP nsXULSelectableAccessible::ClearSelection() +bool +nsXULSelectableAccessible::UnselectAll() { - if (!mSelectControl) { - return NS_ERROR_FAILURE; + nsCOMPtr multiSelectControl = + do_QueryInterface(mSelectControl); + multiSelectControl ? + multiSelectControl->ClearSelection() : mSelectControl->SetSelectedIndex(-1); + + return true; +} + +bool +nsXULSelectableAccessible::SelectAll() +{ + nsCOMPtr multiSelectControl = + do_QueryInterface(mSelectControl); + if (multiSelectControl) { + multiSelectControl->SelectAll(); + return true; } - nsCOMPtr xulMultiSelect = - do_QueryInterface(mSelectControl); - return xulMultiSelect ? xulMultiSelect->ClearSelection() : mSelectControl->SetSelectedIndex(-1); -} - -NS_IMETHODIMP nsXULSelectableAccessible::SelectAllSelection(PRBool *aSucceeded) -{ - *aSucceeded = PR_TRUE; - - nsCOMPtr xulMultiSelect = - do_QueryInterface(mSelectControl); - if (xulMultiSelect) - return xulMultiSelect->SelectAll(); // otherwise, don't support this method - *aSucceeded = PR_FALSE; - return NS_ERROR_NOT_IMPLEMENTED; + return false; } diff --git a/accessible/src/xul/nsXULMenuAccessible.h b/accessible/src/xul/nsXULMenuAccessible.h index 48571943940..db55eb784b7 100644 --- a/accessible/src/xul/nsXULMenuAccessible.h +++ b/accessible/src/xul/nsXULMenuAccessible.h @@ -40,27 +40,32 @@ #define _nsXULMenuAccessible_H_ #include "nsAccessibleWrap.h" -#include "nsIAccessibleSelectable.h" #include "nsIDOMXULSelectCntrlEl.h" /** - * The basic implementation of nsIAccessibleSelectable. + * The basic implementation of SelectAccessible for XUL select controls. */ class nsXULSelectableAccessible : public nsAccessibleWrap { public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIACCESSIBLESELECTABLE - nsXULSelectableAccessible(nsIContent *aContent, nsIWeakReference *aShell); virtual ~nsXULSelectableAccessible() {} // nsAccessNode virtual void Shutdown(); -protected: - nsresult ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState); + // SelectAccessible + virtual bool IsSelect(); + virtual already_AddRefed SelectedItems(); + virtual PRUint32 SelectedItemCount(); + virtual nsAccessible* GetSelectedItem(PRUint32 aIndex); + virtual bool IsItemSelected(PRUint32 aIndex); + virtual bool AddItemToSelection(PRUint32 aIndex); + virtual bool RemoveItemFromSelection(PRUint32 aIndex); + virtual bool SelectAll(); + virtual bool UnselectAll(); +protected: // nsIDOMXULMultiSelectControlElement inherits from this, so we'll always have // one of these if the widget is valid and not defunct nsCOMPtr mSelectControl; diff --git a/accessible/src/xul/nsXULTreeAccessible.cpp b/accessible/src/xul/nsXULTreeAccessible.cpp index 96ec6dbe26e..88fc9f96dcc 100644 --- a/accessible/src/xul/nsXULTreeAccessible.cpp +++ b/accessible/src/xul/nsXULTreeAccessible.cpp @@ -57,7 +57,7 @@ nsXULTreeAccessible:: nsXULTreeAccessible(nsIContent *aContent, nsIWeakReference *aShell) : - nsXULSelectableAccessible(aContent, aShell) + nsAccessibleWrap(aContent, aShell) { mTree = nsCoreUtils::GetTreeBoxObject(aContent); if (mTree) @@ -85,10 +85,10 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXULTreeAccessible) NS_INTERFACE_MAP_STATIC_AMBIGUOUS(nsXULTreeAccessible) -NS_INTERFACE_MAP_END_INHERITING(nsXULSelectableAccessible) +NS_INTERFACE_MAP_END_INHERITING(nsAccessible) -NS_IMPL_ADDREF_INHERITED(nsXULTreeAccessible, nsXULSelectableAccessible) -NS_IMPL_RELEASE_INHERITED(nsXULTreeAccessible, nsXULSelectableAccessible) +NS_IMPL_ADDREF_INHERITED(nsXULTreeAccessible, nsAccessible) +NS_IMPL_RELEASE_INHERITED(nsXULTreeAccessible, nsAccessible) //////////////////////////////////////////////////////////////////////////////// // nsXULTreeAccessible: nsAccessible implementation @@ -160,7 +160,7 @@ nsXULTreeAccessible::GetValue(nsAString& aValue) PRBool nsXULTreeAccessible::IsDefunct() { - return nsXULSelectableAccessible::IsDefunct() || !mTree || !mTreeView; + return nsAccessibleWrap::IsDefunct() || !mTree || !mTreeView; } void @@ -175,7 +175,7 @@ nsXULTreeAccessible::Shutdown() mTree = nsnull; mTreeView = nsnull; - nsXULSelectableAccessible::Shutdown(); + nsAccessibleWrap::Shutdown(); } //////////////////////////////////////////////////////////////////////////////// @@ -262,8 +262,7 @@ nsXULTreeAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY, // If we failed to find tree cell for the given point then it might be // tree columns. if (row == -1 || !column) - return nsXULSelectableAccessible:: - GetChildAtPoint(aX, aY, aDeepestChild, aChild); + return nsAccessibleWrap::GetChildAtPoint(aX, aY, aDeepestChild, aChild); nsAccessible *child = GetTreeItemAccessible(row); if (aDeepestChild && child) { @@ -280,23 +279,26 @@ nsXULTreeAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY, } //////////////////////////////////////////////////////////////////////////////// -// nsXULTreeAccessible: nsAccessibleSelectable implementation +// nsXULTreeAccessible: SelectAccessible -NS_IMETHODIMP nsXULTreeAccessible::GetSelectedChildren(nsIArray **_retval) +bool +nsXULTreeAccessible::IsSelect() { - // Ask tree selection to get all selected children - *_retval = nsnull; - - if (IsDefunct()) - return NS_ERROR_FAILURE; + return true; +} +already_AddRefed +nsXULTreeAccessible::SelectedItems() +{ nsCOMPtr selection; mTreeView->GetSelection(getter_AddRefs(selection)); if (!selection) - return NS_ERROR_FAILURE; - nsCOMPtr selectedAccessibles = + return nsnull; + + nsCOMPtr selectedItems = do_CreateInstance(NS_ARRAY_CONTRACTID); - NS_ENSURE_STATE(selectedAccessibles); + if (!selectedItems) + return nsnull; PRInt32 rowIndex, rowCount; PRBool isSelected; @@ -304,98 +306,95 @@ NS_IMETHODIMP nsXULTreeAccessible::GetSelectedChildren(nsIArray **_retval) for (rowIndex = 0; rowIndex < rowCount; rowIndex++) { selection->IsSelected(rowIndex, &isSelected); if (isSelected) { - nsIAccessible *tempAccessible = GetTreeItemAccessible(rowIndex); - NS_ENSURE_STATE(tempAccessible); - - selectedAccessibles->AppendElement(tempAccessible, PR_FALSE); + nsIAccessible* item = GetTreeItemAccessible(rowIndex); + if (item) + selectedItems->AppendElement(item, PR_FALSE); } } - PRUint32 length; - selectedAccessibles->GetLength(&length); - if (length != 0) { - *_retval = selectedAccessibles; - NS_IF_ADDREF(*_retval); - } - - return NS_OK; + nsIMutableArray* items = nsnull; + selectedItems.forget(&items); + return items; } -NS_IMETHODIMP nsXULTreeAccessible::GetSelectionCount(PRInt32 *aSelectionCount) +PRUint32 +nsXULTreeAccessible::SelectedItemCount() { - *aSelectionCount = 0; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - nsCOMPtr selection; - mTreeView->GetSelection(getter_AddRefs(selection)); - if (selection) - selection->GetCount(aSelectionCount); - - return NS_OK; -} - -NS_IMETHODIMP nsXULTreeAccessible::ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState) -{ - if (IsDefunct()) - return NS_ERROR_FAILURE; - nsCOMPtr selection; mTreeView->GetSelection(getter_AddRefs(selection)); if (selection) { - selection->IsSelected(aIndex, aSelState); - if ((!(*aSelState) && eSelection_Add == aMethod) || - ((*aSelState) && eSelection_Remove == aMethod)) - return selection->ToggleSelect(aIndex); + PRInt32 count = 0; + selection->GetCount(&count); + return count; } - return NS_OK; + return 0; } -NS_IMETHODIMP nsXULTreeAccessible::AddChildToSelection(PRInt32 aIndex) +bool +nsXULTreeAccessible::AddItemToSelection(PRUint32 aIndex) { - PRBool isSelected; - return ChangeSelection(aIndex, eSelection_Add, &isSelected); -} - -NS_IMETHODIMP nsXULTreeAccessible::RemoveChildFromSelection(PRInt32 aIndex) -{ - PRBool isSelected; - return ChangeSelection(aIndex, eSelection_Remove, &isSelected); -} - -NS_IMETHODIMP nsXULTreeAccessible::IsChildSelected(PRInt32 aIndex, PRBool *_retval) -{ - return ChangeSelection(aIndex, eSelection_GetState, _retval); -} - -NS_IMETHODIMP nsXULTreeAccessible::ClearSelection() -{ - if (IsDefunct()) - return NS_ERROR_FAILURE; - nsCOMPtr selection; mTreeView->GetSelection(getter_AddRefs(selection)); - if (selection) - selection->ClearSelection(); + if (selection) { + PRBool isSelected = PR_FALSE; + selection->IsSelected(aIndex, &isSelected); + if (!isSelected) + selection->ToggleSelect(aIndex); - return NS_OK; + return true; + } + return false; } -NS_IMETHODIMP -nsXULTreeAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **aAccessible) +bool +nsXULTreeAccessible::RemoveItemFromSelection(PRUint32 aIndex) { - NS_ENSURE_ARG_POINTER(aAccessible); - *aAccessible = nsnull; + nsCOMPtr selection; + mTreeView->GetSelection(getter_AddRefs(selection)); + if (selection) { + PRBool isSelected = PR_FALSE; + selection->IsSelected(aIndex, &isSelected); + if (isSelected) + selection->ToggleSelect(aIndex); - if (IsDefunct()) - return NS_ERROR_FAILURE; + return true; + } + return false; +} +bool +nsXULTreeAccessible::IsItemSelected(PRUint32 aIndex) +{ + nsCOMPtr selection; + mTreeView->GetSelection(getter_AddRefs(selection)); + if (selection) { + PRBool isSelected = PR_FALSE; + selection->IsSelected(aIndex, &isSelected); + return isSelected; + } + return false; +} + +bool +nsXULTreeAccessible::UnselectAll() +{ nsCOMPtr selection; mTreeView->GetSelection(getter_AddRefs(selection)); if (!selection) - return NS_ERROR_FAILURE; + return false; + + selection->ClearSelection(); + return true; +} + +nsAccessible* +nsXULTreeAccessible::GetSelectedItem(PRUint32 aIndex) +{ + nsCOMPtr selection; + mTreeView->GetSelection(getter_AddRefs(selection)); + if (!selection) + return nsnull; PRInt32 rowIndex, rowCount; PRInt32 selCount = 0; @@ -404,26 +403,19 @@ nsXULTreeAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **aAccessible) for (rowIndex = 0; rowIndex < rowCount; rowIndex++) { selection->IsSelected(rowIndex, &isSelected); if (isSelected) { - if (selCount == aIndex) { - NS_IF_ADDREF(*aAccessible = GetTreeItemAccessible(rowIndex)); - return NS_OK; - } + if (selCount == aIndex) + return GetTreeItemAccessible(rowIndex); + selCount++; } } - return NS_OK; + return nsnull; } -NS_IMETHODIMP -nsXULTreeAccessible::SelectAllSelection(PRBool *aIsMultiSelectable) +bool +nsXULTreeAccessible::SelectAll() { - NS_ENSURE_ARG_POINTER(aIsMultiSelectable); - *aIsMultiSelectable = PR_FALSE; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - // see if we are multiple select if so set ourselves as such nsCOMPtr selection; mTreeView->GetSelection(getter_AddRefs(selection)); @@ -431,12 +423,12 @@ nsXULTreeAccessible::SelectAllSelection(PRBool *aIsMultiSelectable) PRBool single = PR_FALSE; selection->GetSingle(&single); if (!single) { - *aIsMultiSelectable = PR_TRUE; selection->SelectAll(); + return true; } } - return NS_OK; + return false; } //////////////////////////////////////////////////////////////////////////////// diff --git a/accessible/src/xul/nsXULTreeAccessible.h b/accessible/src/xul/nsXULTreeAccessible.h index 9a0cf28da76..43bd7db982a 100644 --- a/accessible/src/xul/nsXULTreeAccessible.h +++ b/accessible/src/xul/nsXULTreeAccessible.h @@ -61,7 +61,7 @@ const PRUint32 kDefaultTreeCacheSize = 256; { 0xb8, 0xe1, 0x2c, 0x44, 0xb0, 0x41, 0x85, 0xe3 } \ } -class nsXULTreeAccessible : public nsXULSelectableAccessible +class nsXULTreeAccessible : public nsAccessibleWrap { public: using nsAccessible::GetChildCount; @@ -79,9 +79,6 @@ public: NS_IMETHOD GetValue(nsAString& aValue); NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild); - // nsIAccessibleSelectable - NS_DECL_NSIACCESSIBLESELECTABLE - // nsAccessNode virtual PRBool IsDefunct(); virtual void Shutdown(); @@ -96,6 +93,17 @@ public: virtual nsAccessible* GetChildAt(PRUint32 aIndex); virtual PRInt32 GetChildCount(); + // SelectAccessible + virtual bool IsSelect(); + virtual already_AddRefed SelectedItems(); + virtual PRUint32 SelectedItemCount(); + virtual nsAccessible* GetSelectedItem(PRUint32 aIndex); + virtual bool IsItemSelected(PRUint32 aIndex); + virtual bool AddItemToSelection(PRUint32 aIndex); + virtual bool RemoveItemFromSelection(PRUint32 aIndex); + virtual bool SelectAll(); + virtual bool UnselectAll(); + // nsXULTreeAccessible NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEACCESSIBLE_IMPL_CID) @@ -144,8 +152,6 @@ protected: nsCOMPtr mTree; nsCOMPtr mTreeView; nsAccessibleHashtable mAccessibleCache; - - NS_IMETHOD ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState); }; NS_DEFINE_STATIC_IID_ACCESSOR(nsXULTreeAccessible, diff --git a/accessible/tests/mochitest/selectable.js b/accessible/tests/mochitest/selectable.js index 7dd51e952f9..5ec4c47de19 100644 --- a/accessible/tests/mochitest/selectable.js +++ b/accessible/tests/mochitest/selectable.js @@ -4,33 +4,79 @@ * @param aIdentifier [in] selectable container accessible * @param aSelectedChildren [in] array of selected children */ -function testSelectableSelection(aIdentifier, aSelectedChildren) +function testSelectableSelection(aIdentifier, aSelectedChildren, aMsg) { var acc = getAccessible(aIdentifier, [nsIAccessibleSelectable]); if (!acc) return; + var msg = aMsg ? aMsg : ""; var len = aSelectedChildren.length; // getSelectedChildren var selectedChildren = acc.GetSelectedChildren(); - is(selectedChildren ? selectedChildren.length : 0, aSelectedChildren.length, - "getSelectedChildren: wrong selected children count for " + prettyName(aIdentifier)); + is(selectedChildren ? selectedChildren.length : 0, len, + msg + "getSelectedChildren: wrong selected children count for " + + prettyName(aIdentifier)); for (var idx = 0; idx < len; idx++) { var expectedAcc = getAccessible(aSelectedChildren[idx]); - is(selectedChildren.queryElementAt(idx, nsIAccessible), expectedAcc, - "getSelectedChildren: wrong selected child at index " + idx + " for " + prettyName(aIdentifier)); + var actualAcc = selectedChildren.queryElementAt(idx, nsIAccessible); + is(actualAcc, expectedAcc, + msg + "getSelectedChildren: wrong selected child at index " + idx + + " for " + prettyName(aIdentifier) + " { actual : " + + prettyName(actualAcc) + ", expected: " + prettyName(expectedAcc) + "}"); } // selectionCount - is(acc.selectionCount, aSelectedChildren.length, - "selectionCount: wrong selected children count for " + prettyName(aIdentifier)); + // XXX: nsIAccessibleText and nsIAccessibleSelectable both have + // selectionCount property. + //is(acc.selectionCount, aSelectedChildren.length, + // "selectionCount: wrong selected children count for " + prettyName(aIdentifier)); // refSelection for (var idx = 0; idx < len; idx++) { var expectedAcc = getAccessible(aSelectedChildren[idx]); is(acc.refSelection(idx), expectedAcc, - "refSelection: wrong selected child at index " + idx + " for " + prettyName(aIdentifier)); + msg + "refSelection: wrong selected child at index " + idx + " for " + + prettyName(aIdentifier)); + } + + // isChildSelected + testIsChildSelected(acc, acc, { value: 0 }, aSelectedChildren, msg); +} + +/** + * Test isChildSelected method, helper for testSelectableSelection + */ +function testIsChildSelected(aSelectAcc, aTraversedAcc, aIndexObj, aSelectedChildren, aMsg) +{ + var childCount = aTraversedAcc.childCount; + for (var idx = 0; idx < childCount; idx++) { + var child = aTraversedAcc.getChildAt(idx); + var [state, extraState] = getStates(child); + if (state & STATE_SELECTABLE) { + var isSelected = false; + var len = aSelectedChildren.length; + for (var jdx = 0; jdx < len; jdx++) { + if (child == getAccessible(aSelectedChildren[jdx])) { + isSelected = true; + break; + } + } + + // isChildSelected + is(aSelectAcc.isChildSelected(aIndexObj.value++), isSelected, + aMsg + "isChildSelected: wrong selected child " + prettyName(child) + + " for " + prettyName(aSelectAcc)); + + // selected state + testStates(child, isSelected ? STATE_SELECTED : 0, 0, + !isSelected ? STATE_SELECTED : 0 , 0); + + continue; + } + + testIsChildSelected(aSelectAcc, child, aIndexObj, aSelectedChildren); } } diff --git a/accessible/tests/mochitest/selectable/Makefile.in b/accessible/tests/mochitest/selectable/Makefile.in index 48cc8406231..bcc960766b9 100644 --- a/accessible/tests/mochitest/selectable/Makefile.in +++ b/accessible/tests/mochitest/selectable/Makefile.in @@ -47,6 +47,9 @@ include $(topsrcdir)/config/rules.mk _TEST_FILES =\ test_aria.html \ + test_listbox.xul \ + test_menu.xul \ + test_menulist.xul \ test_select.html \ test_tree.xul \ $(NULL) diff --git a/accessible/tests/mochitest/selectable/test_aria.html b/accessible/tests/mochitest/selectable/test_aria.html index 12d3f01e439..fa2e67c8a02 100644 --- a/accessible/tests/mochitest/selectable/test_aria.html +++ b/accessible/tests/mochitest/selectable/test_aria.html @@ -17,6 +17,8 @@ src="../common.js"> + @@ -36,32 +38,88 @@ function doTest() { + ////////////////////////////////////////////////////////////////////////// + // role="list" + var id = "list1"; ok(isAccessible(id, [nsIAccessibleSelectable]), "No selectable accessible for " + id); + testSelectableSelection(id, [ ]); + + var select = getAccessible(id, [nsIAccessibleSelectable]); + select.addChildToSelection(0); + testSelectableSelection(id, [ ]); + select.removeChildFromSelection(0); + testSelectableSelection(id, [ ]); + select.selectAllSelection(); + testSelectableSelection(id, [ ]); + select.clearSelection(); + testSelectableSelection(id, [ ]); + + ////////////////////////////////////////////////////////////////////////// + // role="listbox" + id = "listbox1"; ok(isAccessible(id, [nsIAccessibleSelectable]), "No selectable accessible for " + id); + testSelectableSelection(id, [ ]); + + ////////////////////////////////////////////////////////////////////////// + // role="listbox" aria-multiselectable + id = "listbox2"; ok(isAccessible(id, [nsIAccessibleSelectable]), "No selectable accessible for " + id); + testSelectableSelection(id, [ ]); + + select = getAccessible(id, [nsIAccessibleSelectable]); + select.addChildToSelection(0); + testSelectableSelection(id, [ "listbox2_item1" ]); + select.removeChildFromSelection(0); + testSelectableSelection(id, [ ]); + select.selectAllSelection(); + testSelectableSelection(id, [ "listbox2_item1", "listbox2_item2" ]); + select.clearSelection(); + testSelectableSelection(id, [ ]); + + ////////////////////////////////////////////////////////////////////////// + // role="grid" + id = "grid1"; ok(isAccessible(id, [nsIAccessibleSelectable]), "No selectable accessible for " + id); + testSelectableSelection(id, [ ]); + + ////////////////////////////////////////////////////////////////////////// + // role="tree" + id = "tree1"; ok(isAccessible(id, [nsIAccessibleSelectable]), "No selectable accessible for " + id); + testSelectableSelection(id, [ ]); + + ////////////////////////////////////////////////////////////////////////// + // role="treegrid" + id = "treegrid1"; ok(isAccessible(id, [nsIAccessibleSelectable]), "No selectable accessible for " + id); - // Test selection methods for selectable children in subtree. - testSelectable("grid2", + testSelectableSelection(id, [ ]); + + ////////////////////////////////////////////////////////////////////////// + // role="grid" aria-multiselectable, selectable children in subtree + + id = "grid2"; + ok(isAccessible(id, [nsIAccessibleSelectable]), + "No selectable accessible for " + id); + + testSelectable(id, ["grid2_colhead1", "grid2_colhead2", "grid2_colhead3", "grid2_rowhead", "grid2_cell1", "grid2_cell2"]); @@ -86,6 +144,11 @@ title="ARIA grid and accessible selectable methods shouldn't use GetNextSibling"> Mozilla Bug 566551
+ + Mozilla Bug 590176 +

@@ -102,8 +165,8 @@
   
 
   
-
item1
-
item2
+
item1
+
item2
diff --git a/accessible/tests/mochitest/selectable/test_listbox.xul b/accessible/tests/mochitest/selectable/test_listbox.xul new file mode 100644 index 00000000000..b2fe1a7244f --- /dev/null +++ b/accessible/tests/mochitest/selectable/test_listbox.xul @@ -0,0 +1,155 @@ + + + + + + + + + + + + + Mozilla Bug 590176 +
+

+ +
+      
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ diff --git a/accessible/tests/mochitest/selectable/test_menu.xul b/accessible/tests/mochitest/selectable/test_menu.xul new file mode 100644 index 00000000000..a4f73894db4 --- /dev/null +++ b/accessible/tests/mochitest/selectable/test_menu.xul @@ -0,0 +1,81 @@ + + + + + + + + + + + + + Mozilla Bug 590176 +
+

+ +
+      
+ + + + + + + + + + + + +
+ +
+ diff --git a/accessible/tests/mochitest/selectable/test_menulist.xul b/accessible/tests/mochitest/selectable/test_menulist.xul new file mode 100644 index 00000000000..dbb7cdf9ba8 --- /dev/null +++ b/accessible/tests/mochitest/selectable/test_menulist.xul @@ -0,0 +1,99 @@ + + + + + + + + + + + + + Mozilla Bug 590176 +
+

+ +
+      
+ + + + + + + + + + + + +
+ +
+ diff --git a/accessible/tests/mochitest/selectable/test_select.html b/accessible/tests/mochitest/selectable/test_select.html index 67829bf94f1..c641df5a844 100644 --- a/accessible/tests/mochitest/selectable/test_select.html +++ b/accessible/tests/mochitest/selectable/test_select.html @@ -17,20 +17,168 @@ src="../common.js"> + +