Bug 365973 - cant expose <listbox> with multiple columns, r=evan.yan, a=mtschrep

This commit is contained in:
surkov.alexander@gmail.com 2008-02-19 01:07:35 -08:00
Родитель f2ed87bab9
Коммит 329e99b306
7 изменённых файлов: 493 добавлений и 21 удалений

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

@ -77,9 +77,10 @@ interface nsIAccessibleProvider : nsISupports
const long XULImage = 0x00001009;
const long XULLink = 0x0000100A;
const long XULListbox = 0x0000100B;
const long XULListitem = 0x0000100C;
const long XULListCell = 0x00001026;
const long XULListHead = 0x00001024;
const long XULListHeader = 0x00001025;
const long XULListitem = 0x0000100C;
const long XULMenubar = 0x0000100D;
const long XULMenuitem = 0x0000100E;
const long XULMenupopup = 0x0000100F;

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

@ -116,6 +116,8 @@ ACCESSIBILITY_ATOM(label, "label")
ACCESSIBILITY_ATOM(legend, "legend")
ACCESSIBILITY_ATOM(li, "li")
ACCESSIBILITY_ATOM(link, "link")
ACCESSIBILITY_ATOM(listhead, "listhead") // XUL
ACCESSIBILITY_ATOM(listheader, "listheader") // XUL
ACCESSIBILITY_ATOM(map, "map")
ACCESSIBILITY_ATOM(math, "math")
ACCESSIBILITY_ATOM(menu, "menu") // XUL

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

