Bug 503727 - Reorganize implementation of XUL tree accessibility, r=marcoz, ginn, sr=neil

This commit is contained in:
Alexander Surkov 2009-08-20 14:45:19 +08:00
parent b61d0f7850
commit 4f036876e8
41 changed files with 4221 additions and 1511 deletions

View File

@ -45,66 +45,15 @@
// --------------------------------------------------------
// nsXULTreeAccessibleWrap Accessible
// --------------------------------------------------------
NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeAccessibleWrap, nsXULTreeAccessible, nsIAccessibleTable)
nsXULTreeAccessibleWrap::nsXULTreeAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
nsXULTreeAccessible(aDOMNode, aShell)
nsXULTreeGridAccessibleWrap::
nsXULTreeGridAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
nsXULTreeGridAccessible(aDOMNode, aShell)
{
}
// tree's children count is row count * col count + treecols count
// override "children count = row count + treecols count" defined in
// nsXULTreeAccessible
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetChildCount(PRInt32 *aAccChildCount)
{
NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
// get treecols count, which is cached by nsAccessibleTreeWalker
// by going through DOM structure of XUL tree
nsAccessible::GetChildCount(aAccChildCount);
if (*aAccChildCount != 0 && *aAccChildCount != eChildCountUninitialized) {
// add the count of table cell (or tree item) accessibles, which are
// created and appended by XUL tree accessible implementation
PRInt32 rowCount, colCount = 1;
mTreeView->GetRowCount(&rowCount);
GetColumns(&colCount);
*aAccChildCount += rowCount * colCount;
}
return NS_OK;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetCaption(nsIAccessible **aCaption)
{
*aCaption = nsnull;
return NS_OK;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetSummary(nsAString &aSummary)
{
aSummary.Truncate();
return NS_OK;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetColumns(PRInt32 *aColumnCount)
{
NS_ENSURE_ARG_POINTER(aColumnCount);
*aColumnCount = 0;
nsCOMPtr<nsITreeColumn> column;
column = GetFirstVisibleColumn(mTree);
if (!column)
return NS_ERROR_FAILURE;
do {
(*aColumnCount)++;
} while ((column = GetNextVisibleColumn(column)));
return NS_OK;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetColumnHeader(nsIAccessibleTable **aColumnHeader)
NS_IMETHODIMP
nsXULTreeGridAccessibleWrap::GetColumnHeader(nsIAccessibleTable **aColumnHeader)
{
nsresult rv = NS_OK;
@ -121,210 +70,8 @@ NS_IMETHODIMP nsXULTreeAccessibleWrap::GetColumnHeader(nsIAccessibleTable **aCol
return rv;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetRows(PRInt32 *aRows)
{
NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
return mTreeView->GetRowCount(aRows);
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetRowHeader(nsIAccessibleTable **aRowHeader)
{
// Row header not supported
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULTreeAccessibleWrap::GetSelectedCellsCount(PRUint32* aCount)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULTreeAccessibleWrap::GetSelectedColumnsCount(PRUint32* aCount)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULTreeAccessibleWrap::GetSelectedRowsCount(PRUint32* aCount)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULTreeAccessibleWrap::GetSelectedCells(PRUint32 *aNumCells,
PRInt32 **aCells)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetSelectedColumns(PRUint32 *aNumColumns, PRInt32 **aColumns)
{
// If all the row has been selected, then all the columns are selected.
// Because we can't select a column alone.
NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
NS_ENSURE_ARG_POINTER(aNumColumns);
nsresult rv = NS_OK;
PRInt32 rows;
rv = GetRows(&rows);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 selectedRows;
rv = GetSelectionCount(&selectedRows);
NS_ENSURE_SUCCESS(rv, rv);
if (rows == selectedRows) {
PRInt32 columns;
rv = GetColumns(&columns);
NS_ENSURE_SUCCESS(rv, rv);
*aNumColumns = columns;
} else {
*aNumColumns = 0;
return rv;
}
PRInt32 *outArray = (PRInt32 *)nsMemory::Alloc((*aNumColumns) * sizeof(PRInt32));
NS_ENSURE_TRUE(outArray, NS_ERROR_OUT_OF_MEMORY);
for (PRUint32 index = 0; index < *aNumColumns; index++) {
outArray[index] = index;
}
*aColumns = outArray;
return rv;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetSelectedRows(PRUint32 *aNumRows, PRInt32 **aRows)
{
NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
NS_ENSURE_ARG_POINTER(aNumRows);
nsresult rv = NS_OK;
rv = GetSelectionCount((PRInt32 *)aNumRows);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 *outArray = (PRInt32 *)nsMemory::Alloc((*aNumRows) * sizeof(PRInt32));
NS_ENSURE_TRUE(outArray, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsITreeView> view;
rv = mTree->GetView(getter_AddRefs(view));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsITreeSelection> selection;
rv = view->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 rowCount;
rv = GetRows(&rowCount);
NS_ENSURE_SUCCESS(rv, rv);
PRBool isSelected;
PRInt32 index, curr = 0;
for (index = 0; index < rowCount; index++) {
selection->IsSelected(index, &isSelected);
if (isSelected) {
outArray[curr++] = index;
}
}
*aRows = outArray;
return rv;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::CellRefAt(PRInt32 aRow, PRInt32 aColumn, nsIAccessible **aAccessibleCell)
{
NS_ENSURE_TRUE(mDOMNode && mTree, NS_ERROR_FAILURE);
nsresult rv = NS_OK;
PRInt32 index;
rv = GetIndexAt(aRow, aColumn, &index);
NS_ENSURE_SUCCESS(rv, rv);
return GetChildAt(index, aAccessibleCell);
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetIndexAt(PRInt32 aRow, PRInt32 aColumn, PRInt32 *aIndex)
{
NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
NS_ENSURE_ARG_POINTER(aIndex);
nsresult rv = NS_OK;
PRInt32 columns;
rv = GetColumns(&columns);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 treeCols;
nsAccessible::GetChildCount(&treeCols);
*aIndex = aRow * columns + aColumn + treeCols;
return NS_OK;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetColumnAtIndex(PRInt32 aIndex, PRInt32 *aColumn)
{
NS_ENSURE_ARG_POINTER(aColumn);
*aColumn = -1;
nsresult rv = NS_OK;
PRInt32 columns;
rv = GetColumns(&columns);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 treeCols;
nsAccessible::GetChildCount(&treeCols);
if (aIndex >= treeCols) {
*aColumn = (aIndex - treeCols) % columns;
}
return NS_OK;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetRowAtIndex(PRInt32 aIndex, PRInt32 *aRow)
{
NS_ENSURE_ARG_POINTER(aRow);
*aRow = -1;
nsresult rv = NS_OK;
PRInt32 columns;
rv = GetColumns(&columns);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 treeCols;
nsAccessible::GetChildCount(&treeCols);
if (aIndex >= treeCols) {
*aRow = (aIndex - treeCols) / columns;
}
return NS_OK;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetColumnExtentAt(PRInt32 aRow, PRInt32 aColumn, PRInt32 *_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
*_retval = 1;
return NS_OK;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetRowExtentAt(PRInt32 aRow, PRInt32 aColumn, PRInt32 *_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
*_retval = 1;
return NS_OK;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetColumnDescription(PRInt32 aColumn, nsAString & _retval)
nsXULTreeGridAccessibleWrap::GetColumnDescription(PRInt32 aColumn, nsAString & _retval)
{
nsCOMPtr<nsIAccessibleTable> columnHeader;
nsresult rv = GetColumnHeader(getter_AddRefs(columnHeader));
@ -334,112 +81,6 @@ NS_IMETHODIMP nsXULTreeAccessibleWrap::GetColumnDescription(PRInt32 aColumn, nsA
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetRowDescription(PRInt32 aRow, nsAString & _retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::IsColumnSelected(PRInt32 aColumn, PRBool *_retval)
{
// If all the row has been selected, then all the columns are selected.
// Because we can't select a column alone.
NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
NS_ENSURE_ARG_POINTER(_retval);
nsresult rv = NS_OK;
PRInt32 rows;
rv = GetRows(&rows);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 selectedRows;
rv = GetSelectionCount(&selectedRows);
NS_ENSURE_SUCCESS(rv, rv);
*_retval = rows == selectedRows;
return rv;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::IsRowSelected(PRInt32 aRow, PRBool *_retval)
{
NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
nsresult rv = NS_OK;
nsCOMPtr<nsITreeView> view;
rv = mTree->GetView(getter_AddRefs(view));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsITreeSelection> selection;
rv = view->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(rv, rv);
return selection->IsSelected(aRow, _retval);
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::IsCellSelected(PRInt32 aRow, PRInt32 aColumn, PRBool *_retval)
{
return IsRowSelected(aRow, _retval);
}
NS_IMETHODIMP
nsXULTreeAccessibleWrap::SelectRow(PRInt32 aRow)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULTreeAccessibleWrap::SelectColumn(PRInt32 aColumn)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULTreeAccessibleWrap::UnselectRow(PRInt32 aRow)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsXULTreeAccessibleWrap::UnselectColumn(PRInt32 aColumn)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState)
{
NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
PRInt32 rowIndex;
nsresult rv = GetRowAtIndex(aIndex, &rowIndex);
nsCOMPtr<nsITreeSelection> selection;
rv = mTreeView->GetSelection(getter_AddRefs(selection));
NS_ASSERTION(selection, "Can't get selection from mTreeView");
if (selection) {
selection->IsSelected(rowIndex, aSelState);
// XXX: Can move to nsXULTreeAccessible if this can be applied to cross-platform
if ((!(*aSelState) && eSelection_Add == aMethod)) {
nsresult rv = selection->Select(rowIndex);
mTree->EnsureRowIsVisible(aIndex);
return rv;
}
// XXX: Will eSelection_Remove happen for XULTree? Leave the original implementation here
if ((*aSelState) && eSelection_Remove == aMethod) {
return selection->ToggleSelect(rowIndex);
}
}
return NS_OK;
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::IsProbablyForLayout(PRBool *aIsProbablyForLayout)
{
*aIsProbablyForLayout = PR_FALSE;
return NS_OK;
}
// --------------------------------------------------------
// nsXULTreeColumnsAccessibleWrap Accessible
// --------------------------------------------------------

View File

@ -40,27 +40,16 @@
#ifndef __nsXULTreeAccessibleWrap_h__
#define __nsXULTreeAccessibleWrap_h__
#include "nsIAccessibleTable.h"
#include "nsXULTreeAccessible.h"
#include "nsXULTreeGridAccessible.h"
typedef class nsXULTreeitemAccessible nsXULTreeitemAccessibleWrap;
class nsXULTreeAccessibleWrap : public nsXULTreeAccessible,
public nsIAccessibleTable
class nsXULTreeGridAccessibleWrap : public nsXULTreeGridAccessible
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIACCESSIBLETABLE
nsXULTreeGridAccessibleWrap(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
nsXULTreeAccessibleWrap(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
virtual ~nsXULTreeAccessibleWrap() {}
// nsIAccessible
NS_IMETHOD GetChildCount(PRInt32 *_retval);
protected:
NS_IMETHOD ChangeSelection(PRInt32 aIndex, PRUint8 aMethod,
PRBool *aSelState);
// nsIAccessibleTable
NS_IMETHOD GetColumnHeader(nsIAccessibleTable **aColumnHeader);
NS_IMETHOD GetColumnDescription(PRInt32 aColumn, nsAString& aDescription);
};
class nsXULTreeColumnsAccessibleWrap : public nsXULTreeColumnsAccessible,
@ -71,7 +60,6 @@ public:
NS_DECL_NSIACCESSIBLETABLE
nsXULTreeColumnsAccessibleWrap(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
virtual ~nsXULTreeColumnsAccessibleWrap() {}
};
#endif

View File

@ -50,7 +50,7 @@
#include "nsAccessibleTreeWalker.h"
#include "nsAccessible.h"
#include "nsARIAMap.h"
#include "nsXULTreeAccessible.h"
#include "nsXULTreeGridAccessible.h"
#include "nsIDOMXULContainerElement.h"
#include "nsIDOMXULSelectCntrlEl.h"
@ -779,16 +779,6 @@ nsAccUtils::QueryAccessibleTree(nsIAccessible *aAccessible)
return accessible;
}
already_AddRefed<nsXULTreeitemAccessible>
nsAccUtils::QueryAccessibleTreeitem(nsIAccessNode *aAccessNode)
{
nsXULTreeitemAccessible* accessible = nsnull;
if (aAccessNode)
CallQueryInterface(aAccessNode, &accessible);
return accessible;
}
#endif
#ifdef DEBUG_A11Y

View File

@ -58,7 +58,6 @@ class nsHTMLTableAccessible;
class nsDocAccessible;
#ifdef MOZ_XUL
class nsXULTreeAccessible;
class nsXULTreeitemAccessible;
#endif
class nsAccUtils
@ -289,6 +288,28 @@ public:
*/
static void GetLiveAttrValue(PRUint32 aRule, nsAString& aValue);
/**
* Query DestinationType from the given SourceType.
*/
template<class DestinationType, class SourceType> static inline
already_AddRefed<DestinationType> QueryObject(SourceType *aObject)
{
DestinationType* object = nsnull;
if (aObject)
CallQueryInterface(aObject, &object);
return object;
}
template<class DestinationType, class SourceType> static inline
already_AddRefed<DestinationType> QueryObject(nsCOMPtr<SourceType>& aObject)
{
DestinationType* object = nsnull;
if (aObject)
CallQueryInterface(aObject, &object);
return object;
}
/**
* Query nsAccessNode from the given nsIAccessible.
*/
@ -364,12 +385,6 @@ public:
*/
static already_AddRefed<nsXULTreeAccessible>
QueryAccessibleTree(nsIAccessible *aAccessible);
/**
* Query nsXULTreeitemAccessible from the given nsIAccessNode.
*/
static already_AddRefed<nsXULTreeitemAccessible>
QueryAccessibleTreeitem(nsIAccessNode *aAccessNode);
#endif
#ifdef DEBUG_A11Y

View File

@ -74,6 +74,18 @@ class nsIDocShellTreeItem;
typedef nsInterfaceHashtable<nsVoidPtrHashKey, nsIAccessNode>
nsAccessNodeHashtable;
// What we want is: NS_INTERFACE_MAP_ENTRY(self) for static IID accessors,
// but some of our classes have an ambiguous base class of nsISupports which
// prevents this from working (the default macro converts it to nsISupports,
// then addrefs it, then returns it). Therefore, we expand the macro here and
// change it so that it works. Yuck.
#define NS_INTERFACE_MAP_STATIC_AMBIGUOUS(_class) \
if (aIID.Equals(NS_GET_IID(_class))) { \
NS_ADDREF(this); \
*aInstancePtr = this; \
return NS_OK; \
} else
#define NS_OK_DEFUNCT_OBJECT \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x22)

View File

@ -1912,8 +1912,7 @@ nsresult nsAccessibilityService::GetAccessibleByType(nsIDOMNode *aNode,
*aAccessible = new nsXULThumbAccessible(aNode, weakShell);
break;
case nsIAccessibleProvider::XULTree:
*aAccessible = new nsXULTreeAccessibleWrap(aNode, weakShell);
break;
return GetAccessibleForXULTree(aNode, weakShell, aAccessible);
case nsIAccessibleProvider::XULTreeColumns:
*aAccessible = new nsXULTreeColumnsAccessibleWrap(aNode, weakShell);
break;
@ -2147,3 +2146,34 @@ nsAccessibilityService::GetAccessibleForDeckChildren(nsIDOMNode *aNode, nsIAcces
return NS_OK;
}
#ifdef MOZ_XUL
nsresult
nsAccessibilityService::GetAccessibleForXULTree(nsIDOMNode *aNode,
nsIWeakReference *aWeakShell,
nsIAccessible **aAccessible)
{
nsCOMPtr<nsITreeBoxObject> treeBoxObj;
nsCoreUtils::GetTreeBoxObject(aNode, getter_AddRefs(treeBoxObj));
if (!treeBoxObj)
return NS_ERROR_FAILURE;
nsCOMPtr<nsITreeColumns> treeColumns;
treeBoxObj->GetColumns(getter_AddRefs(treeColumns));
if (!treeColumns)
return NS_OK;
PRInt32 count = 0;
treeColumns->GetCount(&count);
if (count == 1) // outline of list accessible
*aAccessible = new nsXULTreeAccessible(aNode, aWeakShell);
else // table or tree table accessible
*aAccessible = new nsXULTreeGridAccessibleWrap(aNode, aWeakShell);
if (!*aAccessible)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aAccessible);
return NS_OK;
}
#endif

View File

@ -136,6 +136,15 @@ private:
nsresult GetAccessibleForDeckChildren(nsIDOMNode *aNode,
nsIAccessible **aAccessible);
#ifdef MOZ_XUL
/**
* Create accessible for XUL tree element.
*/
nsresult GetAccessibleForXULTree(nsIDOMNode *aNode,
nsIWeakReference *aWeakShell,
nsIAccessible **aAccessible);
#endif
static nsAccessibilityService *gAccessibilityService;
/**

View File

@ -2700,48 +2700,9 @@ NS_IMETHODIMP nsAccessible::GetNativeInterface(void **aOutAccessible)
return NS_ERROR_NOT_IMPLEMENTED;
}
void nsAccessible::DoCommandCallback(nsITimer *aTimer, void *aClosure)
nsresult
nsAccessible::DoCommand(nsIContent *aContent, PRUint32 aActionIndex)
{
NS_ASSERTION(gDoCommandTimer,
"How did we get here if there was no gDoCommandTimer?");
NS_RELEASE(gDoCommandTimer);
nsCOMPtr<nsIContent> content =
reinterpret_cast<nsIContent*>(aClosure);
nsIDocument *doc = content->GetDocument();
if (!doc)
return;
nsCOMPtr<nsIPresShell> presShell = doc->GetPrimaryShell();
// Scroll into view.
presShell->ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_ANYWHERE,
NS_PRESSHELL_SCROLL_ANYWHERE);
// Fire mouse down and mouse up events.
PRBool res = nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, presShell,
content);
if (!res)
return;
nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_UP, presShell, content);
}
/*
* Use Timer to execute "Click" command of XUL/HTML element (e.g. menuitem, button...).
*
* When "Click" is to open a "modal" dialog/window, it won't return untill the
* dialog/window is closed. If executing "Click" command directly in
* nsXXXAccessible::DoAction, it will block AT-Tools(e.g. GOK) that invoke
* "action" of mozilla accessibles direclty.
*/
nsresult nsAccessible::DoCommand(nsIContent *aContent)
{
nsCOMPtr<nsIContent> content = aContent;
if (!content) {
content = do_QueryInterface(mDOMNode);
}
if (gDoCommandTimer) {
// Already have timer going for another command
NS_WARNING("Doubling up on do command timers doesn't work. This wasn't expected.");
@ -2749,14 +2710,55 @@ nsresult nsAccessible::DoCommand(nsIContent *aContent)
}
nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
if (!timer) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ENSURE_TRUE(timer, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIContent> content = aContent;
if (!content)
content = do_QueryInterface(mDOMNode);
// Command closure object memory will be free in DoCommandCallback().
nsCommandClosure *closure =
new nsCommandClosure(this, content, aActionIndex);
NS_ENSURE_TRUE(closure, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(gDoCommandTimer = timer);
return gDoCommandTimer->InitWithFuncCallback(DoCommandCallback,
(void*)content, 0,
nsITimer::TYPE_ONE_SHOT);
static_cast<void*>(closure),
0, nsITimer::TYPE_ONE_SHOT);
}
void
nsAccessible::DoCommandCallback(nsITimer *aTimer, void *aClosure)
{
NS_ASSERTION(gDoCommandTimer,
"How did we get here if there was no gDoCommandTimer?");
NS_RELEASE(gDoCommandTimer);
nsCommandClosure *closure = static_cast<nsCommandClosure*>(aClosure);
closure->accessible->DispatchClickEvent(closure->content,
closure->actionIndex);
delete closure;
}
void
nsAccessible::DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex)
{
if (IsDefunct())
return;
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
// Scroll into view.
presShell->ScrollContentIntoView(aContent, NS_PRESSHELL_SCROLL_ANYWHERE,
NS_PRESSHELL_SCROLL_ANYWHERE);
// Fire mouse down and mouse up events.
PRBool res = nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, presShell,
aContent);
if (!res)
return;
nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_UP, presShell, aContent);
}
already_AddRefed<nsIAccessible>

View File

@ -338,9 +338,52 @@ protected:
// Hyperlink helpers
virtual nsresult GetLinkOffset(PRInt32* aStartOffset, PRInt32* aEndOffset);
// For accessibles that have actions
//////////////////////////////////////////////////////////////////////////////
// Action helpers
/**
* Used to describe click action target. See DoCommand() method.
*/
struct nsCommandClosure
{
nsCommandClosure(nsAccessible *aAccessible, nsIContent *aContent,
PRUint32 aActionIndex) :
accessible(aAccessible), content(aContent), actionIndex(aActionIndex) {}
nsRefPtr<nsAccessible> accessible;
nsCOMPtr<nsIContent> content;
PRUint32 actionIndex;
};
/**
* Prepares click action that will be invoked in timeout.
*
* @note DoCommand() prepares an action in timeout because when action
* command opens a modal dialog/window, it won't return until the
* dialog/window is closed. If executing action command directly in
* nsIAccessible::DoAction() method, it will block AT tools (e.g. GOK) that
* invoke action of mozilla accessibles direclty (see bug 277888 for details).
*
* @param aContent [in, optional] element to click
* @param aActionIndex [in, optional] index of accessible action
*/
nsresult DoCommand(nsIContent *aContent = nsnull, PRUint32 aActionIndex = 0);
/**
* Dispatch click event to target by calling DispatchClickEvent() method.
*
* @param aTimer [in] timer object
* @param aClosure [in] nsCommandClosure object describing a target.
*/
static void DoCommandCallback(nsITimer *aTimer, void *aClosure);
nsresult DoCommand(nsIContent *aContent = nsnull);
/**
* Dispatch click event.
*/
virtual void DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex);
//////////////////////////////////////////////////////////////////////////////
// Helpers
// Check the visibility across both parent content and chrome
PRBool CheckVisibilityInParentChain(nsIDocument* aDocument, nsIView* aView);

View File

@ -266,8 +266,8 @@ nsAccEvent::GetAccessibleByNode()
if (!accService)
return nsnull;
nsIAccessible *accessible = nsnull;
accService->GetAccessibleFor(mDOMNode, &accessible);
nsCOMPtr<nsIAccessible> accessible;
accService->GetAccessibleFor(mDOMNode, getter_AddRefs(accessible));
#ifdef MOZ_XUL
// hack for xul tree table. We need a better way for firing delayed event
@ -283,18 +283,16 @@ nsAccEvent::GetAccessibleByNode()
PRInt32 treeIndex = -1;
multiSelect->GetCurrentIndex(&treeIndex);
if (treeIndex >= 0) {
nsRefPtr<nsXULTreeAccessible> treeCache =
nsRefPtr<nsXULTreeAccessible> treeAcc =
nsAccUtils::QueryAccessibleTree(accessible);
if (treeCache) {
treeCache->GetCachedTreeitemAccessible(treeIndex, nsnull,
&accessible);
}
if (treeAcc)
treeAcc->GetTreeItemAccessible(treeIndex, getter_AddRefs(accessible));
}
}
}
#endif
return accessible;
return accessible.forget();
}
/* static */

View File

@ -84,6 +84,69 @@ nsCoreUtils::HasListener(nsIContent *aContent, const nsAString& aEventType)
return listenerManager && listenerManager->HasListenersFor(aEventType);
}
void
nsCoreUtils::DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
PRInt32 aRowIndex, nsITreeColumn *aColumn,
const nsCString& aPseudoElt)
{
nsCOMPtr<nsIDOMElement> tcElm;
aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
if (!tcElm)
return;
nsCOMPtr<nsIContent> tcContent(do_QueryInterface(tcElm));
nsIDocument *document = tcContent->GetCurrentDoc();
if (!document)
return;
nsIPresShell *presShell = nsnull;
presShell = document->GetPrimaryShell();
if (!presShell)
return;
// Ensure row is visible.
aTreeBoxObj->EnsureRowIsVisible(aRowIndex);
// Calculate x and y coordinates.
PRInt32 x = 0, y = 0, width = 0, height = 0;
nsresult rv = aTreeBoxObj->GetCoordsForCellItem(aRowIndex, aColumn,
aPseudoElt,
&x, &y, &width, &height);
if (NS_FAILED(rv))
return;
nsCOMPtr<nsIDOMXULElement> tcXULElm(do_QueryInterface(tcElm));
nsCOMPtr<nsIBoxObject> tcBoxObj;
tcXULElm->GetBoxObject(getter_AddRefs(tcBoxObj));
PRInt32 tcX = 0;
tcBoxObj->GetX(&tcX);
PRInt32 tcY = 0;
tcBoxObj->GetY(&tcY);
// Dispatch mouse events.
nsIFrame* tcFrame = presShell->GetPrimaryFrameFor(tcContent);
nsIFrame* rootFrame = presShell->GetRootFrame();
nsPoint offset;
nsIWidget *rootWidget =
rootFrame->GetViewExternal()->GetNearestWidget(&offset);
nsPresContext* presContext = presShell->GetPresContext();
PRInt32 cnvdX = presContext->CSSPixelsToDevPixels(tcX + x + 1) +
presContext->AppUnitsToDevPixels(offset.x);
PRInt32 cnvdY = presContext->CSSPixelsToDevPixels(tcY + y + 1) +
presContext->AppUnitsToDevPixels(offset.y);
DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, cnvdX, cnvdY,
tcContent, tcFrame, presShell, rootWidget);
DispatchMouseEvent(NS_MOUSE_BUTTON_UP, cnvdX, cnvdY,
tcContent, tcFrame, presShell, rootWidget);
}
PRBool
nsCoreUtils::DispatchMouseEvent(PRUint32 aEventType,
nsIPresShell *aPresShell,
@ -109,21 +172,28 @@ nsCoreUtils::DispatchMouseEvent(PRUint32 aEventType,
PRInt32 x = presContext->AppUnitsToDevPixels(point.x + size.width / 2);
PRInt32 y = presContext->AppUnitsToDevPixels(point.y + size.height / 2);
// Fire mouse event.
nsMouseEvent event(PR_TRUE, aEventType, rootWidget,
DispatchMouseEvent(aEventType, x, y, aContent, frame, aPresShell, rootWidget);
return PR_TRUE;
}
void
nsCoreUtils::DispatchMouseEvent(PRUint32 aEventType, PRInt32 aX, PRInt32 aY,
nsIContent *aContent, nsIFrame *aFrame,
nsIPresShell *aPresShell, nsIWidget *aRootWidget)
{
nsMouseEvent event(PR_TRUE, aEventType, aRootWidget,
nsMouseEvent::eReal, nsMouseEvent::eNormal);
event.refPoint = nsIntPoint(x, y);
event.refPoint = nsIntPoint(aX, aY);
event.clickCount = 1;
event.button = nsMouseEvent::eLeftButton;
event.time = PR_IntervalNow();
nsEventStatus status = nsEventStatus_eIgnore;
aPresShell->HandleEventWithTarget(&event, frame, aContent, &status);
return PR_TRUE;
nsEventStatus status = nsEventStatus_eIgnore;
aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
}
PRUint32
@ -891,3 +961,149 @@ nsCoreUtils::GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj)
tcXULElm->GetBoxObject(&boxObj);
return boxObj;
}
void
nsCoreUtils::GetTreeBoxObject(nsIDOMNode *aDOMNode,
nsITreeBoxObject **aBoxObject)
{
nsAutoString name;
nsCOMPtr<nsIDOMNode> parentNode, currentNode;
// Find DOMNode's parents recursively until reach the <tree> tag
currentNode = aDOMNode;
while (currentNode) {
currentNode->GetLocalName(name);
if (name.EqualsLiteral("tree")) {
// We will get the nsITreeBoxObject from the tree node
nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(currentNode));
if (xulElement) {
nsCOMPtr<nsIBoxObject> box;
xulElement->GetBoxObject(getter_AddRefs(box));
nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(box));
if (treeBox) {
*aBoxObject = treeBox;
NS_ADDREF(*aBoxObject);
return;
}
}
}
currentNode->GetParentNode(getter_AddRefs(parentNode));
currentNode = parentNode;
}
*aBoxObject = nsnull;
}
already_AddRefed<nsITreeColumn>
nsCoreUtils::GetFirstSensibleColumn(nsITreeBoxObject *aTree)
{
nsCOMPtr<nsITreeColumns> cols;
aTree->GetColumns(getter_AddRefs(cols));
if (!cols)
return nsnull;
nsCOMPtr<nsITreeColumn> column;
cols->GetFirstColumn(getter_AddRefs(column));
if (column && IsColumnHidden(column))
return GetNextSensibleColumn(column);
return column.forget();
}
already_AddRefed<nsITreeColumn>
nsCoreUtils::GetLastSensibleColumn(nsITreeBoxObject *aTree)
{
nsCOMPtr<nsITreeColumns> cols;
aTree->GetColumns(getter_AddRefs(cols));
if (!cols)
return nsnull;
nsCOMPtr<nsITreeColumn> column;
cols->GetLastColumn(getter_AddRefs(column));
if (column && IsColumnHidden(column))
return GetPreviousSensibleColumn(column);
return column.forget();
}
PRUint32
nsCoreUtils::GetSensibleColumnsCount(nsITreeBoxObject *aTree)
{
PRUint32 count = 0;
nsCOMPtr<nsITreeColumns> cols;
aTree->GetColumns(getter_AddRefs(cols));
if (!cols)
return count;
nsCOMPtr<nsITreeColumn> column;
cols->GetFirstColumn(getter_AddRefs(column));
while (column) {
if (!IsColumnHidden(column))
count++;
nsCOMPtr<nsITreeColumn> nextColumn;
column->GetNext(getter_AddRefs(nextColumn));
column.swap(nextColumn);
}
return count;
}
already_AddRefed<nsITreeColumn>
nsCoreUtils::GetSensibleColumnAt(nsITreeBoxObject *aTree, PRUint32 aIndex)
{
PRUint32 idx = aIndex;
nsCOMPtr<nsITreeColumn> column = GetFirstSensibleColumn(aTree);
while (column) {
if (idx == 0)
return column.forget();
idx--;
column = GetNextSensibleColumn(column);
}
return nsnull;
}
already_AddRefed<nsITreeColumn>
nsCoreUtils::GetNextSensibleColumn(nsITreeColumn *aColumn)
{
nsCOMPtr<nsITreeColumn> nextColumn;
aColumn->GetNext(getter_AddRefs(nextColumn));
while (nextColumn && IsColumnHidden(nextColumn)) {
nsCOMPtr<nsITreeColumn> tempColumn;
nextColumn->GetNext(getter_AddRefs(tempColumn));
nextColumn.swap(tempColumn);
}
return nextColumn.forget();
}
already_AddRefed<nsITreeColumn>
nsCoreUtils::GetPreviousSensibleColumn(nsITreeColumn *aColumn)
{
nsCOMPtr<nsITreeColumn> prevColumn;
aColumn->GetPrevious(getter_AddRefs(prevColumn));
while (prevColumn && IsColumnHidden(prevColumn)) {
nsCOMPtr<nsITreeColumn> tempColumn;
prevColumn->GetPrevious(getter_AddRefs(tempColumn));
prevColumn.swap(tempColumn);
}
return prevColumn.forget();
}
PRBool
nsCoreUtils::IsColumnHidden(nsITreeColumn *aColumn)
{
nsCOMPtr<nsIDOMElement> element;
aColumn->GetElement(getter_AddRefs(element));
nsCOMPtr<nsIContent> content = do_QueryInterface(element);
return content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::hidden,
nsAccessibilityAtoms::_true, eCaseMatters);
}

View File

@ -45,6 +45,7 @@
#include "nsIContent.h"
#include "nsIBoxObject.h"
#include "nsITreeBoxObject.h"
#include "nsITreeColumns.h"
#include "nsIFrame.h"
#include "nsIDocShellTreeItem.h"
@ -62,16 +63,45 @@ public:
static PRBool HasListener(nsIContent *aContent, const nsAString& aEventType);
/**
* Send mouse events to the given element.
* Dispatch click event to XUL tree cell.
*
* @param aEventType an event type (see nsGUIEvent.h for constants)
* @param aPresShell the presshell for the given element
* @param aContent the element element
* @param aTreeBoxObj [in] tree box object
* @param aRowIndex [in] row index
* @param aColumn [in] column object
* @param aPseudoElm [in] pseudo elemenet inside the cell, see
* nsITreeBoxObject for available values
*/
static void DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
PRInt32 aRowIndex, nsITreeColumn *aColumn,
const nsCString& aPseudoElt = EmptyCString());
/**
* Send mouse event to the given element.
*
* @param aEventType [in] an event type (see nsGUIEvent.h for constants)
* @param aPresShell [in] the presshell for the given element
* @param aContent [in] the element
*/
static PRBool DispatchMouseEvent(PRUint32 aEventType,
nsIPresShell *aPresShell,
nsIContent *aContent);
/**
* Send mouse event to the given element.
*
* @param aEventType [in] an event type (see nsGUIEvent.h for constants)
* @param aX [in] x coordinate in dev pixels
* @param aY [in] y coordinate in dev pixels
* @param aContent [in] the element
* @param aFrame [in] frame of the element
* @param aPresShell [in] the presshell for the element
* @param aRootWidget [in] the root widget of the element
*/
static void DispatchMouseEvent(PRUint32 aEventType, PRInt32 aX, PRInt32 aY,
nsIContent *aContent, nsIFrame *aFrame,
nsIPresShell *aPresShell,
nsIWidget *aRootWidget);
/**
* Return an accesskey registered on the given element by
* nsIEventStateManager or 0 if there is no registered accesskey.
@ -362,6 +392,52 @@ public:
static already_AddRefed<nsIBoxObject>
GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj);
/**
* Return tree box object from any levels DOMNode under the XUL tree.
*/
static void
GetTreeBoxObject(nsIDOMNode* aDOMNode, nsITreeBoxObject** aBoxObject);
/**
* Return first sensible column for the given tree box object.
*/
static already_AddRefed<nsITreeColumn>
GetFirstSensibleColumn(nsITreeBoxObject *aTree);
/**
* Return last sensible column for the given tree box object.
*/
static already_AddRefed<nsITreeColumn>
GetLastSensibleColumn(nsITreeBoxObject *aTree);
/**
* Return sensible columns count for the given tree box object.
*/
static PRUint32 GetSensibleColumnsCount(nsITreeBoxObject *aTree);
/**
* Return sensible column at the given index for the given tree box object.
*/
static already_AddRefed<nsITreeColumn>
GetSensibleColumnAt(nsITreeBoxObject *aTree, PRUint32 aIndex);
/**
* Return next sensible column for the given column.
*/
static already_AddRefed<nsITreeColumn>
GetNextSensibleColumn(nsITreeColumn *aColumn);
/**
* Return previous sensible column for the given column.
*/
static already_AddRefed<nsITreeColumn>
GetPreviousSensibleColumn(nsITreeColumn *aColumn);
/**
* Return true if the given column is hidden (i.e. not sensible).
*/
static PRBool IsColumnHidden(nsITreeColumn *aColumn);
/**
* Return true if the given node is table header element.
*/

View File

@ -150,18 +150,6 @@ ElementTraverser(const void *aKey, nsIAccessNode *aAccessNode,
return PL_DHASH_NEXT;
}
// What we want is: NS_INTERFACE_MAP_ENTRY(self) for static IID accessors,
// but some of our classes have an ambiguous base class of nsISupports which
// prevents this from working (the default macro converts it to nsISupports,
// then addrefs it, then returns it). Therefore, we expand the macro here and
// change it so that it works. Yuck.
#define NS_INTERFACE_MAP_STATIC_AMBIGUOUS(_class) \
if (aIID.Equals(NS_GET_IID(_class))) { \
NS_ADDREF(this); \
*aInstancePtr = this; \
return NS_OK; \
} else
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocAccessible)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDocAccessible, nsAccessible)
@ -581,6 +569,17 @@ nsDocAccessible::CacheAccessNode(void *aUniqueID, nsIAccessNode *aAccessNode)
PutCacheEntry(mAccessNodeCache, aUniqueID, aAccessNode);
}
void
nsDocAccessible::RemoveAccessNodeFromCache(nsIAccessNode *aAccessNode)
{
if (!aAccessNode)
return;
void *uniqueID = nsnull;
aAccessNode->GetUniqueID(&uniqueID);
mAccessNodeCache.Remove(uniqueID);
}
NS_IMETHODIMP nsDocAccessible::GetParent(nsIAccessible **aParent)
{
// Hook up our new accessible with our parent

View File

@ -56,11 +56,11 @@ class nsIScrollableView;
const PRUint32 kDefaultCacheSize = 256;
#define NS_DOCACCESSIBLE_IMPL_CID \
{ /* 0ed1be1d-52a7-4bfd-b4f5-0de7caed4617 */ \
0x0ed1be1d, \
0x52a7, \
0x4bfd, \
{ 0xb4, 0xf5, 0x0d, 0xe7, 0xca, 0xed, 0x46, 0x17 } \
{ /* 9735bc5f-a4b6-4668-ab73-6f8434c8e750 */ \
0x9735bc5f, \
0xa4b6, \
0x4668, \
{ 0xab, 0x73, 0x6f, 0x84, 0x34, 0xc8, 0xe7, 0x50 } \
}
class nsDocAccessible : public nsHyperTextAccessibleWrap,
@ -160,6 +160,11 @@ public:
*/
void CacheAccessNode(void *aUniqueID, nsIAccessNode *aAccessNode);
/**
* Remove the given access node from document cache.
*/
void RemoveAccessNodeFromCache(nsIAccessNode *aAccessNode);
/**
* Fires pending events.
*/

View File

@ -736,11 +736,11 @@ nsresult nsRootAccessible::HandleEventWithTarget(nsIDOMEvent* aEvent,
PRInt32 treeIndex = -1;
multiSelect->GetCurrentIndex(&treeIndex);
if (treeIndex >= 0) {
nsRefPtr<nsXULTreeAccessible> treeCache =
nsRefPtr<nsXULTreeAccessible> treeAcc =
nsAccUtils::QueryAccessibleTree(accessible);
if (treeCache) {
treeCache->GetCachedTreeitemAccessible(treeIndex, nsnull,
getter_AddRefs(treeItemAccessible));
if (treeAcc) {
treeAcc->GetTreeItemAccessible(treeIndex,
getter_AddRefs(treeItemAccessible));
if (treeItemAccessible)
accessible = treeItemAccessible;
}

View File

@ -38,9 +38,8 @@
#ifndef __nsXULTreeAccessibleWrap_h__
#define __nsXULTreeAccessibleWrap_h__
#include "nsXULTreeAccessible.h"
typedef class nsXULTreeAccessible nsXULTreeAccessibleWrap;
typedef class nsXULTreeitemAccessible nsXULTreeitemAccessibleWrap;
#include "nsXULTreeGridAccessible.h"
typedef class nsXULTreeGridAccessible nsXULTreeGridAccessibleWrap;
typedef class nsXULTreeColumnsAccessible nsXULTreeColumnsAccessibleWrap;
#endif

View File

@ -1294,6 +1294,15 @@ __try {
"MSAA role map skewed");
*aRole = gWindowsRoleMap[xpRole].ia2Role;
// Special case, if there is a ROLE_ROW inside of a ROLE_TREE_TABLE, then call
// the IA2 role a ROLE_OUTLINEITEM.
if (xpRole == nsIAccessibleRole::ROLE_ROW) {
nsCOMPtr<nsIAccessible> parent = GetParent();
if (nsAccUtils::Role(parent) == nsIAccessibleRole::ROLE_TREE_TABLE)
*aRole = ROLE_SYSTEM_OUTLINEITEM;
}
return S_OK;
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }

View File

@ -20,7 +20,8 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Leventhal
* Aaron Leventhal <aaronleventhal@moonset.net> (original author)
* Alexander Surkov <surkov.alexander@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -38,124 +39,19 @@
#include "nsXULTreeAccessibleWrap.h"
#include "nsTextFormatter.h"
#include "nsIFrame.h"
////////////////////////////////////////////////////////////////////////////////
// nsXULTreeGridAccessibleWrap
////////////////////////////////////////////////////////////////////////////////
// --------------------------------------------------------
// nsXULTreeAccessibleWrap
// --------------------------------------------------------
nsXULTreeAccessibleWrap::nsXULTreeAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
nsXULTreeAccessible(aDOMNode, aShell)
nsXULTreeGridAccessibleWrap::
nsXULTreeGridAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell) :
nsXULTreeGridAccessible(aDOMNode, aShell)
{
}
nsresult
nsXULTreeAccessibleWrap::GetRoleInternal(PRUint32 *aRole)
{
NS_ENSURE_STATE(mTree);
nsCOMPtr<nsITreeColumns> cols;
mTree->GetColumns(getter_AddRefs(cols));
nsCOMPtr<nsITreeColumn> primaryCol;
if (cols) {
cols->GetPrimaryColumn(getter_AddRefs(primaryCol));
}
// No primary column means we're in a list
// In fact, history and mail turn off the primary flag when switching to a flat view
*aRole = primaryCol ? nsIAccessibleRole::ROLE_OUTLINE :
nsIAccessibleRole::ROLE_LIST;
return NS_OK;
}
// --------------------------------------------------------
// nsXULTreeitemAccessibleWrap Accessible
// --------------------------------------------------------
nsXULTreeitemAccessibleWrap::nsXULTreeitemAccessibleWrap(nsIAccessible *aParent,
nsIDOMNode *aDOMNode,
nsIWeakReference *aShell,
PRInt32 aRow,
nsITreeColumn* aColumn) :
nsXULTreeitemAccessible(aParent, aDOMNode, aShell, aRow, aColumn)
{
}
nsresult
nsXULTreeitemAccessibleWrap::GetRoleInternal(PRUint32 *aRole)
{
// No primary column means we're in a list
// In fact, history and mail turn off the primary flag when switching to a flat view
NS_ENSURE_STATE(mColumn);
PRBool isPrimary = PR_FALSE;
mColumn->GetPrimary(&isPrimary);
*aRole = isPrimary ? nsIAccessibleRole::ROLE_OUTLINEITEM :
nsIAccessibleRole::ROLE_LISTITEM;
return NS_OK;
}
NS_IMETHODIMP
nsXULTreeitemAccessibleWrap::GetBounds(PRInt32 *aX, PRInt32 *aY,
PRInt32 *aWidth, PRInt32 *aHeight)
{
NS_ENSURE_ARG_POINTER(aX);
*aX = 0;
NS_ENSURE_ARG_POINTER(aY);
*aY = 0;
NS_ENSURE_ARG_POINTER(aWidth);
*aWidth = 0;
NS_ENSURE_ARG_POINTER(aHeight);
*aHeight = 0;
if (IsDefunct())
return NS_ERROR_FAILURE;
// Get x coordinate and width from treechildren element, get y coordinate and
// height from tree cell.
nsCOMPtr<nsIBoxObject> boxObj = nsCoreUtils::GetTreeBodyBoxObject(mTree);
NS_ENSURE_STATE(boxObj);
PRInt32 cellStartX, cellWidth;
nsresult rv = mTree->GetCoordsForCellItem(mRow, mColumn, EmptyCString(),
&cellStartX, aY,
&cellWidth, aHeight);
NS_ENSURE_SUCCESS(rv, rv);
boxObj->GetWidth(aWidth);
PRInt32 tcX = 0, tcY = 0;
boxObj->GetScreenX(&tcX);
boxObj->GetScreenY(&tcY);
*aX = tcX;
*aY += tcY;
return NS_OK;
}
NS_IMETHODIMP
nsXULTreeitemAccessibleWrap::GetName(nsAString& aName)
{
NS_ENSURE_STATE(mTree);
nsCOMPtr<nsITreeColumns> cols;
mTree->GetColumns(getter_AddRefs(cols));
if (!cols) {
return NS_OK;
}
nsCOMPtr<nsITreeColumn> column;
cols->GetFirstColumn(getter_AddRefs(column));
while (column) {
nsAutoString colText;
mTreeView->GetCellText(mRow, column, colText);
aName += colText + NS_LITERAL_STRING(" ");
nsCOMPtr<nsITreeColumn> nextColumn;
column->GetNext(getter_AddRefs(nextColumn));
column = nextColumn;
}
return NS_OK;
}
NS_IMPL_ISUPPORTS_INHERITED0(nsXULTreeGridAccessibleWrap,
nsXULTreeGridAccessible)
IMPL_IUNKNOWN_INHERITED1(nsXULTreeGridAccessibleWrap,
nsAccessibleWrap,
CAccessibleTable);

View File

@ -20,7 +20,8 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Pete Zha (pete.zha@sun.com)
* Pete Zha <pete.zha@sun.com> (original author)
* Alexander Surkov <surkov.alexander@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -39,33 +40,28 @@
#ifndef __nsXULTreeAccessibleWrap_h__
#define __nsXULTreeAccessibleWrap_h__
#include "nsXULTreeAccessible.h"
#include "nsXULTreeGridAccessible.h"
#include "CAccessibleTable.h"
typedef class nsXULTreeColumnsAccessible nsXULTreeColumnsAccessibleWrap;
class nsXULTreeAccessibleWrap : public nsXULTreeAccessible
/**
* IA2 wrapper of nsXULTreeGridAccessible class, implements IAccessibleTable
* interface.
*/
class nsXULTreeGridAccessibleWrap : public nsXULTreeGridAccessible,
public CAccessibleTable
{
public:
nsXULTreeAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell);
virtual ~nsXULTreeAccessibleWrap() {}
nsXULTreeGridAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell);
virtual ~nsXULTreeGridAccessibleWrap() {}
// nsAccessible
virtual nsresult GetRoleInternal(PRUint32 *aRole);
};
// IUnknown
DECL_IUNKNOWN_INHERITED
class nsXULTreeitemAccessibleWrap : public nsXULTreeitemAccessible
{
public:
nsXULTreeitemAccessibleWrap(nsIAccessible *aParent, nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
PRInt32 aRow, nsITreeColumn* aColumn);
virtual ~nsXULTreeitemAccessibleWrap() {}
// nsIAccessible
NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
NS_IMETHOD GetName(nsAString &aName);
// nsAccessible
virtual nsresult GetRoleInternal(PRUint32 *aRole);
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
};
#endif

View File

@ -38,9 +38,8 @@
#ifndef __nsXULTreeAccessibleWrap_h__
#define __nsXULTreeAccessibleWrap_h__
#include "nsXULTreeAccessible.h"
typedef class nsXULTreeAccessible nsXULTreeAccessibleWrap;
typedef class nsXULTreeitemAccessible nsXULTreeitemAccessibleWrap;
#include "nsXULTreeGridAccessible.h"
typedef class nsXULTreeGridAccessible nsXULTreeGridAccessibleWrap;
typedef class nsXULTreeColumnsAccessible nsXULTreeColumnsAccessibleWrap;
#endif

View File

@ -77,6 +77,7 @@ CPPSRCS = \
nsXULTabAccessible.cpp \
nsXULTextAccessible.cpp \
nsXULTreeAccessible.cpp \
nsXULTreeGridAccessible.cpp \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.

File diff suppressed because it is too large Load Diff

View File

@ -65,22 +65,25 @@ class nsXULTreeAccessible : public nsXULSelectableAccessible
{
public:
nsXULTreeAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
virtual ~nsXULTreeAccessible() {}
// nsISupports
// nsISupports and cycle collection
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeAccessible,
nsAccessible)
// nsIAccessible
NS_IMETHOD GetValue(nsAString& aValue);
NS_IMETHOD GetFirstChild(nsIAccessible **aFirstChild);
NS_IMETHOD GetLastChild(nsIAccessible **aLastChild);
NS_IMETHOD GetChildCount(PRInt32 *aChildCount);
NS_IMETHOD GetChildAt(PRInt32 aChildIndex, nsIAccessible **aChild);
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
// nsIAccessibleSelectable
NS_DECL_NSIACCESSIBLESELECTABLE
// nsIAccessible
NS_IMETHOD GetValue(nsAString& _retval);
NS_IMETHOD GetFirstChild(nsIAccessible **_retval);
NS_IMETHOD GetLastChild(nsIAccessible **_retval);
NS_IMETHOD GetChildCount(PRInt32 *_retval);
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
// nsAccessNode
virtual PRBool IsDefunct();
virtual nsresult Shutdown();
@ -97,16 +100,13 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEACCESSIBLE_IMPL_CID)
/**
* Return tree item accessible at the givem row and column. If accessible
* doesn't exist in the cache then create it.
* Return tree item accessible at the givem row. If accessible doesn't exist
* in the cache then create and cache it.
*
* @param aRow [in] the given row index
* @param aColumn [in] the given column object. If is is nsnull then
* primary column is used
* @param aAccessible [out] tree item accessible
*/
void GetCachedTreeitemAccessible(PRInt32 aRow, nsITreeColumn *aColumn,
nsIAccessible **aAccessible);
void GetTreeItemAccessible(PRInt32 aRow, nsIAccessible **aAccessible);
/**
* Invalidates the number of cached treeitem accessibles.
@ -135,18 +135,16 @@ public:
*/
void TreeViewChanged();
static void GetTreeBoxObject(nsIDOMNode* aDOMNode, nsITreeBoxObject** aBoxObject);
static nsresult GetColumnCount(nsITreeBoxObject* aBoxObject, PRInt32 *aCount);
static PRBool IsColumnHidden(nsITreeColumn *aColumn);
static already_AddRefed<nsITreeColumn> GetNextVisibleColumn(nsITreeColumn *aColumn);
static already_AddRefed<nsITreeColumn> GetFirstVisibleColumn(nsITreeBoxObject *aTree);
static already_AddRefed<nsITreeColumn> GetLastVisibleColumn(nsITreeBoxObject *aTree);
protected:
/**
* Creates tree item accessible for the given row index.
*/
virtual void CreateTreeItemAccessible(PRInt32 aRowIndex,
nsAccessNode** aAccessNode);
nsCOMPtr<nsITreeBoxObject> mTree;
nsCOMPtr<nsITreeView> mTreeView;
nsAccessNodeHashtable *mAccessNodeCache;
nsAccessNodeHashtable mAccessNodeCache;
NS_IMETHOD ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState);
};
@ -155,47 +153,112 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsXULTreeAccessible,
NS_XULTREEACCESSIBLE_IMPL_CID)
/**
* Accessible class for items for XUL tree.
* Base class for tree item accessibles.
*/
#define NS_XULTREEITEMACCESSIBLE_IMPL_CID \
{ /* 7b1aa039-7270-4523-aeb3-61063a13ac3f */ \
0x7b1aa039, \
0x7270, \
0x4523, \
{ 0xae, 0xb3, 0x61, 0x06, 0x3a, 0x13, 0xac, 0x3f } \
#define NS_XULTREEITEMBASEACCESSIBLE_IMPL_CID \
{ /* 1ab79ae7-766a-443c-940b-b1e6b0831dfc */ \
0x1ab79ae7, \
0x766a, \
0x443c, \
{ 0x94, 0x0b, 0xb1, 0xe6, 0xb0, 0x83, 0x1d, 0xfc } \
}
class nsXULTreeitemAccessible : public nsLeafAccessible
class nsXULTreeItemAccessibleBase : public nsAccessibleWrap
{
public:
enum { eAction_Click = 0, eAction_Expand = 1 };
nsXULTreeitemAccessible(nsIAccessible *aParent, nsIDOMNode *aDOMNode, nsIWeakReference *aShell, PRInt32 aRow, nsITreeColumn* aColumn = nsnull);
virtual ~nsXULTreeitemAccessible() {}
nsXULTreeItemAccessibleBase(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
nsIAccessible *aParent, nsITreeBoxObject *aTree,
nsITreeView *aTreeView, PRInt32 aRow);
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIAccessNode
NS_IMETHOD GetUniqueID(void **aUniqueID);
// nsIAccessible
NS_IMETHOD GetName(nsAString& aName);
NS_IMETHOD GetNumActions(PRUint8 *_retval);
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
NS_IMETHOD GetParent(nsIAccessible **aParent);
NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
NS_IMETHOD GetPreviousSibling(nsIAccessible **aPreviousSibling);
NS_IMETHOD GetParent(nsIAccessible **_retval);
NS_IMETHOD GetNextSibling(nsIAccessible **_retval);
NS_IMETHOD GetPreviousSibling(nsIAccessible **_retval);
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
NS_IMETHOD GetBounds(PRInt32 *aX, PRInt32 *aY,
PRInt32 *aWidth, PRInt32 *aHeight);
NS_IMETHOD DoAction(PRUint8 index);
NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
NS_IMETHOD SetSelected(PRBool aSelect);
NS_IMETHOD TakeFocus(void);
NS_IMETHOD TakeFocus();
NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
nsIAccessibleRelation **aRelation);
// nsIAccessNode
NS_IMETHOD GetUniqueID(void **aUniqueID);
NS_IMETHOD GetNumActions(PRUint8 *aCount);
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
NS_IMETHOD DoAction(PRUint8 aIndex);
// nsAccessNode
virtual PRBool IsDefunct();
virtual nsresult Shutdown();
// nsAccessible
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
// nsXULTreeItemAccessibleBase
NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEITEMBASEACCESSIBLE_IMPL_CID)
/**
* Return cell accessible for the given column. If XUL tree accessible is not
* accessible table then return null.
*/
virtual void GetCellAccessible(nsITreeColumn *aColumn,
nsIAccessible **aCellAcc)
{ *aCellAcc = nsnull; }
/**
* Proccess row invalidation. Used to fires name change events.
*/
virtual void RowInvalidated(PRInt32 aStartColIdx, PRInt32 aEndColIdx) = 0;
protected:
enum { eAction_Click = 0, eAction_Expand = 1 };
// nsAccessible
virtual void DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex);
// nsXULTreeItemAccessibleBase
/**
* Return true if the tree item accessible is expandable (contains subrows).
*/
PRBool IsExpandable();
nsCOMPtr<nsITreeBoxObject> mTree;
nsCOMPtr<nsITreeView> mTreeView;
PRInt32 mRow;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsXULTreeItemAccessibleBase,
NS_XULTREEITEMBASEACCESSIBLE_IMPL_CID)
/**
* Accessible class for items for XUL tree.
*/
class nsXULTreeItemAccessible : public nsXULTreeItemAccessibleBase
{
public:
nsXULTreeItemAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
nsIAccessible *aParent, nsITreeBoxObject *aTree,
nsITreeView *aTreeView, PRInt32 aRow);
// nsIAccessible
NS_IMETHOD GetFirstChild(nsIAccessible **aFirstChild);
NS_IMETHOD GetLastChild(nsIAccessible **aLastChild);
NS_IMETHOD GetChildCount(PRInt32 *aChildCount);
NS_IMETHOD GetName(nsAString& aName);
// nsAccessNode
virtual PRBool IsDefunct();
@ -203,30 +266,16 @@ public:
virtual nsresult Shutdown();
// nsAccessible
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
// nsXULTreeitemAccessible
NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEITEMACCESSIBLE_IMPL_CID)
/**
* Get/set cached name.
*/
void GetCachedName(nsAString& aName);
void SetCachedName(const nsAString& aName);
// nsXULTreeItemAccessibleBase
virtual void RowInvalidated(PRInt32 aStartColIdx, PRInt32 aEndColIdx);
protected:
PRBool IsExpandable();
nsCOMPtr<nsITreeBoxObject> mTree;
nsCOMPtr<nsITreeView> mTreeView;
PRInt32 mRow;
nsCOMPtr<nsITreeColumn> mColumn;
nsString mCachedName;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsXULTreeitemAccessible,
NS_XULTREEITEMACCESSIBLE_IMPL_CID)
/**
* Accessible class for columns element of XUL tree.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,203 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __nsXULTreeGridAccessible_h__
#define __nsXULTreeGridAccessible_h__
#include "nsIAccessibleTable.h"
#include "nsXULTreeAccessible.h"
/**
* Represents accessible for XUL tree in the case when it has multiple columns.
*/
class nsXULTreeGridAccessible : public nsXULTreeAccessible,
public nsIAccessibleTable
{
public:
nsXULTreeGridAccessible(nsIDOMNode *aDOMNode,
nsIWeakReference *aShell);
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIAccessibleTable
NS_DECL_NSIACCESSIBLETABLE
// nsAccessible
virtual nsresult GetRoleInternal(PRUint32 *aRole);
protected:
// nsXULTreeAccessible
virtual void CreateTreeItemAccessible(PRInt32 aRow,
nsAccessNode** aAccessNode);
};
/**
* Represents accessible for XUL tree item in the case when XUL tree has
* multiple columns.
*/
class nsXULTreeGridRowAccessible : public nsXULTreeItemAccessibleBase
{
public:
nsXULTreeGridRowAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
nsIAccessible *aParent, nsITreeBoxObject *aTree,
nsITreeView *aTreeView, PRInt32 aRow);
// nsISupports and cycle collection
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeGridRowAccessible,
nsAccessible)
// nsIAccessible
NS_IMETHOD GetFirstChild(nsIAccessible **aFirstChild);
NS_IMETHOD GetLastChild(nsIAccessible **aLastChild);
NS_IMETHOD GetChildCount(PRInt32 *aChildCount);
NS_IMETHOD GetChildAt(PRInt32 aChildIndex, nsIAccessible **aChild);
// nsAccessNode
virtual nsresult Shutdown();
// nsAccessible
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetChildAtPoint(PRInt32 aX, PRInt32 aY,
PRBool aDeepestChild,
nsIAccessible **aChild);
// nsXULTreeItemAccessibleBase
virtual void GetCellAccessible(nsITreeColumn *aColumn, nsIAccessible **aCell);
virtual void RowInvalidated(PRInt32 aStartColIdx, PRInt32 aEndColIdx);
protected:
nsAccessNodeHashtable mAccessNodeCache;
};
/**
* Represents an accessible for XUL tree cell in the case when XUL tree has
* multiple columns.
*/
#define NS_XULTREEGRIDCELLACCESSIBLE_IMPL_CID \
{ /* 84588ad4-549c-4196-a932-4c5ca5de5dff */ \
0x84588ad4, \
0x549c, \
0x4196, \
{ 0xa9, 0x32, 0x4c, 0x5c, 0xa5, 0xde, 0x5d, 0xff } \
}
class nsXULTreeGridCellAccessible : public nsLeafAccessible
{
public:
nsXULTreeGridCellAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
nsXULTreeGridRowAccessible *aRowAcc,
nsITreeBoxObject *aTree, nsITreeView *aTreeView,
PRInt32 aRow, nsITreeColumn* aColumn);
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIAccessNode
NS_IMETHOD GetUniqueID(void **aUniqueID);
// nsIAccessible
NS_IMETHOD GetParent(nsIAccessible **aParent);
NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
NS_IMETHOD GetPreviousSibling(nsIAccessible **aPrevSibling);
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
NS_IMETHOD GetName(nsAString& aName);
NS_IMETHOD GetBounds(PRInt32 *aX, PRInt32 *aY,
PRInt32 *aWidth, PRInt32 *aHeight);
NS_IMETHOD GetNumActions(PRUint8 *aCount);
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
NS_IMETHOD DoAction(PRUint8 aIndex);
// nsAccessNode
virtual PRBool IsDefunct();
virtual nsresult Init();
// nsAccessible
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
// nsXULTreeGridCellAccessible
NS_DECLARE_STATIC_IID_ACCESSOR(NS_XULTREEGRIDCELLACCESSIBLE_IMPL_CID)
/**
* Return index of the column.
*/
PRInt32 GetColumnIndex() const;
/**
* Fire name or state change event if the accessible text or value has been
* changed.
*/
void CellInvalidated();
protected:
// nsAccessible
virtual void DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex);
// nsXULTreeGridCellAccessible
/**
* Return true if value of cell can be modified.
*/
PRBool IsEditable() const;
enum { eAction_Click = 0 };
nsCOMPtr<nsITreeBoxObject> mTree;
nsCOMPtr<nsITreeView> mTreeView;
PRInt32 mRow;
nsCOMPtr<nsITreeColumn> mColumn;
nsString mCachedTextEquiv;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsXULTreeGridCellAccessible,
NS_XULTREEGRIDCELLACCESSIBLE_IMPL_CID)
#endif

