bug 201922 Make XUL tree accessibles keep track of their own tree item accessibles

r = aaronleventhal
sr= Henry.Jia
This commit is contained in:
louie.zhao%sun.com 2004-06-16 06:19:12 +00:00
parent 26ee61eb3e
commit 69c97f7259
7 changed files with 157 additions and 66 deletions

View File

@ -64,6 +64,7 @@ XPIDLSRCS = \
nsPIAccessibleDocument.idl \
nsIAccessibleProvider.idl \
nsIAccessibleSelectable.idl \
nsIAccessibleTreeCache.idl \
nsIAccessNode.idl \
nsPIAccessNode.idl \
nsIAccessibleEvent.idl \

View File

@ -0,0 +1,53 @@
/* -*- 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
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* 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
* 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 ***** */
#include "nsISupports.idl"
#include "nsITreeColumns.idl"
interface nsIAccessible;
/**
* A cross-platform interface that supports cache for tree item
*
* @status UNDER_REVIEW
*/
[scriptable, uuid(CC742DA2-9C25-4D04-96CD-DA407D676C6D)]
interface nsIAccessibleTreeCache : nsISupports
{
/**
* Get tree item from cache according to row and column, create if doesn't exist in cache
* "aColumn" can be nsnull
*/
[noscript] nsIAccessible getCachedTreeitemAccessible(in PRInt32 aRow, in nsITreeColumn aColumn);
};

View File

@ -869,7 +869,7 @@ getIndexInParentCB(AtkObject *aAtkObj)
nsCOMPtr<nsIAccessible> accChild;
nsCOMPtr<nsIAccessible> accTmpChild;
accWrap->GetFirstChild(getter_AddRefs(accChild));
accParent->GetFirstChild(getter_AddRefs(accChild));
PRInt32 currentIndex = -1;
void *currentAccId = nsnull;

View File

@ -225,12 +225,7 @@ NS_IMETHODIMP nsXULTreeAccessibleWrap::CellRefAt(PRInt32 aRow, PRInt32 aColumn,
rv = treeColumns->GetColumnFor(columnElement, getter_AddRefs(treeColumn));
NS_ENSURE_SUCCESS(rv, rv);
*_retval = new nsXULTreeitemAccessible(this, mDOMNode, mWeakShell, aRow, treeColumn);
NS_ENSURE_TRUE(*_retval, NS_ERROR_OUT_OF_MEMORY);
NS_IF_ADDREF(*_retval);
return NS_OK;
return GetCachedTreeitemAccessible(aRow, treeColumn, _retval);
}
NS_IMETHODIMP nsXULTreeAccessibleWrap::GetIndexAt(PRInt32 aRow, PRInt32 aColumn, PRInt32 *_retval)
@ -257,7 +252,11 @@ NS_IMETHODIMP nsXULTreeAccessibleWrap::GetColumnAtIndex(PRInt32 aIndex, PRInt32
rv = GetColumns(&columns);
NS_ENSURE_SUCCESS(rv, rv);
*_retval = aIndex % columns;
PRInt32 treeCols;
nsAccessible::GetChildCount(&treeCols);
*_retval = (aIndex - treeCols) % columns;
return NS_OK;
}
@ -271,7 +270,11 @@ NS_IMETHODIMP nsXULTreeAccessibleWrap::GetRowAtIndex(PRInt32 aIndex, PRInt32 *_r
rv = GetColumns(&columns);
NS_ENSURE_SUCCESS(rv, rv);
*_retval = aIndex / columns;
PRInt32 treeCols;
nsAccessible::GetChildCount(&treeCols);
*_retval = (aIndex - treeCols) / columns;
return NS_OK;
}

View File

@ -384,15 +384,14 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
PRInt32 treeIndex = -1;
multiSelect->GetCurrentIndex(&treeIndex);
if (treeIndex >= 0) {
// XXX todo Kyle - fix bug 201922 so that tree is responsible for keeping track
// of it's own accessibles. Then we'll ask the tree so we can reuse
// the accessibles already created.
nsCOMPtr<nsIWeakReference> weakEventShell(do_GetWeakReference(eventShell));
treeItemAccessible = new nsXULTreeitemAccessible(accessible, targetNode,
weakEventShell, treeIndex);
if (!treeItemAccessible) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsIAccessibleTreeCache> treeCache(do_QueryInterface(accessible));
if (!treeCache ||
NS_FAILED(treeCache->GetCachedTreeitemAccessible(
treeIndex,
nsnull,
getter_AddRefs(treeItemAccessible))) ||
!treeItemAccessible)
return NS_ERROR_OUT_OF_MEMORY;
}
}
}

View File