@ -1698,6 +1698,9 @@ nsresult nsAccessibilityService::GetAccessibleByType(nsIDOMNode *aNode,
case nsIAccessibleProvider::XULListbox:
*aAccessible = new nsXULListboxAccessible(aNode, weakShell);
break;
case nsIAccessibleProvider::XULListCell:
*aAccessible = new nsXULListCellAccessible(aNode, weakShell);
break;
case nsIAccessibleProvider::XULListHead:
*aAccessible = new nsXULColumnsAccessible(aNode, weakShell);
break;

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

@ -258,7 +258,11 @@ static const char kRoleNames[][20] = {
"calendar", //ROLE_CALENDAR
"combobox list", //ROLE_COMBOBOX_LIST
"combobox option", //ROLE_COMBOBOX_OPTION
"image map" //ROLE_IMAGE_MAP
"image map", //ROLE_IMAGE_MAP
"listbox option", //ROLE_OPTION
"listbox rich option", //ROLE_RICH_OPTION
"listbox" //ROLE_LISTBOX
};
/**

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

@ -144,21 +144,53 @@ nsXULColumnItemAccessible::DoAction(PRUint8 aIndex)
////////////////////////////////////////////////////////////////////////////////
// nsXULListboxAccessible
/** Constructor */
nsXULListboxAccessible::nsXULListboxAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
nsXULSelectableAccessible(aDOMNode, aShell)
nsXULListboxAccessible::
nsXULListboxAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell) :
nsXULSelectableAccessible(aDOMNode, aShell)
{
}
/**
* As a nsXULListboxAccessible we can have the following states:
* nsIAccessibleStates::STATE_FOCUSED
* nsIAccessibleStates::STATE_READONLY
* nsIAccessibleStates::STATE_FOCUSABLE
*/
NS_IMPL_ADDREF_INHERITED(nsXULListboxAccessible, nsXULSelectableAccessible)
NS_IMPL_RELEASE_INHERITED(nsXULListboxAccessible, nsXULSelectableAccessible)
nsresult
nsXULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
nsresult rv = nsXULSelectableAccessible::QueryInterface(aIID, aInstancePtr);
if (*aInstancePtr)
return rv;
if (aIID.Equals(NS_GET_IID(nsIAccessibleTable)) && IsTree()) {
*aInstancePtr = static_cast<nsIAccessibleTable*>(this);
NS_ADDREF_THIS();
return NS_OK;
}
return NS_ERROR_NO_INTERFACE;
}
PRBool
nsXULListboxAccessible::IsTree()
{
PRInt32 numColumns = 0;
nsresult rv = GetColumns(&numColumns);
if (NS_FAILED(rv))
return PR_FALSE;
return numColumns > 1;
}
////////////////////////////////////////////////////////////////////////////////
// nsXULListboxAccessible. nsIAccessible
NS_IMETHODIMP
nsXULListboxAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
{
// As a nsXULListboxAccessible we can have the following states:
// STATE_FOCUSED
// STATE_READONLY
// STATE_FOCUSABLE
// Get focus status from base class
nsresult rv = nsAccessible::GetState(aState, aExtraState);
NS_ENSURE_SUCCESS(rv, rv);
@ -208,15 +240,343 @@ NS_IMETHODIMP nsXULListboxAccessible::GetRole(PRUint32 *aRole)
return NS_OK;
}
}
*aRole = nsIAccessibleRole::ROLE_LIST;
if (IsTree())
*aRole = nsIAccessibleRole::ROLE_TABLE;
else
*aRole = nsIAccessibleRole::ROLE_LISTBOX;
return NS_OK;
}
/** ----- nsXULListitemAccessible ----- */
////////////////////////////////////////////////////////////////////////////////
// nsXULListboxAccessible. nsIAccessibleTable
/** Constructor */
nsXULListitemAccessible::nsXULListitemAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
nsXULMenuitemAccessible(aDOMNode, aShell)
NS_IMETHODIMP
nsXULListboxAccessible::GetCaption(nsIAccessible **aCaption)
{
NS_ENSURE_ARG_POINTER(aCaption);
*aCaption = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetSummary(nsAString &aSummary)
{
aSummary.Truncate();
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetColumns(PRInt32 *aNumColumns)
{
NS_ENSURE_ARG_POINTER(aNumColumns);
*aNumColumns = 0;
if (!mDOMNode)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
nsCOMPtr<nsIContent> headContent;
PRUint32 count = content->GetChildCount();
for (PRUint32 index = 0; index < count; ++index) {
nsCOMPtr<nsIContent> childContent(content->GetChildAt(index));
NS_ENSURE_STATE(childContent);
if (childContent->NodeInfo()->Equals(nsAccessibilityAtoms::listhead,
kNameSpaceID_XUL)) {
headContent = childContent;
}
}
if (!headContent)
return NS_OK;
PRUint32 columnCount = 0;
count = headContent->GetChildCount();
for (PRUint32 index = 0; index < count; ++index) {
nsCOMPtr<nsIContent> childContent(headContent->GetChildAt(index));
NS_ENSURE_STATE(childContent);
if (childContent->NodeInfo()->Equals(nsAccessibilityAtoms::listheader,
kNameSpaceID_XUL)) {
columnCount++;
}
}
*aNumColumns = columnCount;
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetColumnHeader(nsIAccessibleTable **aColumnHeader)
{
NS_ENSURE_ARG_POINTER(aColumnHeader);
*aColumnHeader = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetRows(PRInt32 *aNumRows)
{
NS_ENSURE_ARG_POINTER(aNumRows);
*aNumRows = 0;
if (!mDOMNode)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMXULSelectControlElement> element(do_QueryInterface(mDOMNode));
NS_ENSURE_STATE(element);
PRUint32 itemCount = 0;
nsresult rv = element->GetItemCount(&itemCount);
NS_ENSURE_SUCCESS(rv, rv);
*aNumRows = itemCount;
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetRowHeader(nsIAccessibleTable **aRowHeader)
{
NS_ENSURE_ARG_POINTER(aRowHeader);
*aRowHeader = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::CellRefAt(PRInt32 aRow, PRInt32 aColumn,
nsIAccessible **aAccessibleCell)
{
NS_ENSURE_ARG_POINTER(aAccessibleCell);
*aAccessibleCell = nsnull;
if (IsDefunct())
return NS_OK;
nsCOMPtr<nsIDOMXULSelectControlElement> control =
do_QueryInterface(mDOMNode);
nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
control->GetItemAtIndex(aRow, getter_AddRefs(item));
NS_ENSURE_TRUE(item, NS_ERROR_INVALID_ARG);
nsCOMPtr<nsIAccessible> accessibleRow;
GetAccService()->GetAccessibleInWeakShell(item, mWeakShell,
getter_AddRefs(accessibleRow));
NS_ENSURE_STATE(accessibleRow);
nsresult rv = accessibleRow->GetChildAt(aColumn, aAccessibleCell);
NS_ENSURE_SUCCESS(rv, NS_ERROR_INVALID_ARG);
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetIndexAt(PRInt32 aRow, PRInt32 aColumn,
PRInt32 *aIndex)
{
NS_ENSURE_ARG_POINTER(aIndex);
*aIndex = -1;
PRInt32 rowCount = 0;
nsresult rv = GetRows(&rowCount);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(0 <= aRow && aRow <= rowCount, NS_ERROR_INVALID_ARG);
PRInt32 columnCount = 0;
rv = GetColumns(&columnCount);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(0 <= aColumn && aColumn <= columnCount, NS_ERROR_INVALID_ARG);
*aIndex = aRow * columnCount + aColumn;
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetColumnAtIndex(PRInt32 aIndex, PRInt32 *aColumn)
{
NS_ENSURE_ARG_POINTER(aColumn);
*aColumn = -1;
PRInt32 columnCount = 0;
nsresult rv = GetColumns(&columnCount);
NS_ENSURE_SUCCESS(rv, rv);
*aColumn = aIndex % columnCount;
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetRowAtIndex(PRInt32 aIndex, PRInt32 *aRow)
{
NS_ENSURE_ARG_POINTER(aRow);
*aRow = -1;
PRInt32 columnCount = 0;
nsresult rv = GetColumns(&columnCount);
NS_ENSURE_SUCCESS(rv, rv);
*aRow = aIndex / columnCount;
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetColumnExtentAt(PRInt32 aRow, PRInt32 aColumn,
PRInt32 *aCellSpans)
{
NS_ENSURE_ARG_POINTER(aCellSpans);
*aCellSpans = 1;
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetRowExtentAt(PRInt32 aRow, PRInt32 aColumn,
PRInt32 *aCellSpans)
{
NS_ENSURE_ARG_POINTER(aCellSpans);
*aCellSpans = 1;
return NS_OK;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetColumnDescription(PRInt32 aColumn,
nsAString& aDescription)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetRowDescription(PRInt32 aRow, nsAString& aDescription)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::IsColumnSelected(PRInt32 aColumn, PRBool *aIsSelected)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::IsRowSelected(PRInt32 aRow, PRBool *aIsSelected)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
PRBool *aIsSelected)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetSelectedCellsCount(PRUint32* aCount)
{
NS_ENSURE_ARG_POINTER(aCount);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetSelectedColumnsCount(PRUint32* aCount)
{
NS_ENSURE_ARG_POINTER(aCount);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetSelectedRowsCount(PRUint32* aCount)
{
NS_ENSURE_ARG_POINTER(aCount);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetSelectedCells(PRUint32 *aNumCells, PRInt32 **aCells)
{
NS_ENSURE_ARG_POINTER(aNumCells);
NS_ENSURE_ARG_POINTER(aCells);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetSelectedColumns(PRUint32 *aNumColumns,
PRInt32 **aColumns)
{
NS_ENSURE_ARG_POINTER(aNumColumns);
NS_ENSURE_ARG_POINTER(aColumns);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::GetSelectedRows(PRUint32 *aNumRows, PRInt32 **aRows)
{
NS_ENSURE_ARG_POINTER(aNumRows);
NS_ENSURE_ARG_POINTER(aRows);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::SelectRow(PRInt32 aRow)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::SelectColumn(PRInt32 aColumn)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::UnselectRow(PRInt32 aRow)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::UnselectColumn(PRInt32 aColumn)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULListboxAccessible::IsProbablyForLayout(PRBool *aIsProbablyForLayout)
{
NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
*aIsProbablyForLayout = PR_FALSE;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsXULListitemAccessible
nsXULListitemAccessible::
nsXULListitemAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell) :
nsXULMenuitemAccessible(aDOMNode, aShell)
{
mIsCheckbox = PR_FALSE;
nsCOMPtr<nsIDOMElement> listItem (do_QueryInterface(mDOMNode));
@ -231,6 +591,28 @@ nsXULMenuitemAccessible(aDOMNode, aShell)
/** Inherit the ISupports impl from nsAccessible, we handle nsIAccessibleSelectable */
NS_IMPL_ISUPPORTS_INHERITED0(nsXULListitemAccessible, nsAccessible)
already_AddRefed<nsIAccessible>
nsXULListitemAccessible::GetListAccessible()
{
if (IsDefunct())
return nsnull;
nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
do_QueryInterface(mDOMNode);
nsCOMPtr<nsIDOMXULSelectControlElement> list;
listItem->GetControl(getter_AddRefs(list));
if (!list)
return nsnull;
nsIAccessible *listAcc = nsnull;
GetAccService()->GetAccessibleInWeakShell(list, mWeakShell, &listAcc);
return listAcc;
}
////////////////////////////////////////////////////////////////////////////////
// nsXULListitemAccessible. nsIAccessible
/**
* If there is a Listcell as a child ( not anonymous ) use it, otherwise
* default to getting the name from GetXULName
@ -260,6 +642,14 @@ NS_IMETHODIMP nsXULListitemAccessible::GetName(nsAString& _retval)
*/
NS_IMETHODIMP nsXULListitemAccessible::GetRole(PRUint32 *aRole)
{
nsCOMPtr<nsIAccessible> listAcc = GetListAccessible();
NS_ENSURE_STATE(listAcc);
if (Role(listAcc) == nsIAccessibleRole::ROLE_TABLE) {
*aRole = nsIAccessibleRole::ROLE_ROW;
return NS_OK;
}
if (mIsCheckbox)
*aRole = nsIAccessibleRole::ROLE_CHECKBUTTON;
else if (mParent && Role(mParent) == nsIAccessibleRole::ROLE_COMBOBOX_LIST)
@ -331,6 +721,23 @@ nsXULListitemAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildr
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsXULListCellAccessible
nsXULListCellAccessible::
nsXULListCellAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
nsHyperTextAccessibleWrap(aDOMNode, aShell)
{
}
NS_IMETHODIMP
nsXULListCellAccessible::GetRole(PRUint32 *aRole)
{
NS_ENSURE_ARG_POINTER(aRole);
*aRole = nsIAccessibleRole::ROLE_CELL;
return NS_OK;
}
/** ------------------------------------------------------ */
/** Finally, the Combobox widgets */
/** ------------------------------------------------------ */

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

@ -38,6 +38,8 @@
#ifndef __nsXULSelectAccessible_h__
#define __nsXULSelectAccessible_h__
#include "nsIAccessibleTable.h"
#include "nsCOMPtr.h"
#include "nsXULMenuAccessible.h"
#include "nsBaseWidgetAccessible.h"
@ -101,17 +103,23 @@ public:
/*
* A class the represents the XUL Listbox widget.
*/
class nsXULListboxAccessible : public nsXULSelectableAccessible
class nsXULListboxAccessible : public nsXULSelectableAccessible,
public nsIAccessibleTable
{
public:
nsXULListboxAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
virtual ~nsXULListboxAccessible() {}
/* ----- nsIAccessible ----- */
NS_IMETHOD GetRole(PRUint32 *_retval);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIACCESSIBLETABLE
// nsIAccessible
NS_IMETHOD GetRole(PRUint32 *aRole);
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
NS_IMETHOD GetValue(nsAString& _retval);
NS_IMETHOD GetValue(nsAString& aValue);
protected:
PRBool IsTree();
};
/**
@ -136,10 +144,25 @@ public:
NS_IMETHOD GetDescription(nsAString& aDesc) { return nsAccessibleWrap::GetDescription(aDesc); }
NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
protected:
already_AddRefed<nsIAccessible> GetListAccessible();
private:
PRBool mIsCheckbox;
};
/**
* Class represents xul:listcell.
*/
class nsXULListCellAccessible : public nsHyperTextAccessibleWrap
{
public:
nsXULListCellAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
// nsIAccessible
NS_IMETHOD GetRole(PRUint32 *aRole);
};
/** ------------------------------------------------------ */
/** Finally, the Combobox widgets */
/** ------------------------------------------------------ */

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

@ -1067,6 +1067,38 @@
<xul:label class="listcell-label" xbl:inherits="value=label,flex=flexlabel,crop,disabled" flex="1" crop="right"/>
</children>
</content>
<implementation implements="nsIAccessibleProvider">
<property name="accessibleType" readonly="true">
<getter>
<![CDATA[
// Don't expose xul:listcell as cell accessible until listbox is
// multicolumn.
const Ci = Components.interfaces;
const kNoAccessible = Ci.nsIAccessibleProvider.NoAccessible;
const kListCellAccessible = Ci.nsIAccessibleProvider.XULListCell;
var listitem = this.parentNode;
if (!(listitem instanceof Ci.nsIDOMXULSelectControlItemElement))
return kNoAccessible;
var list = listitem.control;
if (!list)
return kNoAccessible;
var listhead = list.getElementsByTagName("listhead")[0];
if (!listhead)
return kNoAccessible;
var listheaders = listhead.getElementsByTagName("listheader");
if (listheaders.length <= 1)
return kNoAccessible;
return kListCellAccessible;
]]>
</getter>
</property>
</implementation>
</binding>
<binding id="listcell-iconic"