View File

@ -68,9 +68,11 @@ _TEST_FILES =\
table.js \
value.js \
test_accessnode_invalidation.html \
test_actions.xul \
test_actions_aria.html \
test_actions_inputs.html \
test_actions.xul \
test_actions_tree.xul \
test_actions_treegrid.xul \
test_aria_activedescendant.html \
test_aria_role_article.html \
test_aria_role_equation.html \
@ -78,6 +80,7 @@ _TEST_FILES =\
test_aria_roles.html \
test_aria_roles.xul \
test_aria_token_attrs.html \
test_attrs_elm_tree.xul \
test_bug420863.html \
$(warning test_childAtPoint.html temporarily disabled) \
$(warning test_childAtPoint.xul temporarily disabled) \
@ -86,6 +89,7 @@ _TEST_FILES =\
test_elm_filectrl.html \
$(warning test_elm_media.html temporarily disabled) \
test_elm_table.html \
test_elm_tree.xul \
test_elm_txtcntnr.html \
test_events_caretmove.html \
test_events_doc.html \
@ -117,6 +121,7 @@ _TEST_FILES =\
test_relations.html \
test_relations.xul \
test_relations_table.html \
test_relations_tree.xul \
test_role_nsHyperTextAcc.html \
test_role_table_cells.html \
test_states.html \
@ -124,19 +129,23 @@ _TEST_FILES =\
test_states_doc.html \
test_states_docarticle.html \
test_states_frames.html \
test_states_tree.xul \
test_table_1.html \
test_table_2.html \
test_table_4.html \
test_table_indexes.html \
test_table_indexes_ariagrid.html \
test_table_indexes_tree.xul \
test_table_layoutguess.html \
test_table_sels.html \
test_table_sels_ariagrid.html \
test_table_sels_tree.xul \
test_textattrs.html \
test_textboxes.html \
test_textboxes.xul \
test_value.xul \
testTextboxes.js \
treeview.css \
treeview.js \
z_states_frame.html \
z_states_framearticle.html \

View File

@ -18,14 +18,25 @@ const ALL_EVENTS = CLICK_EVENTS | COMMAND_EVENT;
* Action tester interface is:
*
* var actionObj = {
* // identifier of accessible
* // identifier of accessible to perform an action on
* get ID() {},
*
* // name of default action
* // index of the action
* get actionIndex() {},
*
* // name of the action
* get actionName() {},
*
* // event constant defined above
* get events() {}
* // DOM events (see constants defined above)
* get events() {},
*
* // [optional] identifier of target DOM events listeners are registered on,
* // used with 'events', if missing then 'ID' is used instead.
* get targetID() {},
*
* // [optional] perform checks when 'click' event is handled if 'events'
* // is used.
* checkOnClickEvent: function() {},
*
* // [optional] an array of invoker's checker objects (see eventQueue
* // constructor events.js)
@ -43,13 +54,15 @@ function testActions(aArray)
var actionObj = aArray[idx];
var accOrElmOrID = actionObj.ID;
var actionIndex = actionObj.actionIndex;
var actionName = actionObj.actionName;
var events = actionObj.events;
var accOrElmOrIDOfTarget = actionObj.targetID ?
actionObj.targetID : accOrElmOrID;
var eventSeq = new Array();
if (events) {
var elm = getNode(accOrElmOrID);
//alert(elm.QueryInterface(Components.interfaces.nsIDOMNode));
var elm = getNode(accOrElmOrIDOfTarget);
if (events & MOUSEDOWN_EVENT)
eventSeq.push(new checkerOfActionInvoker("mousedown", elm));
@ -66,7 +79,8 @@ function testActions(aArray)
if (actionObj.eventSeq)
eventSeq = eventSeq.concat(actionObj.eventSeq);
var invoker = new actionInvoker(accOrElmOrID, actionName, eventSeq);
var invoker = new actionInvoker(accOrElmOrID, actionIndex, actionName,
eventSeq);
gActionsQueue.push(invoker);
}
@ -78,7 +92,7 @@ function testActions(aArray)
var gActionsQueue = null;
function actionInvoker(aAccOrElmOrId, aActionName, aEventSeq)
function actionInvoker(aAccOrElmOrId, aActionIndex, aActionName, aEventSeq)
{
this.invoke = function actionInvoker_invoke()
{
@ -93,14 +107,14 @@ function actionInvoker(aAccOrElmOrId, aActionName, aEventSeq)
if (!isThereActions)
return INVOKER_ACTION_FAILED;
is(acc.getActionName(0), aActionName,
is(acc.getActionName(aActionIndex), aActionName,
"Wrong action name of the accessible for " + prettyName(aAccOrElmOrId));
try {
acc.doAction(0);
acc.doAction(aActionIndex);
}
catch (e){
ok(false, "doAction(0) failed with: " + e.name);
ok(false, "doAction(" + aActionIndex + ") failed with: " + e.name);
return INVOKER_ACTION_FAILED;
}
}
@ -114,6 +128,8 @@ function checkerOfActionInvoker(aType, aTarget, aActionObj)
this.target = aTarget;
this.phase = false;
this.getID = function getID()
{
return aType + " event handling";
@ -121,7 +137,7 @@ function checkerOfActionInvoker(aType, aTarget, aActionObj)
this.check = function check(aEvent)
{
if (aActionObj && "check" in aActionObj)
aActionObj.check(aEvent);
if (aActionObj && "checkOnClickEvent" in aActionObj)
aActionObj.checkOnClickEvent(aEvent);
}
}

View File

@ -179,11 +179,11 @@ function testAttrsInternal(aAccOrElmOrID, aAttrs, aSkipUnexpectedAttrs,
} catch (e) { }
if (!attrs) {
ok(false, "Can't get object attributes for " + aAccOrElmOrID);
ok(false, "Can't get object attributes for " + prettyName(aAccOrElmOrID));
return;
}
var errorMsg = " for " + aAccOrElmOrID;
var errorMsg = " for " + prettyName(aAccOrElmOrID);
compareAttrs(errorMsg, attrs, aAttrs, aSkipUnexpectedAttrs, aAbsentAttrs);
}
@ -199,7 +199,7 @@ function compareAttrs(aErrorMsg, aAttrs, aExpectedAttrs, aSkipUnexpectedAttrs,
ok(false, "Unexpected attribute '" + prop.key + "' having '" +
prop.value + "'" + aErrorMsg);
} else {
var msg = "Attribute '" + prop.key + " 'has wrong value" + aErrorMsg;
var msg = "Attribute '" + prop.key + "' has wrong value" + aErrorMsg;
var expectedValue = aExpectedAttrs[prop.key];
if (typeof expectedValue == "function")

View File

@ -6,6 +6,7 @@ const EVENT_DOCUMENT_LOAD_COMPLETE =
const EVENT_DOM_DESTROY = nsIAccessibleEvent.EVENT_DOM_DESTROY;
const EVENT_FOCUS = nsIAccessibleEvent.EVENT_FOCUS;
const EVENT_NAME_CHANGE = nsIAccessibleEvent.EVENT_NAME_CHANGE;
const EVENT_STATE_CHANGE = nsIAccessibleEvent.EVENT_STATE_CHANGE;
const EVENT_REORDER = nsIAccessibleEvent.EVENT_REORDER;
////////////////////////////////////////////////////////////////////////////////
@ -133,6 +134,7 @@ function invokerChecker(aEventType, aTarget)
* // var checker = {
* // type getter: function() {}, // DOM or a11y event type
* // target getter: function() {}, // DOM node or accessible
* // phase getter: function() {}, // DOM event phase (false - bubbling)
* // check: function(aEvent) {},
* // getID: function() {}
* // };
@ -281,26 +283,10 @@ function eventQueue(aEventType)
// We wait for events in order specified by eventSeq variable.
var idx = this.mEventSeqIdx + 1;
if (gA11yEventDumpID) { // debug stuff
var matched = this.compareEvents(idx, aEvent);
this.dumpEventToDOM(aEvent, idx, matched);
if (aEvent instanceof nsIDOMEvent) {
var info = "Event type: " + aEvent.type;
info += ". Target: " + prettyName(aEvent.originalTarget);
dumpInfoToDOM(info);
}
var currType = this.getEventType(idx);
var currTarget = this.getEventTarget(idx);
var info = "Event queue processing. Expected event type: ";
info += (typeof currType == "string") ?
currType : eventTypeToString(currType);
info += ". Target: " + prettyName(currTarget);
dumpInfoToDOM(info);
}
if (this.compareEvents(idx, aEvent)) {
if (matched) {
this.checkEvent(idx, aEvent);
invoker.wasCaught[idx] = true;
@ -341,7 +327,7 @@ function eventQueue(aEventType)
for (var idx = 0; idx < this.mEventSeq.length; idx++) {
var eventType = this.getEventType(idx);
if (typeof eventType == "string") // DOM event
document.addEventListener(eventType, this, true);
document.addEventListener(eventType, this, this.getEventPhase(idx));
else // A11y event
addA11yEventListener(eventType, this);
}
@ -354,7 +340,7 @@ function eventQueue(aEventType)
for (var idx = 0; idx < this.mEventSeq.length; idx++) {
var eventType = this.getEventType(idx);
if (typeof eventType == "string") // DOM event
document.removeEventListener(eventType, this, true);
document.removeEventListener(eventType, this, this.getEventPhase(idx));
else // A11y event
removeA11yEventListener(eventType, this);
}
@ -373,6 +359,15 @@ function eventQueue(aEventType)
return this.mEventSeq[aIdx].target;
}
this.getEventPhase = function eventQueue_getEventPhase(aIdx)
{
var eventItem = this.mEventSeq[aIdx];
if ("phase" in eventItem)
return eventItem.phase;
return true;
}
this.compareEvents = function eventQueue_compareEvents(aIdx, aEvent)
{
var eventType1 = this.getEventType(aIdx);
@ -419,6 +414,32 @@ function eventQueue(aEventType)
return invoker.getID();
}
this.dumpEventToDOM = function eventQueue_dumpEventToDOM(aOrigEvent,
aExpectedEventIdx,
aMatch)
{
if (!gA11yEventDumpID) // debug stuff
return;
// Dump DOM event information. Skip a11y event since it is dumped by
// gA11yEventObserver.
if (aOrigEvent instanceof nsIDOMEvent) {
var info = "Event type: " + aOrigEvent.type;
info += ". Target: " + prettyName(aOrigEvent.originalTarget);
dumpInfoToDOM(info);
}
var currType = this.getEventType(aExpectedEventIdx);
var currTarget = this.getEventTarget(aExpectedEventIdx);
var info = "EQ: " + (aMatch ? "matched" : "expected") + " event, type: ";
info += (typeof currType == "string") ?
currType : eventTypeToString(currType);
info += ". Target: " + prettyName(currTarget);
dumpInfoToDOM(info);
}
this.mDefEventType = aEventType;
this.mInvokers = new Array();

View File

@ -24,8 +24,11 @@ const ROLE_LABEL = nsIAccessibleRole.ROLE_LABEL;
const ROLE_LINK = nsIAccessibleRole.ROLE_LINK;
const ROLE_LIST = nsIAccessibleRole.ROLE_LIST;
const ROLE_LISTBOX = nsIAccessibleRole.ROLE_LISTBOX;
const ROLE_LISTITEM = nsIAccessibleRole.ROLE_LISTITEM;
const ROLE_NOTHING = nsIAccessibleRole.ROLE_NOTHING;
const ROLE_OPTION = nsIAccessibleRole.ROLE_OPTION;
const ROLE_OUTLINE = nsIAccessibleRole.ROLE_OUTLINE;
const ROLE_OUTLINEITEM = nsIAccessibleRole.ROLE_OUTLINEITEM;
const ROLE_PARAGRAPH = nsIAccessibleRole.ROLE_PARAGRAPH;
const ROLE_PASSWORD_TEXT = nsIAccessibleRole.ROLE_PASSWORD_TEXT;
const ROLE_PROGRESSBAR = nsIAccessibleRole.ROLE_PROGRESSBAR;
@ -37,6 +40,7 @@ const ROLE_TABLE = nsIAccessibleRole.ROLE_TABLE;
const ROLE_TEXT_CONTAINER = nsIAccessibleRole.ROLE_TEXT_CONTAINER;
const ROLE_TEXT_LEAF = nsIAccessibleRole.ROLE_TEXT_LEAF;
const ROLE_TOGGLE_BUTTON = nsIAccessibleRole.ROLE_TOGGLE_BUTTON;
const ROLE_TREE_TABLE = nsIAccessibleRole.ROLE_TREE_TABLE;
////////////////////////////////////////////////////////////////////////////////
// Public methods

View File

@ -0,0 +1,139 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible XUL tree actions tests">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/treeview.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/states.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/events.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/actions.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Accessible tree testers
function focusChecker(aAcc, aStates)
{
this.type = EVENT_FOCUS;
this.target = aAcc;
this.getID = function focusChecker_getID()
{
return "focus handling";
}
this.check = function focusChecker_check(aEvent)
{
var states = aStates ? aStates : 0;
testStates(this.target, STATE_FOCUSED | STATE_SELECTED | states);
}
}
////////////////////////////////////////////////////////////////////////////
// Test
// gA11yEventDumpID = "debug";
function doTestActions()
{
var treeNode = getNode("tree");
treeNode.removeEventListener("TreeViewChanged", doTestActions, false);
var treeBodyNode = treeNode.boxObject.treeBody;
var tree = getAccessible(treeNode);
var expandedTreeItem = tree.getChildAt(2);
var collapsedTreeItem = tree.getChildAt(5);
var actions = [
{
ID: expandedTreeItem,
actionName: "activate",
actionIndex: 0,
events: CLICK_EVENTS,
targetID: treeBodyNode,
eventSeq: [
new focusChecker(expandedTreeItem, STATE_EXPANDED)
]
},
{
ID: collapsedTreeItem,
actionName: "expand",
actionIndex: 1,
events: CLICK_EVENTS,
targetID: treeBodyNode,
checkOnClickEvent: function check(aEvent)
{
testStates(this.ID, STATE_EXPANDED);
}
},
{
ID: collapsedTreeItem,
actionName: "collapse",
actionIndex: 1,
events: CLICK_EVENTS,
targetID: treeBodyNode,
checkOnClickEvent: function check(aEvent)
{
testStates(this.ID, STATE_COLLAPSED);
}
}
];
testActions(actions); // Will call SimpleTest.finish();
}
function doTest()
{
var treeNode = getNode("tree");
treeNode.addEventListener("TreeViewChanged", doTestActions, false);
treeNode.view = new nsTreeTreeView();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
title="Reorganize implementation of XUL tree accessibility">
Mozilla Bug 503727
</a><br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<tree id="tree" flex="1" minheight="100px">
<treecols>
<treecol id="col" flex="1" primary="true" label="column"/>
</treecols>
<treechildren/>
</tree>
<vbox id="debug"/>
</vbox>
</hbox>
</window>

View File

@ -0,0 +1,200 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/a11y/accessible/treeview.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible XUL tree actions tests">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/treeview.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/states.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/events.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/actions.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Accessible tree testers
function focusChecker(aAcc, aStates)
{
this.type = EVENT_FOCUS;
this.target = aAcc;
this.getID = function focusChecker_getID()
{
return "focus handling";
}
this.check = function focusChecker_check(aEvent)
{
var states = aStates ? aStates : 0;
testStates(this.target, STATE_FOCUSED | STATE_SELECTED | states);
}
}
function stateChangeChecker(aAcc, aIsEnabled)
{
this.type = EVENT_STATE_CHANGE;
this.target = aAcc;
this.getID = function stateChangeChecker_getID()
{
return "state change handling";
}
this.check = function stateChangeChecker_check(aEvent)
{
if (aIsEnabled)
testStates(this.target, STATE_CHECKED);
else
testStates(this.target, STATE_CHECKABLE, 0, STATE_CHECKED);
}
}
////////////////////////////////////////////////////////////////////////////
// Test
function doTestActions()
{
var treeNode = getNode("tabletree");
treeNode.removeEventListener("TreeViewChanged", doTestActions, false);
var treeBodyNode = treeNode.boxObject.treeBody;
treeNode.focus();
var tree = getAccessible(treeNode);
var expandedTreeItem = tree.getChildAt(2);
var collapsedTreeItem = tree.getChildAt(5);
var cycleCell = expandedTreeItem.getChildAt(0);
var checkableCell = expandedTreeItem.getChildAt(3);
var actions = [
{
ID: expandedTreeItem,
actionName: "activate",
actionIndex: 0,
events: CLICK_EVENTS,
targetID: treeBodyNode,
eventSeq: [
new focusChecker(expandedTreeItem, STATE_EXPANDED)
]
},
{
ID: collapsedTreeItem,
actionName: "expand",
actionIndex: 1,
events: CLICK_EVENTS,
targetID: treeBodyNode,
check: function check(aEvent)
{
testStates(this.ID, STATE_EXPANDED);
}
},
{
ID: collapsedTreeItem,
actionName: "collapse",
actionIndex: 1,
events: CLICK_EVENTS,
targetID: treeBodyNode,
check: function check(aEvent)
{
testStates(this.ID, STATE_COLLAPSED);
}
},
{
ID: cycleCell,
actionName: "cycle",
actionIndex: 0,
events: CLICK_EVENTS,
targetID: treeBodyNode
},
{
ID: checkableCell,
actionName: "uncheck",
actionIndex: 0,
events: CLICK_EVENTS,
targetID: treeBodyNode,
eventSeq: [
new stateChangeChecker(checkableCell, false)
]
},
{
ID: checkableCell,
actionName: "check",
actionIndex: 0,
events: CLICK_EVENTS,
targetID: treeBodyNode,
eventSeq: [
new stateChangeChecker(checkableCell, true)
]
}
];
testActions(actions); // Will call SimpleTest.finish();
}
// gA11yEventDumpID = "debug";
function doTest()
{
var treeNode = getNode("tabletree");
treeNode.addEventListener("TreeViewChanged", doTestActions, false);
treeNode.view = new nsTreeTreeView();
}
function test1()
{
var boxObj = getNode("tabletree").treeBoxObject;
boxObj.view.setCellValue(0, boxObj.columns.firstColumn, "false");
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
title="Reorganize implementation of XUL tree accessibility">
Mozilla Bug 503727
</a><br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<tree id="tabletree" flex="1" editable="true">
<treecols>
<treecol id="tabletree_col1" cycler="true" label="cycler"/>
<treecol id="tabletree_col2" flex="1" primary="true" label="column1"/>
<treecol id="tabletree_col3" flex="1" label="column2"/>
<treecol id="tabletree_col4" flex="1" label="checker"
type="checkbox" editable="true"/>
</treecols>
<treechildren/>
</tree>
<vbox id="debug"/>
<button oncommand="test1();" label="uncheck"/>
</vbox>
</hbox>
</window>

View File

@ -0,0 +1,93 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible XUL tree attributes tests">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/treeview.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/attributes.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Test
function doTestAttrs()
{
var treeNode = getNode("tree");
treeNode.removeEventListener("TreeViewChanged", doTestAttrs, false);
var tree = getAccessible(treeNode);
var treeitem1 = tree.firstChild.nextSibling;
testGroupAttrs(treeitem1, "1", "4", "1");
var treeitem2 = treeitem1.nextSibling;
testGroupAttrs(treeitem2, "2", "4", "1");
var treeitem3 = treeitem2.nextSibling;
testGroupAttrs(treeitem3, "1", "2", "2");
var treeitem4 = treeitem3.nextSibling;
testGroupAttrs(treeitem4, "2", "2", "2");
var treeitem5 = treeitem4.nextSibling;
testGroupAttrs(treeitem5, "3", "4", "1");
var treeitem6 = treeitem5.nextSibling;
testGroupAttrs(treeitem6, "4", "4", "1");
SimpleTest.finish();
}
function doTest()
{
var treeNode = getNode("tree");
treeNode.addEventListener("TreeViewChanged", doTestAttrs, false);
treeNode.view = new nsTreeTreeView();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
title="Reorganize implementation of XUL tree accessibility">
Mozilla Bug 503727
</a><br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<tree id="tree" flex="1">
<treecols>
<treecol id="col" flex="1" primary="true" label="column"/>
</treecols>
<treechildren/>
</tree>
<vbox id="debug"/>
</vbox>
</hbox>
</window>

View File

@ -0,0 +1,185 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible XUL tree hierarchy tests">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/treeview.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/role.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/events.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Accessible tree testers
function getTreeItemAccTree(aTableRole, aColumnsCount)
{
var treeItemRole;
switch (aTableRole) {
case ROLE_LIST:
treeItemRole = ROLE_LISTITEM;
break;
case ROLE_OUTLINE:
treeItemRole = ROLE_OUTLINEITEM;
break;
case ROLE_TABLE: case ROLE_TREE_TABLE:
treeItemRole = ROLE_ROW;
break;
}
var accTree = {
role: treeItemRole,
children: []
};
if (aTableRole == ROLE_TABLE || aTableRole == ROLE_TREE_TABLE) {
for (var idx = 0; idx < aColumnsCount; idx++) {
var cellAccTree = {
role: ROLE_GRID_CELL,
children: []
};
accTree.children.push(cellAccTree);
}
}
return accTree;
}
function testAccessibleTreeFor(aTree, aRole)
{
var accTreeForColumns = {
role: ROLE_LIST,
children: []
};
var accTreeForTree = {
role: aRole,
children: [
accTreeForColumns
]
};
var treeBoxObject = aTree.treeBoxObject;
var view = treeBoxObject.view;
var columnsCount = treeBoxObject.columns.count;
for (var idx = 0; idx < columnsCount; idx++)
accTreeForColumns.children.push({ role: ROLE_COLUMNHEADER, children: []});
if (!aTree.hasAttribute("hidecolumnpicker"))
accTreeForColumns.children.push({ role: ROLE_PUSHBUTTON, children: []});
for (var idx = 0; idx < view.rowCount; idx++)
accTreeForTree.children.push(getTreeItemAccTree(aRole, columnsCount));
testAccessibleTree(aTree, accTreeForTree);
}
/**
* Event queue invoker object to test accessible tree for XUL tree element.
*/
function treeChecker(aID, aView, aRole)
{
this.DOMNode = getNode(aID);
this.invoke = function invoke()
{
this.DOMNode.treeBoxObject.view = aView;
}
this.check = function check(aEvent)
{
testAccessibleTreeFor(this.DOMNode, aRole);
}
this.getID = function getID()
{
return "Tree testing of " + aID;
}
}
////////////////////////////////////////////////////////////////////////////
// Test
// gA11yEventDumpID = "debug";
var gQueue = null;
function doTest()
{
var gQueue = new eventQueue("TreeViewChanged");
gQueue.push(new treeChecker("list", new nsTableTreeView(3), ROLE_LIST));
gQueue.push(new treeChecker("tree", new nsTreeTreeView(), ROLE_OUTLINE));
gQueue.push(new treeChecker("table", new nsTableTreeView(3), ROLE_TABLE));
gQueue.push(new treeChecker("treetable", new nsTreeTreeView(), ROLE_TREE_TABLE));
gQueue.invoke(); // Will call SimpleTest.finish()
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
title="Reorganize implementation of XUL tree accessibility">
Mozilla Bug 503727
</a><br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<tree id="list" flex="1" hidecolumnpicker="true">
<treecols>
<treecol id="col" flex="1" hideheader="true"/>
</treecols>
<treechildren/>
</tree>
<tree id="tree" flex="1">
<treecols>
<treecol id="col" flex="1" primary="true" label="column"/>
</treecols>
<treechildren/>
</tree>
<tree id="table" flex="1">
<treecols>
<treecol id="col1" flex="1" label="column"/>
<treecol id="col2" flex="1" label="column 2"/>
</treecols>
<treechildren/>
</tree>
<tree id="treetable" flex="1">
<treecols>
<treecol id="col1" flex="1" primary="true" label="column"/>
<treecol id="col2" flex="1" label="column 2"/>
</treecols>
<treechildren/>
</tree>
<vbox id="debug"/>
</vbox>
</hbox>
</window>

View File

@ -30,6 +30,24 @@
////////////////////////////////////////////////////////////////////////////
// Invoker's checkers
/**
* Check TreeViewChanged event and run through accessible tree to ensure
* it's created.
*/
function treeViewChangedChecker(aMsg)
{
this.type = "TreeViewChanged";
this.target = gTree;
this.check = function check(aEvent)
{
ensureAccessibleTree(gTree);
}
this.getID = function getID()
{
return "TreeViewChanged";
}
}
/**
* Check TreeRowCountChanged event.
*/
@ -93,13 +111,8 @@
{
var acc = getAccessible(gTree);
var tableAcc = getAccessible(acc, [nsIAccessibleTable], null,
DONOTFAIL_IF_NO_INTERFACE);
if (tableAcc)
return tableAcc.cellRefAt(aRow, aCol);
return acc.getChildAt(aRow + 1);
var tableAcc = getAccessible(acc, [nsIAccessibleTable]);
return tableAcc.cellRefAt(aRow, aCol);
}
this.getID = function getID()
{
@ -122,7 +135,7 @@
this.getID = function setTreeView_getID() { return "TreeViewChanged"; }
this.eventSeq = [ new invokerChecker("TreeViewChanged", gTree) ];
this.eventSeq = [ new treeViewChangedChecker() ];
};
/**
@ -133,7 +146,7 @@
{
this.invoke = function insertRow_invoke()
{
++gView.mRowCount;
gView.appendItem("last");
gTreeBox.rowCountChanged(0, 1);
}
@ -154,18 +167,14 @@
{
// Make sure accessibles for the tree is created because it makes
// sure accessible events will be fired.
var treeAcc = getAccessible(gTree);
// Makes sure tree children accessibles are created otherwise they won't
// Make sure tree children accessibles are created otherwise they won't
// be a cause of name changed events.
var children = treeAcc.children;
ensureAccessibleTree(gTree);
// Fire 'TreeInvalidated' event by InvalidateColumn()
var firstCol = gTree.columns.getFirstColumn();
for (var i = 0; i < gView.mRowCount; i++) {
var key = String(i) + firstCol.id;
gView.mData[key] = key + "_col";
}
for (var i = 0; i < gView.rowCount; i++)
gView.setCellText(i, firstCol, "hey " + String(i) + "x0");
gTreeBox.invalidateColumn(firstCol);
}
@ -193,9 +202,10 @@
{
// Fire 'TreeInvalidated' event by InvalidateRow()
var colCount = gTree.columns.count;
for (var i = 0; i < colCount; i++) {
var key = "1" + gTree.columns.getColumnAt(i).id;
gView.mData[key] = key + "_row";
var column = gTree.columns.getFirstColumn();
while (column) {
gView.setCellText(1, column, "aloha 1x" + String(column.index));
column = column.getNext();
}
gTreeBox.invalidateRow(1);
@ -204,6 +214,7 @@
this.eventSeq =
[
new nameChangeChecker("invalidateColumn: ", 1, 0),
new nameChangeChecker("invalidateColumn: ", 1, 1),
new treeInvalidatedChecker("invalidateColumn", 1, 1, null, null)
];
}
@ -223,9 +234,7 @@
// Initialize the tree
gTree = document.getElementById("tree");
gTreeBox = gTree.treeBoxObject;
gView = new inTreeView();
gView.mRowCount = 5;
gView = new nsTableTreeView(5);
// Perform actions
gQueue = new eventQueue();
@ -265,8 +274,8 @@
<vbox id="debug"/>
<tree id="tree" flex="1">
<treecols>
<treecol id="col" flex="1" primary="true" label="column"/>
<treecol id="scol" flex="1" label="column 2"/>
<treecol id="col1" flex="1" primary="true" label="column"/>
<treecol id="col2" flex="1" label="column 2"/>
</treecols>
<treechildren id="treechildren"/>
</tree>

View File

@ -0,0 +1,93 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible XUL tree relations tests">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/treeview.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/relations.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Test
function doTestRelations()
{
var treeNode = getNode("tree");
treeNode.removeEventListener("TreeViewChanged", doTestRelations, false);
var tree = getAccessible(treeNode);
var treeitem1 = tree.firstChild.nextSibling;
testRelation(treeitem1, RELATION_NODE_CHILD_OF, [tree]);
var treeitem2 = treeitem1.nextSibling;
testRelation(treeitem2, RELATION_NODE_CHILD_OF, [tree]);
var treeitem3 = treeitem2.nextSibling;
testRelation(treeitem3, RELATION_NODE_CHILD_OF, [treeitem2]);
var treeitem4 = treeitem3.nextSibling;
testRelation(treeitem4, RELATION_NODE_CHILD_OF, [treeitem2]);
var treeitem5 = treeitem4.nextSibling;
testRelation(treeitem5, RELATION_NODE_CHILD_OF, [tree]);
var treeitem6 = treeitem5.nextSibling;
testRelation(treeitem6, RELATION_NODE_CHILD_OF, [tree]);
SimpleTest.finish();
}
function doTest()
{
var treeNode = getNode("tree");
treeNode.addEventListener("TreeViewChanged", doTestRelations, false);
treeNode.view = new nsTreeTreeView();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
title="Reorganize implementation of XUL tree accessibility">
Mozilla Bug 503727
</a><br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<tree id="tree" flex="1">
<treecols>
<treecol id="col" flex="1" primary="true" label="column"/>
</treecols>
<treechildren/>
</tree>
<vbox id="debug"/>
</vbox>
</hbox>
</window>

View File

@ -0,0 +1,145 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/a11y/accessible/treeview.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible XUL tree states tests">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/treeview.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/states.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/events.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Test
// gA11yEventDumpID = "debug";
/**
* Event queue invoker object to test accessible states for XUL tree
* accessible.
*/
function statesChecker(aTreeID, aView)
{
this.DOMNode = getNode(aTreeID);
this.invoke = function invoke()
{
this.DOMNode.treeBoxObject.view = aView;
}
this.check = function check()
{
var tree = getAccessible(this.DOMNode);
// tree states
testStates(tree, STATE_READONLY);
if (this.DOMNode.getAttribute("seltype") != "single")
testStates(tree, STATE_MULTISELECTABLE);
else
testStates(tree, 0, 0, STATE_MULTISELECTABLE);
// tree item states
var expandedItem = tree.getChildAt(2);
testStates(expandedItem,
STATE_SELECTABLE | STATE_FOCUSABLE | STATE_EXPANDED);
var collapsedItem = tree.getChildAt(5);
testStates(collapsedItem,
STATE_SELECTABLE | STATE_FOCUSABLE | STATE_COLLAPSED);
// cells states if any
var cells = collapsedItem.children;
if (cells && cells.length) {
for (var idx = 0; idx < cells.length; idx++) {
var cell = cells.queryElementAt(idx, nsIAccessible);
testStates(cell, STATE_SELECTABLE);
}
var checkboxCell = cells.queryElementAt(3, nsIAccessible);
testStates(checkboxCell, STATE_CHECKABLE | STATE_CHECKED);
}
}
this.getID = function getID()
{
"tree processor for " + prettyName(aTreeID);
}
}
var gQueue = null;
function doTest()
{
gQueue = new eventQueue("TreeViewChanged");
gQueue.push(new statesChecker("tree", new nsTreeTreeView()));
gQueue.push(new statesChecker("treesingle", new nsTreeTreeView()));
gQueue.push(new statesChecker("tabletree", new nsTreeTreeView()));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
title="Reorganize implementation of XUL tree accessibility">
Mozilla Bug 503727
</a><br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<tree id="tree" flex="1">
<treecols>
<treecol id="col" flex="1" primary="true" label="column"/>
</treecols>
<treechildren/>
</tree>
<tree id="treesingle" flex="1" seltype="single">
<treecols>
<treecol id="col_single" flex="1" primary="true" label="column"/>
</treecols>
<treechildren/>
</tree>
<tree id="tabletree" flex="1" editable="true">
<treecols>
<treecol id="tabletree_col1" cycler="true" label="cycler"/>
<treecol id="tabletree_col2" flex="1" primary="true" label="column1"/>
<treecol id="tabletree_col3" flex="1" label="column2"/>
<treecol id="tabletree_col4" flex="1" label="checker"
type="checkbox" editable="true"/>
</treecols>
<treechildren/>
</tree>
<vbox id="debug"/>
</vbox>
</hbox>
</window>

View File

@ -0,0 +1,88 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible Table indexes tests">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/treeview.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/table.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Test
var gTree = null;
var gTreeBox = null;
var gTreeView = null;
// gA11yEventDumpID = "debug";
function doTest()
{
// Initialize the tree
gTree = document.getElementById("tree");
gTreeBox = gTree.treeBoxObject;
gView = new nsTableTreeView(3);
gTree.addEventListener("TreeViewChanged", continueTest, false);
gTreeBox.view = gView;
}
function continueTest()
{
gTree.removeEventListener("TreeViewChanged", continueTest, false);
var idxes = [
[0, 1],
[2, 3],
[4, 5]
];
testTableIndexes(gTree, idxes);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
title="Reorganize implementation of XUL tree accessibility">
Mozilla Bug 503727
</a><br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox id="debug"/>
<tree id="tree" flex="1">
<treecols>
<treecol id="col" flex="1" primary="true" label="column"/>
<treecol id="scol" flex="1" label="column 2"/>
</treecols>
<treechildren id="treechildren"/>
</tree>
</hbox>
</window>

View File

@ -0,0 +1,94 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible Table selection tests">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/treeview.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/states.js" />
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/table.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Test
var gTree = null;
var gTreeBox = null;
var gTreeView = null;
// gA11yEventDumpID = "debug";
function doTest()
{
// Initialize the tree
gTree = document.getElementById("tree");
gTreeBox = gTree.treeBoxObject;
gView = new nsTableTreeView(3);
gTree.addEventListener("TreeViewChanged", continueTest, false);
gTreeBox.view = gView;
}
function continueTest()
{
gTree.removeEventListener("TreeViewChanged", continueTest, false);
var cellsArray =
[
[false, false],
[false, false],
[false, false]
];
testTableSelection(gTree, cellsArray);
testSelectTableRow(gTree, 0, cellsArray);
testUnselectTableRow(gTree, 0, cellsArray);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
title="Reorganize implementation of XUL tree accessibility">
Mozilla Bug 503727
</a><br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox id="debug"/>
<tree id="tree" flex="1">
<treecols>
<treecol id="col" flex="1" primary="true" label="column"/>
<treecol id="scol" flex="1" label="column 2"/>
</treecols>
<treechildren id="treechildren"/>
</tree>
</hbox>
</window>

View File

@ -0,0 +1,15 @@
treechildren::-moz-tree-checkbox(checked) {
list-style-image: url("chrome://global/skin/checkbox/cbox-check.gif");
}
treechildren::-moz-tree-image(cyclerState1) {
list-style-image: url("chrome://global/skin/console/bullet-question.png");
}
treechildren::-moz-tree-image(cyclerState2) {
list-style-image: url("chrome://global/skin/console/bullet-warning.png");
}
treechildren::-moz-tree-image(cyclerState3) {
list-style-image: url("chrome://global/skin/console/bullet-error.png");
}

View File

@ -1,14 +1,33 @@
function inTreeView() { }
inTreeView.prototype =
function nsTableTreeView(aRowCount)
{
mRowCount: 0,
mTree: null,
mData: {},
this.__proto__ = new nsTreeView();
for (var idx = 0; idx < aRowCount; idx++)
this.mData.push(new treeItem("row" + String(idx) + "_"));
}
function nsTreeTreeView()
{
this.__proto__ = new nsTreeView();
this.mData = [
new treeItem("row1"),
new treeItem("row2_", true, [new treeItem("row2.1_"), new treeItem("row2.2_")]),
new treeItem("row3_", false, [new treeItem("row3.1_"), new treeItem("row3.2_")]),
new treeItem("row4")
];
}
function nsTreeView() { }
nsTreeView.prototype =
{
//////////////////////////////////////////////////////////////////////////////
// nsITreeView implementation
get rowCount()
{
return this.mRowCount;
return this.getRowCountIntl(this.mData);
},
setTree: function setTree(aTree)
{
@ -16,35 +35,198 @@ inTreeView.prototype =
},
getCellText: function getCellText(aRow, aCol)
{
var key = String(aRow) + aCol.id;
if (key in this.mData)
return this.mData[key];
return "hello";
var data = this.getDataForIndex(aRow);
if (aCol in data.colsText)
return data.colsText[aCol];
return data.text + aCol.id;
},
getCellValue: function getCellValue(aRow, aCol)
{
var data = this.getDataForIndex(aRow);
return data.value;
},
getRowProperties: function getRowProperties(aIndex, aProperties) {},
getCellProperties: function getCellProperties(aIndex, aCol, aProperties) {},
getCellProperties: function getCellProperties(aIndex, aCol, aProperties)
{
if (!aCol.cycler)
return;
var data = this.getDataForIndex(aIndex);
var atom = this.mCyclerStates[data.cyclerState];
aProperties.AppendElement(atom);
},
getColumnProperties: function getColumnProperties(aCol, aProperties) {},
getParentIndex: function getParentIndex(aRowIndex) { },
getParentIndex: function getParentIndex(aRowIndex)
{
var info = this.getInfoByIndex(aRowIndex);
return info.parentIndex;
},
hasNextSibling: function hasNextSibling(aRowIndex, aAfterIndex) { },
getLevel: function getLevel(aIndex) {},
getLevel: function getLevel(aIndex)
{
var info = this.getInfoByIndex(aIndex);
return info.level;
},
getImageSrc: function getImageSrc(aRow, aCol) {},
getProgressMode: function getProgressMode(aRow, aCol) {},
getCellValue: function getCellValue(aRow, aCol) {},
isContainer: function isContainer(aIndex) {},
isContainerOpen: function isContainerOpen(aIndex) {},
isContainerEmpty: function isContainerEmpty(aIndex) {},
isContainer: function isContainer(aIndex)
{
var data = this.getDataForIndex(aIndex);
return data.open != undefined;
},
isContainerOpen: function isContainerOpen(aIndex)
{
var data = this.getDataForIndex(aIndex);
return data.open;
},
isContainerEmpty: function isContainerEmpty(aIndex)
{
var data = this.getDataForIndex(aIndex);
return data.open == undefined;
},
isSeparator: function isSeparator(aIndex) {},
isSorted: function isSorted() {},
toggleOpenState: function toggleOpenState(aIndex) {},
toggleOpenState: function toggleOpenState(aIndex)
{
var data = this.getDataForIndex(aIndex);
data.open = !data.open;
var rowCount = this.getRowCountIntl(data.children);
if (data.open)
this.mTree.rowCountChanged(aIndex + 1, rowCount);
else
this.mTree.rowCountChanged(aIndex + 1, -rowCount);
},
selectionChanged: function selectionChanged() {},
cycleHeader: function cycleHeader(aCol) {},
cycleCell: function cycleCell(aRow, aCol) {},
isEditable: function isEditable(aRow, aCol) {},
cycleCell: function cycleCell(aRow, aCol)
{
var data = this.getDataForIndex(aRow);
data.cyclerState = (data.cyclerState + 1) % 3;
this.mTree.invalidateCell(aRow, aCol);
},
isEditable: function isEditable(aRow, aCol)
{
return true;
},
isSelectable: function isSelectable(aRow, aCol) {},
setCellValue: function setCellValue(aRow, aCol, aValue) {},
setCellText: function setCellText(aRow, aCol, aValue) { },
setCellText: function setCellText(aRow, aCol, aValue)
{
var data = this.getDataForIndex(aRow);
data.colsText[aCol] = aValue;
},
setCellValue: function setCellValue(aRow, aCol, aValue)
{
var data = this.getDataForIndex(aRow);
data.value = aValue;
this.mTree.invalidateCell(aRow, aCol);
},
performAction: function performAction(aAction) {},
performActionOnRow: function performActionOnRow(aAction, aRow) {},
performActionOnCell: function performActionOnCell(aAction, aRow, aCol) {}
performActionOnCell: function performActionOnCell(aAction, aRow, aCol) {},
//////////////////////////////////////////////////////////////////////////////
// public implementation
appendItem: function appendItem(aText)
{
this.mData.push(new treeItem(aText));
},
//////////////////////////////////////////////////////////////////////////////
// private implementation
getDataForIndex: function getDataForIndex(aRowIndex)
{
return this.getInfoByIndex(aRowIndex).data;
},
getInfoByIndex: function getInfoByIndex(aRowIndex)
{
var info = {
data: null,
parentIndex: -1,
level: 0,
index: -1
};
this.getInfoByIndexIntl(aRowIndex, info, this.mData, 0);
return info;
},
getRowCountIntl: function getRowCountIntl(aChildren)
{
var rowCount = 0;
for (var childIdx = 0; childIdx < aChildren.length; childIdx++) {
rowCount++;
var data = aChildren[childIdx];
if (data.open)
rowCount += this.getRowCountIntl(data.children);
}
return rowCount;
},
getInfoByIndexIntl: function getInfoByIndexIntl(aRowIdx, aInfo,
aChildren, aLevel)
{
var rowIdx = aRowIdx;
for (var childIdx = 0; childIdx < aChildren.length; childIdx++) {
var data = aChildren[childIdx];
aInfo.index++;
if (rowIdx == 0) {
aInfo.data = data;
aInfo.level = aLevel;
return -1;
}
if (data.open) {
var parentIdx = aInfo.index;
rowIdx = this.getInfoByIndexIntl(rowIdx - 1, aInfo, data.children,
aLevel + 1);
if (rowIdx == -1) {
if (aInfo.parentIndex == -1)
aInfo.parentIndex = parentIdx;
return 0;
}
} else {
rowIdx--;
}
}
return rowIdx;
},
mTree: null,
mData: [],
mCyclerStates: [
createAtom("cyclerState1"),
createAtom("cyclerState2"),
createAtom("cyclerState3")
]
};
function treeItem(aText, aOpen, aChildren)
{
this.text = aText;
this.colsText = {};
this.open = aOpen;
this.value = "true";
this.cyclerState = 0;
if (aChildren)
this.children = aChildren;
}
function createAtom(aName)
{
return Components.classes["@mozilla.org/atom-service;1"]
.getService(Components.interfaces.nsIAtomService).getAtom(aName);
}