@ -47,18 +47,33 @@
#include "nsIAccessibleTable.h"
#endif
#define kMaxTreeColumns 100
// ---------- nsXULTreeAccessible ----------
nsXULTreeAccessible::nsXULTreeAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
nsXULSelectableAccessible(aDOMNode, aShell)
nsXULSelectableAccessible(aDOMNode, aShell),
mAccessNodeCache(nsnull)
{
GetTreeBoxObject(aDOMNode, getter_AddRefs(mTree));
if (mTree)
mTree->GetView(getter_AddRefs(mTreeView));
NS_ASSERTION(mTree && mTreeView, "Can't get mTree or mTreeView!\n");
mAccessNodeCache = new nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode>;
mAccessNodeCache->Init(kDefaultTreeCacheSize);
}
NS_IMPL_ISUPPORTS_INHERITED0(nsXULTreeAccessible, nsXULSelectableAccessible)
nsXULTreeAccessible::~nsXULTreeAccessible()
{
if (mAccessNodeCache) {
ClearCache(*mAccessNodeCache);
mAccessNodeCache = nsnull;
}
}
NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeAccessible, nsXULSelectableAccessible, nsIAccessibleTreeCache)
// Get the nsITreeBoxObject interface from any levels DOMNode under the <tree>
void nsXULTreeAccessible::GetTreeBoxObject(nsIDOMNode *aDOMNode, nsITreeBoxObject **aBoxObject)
@ -158,10 +173,7 @@ NS_IMETHODIMP nsXULTreeAccessible::GetFirstChild(nsIAccessible **aFirstChild)
PRInt32 rowCount;
mTreeView->GetRowCount(&rowCount);
if (rowCount > 0) {
*aFirstChild = new nsXULTreeitemAccessible(this, mDOMNode, mWeakShell, 0);
if (! *aFirstChild)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aFirstChild);
return GetCachedTreeitemAccessible(0, nsnull, aFirstChild);
}
}
@ -175,10 +187,7 @@ NS_IMETHODIMP nsXULTreeAccessible::GetLastChild(nsIAccessible **aLastChild)
PRInt32 rowCount;
mTreeView->GetRowCount(&rowCount);
if (rowCount > 0) {
*aLastChild = new nsXULTreeitemAccessible(this, mDOMNode, mWeakShell, rowCount - 1);
if (! *aLastChild)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aLastChild);
return GetCachedTreeitemAccessible(rowCount - 1, nsnull, aLastChild);
}
else // if there is not any rows, use treecols as tree's last child
nsAccessible::GetLastChild(aLastChild);
@ -223,8 +232,8 @@ NS_IMETHODIMP nsXULTreeAccessible::GetSelectedChildren(nsIArray **_retval)
selection->IsSelected(rowIndex, &isSelected);
if (isSelected) {
nsCOMPtr<nsIAccessible> tempAccess;
tempAccess = new nsXULTreeitemAccessible(this, mDOMNode, mWeakShell, rowIndex);
if (!tempAccess)
if (NS_FAILED(GetCachedTreeitemAccessible(rowIndex, nsnull, getter_AddRefs(tempAccess))) || !tempAccess)
return NS_ERROR_OUT_OF_MEMORY;
selectedAccessibles->AppendElement(tempAccess, PR_FALSE);
}
@ -318,12 +327,7 @@ NS_IMETHODIMP nsXULTreeAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **
selection->IsSelected(rowIndex, &isSelected);
if (isSelected) {
if (selCount == aIndex) {
nsCOMPtr<nsIAccessible> tempAccess;
tempAccess = new nsXULTreeitemAccessible(this, mDOMNode, mWeakShell, rowIndex);
if (!tempAccess)
return NS_ERROR_OUT_OF_MEMORY;
*_retval = tempAccess;
NS_ADDREF(*_retval);
return GetCachedTreeitemAccessible(rowIndex, nsnull, _retval);
}
selCount++;
}
@ -355,6 +359,39 @@ NS_IMETHODIMP nsXULTreeAccessible::SelectAllSelection(PRBool *_retval)
return NS_OK;
}
NS_IMETHODIMP nsXULTreeAccessible::GetCachedTreeitemAccessible(PRInt32 aRow, nsITreeColumn* aColumn, nsIAccessible** aAccessible)
{
NS_ASSERTION(mAccessNodeCache, "No accessibility cache for tree");
NS_ASSERTION(mTree && mTreeView, "Can't get mTree or mTreeView!\n");
nsCOMPtr<nsITreeColumn> col = aColumn;
PRInt32 columnIndex = -1;
if (!col && mTree) {
nsCOMPtr<nsITreeColumns> cols;
mTree->GetColumns(getter_AddRefs(cols));
if (cols)
cols->GetKeyColumn(getter_AddRefs(col));
}
if (col)
col->GetIndex(&columnIndex);
nsCOMPtr<nsIAccessNode> accessNode;
GetCacheEntry(*mAccessNodeCache, (void*)(aRow * kMaxTreeColumns + columnIndex), getter_AddRefs(accessNode));
if (!accessNode)
{
accessNode = new nsXULTreeitemAccessible(this, mDOMNode, mWeakShell, aRow, col);
if (! accessNode)
return NS_ERROR_OUT_OF_MEMORY;
PutCacheEntry(*mAccessNodeCache, (void*)(aRow * kMaxTreeColumns + columnIndex), accessNode);
}
nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(accessNode));
NS_IF_ADDREF(*aAccessible = accessible);
return NS_OK;
}
// ---------- nsXULTreeitemAccessible ----------
nsXULTreeitemAccessible::nsXULTreeitemAccessible(nsIAccessible *aParent, nsIDOMNode *aDOMNode, nsIWeakReference *aShell, PRInt32 aRow, nsITreeColumn* aColumn)
@ -513,18 +550,17 @@ NS_IMETHODIMP nsXULTreeitemAccessible::GetNextSibling(nsIAccessible **aNextSibli
NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
nsCOMPtr<nsIAccessibleTreeCache> treeCache(do_QueryInterface(mParent));
NS_ENSURE_TRUE(treeCache, NS_ERROR_FAILURE);
PRInt32 rowCount;
mTreeView->GetRowCount(&rowCount);
if (!mColumn) {
if (mRow < rowCount - 1) {
*aNextSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mWeakShell, mRow + 1);
if (! *aNextSibling)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aNextSibling);
}
return NS_OK;
if (mRow < rowCount - 1)
return treeCache->GetCachedTreeitemAccessible(mRow + 1, nsnull, aNextSibling);
else
return NS_OK;
}
nsresult rv = NS_OK;
@ -542,10 +578,7 @@ NS_IMETHODIMP nsXULTreeitemAccessible::GetNextSibling(nsIAccessible **aNextSibli
cols->GetFirstColumn(getter_AddRefs(column));
}
*aNextSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mWeakShell, row, column);
NS_ENSURE_TRUE(*aNextSibling, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aNextSibling);
rv = treeCache->GetCachedTreeitemAccessible(row, column, aNextSibling);
#endif //MOZ_ACCESSIBILITY_ATK
return rv;
@ -559,16 +592,15 @@ NS_IMETHODIMP nsXULTreeitemAccessible::GetPreviousSibling(nsIAccessible **aPrevi
NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
if (!mColumn && mRow > 0) {
*aPreviousSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mWeakShell, mRow - 1);
if (! *aPreviousSibling)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aPreviousSibling);
return NS_OK;
}
nsCOMPtr<nsIAccessibleTreeCache> treeCache(do_QueryInterface(mParent));
NS_ENSURE_TRUE(treeCache, NS_ERROR_FAILURE);
if (!mColumn && mRow > 0)
return treeCache->GetCachedTreeitemAccessible(mRow - 1, nsnull, aPreviousSibling);
nsresult rv = NS_OK;
#ifdef MOZ_ACCESSIBILITY_ATK
PRInt32 row = mRow;
nsCOMPtr<nsITreeColumn> column;
@ -583,10 +615,8 @@ NS_IMETHODIMP nsXULTreeitemAccessible::GetPreviousSibling(nsIAccessible **aPrevi
cols->GetLastColumn(getter_AddRefs(column));
}
*aPreviousSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mWeakShell, row, column);
NS_ENSURE_TRUE(*aPreviousSibling, NS_ERROR_OUT_OF_MEMORY);
rv = treeCache->GetCachedTreeitemAccessible(row, column, aPreviousSibling);
NS_ADDREF(*aPreviousSibling);
#endif //MOZ_ACCESSIBILITY_ATK
return rv;
@ -750,11 +780,9 @@ NS_IMETHODIMP nsXULTreeColumnsAccessible::GetNextSibling(nsIAccessible **aNextSi
PRInt32 rowCount;
treeView->GetRowCount(&rowCount);
if (rowCount > 0) {
*aNextSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mWeakShell, 0);
if (! *aNextSibling)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aNextSibling);
ret = NS_OK;
nsCOMPtr<nsIAccessibleTreeCache> treeCache(do_QueryInterface(mParent));
NS_ENSURE_TRUE(treeCache, NS_ERROR_FAILURE);
ret = treeCache->GetCachedTreeitemAccessible(0, nsnull, aNextSibling);
}
}
}

View File

@ -43,18 +43,24 @@
#include "nsITreeView.h"
#include "nsITreeColumns.h"
#include "nsXULSelectAccessible.h"
#include "nsIAccessibleTreeCache.h"
/*
* A class the represents the XUL Tree widget.
*/
class nsXULTreeAccessible : public nsXULSelectableAccessible
const PRUint32 kDefaultTreeCacheSize = 256;
class nsXULTreeAccessible : public nsXULSelectableAccessible,
public nsIAccessibleTreeCache
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIACCESSIBLESELECTABLE
NS_DECL_NSIACCESSIBLETREECACHE
nsXULTreeAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
virtual ~nsXULTreeAccessible() {}
virtual ~nsXULTreeAccessible();
/* ----- nsIAccessible ----- */
NS_IMETHOD GetRole(PRUint32 *_retval);
@ -70,6 +76,7 @@ public:
protected:
nsCOMPtr<nsITreeBoxObject> mTree;
nsCOMPtr<nsITreeView> mTreeView;
nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> *mAccessNodeCache;
NS_IMETHOD ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState);
};