зеркало из https://github.com/mozilla/pjs.git
bug 77648 implementing get_AccSelection
r=aaronl sr=brendan
This commit is contained in:
Родитель
079c95cba2
Коммит
151fe68669
|
@ -25,9 +25,13 @@
|
|||
#include "nsHTMLListboxAccessible.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIAccessibilityService.h"
|
||||
#include "nsIDOMHTMLCollection.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIDOMHTMLSelectElement.h"
|
||||
#include "nsIDOMHTMLOptionElement.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
|
||||
/** ----- nsHTMLListboxAccessible ----- */
|
||||
|
@ -42,7 +46,7 @@ nsHTMLListboxAccessible::nsHTMLListboxAccessible(nsIDOMNode* aDOMNode,
|
|||
}
|
||||
|
||||
/** Inherit the ISupports impl from nsAccessible */
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLListboxAccessible, nsAccessible)
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsHTMLListboxAccessible, nsAccessible, nsIAccessibleSelectable)
|
||||
|
||||
/**
|
||||
* Tell our caller we are a list ( there isn't a listbox value )
|
||||
|
@ -91,11 +95,58 @@ NS_IMETHODIMP nsHTMLListboxAccessible::GetAccChildCount(PRInt32 *_retval)
|
|||
* of select options and then iterate through that pulling out the selected
|
||||
* items and creating IAccessible objects for them. Put the IAccessibles in
|
||||
* the nsISupportsArray and return them.
|
||||
* retval will be nsnull if:
|
||||
* - there are no options in the select
|
||||
* - there are options but none are selected
|
||||
* - the DOMNode is not a nsIDOMHTMLSelectElement ( shouldn't happen )
|
||||
*/
|
||||
NS_IMETHODIMP nsHTMLListboxAccessible::GetSelectedChildren(nsISupportsArray **_retval)
|
||||
{
|
||||
nsCOMPtr<nsIDOMHTMLSelectElement> select(do_QueryInterface(mDOMNode));
|
||||
if(select) {
|
||||
nsCOMPtr<nsIDOMHTMLCollection> options;
|
||||
// get all the options in the select
|
||||
select->GetOptions(getter_AddRefs(options));
|
||||
if (options) {
|
||||
// set up variables we need to get the selected options and to get their nsIAccessile objects
|
||||
PRUint32 length;
|
||||
options->GetLength(&length);
|
||||
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
|
||||
nsCOMPtr<nsISupportsArray> selectedAccessibles;
|
||||
NS_NewISupportsArray(getter_AddRefs(selectedAccessibles));
|
||||
if (!selectedAccessibles || !accService)
|
||||
return NS_ERROR_FAILURE;
|
||||
// find the selected options and get the accessible objects;
|
||||
PRBool isSelected = PR_FALSE;
|
||||
nsCOMPtr<nsIPresContext> context;
|
||||
GetPresContext(context);
|
||||
for (PRUint32 i = 0 ; i < length ; i++) {
|
||||
nsCOMPtr<nsIDOMNode> tempNode;
|
||||
options->Item(i,getter_AddRefs(tempNode));
|
||||
if (tempNode) {
|
||||
nsCOMPtr<nsIDOMHTMLOptionElement> tempOption(do_QueryInterface(tempNode));
|
||||
if (tempOption)
|
||||
tempOption->GetSelected(&isSelected);
|
||||
if (isSelected) {
|
||||
nsCOMPtr<nsIAccessible> tempAccess;
|
||||
accService->CreateHTMLSelectOptionAccessible(tempOption, this, context, getter_AddRefs(tempAccess));
|
||||
if ( tempAccess )
|
||||
selectedAccessibles->AppendElement(tempAccess);
|
||||
isSelected = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
selectedAccessibles->Count(&length); // reusing length
|
||||
if ( length != 0 ) { // length of nsISupportsArray containing selected options
|
||||
*_retval = selectedAccessibles;
|
||||
NS_IF_ADDREF(*_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
// no options, not a select or none of the options are selected
|
||||
*_retval = nsnull;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,6 +37,13 @@
|
|||
#include "nsINameSpaceManager.h"
|
||||
#include "String.h"
|
||||
|
||||
// for the COM IEnumVARIANT solution in get_AccSelection()
|
||||
#define _ATLBASE_IMPL
|
||||
#include <atlbase.h>
|
||||
extern CComModule _Module;
|
||||
#define _ATLCOM_IMPL
|
||||
#include <atlcom.h>
|
||||
|
||||
/* For documentation of the accessibility architecture,
|
||||
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
|
||||
*/
|
||||
|
@ -55,6 +62,7 @@ EXTERN_C GUID CDECL CLSID_Accessible =
|
|||
* Class Accessible
|
||||
*/
|
||||
|
||||
CComModule _Module;
|
||||
|
||||
//-----------------------------------------------------
|
||||
// construction
|
||||
|
@ -417,11 +425,83 @@ STDMETHODIMP Accessible::get_accFocus(
|
|||
pvarChild->vt = VT_EMPTY;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when a client wants to know which children of a node
|
||||
* are selected. Currently we only handle this for HTML selects, which are the
|
||||
* only nsIAccessible objects to implement nsIAccessibleSelectable.
|
||||
*
|
||||
* 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
|
||||
* of options selected, unless there are none selected in which case we return an empty
|
||||
* VARIANT.
|
||||
*
|
||||
* The typedefs at the beginning set up the structure that will contain an array
|
||||
* of the IAccessibles. It implements the IEnumVARIANT interface, allowing us to
|
||||
* use it to return the IAccessibles in the VARIANT.
|
||||
*
|
||||
* We get the selected options from the select's accessible object and then put create
|
||||
* IAccessible objects for them and put those in the CComObject<EnumeratorType>
|
||||
* object. Then we put the CComObject<EnumeratorType> object in the VARIANT and return.
|
||||
*
|
||||
* returns a VT_EMPTY VARIANT if:
|
||||
* - there are no options in the select
|
||||
* - none of the options are selected
|
||||
* - there is an error QIing to IEnumVARIANT
|
||||
* - The object is not the type that can have children selected
|
||||
*/
|
||||
STDMETHODIMP Accessible::get_accSelection(
|
||||
/* [retval][out] */ VARIANT __RPC_FAR *pvarChildren)
|
||||
{
|
||||
typedef VARIANT ItemType; /* type of the object to be stored in container */
|
||||
typedef ItemType EnumeratorExposedType; /* the type of the item exposed by the enumerator interface */
|
||||
typedef IEnumVARIANT EnumeratorInterface; /* a COM enumerator ( IEnumXXXXX ) interface */
|
||||
typedef _Copy<EnumeratorExposedType> EnumeratorCopyPolicy; /* Copy policy class */
|
||||
typedef CComEnum<EnumeratorInterface,
|
||||
&__uuidof(EnumeratorInterface),
|
||||
EnumeratorExposedType,
|
||||
EnumeratorCopyPolicy > EnumeratorType;
|
||||
|
||||
IEnumVARIANT* pUnk = NULL;
|
||||
CComObject<EnumeratorType>* pEnum = NULL;
|
||||
VariantInit(pvarChildren);
|
||||
pvarChildren->vt = VT_EMPTY;
|
||||
|
||||
nsCOMPtr<nsIAccessibleSelectable> select(do_QueryInterface(mAccessible));
|
||||
if (select) { // do we have an nsIAccessibleSelectable?
|
||||
// we have an accessible that can have children selected
|
||||
nsCOMPtr<nsISupportsArray> 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
|
||||
PRUint32 length;
|
||||
selectedOptions->Count(&length);
|
||||
CComVariant* optionArray = new CComVariant[length]; // needs to be a CComVariant to go into the EnumeratorType object
|
||||
|
||||
// 1) Populate an array to store in the enumeration
|
||||
for (PRUint32 i = 0 ; i < length ; i++) {
|
||||
nsCOMPtr<nsISupports> tempOption;
|
||||
selectedOptions->GetElementAt(i,getter_AddRefs(tempOption)); // this expects an nsISupports
|
||||
if (tempOption) {
|
||||
nsCOMPtr<nsIAccessible> tempAccess(do_QueryInterface(tempOption));
|
||||
if ( tempAccess ) {
|
||||
optionArray[i] = NewAccessible(tempAccess, nsnull, mWnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2) Create and initialize the enumeration
|
||||
HRESULT hr = CComObject<EnumeratorType>::CreateInstance(&pEnum);
|
||||
pEnum->Init(&optionArray[0], &optionArray[length], NULL, AtlFlagCopy);
|
||||
pEnum->QueryInterface(IID_IEnumVARIANT, reinterpret_cast<void**>(&pUnk));
|
||||
delete [] optionArray; // clean up, the Init call copies the data (AtlFlagCopy)
|
||||
|
||||
// 3) Put the enumerator in the VARIANT
|
||||
if (!pUnk)
|
||||
return NS_ERROR_FAILURE;
|
||||
pvarChildren->vt = VT_UNKNOWN; // this must be VT_UNKNOWN for an IEnumVARIANT
|
||||
pvarChildren->punkVal = pUnk;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче