bug 77648 implementing get_AccSelection

r=aaronl sr=brendan
This commit is contained in:
jgaunt%netscape.com 2001-08-06 21:52:01 +00:00
Родитель 079c95cba2
Коммит 151fe68669
2 изменённых файлов: 134 добавлений и 3 удалений

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

@ -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;
}