Active Accessibility: implement support for <tree>

RESOLVED FIXED in mozilla1.0

Status

()

Core
Disability Access APIs
P1
normal
RESOLVED FIXED
16 years ago
16 years ago

People

(Reporter: Aaron Leventhal, Assigned: John Gaunt (redfive))

Tracking

({access, sec508})

Trunk
mozilla1.0
x86
Windows 2000
access, sec508
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(2 attachments, 4 obsolete attachments)

(Reporter)

Description

16 years ago
Most of the trees in our UI will be moving to outliner.

It's very important to make this one accessible.
(Reporter)

Updated

16 years ago
Status: NEW → ASSIGNED
Priority: -- → P1
Target Milestone: --- → mozilla0.9.7
(Reporter)

Comment 1

16 years ago
-> John Gaunt
Assignee: aaronl → jgaunt
Status: ASSIGNED → NEW
(Assignee)

Updated

16 years ago
Status: NEW → ASSIGNED
(Assignee)

Updated

16 years ago
Target Milestone: mozilla0.9.7 → mozilla0.9.8
(Reporter)

Updated

16 years ago
Keywords: access, fcc508
(Assignee)

Updated

16 years ago
Target Milestone: mozilla0.9.8 → mozilla0.9.9
(Reporter)

Updated

16 years ago
Depends on: 110156
(Reporter)

Updated

16 years ago
Keywords: nsbeta1
(Assignee)

Comment 2

16 years ago
moving to 1.0 since the work for this won't be finished until then.
Target Milestone: mozilla0.9.9 → mozilla1.0

Updated

16 years ago
Keywords: nsbeta1 → nsbeta1+

Comment 3

16 years ago
the outliner tags are no more; tweaking summary
Summary: Active Accessibility: implement support for <outliner> → Active Accessibility: implement support for <tree>
(Reporter)

Updated

16 years ago
Blocks: 127812

Comment 4

16 years ago
Hi, John

Did you start working on this issue? If you didn't, I want to take this for me.
(Reporter)

Comment 5

16 years ago
Kyle, John didn't start on this yet. We would both be very grateful if you could
work on this.
(Reporter)

Comment 6

16 years ago
Kyle, be sure to support both kinds of tree syntax. One kind uses nsITreeView,
such as used in mail. The other kind is the traditional kind, that lists it's
contents in DOM nodes.

I think there are a lot of little details to get right with tree. Check
Microsoft's tree implementation and nsIAccessible.idl to see what states you
need to support ... i.e. STATE_EXPANDED, STATE_COLLAPSED, etc.

Good luck, and thank you! Let us know how we can help.

Comment 7

16 years ago
Okay, I'll start my work soon.
(Reporter)

Comment 8

16 years ago
Kyle, you may be able to save some work by inherited from some of the classes in
nsXULSelectAccessible.cpp, such as nsXULSelectOptionAccessible. I believe
<listitem> uses that, and shares a lot in common with tree items.

Comment 9

16 years ago
Thanks, Aaron. I'll study the present code in detail. Whether I need to append 
the new code to nsXULSelectAccessible.cpp/.h, rather than start a new file?

Comment 10

16 years ago
Jay, I want to help Aaron and John to write the accessibility code of <tree> 
support.

Comment 11

16 years ago
sure, remember to learn as much as possible from aaron and john :)

Jay
(Assignee)

Comment 12

16 years ago
Jay, Kyle:

Go for it. Any help you can give is greatly appreciated since I have been stuck
on the Object tag support work. Look closely at how we have done the
implementation for the other XUL elements. Aaron is correct that you should be
able to inherit from some of the other classes in our directory. If you have any
questions for me just post them in the bug as I read all of my bug mail. :-)

Comment 13

16 years ago
I have almost completed this work. But there are some issues remain:

1) <tree> has different behavior from other XUL element, such as <list>,
   so I can rarely inherit from present classes.
2) currently, nsITreeBoxObject and nsITreeView lacks some functions for
   getting a cell's coordinates(row, column) from a nsIDOMNode*, so I have
   to add some interface into those class.

Comment 14

16 years ago
John, 

In RootAccessible::GetIdFor() function, you use the domNode pointer to 
calculate an Id for each nsIAccessible object. But for <tree> event, there is a 
same domNode pointer for all event, so we can not use this Id to distinguish 
the different objects. I suggest that we move the GetIdFor() from 
RootAccessible to nsIAccessible -- let each nsIAccessible object calculate the 
Id itself. Do you agree with me?

Comment 15

16 years ago
I don't know accessibility code, but this sounds reasonable to me.

Comment 16

16 years ago
Created attachment 80562 [details] [diff] [review]
patch to evaluate


1) Two new classes are introduced: 
nsXULTreeAccessible (corresponding to a tree)
nsXULTreeitemAccessible (corresponding to a tree's row)

Through talking with Jan, I store the row/column for nsXULTreeitemAccessible
(don't use the DOMNode to get anything);

2) Added some event process code for tree event;

3) Added a new attribute in nsIAccessible.idl - long accId (see above comment);

   Added a new method in nsIAccessibilityService.idl - createXULTreeAccessible;


4) Modified some makefiles, property files;

5) Midified tree.xml to support nsIAccessibleProvider interface;

a big patch, 17 files (including 2 new files)

John, can you evaluate this patch when you have time.
(Assignee)

Comment 17

16 years ago
Looks good so far. Unsure if your title means it is ready for full review or
not. Here are some nits and style points I noticed as I read through it:

1) stay away from variable names like bx, tbx -- use the full name: box, treeBox

2) I believe we are going to have to ifdef the XUL dependancies in the
makefiles, grep for MOZ_XUL in the accessible directory and you should see some
examples. Ther reason for this is so we can eliminate XUL accessibility code if
there is no XUL ( for future embedding projects )

3) The comments before the create... method in nsAccessibiltiyService look like
they just got copied from another method

4) you have  a variable in one spot called obx, makes no sense, looks like it
should actually be box. 

5) Style nit: ( and we may be guilty of this in places too ) when declaring a **
as an arg keep the *s together: (nsIFoo **aFoo) in the .cpp files.

As for the functionality, everything looked good as I read through it. I will
take a deeper look at it tomorrow. Let me know if this is ready for actual review .

Great work!

Comment 18

16 years ago
Created attachment 80904 [details] [diff] [review]
patch 1


Hi, John, thanks for your suggestions.

I modified this patch. Now, it's ready for review.

> 1) stay away from variable names like bx, tbx -- use the full name: box,
treeBox
> 4) you have  a variable in one spot called obx, makes no sense, looks like it

> should actually be box. 

Unsuitable abbr variable names were eliminated.

> 2) I believe we are going to have to ifdef the XUL dependancies in the
> makefiles, grep for MOZ_XUL in the accessible directory and you should see
some
> examples. Ther reason for this is so we can eliminate XUL accessibility code
if
> there is no XUL ( for future embedding projects )

I modified some makefiles only for:
1) Add two new files to accessible/src/xul/makefile
2) Add a new include dependence dist/layout_xul to accessible/src/base/makefile

I think they will not impact the MOZ_XUL switch.

BTW, I have not modified the makefile for Mac. I'll look at how to do this
later.

> 3) The comments before the create... method in nsAccessibiltiyService look
like
> they just got copied from another method

Deleted the comments. It's seems redundant. I added some comments for other
functions.

> 5) Style nit: ( and we may be guilty of this in places too ) when declaring a
**
> as an arg keep the *s together: (nsIFoo **aFoo) in the .cpp files.

Spaces were adjusted as your suggestion.

For your checking, I copied somes patches from bug 133366 - I added some new
tree methods in that patch.
Attachment #80562 - Attachment is obsolete: true
(Reporter)

Comment 19

16 years ago
In nsTreeBodyFrame:GetKeyColumnIndex() What if GetElement() returns null?
currCol->GetElement()->GetAttr() ...

In nsXULTreeAccessible::GetAccValue()
view->GetCellText(...);
return NS_OK;
can become
return view->GetCellText(...);

Please don't use |i| in for loops, use |index| or |count| or something we can do
text searches for if we need to.

nsXULTreeitemAccessible::GetAccId() can return a unique id that isn't unique.
For example, f you have 2 trees in a row, 100 bytes apart, the 101st row of the
first tree will have the same id as the 1st row 
of the second tree (or something like that).
I'm not sure what to suggest here, except that we could say a unique ID isn't
necessary for tree items.
However, we use the unique id to remember what accessible object an MSAA event
was generated for, 
so that when the client app calls back we can look it up from our cached list of
recent objects events occured on
The list caches unique ids with their accessibles.
Perhaps RootAccessible::GetIDFor() should return mNextPos+1 for tree items.
Are there files from the widget/src/windows directory missing from this patch?

Did you intend to add a method nsIAccessible::GetAccID()?

In any case we don't see where you're currently using GetAccID() to return the
unique ID. Is there a missing part of this patch?

nsXULTreeItemAccessible overrides GetAccFirstChild, GetAccLastChild and
GetAccChildCount so that there are always 0 children.
Why not just inherit from nsLeafAccessible and get that for free.

nsXULTreeitemAccessible::GetAccBounds is constantly redoing the same
calculations for the upper left corner. 
Can this be cached somewhere in the parent (assuming each child holds onto it's
parent accessible)?

We don't use the prefix letter "b" for booleans, we use "is" as in "isContainerOpen"

I took a look at "Windows Explorer" to see how nested tree row levels are
exposed. They use the value field to expose "1", "2", "3", etc. for the level.
So nsXULTreeItemAcessible::GetAccValue should return "1", "2", "3", etc. for
these levels.
(Reporter)

Comment 20

16 years ago
Has this been tested with trees that use the old syntax?

Comment 21

16 years ago
Hi, Aaron, nice to hear from you, welcome to back :)

> In nsTreeBodyFrame:GetKeyColumnIndex() What if GetElement() returns null?
> currCol->GetElement()->GetAttr() ...

I copied this line from other function, such as nsTreeBodyFrame::PaintColumn. 
But it do have potential risk, I'll modify it.

> nsXULTreeitemAccessible::GetAccId() can return a unique id that isn't unique.
> For example, f you have 2 trees in a row, 100 bytes apart, the 101st row of 
the
> first tree will have the same id as the 1st row 
> of the second tree (or something like that).
> I'm not sure what to suggest here, except that we could say a unique ID isn't
> necessary for tree items.
> However, we use the unique id to remember what accessible object an MSAA event
> was generated for, 
> so that when the client app calls back we can look it up from our cached list 
of
> recent objects events occured on
> The list caches unique ids with their accessibles.
> Perhaps RootAccessible::GetIDFor() should return mNextPos+1 for tree items.
> Are there files from the widget/src/windows directory missing from this patch?

> Did you intend to add a method nsIAccessible::GetAccID()?

> In any case we don't see where you're currently using GetAccID() to return the
> unique ID. Is there a missing part of this patch?

I moved the RootAccessible::GetIDFor() to nsIAccessible::accId, because each 
nsXULTreeitemAccessible has not unique DOMNode pointer for this calculation.
I do implemented nsAccessible::GetAccId() at 143 line of this patch. It was 
just copied from RootAccessible::GetIDFor().

For nsXULTreeitemAccessible::GetAccId(), it is mDOMNode + mRow. So if there are 
many trees, their mDOMNode maybe far different. Is abs(treeA::mDOMNode - 
treeB::mDOMNode) < 100 possible?
I think we do need a unique id for each accessible object to let ATs know where 
the events happen from.

> nsXULTreeitemAccessible::GetAccBounds is constantly redoing the same
> calculations for the upper left corner. 
> Can this be cached somewhere in the parent (assuming each child holds onto 
it's
> parent accessible)?

I think you are right. I'll study how to do that.

> Has this been tested with trees that use the old syntax?

What does "the old syntax" mean? I tested this on Preferences category, Manager 
Bookmark, Mail folder, Mail thread.

I will modify this patch soon to suit your other suggestion.

Thank you very much.

(Assignee)

Comment 22

16 years ago
Here are my suggestions. Some of this may get cleared up when I apply the patch
and run through some testcases. I'll be doing that over the w/end.

- The tree view gets accessed alot, it would make sense to cache that so we
don't have to get it from the mTree all the time

- Isn't it possible that treeitems will be offscreen and/or invisible? you are
just turning those state options off. Perhaps we should check first.

- just because a treeitem is selected doesn't mean it is focused right? perhpas
GetCurrentIndex() is a good choice to see if it is focused

- As for the actions, does it follow that if we are selected we will
expand/collapse? There is only the one action? How do twisties fit in to the
picture?

- how do the columns work into the sibling list? are they siblings? children?
can we focus them individually of the entire row? Are they taken into account
with the name and value?

- what does mColumn represent? mRow is clearly a numeric index, but is mColumn
the text in the column? It's not clear to me.

Style nit:
- alphabetize the #includes ( I know we haven't done it for all the other, but
i'm trying to fix that I go)

Comment 23

16 years ago
> - The tree view gets accessed alot, it would make sense to cache that so we
> don't have to get it from the mTree all the time

Yes, I can do that.

> - Isn't it possible that treeitems will be offscreen and/or invisible? you are
> just turning those state options off. Perhaps we should check first.

Yes, we should check for that by doing some rect intersection tests. Since it's 
a little complex, I'm planning to do that later when the main functionalities 
are accepted by you and aaron.

> - just because a treeitem is selected doesn't mean it is focused right? 
perhpas
> GetCurrentIndex() is a good choice to see if it is focused

Right, I'm confused by selectd/focused.

> - As for the actions, does it follow that if we are selected we will
> expand/collapse? There is only the one action? How do twisties fit in to the
> picture?

The selection should not affect the expand/collapse action. By testing in 
Windows, I did not find any more actions for tree.

> - how do the columns work into the sibling list? are they siblings? children?
> can we focus them individually of the entire row? Are they taken into account
> with the name and value?

By comparing to Windows listview, it uses an object which is a sibling of other 
listitem to represent columns. I think we should do that too. I need another 
two classes: nsXULTreeColumnsAccessible and nsXULTreeColumnitemAccessible.

> - what does mColumn represent? mRow is clearly a numeric index, but is mColumn
> the text in the column? It's not clear to me.

nsITreeBoxObject use a PRInt32 to represent mRow, but use a nsAString to 
represent mColumn. It was obtained by mColElement->GetAttr(kNameSpaceID_None, 
nsHTMLAtoms::id, mID), but I dont know why :) You can see that in 
nsITreeBoxObject.h and nsITreeView.h

> Style nit:
> - alphabetize the #includes ( I know we haven't done it for all the other, but
> i'm trying to fix that I go)

OK, I'll do that.

Thanks for your suggestions.

Comment 24

16 years ago
Please, be carefull with caching of mView.
I mean double check that it doesn't leak.

Comment 25

16 years ago
Created attachment 81271 [details] [diff] [review]
patch 2


Changes:

Follow Aaron's suggestions:
1) view->GetCellText(...);
   return NS_OK;
   to
   return view->GetCellText(...);
   
2) eliminated |i| in loop

3) nsXULTreeItemAccessible inherited from nsLeafAccessible now. 

4) eliminated prefix letter "b" for booleans

5) returned row level from nsXULTreeItemAccessible::GetAccValue

Bounds' upper-left corner and GetAccID() is in progress.

Follow John's suggestions:

1) alphabetized the #includes

2) selected and focused state was distinguished

3) catched mTreeView

4) added support for treecols/treecol

invisible/offscreen state judgement is in progress.
Attachment #80904 - Attachment is obsolete: true
(Reporter)

Comment 26

16 years ago
Kyle,

Thanks for the response. I don't see widget/src/windows/Accessible.cpp in the
patch. I think that needs to be included if you changed RootAccessible to get
the unique ID from nsIAccessible.

The "old syntax" is where <treeitem> nodes are used, where there is a DOM node
for each tree row. For example, see
http://lxr.mozilla.org/seamonkey/source/xpfe/components/prefwindow/resources/content/pref-policies.xul#30

Comment 27

16 years ago
Created attachment 81344 [details] [diff] [review]
patch 3


Sorry, I forgot to include /widget/src/windows/Accessible.cpp into the patch.

I read the pref-policies.xul, its syntax looks like preftree.xul (pref
category) that I tested.
Attachment #81271 - Attachment is obsolete: true
(Reporter)

Comment 28

16 years ago
The formula for nsXULTreeitemAccessible::GetAccId still does not produce unique
ID's. There can be ten thousand rows in a tree - in mail, for example. There is
really no limit.

The formula really needs to be based on the memory address for something that is
allocated on the heap for each tree item. If necessary, 1 byte will have to be
allocated for each row when accessibility is turned on, just to keep a unique ID
around.

The alternative is this: make use of the fact that the ID only needs to be
unique within the realm of the last MAX_LIST_SIZE accessible events (as defined
in Accessible.h). When an accessible object is unable to return a unique ID, the
nsRootAccessible::GetIDFor() can use a rotating list of ID's, from 1 through
MAX_LIST_SIZE.

Comment 29

16 years ago
OK, I'll use this method:

NS_IMETHODIMP nsXULTreeitemAccessible::GetAccId(PRInt32 *aAccId)
{
  // Since mDOMNode is same for all tree item, let RootAccessible generate the 
unique Id
  *aAccId = 0;
  return NS_OK;
}

PRUint32 RootAccessible::GetIdFor(nsIAccessible* aAccessible)
{
  ......

  PRInt32 uniqueID;
  aAccessible->GetAccId(&uniqueID);

  if (uniqueID == 0)  // can't get an unique ID, use the mList's index as the 
unique ID
    uniqueID = mNextPos;

  mList[mNextPos].mId = uniqueID;
  mList[mNextPos].mAccessible = aAccessible;
  
  ......
}

void RootAccessible::GetNSAccessibleFor(VARIANT varChild, 
nsCOMPtr<nsIAccessible>& aAcc)
{
  ......

  aAcc = nsnull;
  if (varChild.lVal < 0) {
    ......
  }
  else if (varChild.lVal < mListCount){
    aAcc = mList[varChild.lVal].mAccessible;
    return;
  }

  Accessible::GetNSAccessibleFor(varChild, aAcc);
}
(Reporter)

Comment 30

16 years ago
Ok, that's a little better.

However, I just realized my suggestion was still not quite right, because ID =
0, means return current accessible, id= 1...n means return nth child accessible.

Therefore, you should always add some number to these ID's generated from the
position in the list.

For example,
const PRInt32 MAX_CHILD_ACCESSIBLES 1000000
if (uniqueID == 0)  // can't get an unique ID, use the mList's index + constant
base number as the unique ID
 uniqueID = mNextPos + MAX_CHILD_ACCESSIBLES;

Then let the id's >=0 && < MAX_CHILD_ACCESSIBLES make it through to
Accessible::GetNSAccessibleFor


Comment 31

16 years ago
Created attachment 82883 [details] [diff] [review]
patch 4 (follow aaron's suggestion)


revise the unique ID generation method and some minor changes.

Arron and John, could you land this patch for testing when you have time?
Attachment #81344 - Attachment is obsolete: true
(Reporter)

Comment 32

16 years ago
Comment on attachment 82883 [details] [diff] [review]
patch 4 (follow aaron's suggestion)

What do you mean, land it for testing?

Do you mean land it on the trunk for testing? We can't land it until it has r=
and sr=.

Maybe you mean apply the patch and test it in our local trees.

Have you tested this yourself yet?
(Reporter)

Comment 33

16 years ago
Comment on attachment 82883 [details] [diff] [review]
patch 4 (follow aaron's suggestion)

Kyle says he has tested it. I like the code. Let's get this superreviewed.
Attachment #82883 - Flags: review+
Comment on attachment 82883 [details] [diff] [review]
patch 4 (follow aaron's suggestion)

- In accessible.properties, add a newline at the end of the file.

- In nsGenericAccessible::GetAccId(), don't you want to assert if this
no-yet-implemented method is ever called? Or at least set the out param to
something (0?) to get consisten behavior if this was ever called.

- In nsRootAccessible.cpp:

+	 accessible = new nsXULTreeitemAccessible(accessible, targetNode,
weakShell, treeIndex);

add some OOM protection after the new.

- In nsXULTreeAccessible::GetAccFirstChild():

+      *aAccFirstChild = new nsXULTreeitemAccessible(this, mDOMNode,
mPresShell, 0);
+      if (! *aAccFirstChild)
+	 return NS_ERROR_FAILURE;

Wouldn't it make more sense to return NS_ERROR_OUT_OF_MEMORY here?

Same thing in nsXULTreeAccessible::GetAccLastChild().

- In nsXULTreeAccessible::GetSelectedChildren():

+  NS_NewISupportsArray(getter_AddRefs(selectedAccessibles));
+  if (!selection || !selectedAccessibles)
+    return NS_ERROR_FAILURE;

I'm not sure what !selection means, but !selectedAccessibles means you're OOM,
so return the proper error code in that case.

And also:

+      tempAccess = new nsXULTreeitemAccessible(this, mDOMNode, mPresShell,
rowIndex);
+      selectedAccessibles->AppendElement(tempAccess);

Check for OOM.

- Why does nsXULTreeAccessible::GetTreeBoxObject() return an error code if it
doesn't find a tree boxobject? Isn't returning null as the box object enough?
Think of returning error codes as throwing exceptions, is this really an
exceptional case?

- In nsXULTreeitemAccessible::GetAccNextSibling() and
nsXULTreeitemAccessible::GetAccPreviousSibling(), return the right error code
if OOM.

- In nsXULTreeitemAccessible::AccGetBounds():

+    boxObject->GetElement(getter_AddRefs(boxElement));
+    if (boxElement) {
+      nsCOMPtr<nsIDOMNode> boxNode(do_QueryInterface(boxElement));
+      if (boxNode) {

You can loose the if (boxElement) check here, do_QueryInterface() is null safe.

Also:

+	       nsCOMPtr<nsIDOMXULElement>
xulElement(do_QueryInterface(childNode));
+	       if (xulElement) {
+		 nsCOMPtr<nsIBoxObject> box(do_QueryInterface(xulElement));
+		 xulElement->GetBoxObject(getter_AddRefs(box));

Why QI xulElement into box when you're immediately after that getting a box
object from xulElement into box? Loose the do_QueryInterface in the initializer
of box.

- In nsXULTreeColumnsAccessible::GetAccNextSibling(), return the proper error
code if OOM.

- In nsXULTreeColumnsAccessible::GetAccPreviousSibling(), don't you want to
return the return value from the call into the inherited method?

- In nsTreeBoxObject::GetColumnID(), truncate the out string if there's no
body.

- In nsTreeBoxObject::GetKeyColumnIndex() default the out param to something
(0?) if there's no body.

sr=jst if you fix all that.

>Index: mozilla/accessible/src/base/makefile.win
>===================================================================
>RCS file: /cvsroot/mozilla/accessible/src/base/makefile.win,v
>retrieving revision 1.4
>diff -u -r1.4 makefile.win
>--- mozilla/accessible/src/base/makefile.win	6 Feb 2002 22:18:57 -0000	1.4
>+++ mozilla/accessible/src/base/makefile.win	9 May 2002 02:21:38 -0000
>@@ -30,6 +30,7 @@
>   gfx \
>   intl \
>   layout \
>+  layout_xul \
>   locale \
>   necko \
>   string \
>Index: mozilla/accessible/src/base/nsAccessibilityService.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/accessible/src/base/nsAccessibilityService.cpp,v
>retrieving revision 1.46
>diff -u -r1.46 nsAccessibilityService.cpp
>--- mozilla/accessible/src/base/nsAccessibilityService.cpp	17 Apr 2002 04:16:19 -0000	1.46
>+++ mozilla/accessible/src/base/nsAccessibilityService.cpp	9 May 2002 02:21:41 -0000
>@@ -78,6 +78,7 @@
> #include "nsXULSelectAccessible.h"
> #include "nsXULTabAccessible.h"
> #include "nsXULTextAccessible.h"
>+#include "nsXULTreeAccessible.h"
> #include "nsIAccessible.h"
> 
> // IFrame
>@@ -1135,6 +1136,56 @@
>   return NS_OK;
> }
> 
>+NS_IMETHODIMP nsAccessibilityService::CreateXULTreeAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
>+{
>+#ifdef MOZ_XUL
>+  nsCOMPtr<nsIWeakReference> weakShell;
>+  GetShellFromNode(aNode, getter_AddRefs(weakShell));
>+
>+  *_retval = new nsXULTreeAccessible(aNode, weakShell);
>+  if (! *_retval) 
>+    return NS_ERROR_OUT_OF_MEMORY;
>+
>+  NS_ADDREF(*_retval);
>+#else
>+  *_retval = nsnull;
>+#endif // MOZ_XUL
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsAccessibilityService::CreateXULTreeColumnsAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
>+{
>+#ifdef MOZ_XUL
>+  nsCOMPtr<nsIWeakReference> weakShell;
>+  GetShellFromNode(aNode, getter_AddRefs(weakShell));
>+
>+  *_retval = new nsXULTreeColumnsAccessible(aNode, weakShell);
>+  if (! *_retval) 
>+    return NS_ERROR_OUT_OF_MEMORY;
>+
>+  NS_ADDREF(*_retval);
>+#else
>+  *_retval = nsnull;
>+#endif // MOZ_XUL
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsAccessibilityService::CreateXULTreeColumnitemAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
>+{
>+#ifdef MOZ_XUL
>+  nsCOMPtr<nsIWeakReference> weakShell;
>+  GetShellFromNode(aNode, getter_AddRefs(weakShell));
>+
>+  *_retval = new nsXULTreeColumnitemAccessible(aNode, weakShell);
>+  if (! *_retval) 
>+    return NS_ERROR_OUT_OF_MEMORY;
>+
>+  NS_ADDREF(*_retval);
>+#else
>+  *_retval = nsnull;
>+#endif // MOZ_XUL
>+  return NS_OK;
>+}
> 
> /**
>   * GetAccessibleFor - get an nsIAccessible from a DOM node
>Index: mozilla/accessible/src/base/nsAccessibilityService.h
>===================================================================
>RCS file: /cvsroot/mozilla/accessible/src/base/nsAccessibilityService.h,v
>retrieving revision 1.13
>diff -u -r1.13 nsAccessibilityService.h
>--- mozilla/accessible/src/base/nsAccessibilityService.h	15 Dec 2001 23:50:13 -0000	1.13
>+++ mozilla/accessible/src/base/nsAccessibilityService.h	9 May 2002 02:21:41 -0000
>@@ -59,9 +59,10 @@
>   // nsIAccessibilityService methods:
>   NS_DECL_NSIACCESSIBILITYSERVICE
> 
>+  static nsresult GetShellFromNode(nsIDOMNode *aNode, nsIWeakReference **weakShell);
>+
> private:
>   nsresult GetInfo(nsISupports* aFrame, nsIFrame** aRealFrame, nsIWeakReference** aShell, nsIDOMNode** aContent);
>-  nsresult GetShellFromNode(nsIDOMNode *aNode, nsIWeakReference **weakShell);
>   void GetOwnerFor(nsIPresShell *aPresShell, nsIPresShell **aOwnerShell, nsIContent **aOwnerContent);
>   nsIContent* FindContentForDocShell(nsIPresShell* aPresShell, nsIContent* aContent, nsIDocShell*  aDocShell);
> };
>Index: mozilla/accessible/src/base/nsAccessible.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/accessible/src/base/nsAccessible.cpp,v
>retrieving revision 1.41
>diff -u -r1.41 nsAccessible.cpp
>--- mozilla/accessible/src/base/nsAccessible.cpp	23 Mar 2002 21:47:56 -0000	1.41
>+++ mozilla/accessible/src/base/nsAccessible.cpp	9 May 2002 02:21:43 -0000
>@@ -472,6 +472,12 @@
>   return NS_ERROR_FAILURE;
> }
> 
>+NS_IMETHODIMP nsAccessible::GetAccId(PRInt32 *aAccId)
>+{
>+  *aAccId = - NS_REINTERPRET_CAST(PRInt32, (mDOMNode.get()));
>+  return NS_OK;
>+}
>+
> NS_IMETHODIMP nsAccessible::CacheOptimizations(nsIAccessible *aParent, PRInt32 aSiblingIndex, nsIDOMNodeList *aSiblingList)
> {
>   if (aParent)
>Index: mozilla/accessible/src/base/nsAccessible.h
>===================================================================
>RCS file: /cvsroot/mozilla/accessible/src/base/nsAccessible.h,v
>retrieving revision 1.25
>diff -u -r1.25 nsAccessible.h
>--- mozilla/accessible/src/base/nsAccessible.h	26 Apr 2002 04:50:17 -0000	1.25
>+++ mozilla/accessible/src/base/nsAccessible.h	9 May 2002 02:21:44 -0000
>@@ -75,6 +75,7 @@
>   virtual ~nsAccessible();
> 
>   NS_IMETHOD GetAccName(nsAString& _retval);
>+  NS_IMETHOD GetAccId(PRInt32 *_retval);
>   NS_IMETHOD GetAccParent(nsIAccessible **_retval); 
>   NS_IMETHOD GetAccNextSibling(nsIAccessible **_retval); 
>   NS_IMETHOD GetAccPreviousSibling(nsIAccessible **_retval); 
>Index: mozilla/accessible/src/base/nsGenericAccessible.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/accessible/src/base/nsGenericAccessible.cpp,v
>retrieving revision 1.15
>diff -u -r1.15 nsGenericAccessible.cpp
>--- mozilla/accessible/src/base/nsGenericAccessible.cpp	23 Mar 2002 21:47:57 -0000	1.15
>+++ mozilla/accessible/src/base/nsGenericAccessible.cpp	9 May 2002 02:21:44 -0000
>@@ -105,6 +105,12 @@
>   return NS_ERROR_NOT_IMPLEMENTED;
> }
> 
>+/* readonly attribute long accId; */
>+NS_IMETHODIMP nsGenericAccessible::GetAccId(PRInt32 *aAccId)
>+{
>+    return NS_ERROR_NOT_IMPLEMENTED;
>+}
>+
> /* void setAccName (in wstring name); */
> NS_IMETHODIMP nsGenericAccessible::SetAccName(const nsAString& name)
> {
>Index: mozilla/accessible/src/base/nsRootAccessible.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/accessible/src/base/nsRootAccessible.cpp,v
>retrieving revision 1.37
>diff -u -r1.37 nsRootAccessible.cpp
>--- mozilla/accessible/src/base/nsRootAccessible.cpp	4 Apr 2002 23:27:43 -0000	1.37
>+++ mozilla/accessible/src/base/nsRootAccessible.cpp	9 May 2002 02:21:50 -0000
>@@ -76,6 +76,9 @@
> #include "nsIScriptGlobalObject.h"
> #include "nsIDOMXULSelectCntrlEl.h"
> #include "nsIDOMXULSelectCntrlItemEl.h"
>+#include "nsXULTreeAccessible.h"
>+#include "nsITreeSelection.h"
>+#include "nsAccessibilityService.h"
> 
> NS_INTERFACE_MAP_BEGIN(nsRootAccessible)
>   NS_INTERFACE_MAP_ENTRY(nsIAccessibleDocument)
>@@ -386,12 +389,33 @@
>       optionTargetNode = do_QueryInterface(selectItem);
>     }
> 
>+    // If it's a tree element, need the currently selected item
>+    PRInt32 treeIndex = -1;
>+    nsCOMPtr<nsITreeBoxObject> treeBox;
>+    nsXULTreeAccessible::GetTreeBoxObject(targetNode, getter_AddRefs(treeBox));
>+    if (treeBox) {
>+      nsCOMPtr<nsITreeSelection> selection;
>+      treeBox->GetSelection(getter_AddRefs(selection));
>+      if (selection)
>+        selection->GetCurrentIndex(&treeIndex);
>+    }
>+
>     nsAutoString eventType;
>     aEvent->GetType(eventType);
> 
>     nsCOMPtr<nsIAccessible> accessible;
> 
>     if (NS_SUCCEEDED(mAccService->GetAccessibleFor(targetNode, getter_AddRefs(accessible)))) {
>+      // tree event
>+      if (treeBox && treeIndex >= 0 && 
>+          (eventType.EqualsIgnoreCase("DOMMenuItemActive") || eventType.EqualsIgnoreCase("select"))) {
>+        nsCOMPtr<nsIWeakReference> weakShell;
>+        nsAccessibilityService::GetShellFromNode(targetNode, getter_AddRefs(weakShell));
>+        accessible = new nsXULTreeitemAccessible(accessible, targetNode, weakShell, treeIndex);
>+        mListener->HandleEvent(nsIAccessibleEventListener::EVENT_FOCUS, accessible);
>+        return NS_OK;
>+      }
>+
>       if (eventType.EqualsIgnoreCase("focus") || eventType.EqualsIgnoreCase("DOMMenuItemActive")) { 
>         if (optionTargetNode &&
>             NS_SUCCEEDED(mAccService->GetAccessibleFor(optionTargetNode, getter_AddRefs(accessible)))) {
>@@ -472,7 +496,10 @@
> }
> 
> // gets Select events when text is selected in a textarea or input
>-NS_IMETHODIMP nsRootAccessible::Select(nsIDOMEvent* aEvent) { return NS_OK; }
>+NS_IMETHODIMP nsRootAccessible::Select(nsIDOMEvent* aEvent) 
>+{
>+  return HandleEvent(aEvent);
>+}
> 
> // gets Input events when text is entered or deleted in a textarea or input
> NS_IMETHODIMP nsRootAccessible::Input(nsIDOMEvent* aEvent) { return NS_OK; }
>Index: mozilla/accessible/src/xul/Makefile.in
>===================================================================
>RCS file: /cvsroot/mozilla/accessible/src/xul/Makefile.in,v
>retrieving revision 1.5
>diff -u -r1.5 Makefile.in
>--- mozilla/accessible/src/xul/Makefile.in	18 Dec 2001 02:05:23 -0000	1.5
>+++ mozilla/accessible/src/xul/Makefile.in	9 May 2002 02:21:51 -0000
>@@ -39,6 +39,7 @@
>   imglib2 \
>   intl \
>   layout \
>+  layout_xul \
>   locale \
>   necko \
>   string \
>@@ -57,6 +58,7 @@
>   nsXULSelectAccessible.cpp \
>   nsXULTabAccessible.cpp \
>   nsXULTextAccessible.cpp \
>+  nsXULTreeAccessible.cpp \
>   $(NULL)
> 
> # we don't want the shared lib, but we want to force the creation of a static lib.
>Index: mozilla/accessible/src/xul/makefile.win
>===================================================================
>RCS file: /cvsroot/mozilla/accessible/src/xul/makefile.win,v
>retrieving revision 1.8
>diff -u -r1.8 makefile.win
>--- mozilla/accessible/src/xul/makefile.win	21 Mar 2002 07:33:36 -0000	1.8
>+++ mozilla/accessible/src/xul/makefile.win	9 May 2002 02:21:52 -0000
>@@ -27,6 +27,7 @@
>   dom \
>   gfx \
>   layout \
>+  layout_xul \
>   necko \
>   string \
>   widget \
>@@ -40,6 +41,7 @@
>   .\$(OBJDIR)\nsXULSelectAccessible.obj \
>   .\$(OBJDIR)\nsXULTabAccessible.obj \
>   .\$(OBJDIR)\nsXULTextAccessible.obj \
>+  .\$(OBJDIR)\nsXULTreeAccessible.obj \
>   $(NULL)
> 
> EXPORTS = \
>Index: mozilla/accessible/src/xul/nsXULTreeAccessible.cpp
>===================================================================
>RCS file: nsXULTreeAccessible.cpp
>diff -N nsXULTreeAccessible.cpp
>--- /dev/null	Sat Apr 27 17:00:34 2002
>+++ mozilla/accessible/src/xul/nsXULTreeAccessible.cpp	Sat Apr 27 18:03:26 2002
>@@ -0,0 +1,622 @@
>+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
>+/* ***** BEGIN LICENSE BLOCK *****
>+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
>+ *
>+ * The contents of this file are subject to the Netscape 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/NPL/
>+ *
>+ * 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) 1998
>+ * the Initial Developer. All Rights Reserved.
>+ *
>+ * Contributor(s):
>+ * Author: Kyle Yuan (kyle.yuan@sun.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
>+ * 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 NPL, 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 NPL, the GPL or the LGPL.
>+ *
>+ * ***** END LICENSE BLOCK ***** */
>+
>+#include "nsCOMPtr.h"
>+#include "nsIAccessibilityService.h"
>+#include "nsIBoxObject.h"
>+#include "nsIDOMNodeList.h"
>+#include "nsIDOMXULElement.h"
>+#include "nsITreeSelection.h"
>+#include "nsITreeView.h"
>+#include "nsXULAtoms.h"
>+#include "nsXULTreeAccessible.h"
>+
>+// ---------- nsXULTreeAccessible ----------
>+
>+nsXULTreeAccessible::nsXULTreeAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
>+nsAccessible(aDOMNode, aShell)
>+{
>+  GetTreeBoxObject(aDOMNode, getter_AddRefs(mTree));
>+  if (mTree)
>+    mTree->GetView(getter_AddRefs(mTreeView));
>+  NS_ASSERTION(mTree && mTreeView, "Can't get mTree or mTreeView!\n");
>+}
>+
>+NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeAccessible, nsAccessible, nsIAccessibleSelectable)
>+
>+NS_IMETHODIMP nsXULTreeAccessible::GetAccState(PRUint32 *_retval)
>+{
>+  // Get focus status from base class
>+  nsAccessible::GetAccState(_retval);
>+
>+  // see if we are multiple select if so set ourselves as such
>+  nsCOMPtr<nsIDOMElement> element (do_QueryInterface(mDOMNode));
>+  if (element) {
>+    nsAutoString selType;
>+    element->GetAttribute(NS_LITERAL_STRING("seltype"), selType);
>+    if (!selType.IsEmpty() && selType.Equals(NS_LITERAL_STRING("multiple")))
>+        *_retval |= STATE_MULTISELECTABLE;
>+  }
>+
>+  *_retval |= STATE_READONLY | STATE_FOCUSABLE;
>+
>+  return NS_OK;
>+}
>+
>+// The value is the first selected child
>+NS_IMETHODIMP nsXULTreeAccessible::GetAccValue(nsAString& _retval)
>+{
>+  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
>+
>+  nsCOMPtr<nsITreeSelection> selection;
>+  mTree->GetSelection(getter_AddRefs(selection));
>+  if (selection) {
>+    PRInt32 currentIndex;
>+    nsCOMPtr<nsIDOMElement> selectItem;
>+    selection->GetCurrentIndex(&currentIndex);
>+
>+    nsAutoString colID;
>+    PRInt32 keyColumn;
>+    mTree->GetKeyColumnIndex(&keyColumn);
>+    mTree->GetColumnID(keyColumn, colID);
>+    return mTreeView->GetCellText(currentIndex, colID.get(), _retval);
>+    }
>+
>+  return NS_ERROR_FAILURE;
>+}
>+
>+NS_IMETHODIMP nsXULTreeAccessible::GetAccRole(PRUint32 *_retval)
>+{
>+  *_retval = ROLE_OUTLINE;
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsXULTreeAccessible::GetAccFirstChild(nsIAccessible **aAccFirstChild)
>+{
>+  nsAccessible::GetAccFirstChild(aAccFirstChild);
>+
>+  // in normal case, tree's first child should be treecols, if it is not here, 
>+  //   use the first row as tree's first child
>+  if (*aAccFirstChild == nsnull) {
>+    NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
>+
>+    PRInt32 rowCount;
>+    mTreeView->GetRowCount(&rowCount);
>+    if (rowCount > 0) {
>+      *aAccFirstChild = new nsXULTreeitemAccessible(this, mDOMNode, mPresShell, 0);
>+      if (! *aAccFirstChild)
>+        return NS_ERROR_FAILURE;
>+      NS_ADDREF(*aAccFirstChild);
>+    }
>+  }
>+
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsXULTreeAccessible::GetAccLastChild(nsIAccessible **aAccLastChild)
>+{
>+  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
>+
>+  PRInt32 rowCount;
>+  mTreeView->GetRowCount(&rowCount);
>+  if (rowCount > 0) {
>+    *aAccLastChild = new nsXULTreeitemAccessible(this, mDOMNode, mPresShell, rowCount - 1);
>+    if (! *aAccLastChild)
>+      return NS_ERROR_FAILURE;
>+    NS_ADDREF(*aAccLastChild);
>+  }
>+  else // if there is not any rows, use treecols as tree's last child
>+    nsAccessible::GetAccLastChild(aAccLastChild);
>+
>+  return NS_OK;
>+}
>+
>+// tree's children count is row count + treecols count
>+NS_IMETHODIMP nsXULTreeAccessible::GetAccChildCount(PRInt32 *aAccChildCount)
>+{
>+  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
>+
>+  nsAccessible::GetAccChildCount(aAccChildCount);
>+
>+  PRInt32 rowCount;
>+  mTreeView->GetRowCount(&rowCount);
>+  *aAccChildCount += rowCount;
>+
>+  return NS_OK;
>+}
>+
>+// Ask treeselection to get all selected children
>+NS_IMETHODIMP nsXULTreeAccessible::GetSelectedChildren(nsISupportsArray **_retval)
>+{
>+  *_retval = nsnull;
>+
>+  nsCOMPtr<nsITreeSelection> selection;
>+  mTree->GetSelection(getter_AddRefs(selection));
>+  nsCOMPtr<nsISupportsArray> selectedAccessibles;
>+  NS_NewISupportsArray(getter_AddRefs(selectedAccessibles));
>+  if (!selection || !selectedAccessibles)
>+    return NS_ERROR_FAILURE;
>+
>+  PRInt32 rowIndex, rowCount;
>+  PRBool isSelected;
>+  mTreeView->GetRowCount(&rowCount);
>+  for (rowIndex = 0; rowIndex < rowCount; rowIndex++) {
>+    selection->IsSelected(rowIndex, &isSelected);
>+    if (isSelected) {
>+      nsCOMPtr<nsIAccessible> tempAccess;
>+      tempAccess = new nsXULTreeitemAccessible(this, mDOMNode, mPresShell, rowIndex);
>+      selectedAccessibles->AppendElement(tempAccess);
>+    }
>+  }
>+
>+  PRUint32 length;
>+  selectedAccessibles->Count(&length);
>+  if (length != 0) {
>+    *_retval = selectedAccessibles;
>+    NS_IF_ADDREF(*_retval);
>+  }
>+
>+  return NS_OK;
>+}
>+
>+// Get the nsITreeBoxObject interface from any levels DOMNode under the <tree>
>+nsresult nsXULTreeAccessible::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.Equals(NS_LITERAL_STRING("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 NS_OK;
>+        }
>+      }
>+    }
>+    currentNode->GetParentNode(getter_AddRefs(parentNode));
>+    currentNode = parentNode;
>+  }
>+
>+  *aBoxObject = nsnull;
>+  return NS_ERROR_FAILURE;
>+}
>+
>+// ---------- nsXULTreeitemAccessible ---------- 
>+
>+nsXULTreeitemAccessible::nsXULTreeitemAccessible(nsIAccessible *aParent, nsIDOMNode *aDOMNode, nsIWeakReference *aShell, PRInt32 aRow):
>+nsLeafAccessible(aDOMNode, aShell)
>+{
>+  mParent = aParent;
>+
>+  nsXULTreeAccessible::GetTreeBoxObject(aDOMNode, getter_AddRefs(mTree));
>+  if (mTree)
>+    mTree->GetView(getter_AddRefs(mTreeView));
>+  NS_ASSERTION(mTree && mTreeView, "Can't get mTree or mTreeView!\n");
>+
>+  // Since the real tree item does not correspond to any DOMNode, use the row index to distinguish each item
>+  mRow = aRow;
>+  if (mTree) {
>+    PRInt32 keyColumn;
>+    mTree->GetKeyColumnIndex(&keyColumn);
>+    mTree->GetColumnID(keyColumn, mColumn);
>+  }
>+}
>+
>+NS_IMPL_ISUPPORTS_INHERITED0(nsXULTreeitemAccessible, nsLeafAccessible)
>+
>+NS_IMETHODIMP nsXULTreeitemAccessible::GetAccName(nsAString& _retval)
>+{
>+  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
>+
>+  return mTreeView->GetCellText(mRow, mColumn.get(), _retval);
>+}
>+
>+NS_IMETHODIMP nsXULTreeitemAccessible::GetAccValue(nsAString& _retval)
>+{
>+  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
>+
>+  PRInt32 level;
>+  mTreeView->GetLevel(mRow, &level);
>+
>+  nsCString str;
>+  str.AppendInt(level);
>+  _retval = NS_ConvertASCIItoUCS2(str);
>+
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsXULTreeitemAccessible::GetAccId(PRInt32 *aAccId)
>+{
>+  // Since mDOMNode is same for all tree item, let RootAccessible generate the unique Id
>+  *aAccId = 0;
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsXULTreeitemAccessible::GetAccRole(PRUint32 *_retval)
>+{
>+  *_retval = ROLE_OUTLINEITEM;
>+  return NS_OK;
>+}
>+
>+// Possible states: focused, focusable, selected, expanded/collapsed
>+NS_IMETHODIMP nsXULTreeitemAccessible::GetAccState(PRUint32 *_retval)
>+{
>+  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
>+
>+  *_retval = STATE_FOCUSABLE;
>+
>+  // get expanded/collapsed state
>+  PRBool isContainer, isContainerOpen;
>+  mTreeView->IsContainer(mRow, &isContainer);
>+  if (isContainer) {
>+    mTreeView->IsContainerOpen(mRow, &isContainerOpen);
>+    if (isContainerOpen)
>+      *_retval |= STATE_EXPANDED;
>+    else
>+      *_retval |= STATE_COLLAPSED;
>+  }
>+
>+  // get selected state
>+  nsCOMPtr<nsITreeSelection> selection;
>+  mTree->GetSelection(getter_AddRefs(selection));
>+  if (selection) {
>+    PRBool isSelected, currentIndex;
>+    selection->IsSelected(mRow, &isSelected);
>+    if (isSelected)
>+      *_retval |= STATE_SELECTED;
>+    selection->GetCurrentIndex(&currentIndex);
>+    if (currentIndex == mRow)
>+      *_retval |= STATE_FOCUSED;
>+  }
>+
>+  PRInt32 firstVisibleRow, lastVisibleRow;
>+  mTree->GetFirstVisibleRow(&firstVisibleRow);
>+  mTree->GetLastVisibleRow(&lastVisibleRow);
>+  if (mRow < firstVisibleRow || mRow > lastVisibleRow)
>+    *_retval |= STATE_INVISIBLE;
>+
>+  return NS_OK;
>+}
>+
>+// Only one actions available
>+NS_IMETHODIMP nsXULTreeitemAccessible::GetAccNumActions(PRUint8 *_retval)
>+{
>+  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
>+
>+  *_retval = eNo_Action;
>+
>+  PRBool isContainer;
>+  mTreeView->IsContainer(mRow, &isContainer);
>+  if (isContainer)
>+    *_retval = eSingle_Action;
>+
>+  return NS_OK;
>+}
>+
>+// Return the name of our only action
>+NS_IMETHODIMP nsXULTreeitemAccessible::GetAccActionName(PRUint8 index, nsAString& _retval)
>+{
>+  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
>+
>+  if (index == eAction_Click) {
>+    PRBool isContainer, isContainerOpen;
>+    mTreeView->IsContainer(mRow, &isContainer);
>+    if (isContainer) {
>+      mTreeView->IsContainerOpen(mRow, &isContainerOpen);
>+      if (isContainerOpen)
>+        nsAccessible::GetTranslatedString(NS_LITERAL_STRING("collapse"), _retval);
>+      else
>+        nsAccessible::GetTranslatedString(NS_LITERAL_STRING("expand"), _retval);
>+    }
>+
>+    return NS_OK;
>+  }
>+
>+  return NS_ERROR_INVALID_ARG;
>+}
>+
>+NS_IMETHODIMP nsXULTreeitemAccessible::GetAccParent(nsIAccessible **aAccParent)
>+{
>+  *aAccParent = nsnull;
>+
>+  if (mParent) {
>+    *aAccParent = mParent;
>+    NS_ADDREF(*aAccParent);
>+  }
>+
>+  return NS_OK;
>+}
>+
>+// Return the next row of tree (if any)
>+NS_IMETHODIMP nsXULTreeitemAccessible::GetAccNextSibling(nsIAccessible **aAccNextSibling)
>+{
>+  *aAccNextSibling = nsnull;
>+
>+  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
>+
>+  PRInt32 rowCount;
>+  mTreeView->GetRowCount(&rowCount);
>+
>+  if (mRow < rowCount - 1) {
>+    *aAccNextSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mPresShell, mRow + 1);
>+    if (! *aAccNextSibling)
>+      return NS_ERROR_FAILURE;
>+    NS_ADDREF(*aAccNextSibling);
>+  }
>+
>+  return NS_OK;
>+}
>+
>+// Return the previous row of tree (if any)
>+NS_IMETHODIMP nsXULTreeitemAccessible::GetAccPreviousSibling(nsIAccessible **aAccPreviousSibling)
>+{
>+  *aAccPreviousSibling = nsnull;
>+
>+  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
>+
>+  if (mRow > 0) {
>+    *aAccPreviousSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mPresShell, mRow - 1);
>+    if (! *aAccPreviousSibling)
>+      return NS_ERROR_FAILURE;
>+    NS_ADDREF(*aAccPreviousSibling);
>+  }
>+
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsXULTreeitemAccessible::AccDoAction(PRUint8 index)
>+{
>+  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
>+
>+  if (index == eAction_Click)
>+    return mTreeView->ToggleOpenState(mRow);
>+
>+  return NS_ERROR_INVALID_ARG;
>+}
>+
>+NS_IMETHODIMP nsXULTreeitemAccessible::AccGetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height)
>+{
>+  *x = *y = *width = *height = 0;
>+
>+  NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
>+
>+  const PRUnichar empty[] = {'\0'};
>+
>+  // This Bounds are based on Tree's coord
>+  mTree->GetCoordsForCellItem(mRow, mColumn.get(), empty, x, y, width, height);
>+
>+  // Get treechildren's BoxObject to adjust the Bounds' upper left corner
>+  nsCOMPtr<nsIBoxObject> boxObject(do_QueryInterface(mTree));
>+  if (boxObject) {
>+    nsCOMPtr<nsIDOMElement> boxElement;
>+    boxObject->GetElement(getter_AddRefs(boxElement));
>+    if (boxElement) {
>+      nsCOMPtr<nsIDOMNode> boxNode(do_QueryInterface(boxElement));
>+      if (boxNode) {
>+        nsCOMPtr<nsIDOMNodeList> childNodes;
>+        boxNode->GetChildNodes(getter_AddRefs(childNodes));
>+        if (childNodes) {
>+          nsAutoString name;
>+          nsCOMPtr<nsIDOMNode> childNode;
>+          PRUint32 childCount, childIndex;
>+
>+          childNodes->GetLength(&childCount);
>+          for (childIndex = 0; childIndex < childCount; childIndex++) {
>+            childNodes->Item(childIndex, getter_AddRefs(childNode));
>+            childNode->GetLocalName(name);
>+            if (name.Equals(NS_LITERAL_STRING("treechildren"))) {
>+              nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(childNode));
>+              if (xulElement) {
>+                nsCOMPtr<nsIBoxObject> box(do_QueryInterface(xulElement));
>+                xulElement->GetBoxObject(getter_AddRefs(box));
>+                if (box) {
>+                  PRInt32 myX, myY;
>+                  box->GetScreenX(&myX);
>+                  box->GetScreenY(&myY);
>+                  *x += myX;
>+                  *y += myY;
>+                }
>+              }
>+              break;
>+            }
>+          }
>+        }
>+      }
>+    }
>+  }
>+
>+  return NS_OK;
>+}
>+
>+// ---------- nsXULTreeColumnsAccessible ----------
>+
>+nsXULTreeColumnsAccessible::nsXULTreeColumnsAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
>+nsAccessible(aDOMNode, aShell)
>+{
>+}
>+
>+NS_IMPL_ISUPPORTS_INHERITED0(nsXULTreeColumnsAccessible, nsAccessible)
>+
>+NS_IMETHODIMP nsXULTreeColumnsAccessible::GetAccState(PRUint32 *_retval)
>+{
>+  *_retval = STATE_READONLY;
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsXULTreeColumnsAccessible::GetAccRole(PRUint32 *_retval)
>+{
>+  *_retval = ROLE_LIST;
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsXULTreeColumnsAccessible::GetAccNumActions(PRUint8 *_retval)
>+{
>+  *_retval = eSingle_Action;
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsXULTreeColumnsAccessible::GetAccActionName(PRUint8 index, nsAString& _retval)
>+{
>+  if (index == eAction_Click) {
>+    nsAccessible::GetTranslatedString(NS_LITERAL_STRING("click"), _retval);
>+    return NS_OK;
>+  }
>+
>+  return NS_ERROR_INVALID_ARG;
>+}
>+
>+NS_IMETHODIMP nsXULTreeColumnsAccessible::GetAccNextSibling(nsIAccessible **aAccNextSibling) 
>+{ 
>+  nsAccessible::GetAccNextSibling(aAccNextSibling);
>+
>+  if (*aAccNextSibling == nsnull) { // if there is not other sibling, use the first row as its sibling
>+    nsCOMPtr<nsITreeBoxObject> tree;
>+    nsCOMPtr<nsITreeView> treeView;
>+
>+    nsXULTreeAccessible::GetTreeBoxObject(mDOMNode, getter_AddRefs(tree));
>+    if (tree) {
>+      tree->GetView(getter_AddRefs(treeView));
>+      if (treeView) {
>+        PRInt32 rowCount;
>+        treeView->GetRowCount(&rowCount);
>+
>+        if (rowCount > 0) {
>+          *aAccNextSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mPresShell, 0);
>+          if (! *aAccNextSibling)
>+            return NS_ERROR_FAILURE;
>+          NS_ADDREF(*aAccNextSibling);
>+        }
>+      }
>+    }
>+  }
>+
>+  return NS_OK;  
>+}
>+
>+NS_IMETHODIMP nsXULTreeColumnsAccessible::GetAccPreviousSibling(nsIAccessible **aAccPreviousSibling) 
>+{  
>+  nsAccessible::GetAccPreviousSibling(aAccPreviousSibling);
>+
>+  return NS_OK;  
>+}
>+
>+NS_IMETHODIMP nsXULTreeColumnsAccessible::AccDoAction(PRUint8 index)
>+{
>+  if (index == eAction_Click)
>+    return NS_OK;
>+
>+  return NS_ERROR_INVALID_ARG;
>+}
>+
>+// ---------- nsXULTreeColumnitemAccessible ----------
>+
>+nsXULTreeColumnitemAccessible::nsXULTreeColumnitemAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
>+nsLeafAccessible(aDOMNode, aShell)
>+{
>+}
>+
>+NS_IMPL_ISUPPORTS_INHERITED0(nsXULTreeColumnitemAccessible, nsLeafAccessible)
>+
>+NS_IMETHODIMP nsXULTreeColumnitemAccessible::GetAccState(PRUint32 *_retval)
>+{
>+  *_retval = STATE_READONLY;
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsXULTreeColumnitemAccessible::GetAccName(nsAString& _retval)
>+{
>+  return GetXULAccName(_retval);
>+}
>+
>+NS_IMETHODIMP nsXULTreeColumnitemAccessible::GetAccRole(PRUint32 *_retval)
>+{
>+  *_retval = ROLE_COLUMNHEADER;
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsXULTreeColumnitemAccessible::GetAccNumActions(PRUint8 *_retval)
>+{
>+  *_retval = eSingle_Action;
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsXULTreeColumnitemAccessible::GetAccActionName(PRUint8 index, nsAString& _retval)
>+{
>+  if (index == eAction_Click) {
>+    nsAccessible::GetTranslatedString(NS_LITERAL_STRING("click"), _retval);
>+    return NS_OK;
>+  }
>+
>+  return NS_ERROR_INVALID_ARG;
>+}
>+
>+NS_IMETHODIMP nsXULTreeColumnitemAccessible::AccDoAction(PRUint8 index)
>+{
>+  if (index == eAction_Click) {
>+    nsCOMPtr<nsITreeBoxObject> tree;
>+    nsCOMPtr<nsITreeView> treeView;
>+
>+    nsXULTreeAccessible::GetTreeBoxObject(mDOMNode, getter_AddRefs(tree));
>+    if (tree) {
>+      tree->GetView(getter_AddRefs(treeView));
>+      if (treeView) {
>+        nsCOMPtr<nsIDOMElement> colElement(do_QueryInterface(mDOMNode));
>+        if (colElement) {
>+          nsAutoString colID;
>+          colElement->GetAttribute(NS_LITERAL_STRING("id"), colID);
>+          treeView->CycleHeader(colID.get(), colElement);
>+        }
>+      }
>+    }
>+
>+    return NS_OK;
>+  }
>+
>+  return NS_ERROR_INVALID_ARG;
>+}
>Index: mozilla/accessible/src/xul/nsXULTreeAccessible.h
>===================================================================
>RCS file: nsXULTreeAccessible.h
>diff -N nsXULTreeAccessible.h
>--- /dev/null	Sat Apr 27 17:00:34 2002
>+++ mozilla/accessible/src/xul/nsXULTreeAccessible.h	Sat Apr 27 18:03:26 2002
>@@ -0,0 +1,152 @@
>+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
>+/* ***** BEGIN LICENSE BLOCK *****
>+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
>+ *
>+ * The contents of this file are subject to the Netscape 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/NPL/
>+ *
>+ * 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) 1998
>+ * the Initial Developer. All Rights Reserved.
>+ *
>+ * Contributor(s):
>+ * Author: Kyle Yuan (kyle.yuan@sun.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
>+ * 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 NPL, 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 NPL, the GPL or the LGPL.
>+ *
>+ * ***** END LICENSE BLOCK ***** */
>+#ifndef __nsXULTreeAccessible_h__
>+#define __nsXULTreeAccessible_h__
>+
>+#include "nsAccessible.h"
>+#include "nsBaseWidgetAccessible.h"
>+#include "nsCOMPtr.h"
>+#include "nsIAccessibleSelectable.h"
>+#include "nsIDOMNode.h"
>+#include "nsIWeakReference.h"
>+#include "nsITreeBoxObject.h"
>+#include "nsITreeView.h"
>+
>+/*
>+ * A class the represents the XUL Tree widget.
>+ */
>+class nsXULTreeAccessible : public nsAccessible,
>+                            public nsIAccessibleSelectable
>+{
>+public:
>+  NS_DECL_ISUPPORTS_INHERITED
>+  NS_DECL_NSIACCESSIBLESELECTABLE
>+
>+  nsXULTreeAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
>+  virtual ~nsXULTreeAccessible() {}
>+
>+  /* ----- nsIAccessible ----- */
>+  NS_IMETHOD GetAccRole(PRUint32 *_retval);
>+  NS_IMETHOD GetAccState(PRUint32 *_retval);
>+  NS_IMETHOD GetAccValue(nsAString& _retval);
>+
>+  NS_IMETHOD GetAccFirstChild(nsIAccessible **_retval);
>+  NS_IMETHOD GetAccLastChild(nsIAccessible **_retval);
>+  NS_IMETHOD GetAccChildCount(PRInt32 *_retval);
>+
>+  static nsresult GetTreeBoxObject(nsIDOMNode* aDOMNode, nsITreeBoxObject** aBoxObject);
>+
>+private:
>+  nsCOMPtr<nsITreeBoxObject> mTree;
>+  nsCOMPtr<nsITreeView> mTreeView;
>+};
>+
>+/**
>+  * Treeitems -- used in Trees
>+  */
>+class nsXULTreeitemAccessible : public nsLeafAccessible
>+{
>+public:
>+  NS_DECL_ISUPPORTS_INHERITED
>+
>+  nsXULTreeitemAccessible(nsIAccessible* aParent, nsIDOMNode* aDOMNode, nsIWeakReference* aShell, PRInt32 aRow);
>+  virtual ~nsXULTreeitemAccessible() {}
>+
>+  /* ----- nsIAccessible ----- */
>+  NS_IMETHOD GetAccName(nsAString& _retval);
>+  NS_IMETHOD GetAccValue(nsAString& _retval);
>+  NS_IMETHOD GetAccId(PRInt32 *_retval);
>+  NS_IMETHOD GetAccRole(PRUint32 *_retval);
>+  NS_IMETHOD GetAccState(PRUint32 *_retval);
>+  NS_IMETHOD GetAccNumActions(PRUint8 *_retval);
>+  NS_IMETHOD GetAccActionName(PRUint8 index, nsAString& _retval);
>+
>+  NS_IMETHOD GetAccParent(nsIAccessible **_retval);
>+  NS_IMETHOD GetAccNextSibling(nsIAccessible **_retval);
>+  NS_IMETHOD GetAccPreviousSibling(nsIAccessible **_retval);
>+
>+  NS_IMETHOD AccDoAction(PRUint8 index);
>+  NS_IMETHOD AccGetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
>+
>+private:
>+  nsCOMPtr<nsITreeBoxObject> mTree;
>+  nsCOMPtr<nsITreeView> mTreeView;
>+  PRInt32  mRow;
>+  nsString mColumn;
>+};
>+
>+class nsXULTreeColumnsAccessible : public nsAccessible
>+{
>+public:
>+  NS_DECL_ISUPPORTS_INHERITED
>+
>+  nsXULTreeColumnsAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
>+  virtual ~nsXULTreeColumnsAccessible() {}
>+
>+  /* ----- nsIAccessible ----- */
>+  NS_IMETHOD GetAccRole(PRUint32 *_retval);
>+  NS_IMETHOD GetAccState(PRUint32 *_retval);
>+  NS_IMETHOD GetAccNumActions(PRUint8 *_retval);
>+  NS_IMETHOD GetAccActionName(PRUint8 index, nsAString& _retval);
>+
>+  NS_IMETHOD GetAccNextSibling(nsIAccessible **_retval); 
>+  NS_IMETHOD GetAccPreviousSibling(nsIAccessible **_retval); 
>+
>+  NS_IMETHOD AccDoAction(PRUint8 index);
>+};
>+
>+class nsXULTreeColumnitemAccessible : public nsLeafAccessible
>+{
>+public:
>+  NS_DECL_ISUPPORTS_INHERITED
>+
>+  nsXULTreeColumnitemAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell);
>+  virtual ~nsXULTreeColumnitemAccessible() {}
>+
>+  /* ----- nsIAccessible ----- */
>+  NS_IMETHOD GetAccName(nsAString& _retval);
>+  NS_IMETHOD GetAccRole(PRUint32 *_retval);
>+  NS_IMETHOD GetAccState(PRUint32 *_retval);
>+  NS_IMETHOD GetAccNumActions(PRUint8 *_retval);
>+  NS_IMETHOD GetAccActionName(PRUint8 index, nsAString& _retval);
>+
>+  NS_IMETHOD AccDoAction(PRUint8 index);
>+};
>+
>+#endif
>Index: mozilla/xpfe/global/resources/content/bindings/tree.xml
>===================================================================
>RCS file: /cvsroot/mozilla/xpfe/global/resources/content/bindings/tree.xml,v
>retrieving revision 1.12
>diff -u -r1.12 tree.xml
>--- mozilla/xpfe/global/resources/content/bindings/tree.xml	24 Apr 2002 18:06:00 -0000	1.12
>+++ mozilla/xpfe/global/resources/content/bindings/tree.xml	9 May 2002 02:28:47 -0000
>@@ -19,13 +19,24 @@
>       </xul:treerows>
>     </content>
>     
>-    <implementation>
>+    <implementation implements="nsIAccessibleProvider">
>       <constructor>
>         this.addEventListener("DOMMouseScroll", this._handleMouseScroll, true);
>         if (navigator.platform.indexOf("Mac") != -1)
>           this.pageUpOrDownMovesSelection = false;
>       </constructor>
> 
>+      <!-- ///////////////// nsIAccessibleProvider ///////////////// -->
>+
>+      <property name="accessible">
>+        <getter>
>+          <![CDATA[
>+            var accService = Components.classes["@mozilla.org/accessibilityService;1"].getService(Components.interfaces.nsIAccessibilityService);
>+            return accService.createXULTreeAccessible(this);
>+          ]]>
>+        </getter>
>+      </property>
>+
>       <property name="treeBoxObject"
>                 onget="return this.boxObject.QueryInterface(Components.interfaces.nsITreeBoxObject);"
>                 readonly="true"/>
>@@ -588,6 +599,16 @@
>       <children includes="treecol|splitter"/>
>       <xul:treecolpicker class="treecol-image" fixed="true" ordinal="2147483647"/>
>     </content>
>+    <implementation implements="nsIAccessibleProvider">
>+      <property name="accessible">
>+        <getter>
>+          <![CDATA[
>+            var accService = Components.classes["@mozilla.org/accessibilityService;1"].getService(Components.interfaces.nsIAccessibilityService);
>+            return accService.createXULTreeColumnsAccessible(this);
>+          ]]>
>+        </getter>
>+      </property>
>+    </implementation>
>   </binding>
> 
>   <binding id="treerows" extends="chrome://global/content/bindings/tree.xml#tree-base">
>@@ -914,6 +935,16 @@
>       <xul:label class="treecol-text" xbl:inherits="crop,value=label" flex="1" crop="right"/>
>       <xul:image class="treecol-sortdirection" xbl:inherits="sortDirection"/>
>     </content>
>+    <implementation implements="nsIAccessibleProvider">
>+      <property name="accessible">
>+        <getter>
>+          <![CDATA[
>+            var accService = Components.classes["@mozilla.org/accessibilityService;1"].getService(Components.interfaces.nsIAccessibilityService);
>+            return accService.createXULTreeColumnitemAccessible(this);
>+          ]]>
>+        </getter>
>+      </property>
>+    </implementation>
> 
>     <handlers>
>       <handler event="click" button="0" action="if (event.originalTarget == this) { this.parentNode.parentNode.treeBoxObject.view.cycleHeader(this.id, this); }"/>
>Index: mozilla/layout/xul/base/src/tree/public/nsITreeBoxObject.idl
>===================================================================
>RCS file: /cvsroot/mozilla/layout/xul/base/src/tree/public/nsITreeBoxObject.idl,v
>retrieving revision 1.22
>diff -u -r1.22 nsITreeBoxObject.idl
>--- mozilla/layout/xul/base/src/tree/public/nsITreeBoxObject.idl	29 Mar 2002 02:44:30 -0000	1.22
>+++ mozilla/layout/xul/base/src/tree/public/nsITreeBoxObject.idl	9 May 2002 02:30:28 -0000
>@@ -80,6 +80,16 @@
>   long getColumnIndex(in wstring colID);
> 
>   /**
>+   * Get the ID of the specified column.
>+   */
>+  AString getColumnID(in long colIndex);
>+
>+  /**
>+   * Get the index of the primary column.
>+   */
>+  long getKeyColumnIndex();
>+
>+  /**
>    * Get the index of the first visible row.
>    */
>   long getFirstVisibleRow();
>Index: mozilla/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp,v
>retrieving revision 1.121
>diff -u -r1.121 nsTreeBodyFrame.cpp
>--- mozilla/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp	23 Apr 2002 10:36:23 -0000	1.121
>+++ mozilla/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp	9 May 2002 02:30:40 -0000
>@@ -737,6 +737,59 @@
>   return NS_OK;
> }
> 
>+NS_IMETHODIMP nsTreeBodyFrame::GetColumnID(PRInt32 colIndex, nsAString & _retval)
>+{
>+  _retval = NS_LITERAL_STRING("");
>+  for (nsTreeColumn* currCol = mColumns; currCol; currCol = currCol->GetNext()) {
>+    if (currCol->GetColIndex() == colIndex) {
>+      _retval = currCol->GetID();
>+      break;
>+    }
>+  }
>+
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsTreeBodyFrame::GetKeyColumnIndex(PRInt32 *_retval)
>+{
>+  nsAutoString attr;
>+  PRInt32 first, primary, sorted;
>+
>+  first = primary = sorted = -1;
>+  for (nsTreeColumn* currCol = mColumns; currCol; currCol = currCol->GetNext()) {
>+    // Skip hidden column
>+    currCol->GetElement()->GetAttr(kNameSpaceID_None, nsHTMLAtoms::hidden, attr);
>+    if (attr.EqualsIgnoreCase("true"))
>+      continue;
>+
>+    // Skip non-text column
>+    if (currCol->GetType() != nsTreeColumn::eText)
>+      continue;
>+
>+    if (first == -1)
>+      first = currCol->GetColIndex();
>+    
>+    currCol->GetElement()->GetAttr(kNameSpaceID_None, nsXULAtoms::sortDirection, attr);
>+    if (attr.Length() > 0) { // Use sorted column as the primary
>+      sorted = currCol->GetColIndex();
>+      break;
>+    }
>+
>+    if (currCol->IsPrimary())
>+      if (primary == -1)
>+        primary = currCol->GetColIndex();
>+  }
>+
>+  if (sorted >= 0)
>+    *_retval = sorted;
>+  else if (primary >= 0)
>+    *_retval = primary;
>+  else
>+    *_retval = first;
>+
>+  return NS_OK;
>+}
>+
> NS_IMETHODIMP nsTreeBodyFrame::GetFirstVisibleRow(PRInt32 *_retval)
> {
>   *_retval = mTopRowIndex;
>Index: mozilla/layout/xul/base/src/tree/src/nsTreeBoxObject.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/layout/xul/base/src/tree/src/nsTreeBoxObject.cpp,v
>retrieving revision 1.29
>diff -u -r1.29 nsTreeBoxObject.cpp
>--- mozilla/layout/xul/base/src/tree/src/nsTreeBoxObject.cpp	25 Apr 2002 18:18:12 -0000	1.29
>+++ mozilla/layout/xul/base/src/tree/src/nsTreeBoxObject.cpp	9 May 2002 02:30:41 -0000
>@@ -251,6 +251,22 @@
>   return NS_OK;
> }
> 
>+NS_IMETHODIMP nsTreeBoxObject::GetColumnID(PRInt32 colIndex, nsAString & _retval)
>+{
>+  nsITreeBoxObject* body = GetTreeBody();
>+  if (body)
>+    return body->GetColumnID(colIndex, _retval);
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP nsTreeBoxObject::GetKeyColumnIndex(PRInt32 *_retval)
>+{
>+  nsITreeBoxObject* body = GetTreeBody();
>+  if (body)
>+    return body->GetKeyColumnIndex(_retval);
>+  return NS_OK;
>+}
>+
> NS_IMETHODIMP nsTreeBoxObject::GetFirstVisibleRow(PRInt32 *_retval)
> {
>   nsITreeBoxObject* body = GetTreeBody();
>Index: mozilla/widget/src/windows/Accessible.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/widget/src/windows/Accessible.cpp,v
>retrieving revision 3.17
>diff -u -r3.17 Accessible.cpp
>--- mozilla/widget/src/windows/Accessible.cpp	20 Nov 2001 02:05:18 -0000	3.17
>+++ mozilla/widget/src/windows/Accessible.cpp	9 May 2002 02:31:45 -0000
>@@ -973,6 +973,10 @@
>       }
>     }    
>   }
>+  else if (varChild.lVal >= MAX_CHILD_ACCESSIBLES && varChild.lVal < MAX_CHILD_ACCESSIBLES + mListCount){
>+    aAcc = mList[varChild.lVal - MAX_CHILD_ACCESSIBLES].mAccessible;
>+    return;
>+  }
> 
>   Accessible::GetNSAccessibleFor(varChild, aAcc);
> }
>@@ -994,9 +998,11 @@
>   // can call back and get the IAccessible the event occured on.
>   // We use the unique ID exposed through nsIContent::GetContentID()
> 
>-  nsCOMPtr<nsIDOMNode> domNode;
>-  aAccessible->AccGetDOMNode(getter_AddRefs(domNode));
>-  PRUint32 uniqueID = - NS_REINTERPRET_CAST(PRInt32, (domNode.get()));
>+  PRInt32 uniqueID;
>+  aAccessible->GetAccId(&uniqueID);
>+
>+  if (uniqueID == 0)  // can't get an unique ID, use the mList's index + constant base number as the unique ID
>+    uniqueID = mNextPos + MAX_CHILD_ACCESSIBLES;
> 
>   mList[mNextPos].mId = uniqueID;
>   mList[mNextPos].mAccessible = aAccessible;
>Index: mozilla/widget/src/windows/Accessible.h
>===================================================================
>RCS file: /cvsroot/mozilla/widget/src/windows/Accessible.h,v
>retrieving revision 3.8
>diff -u -r3.8 Accessible.h
>--- mozilla/widget/src/windows/Accessible.h	28 Sep 2001 20:11:59 -0000	3.8
>+++ mozilla/widget/src/windows/Accessible.h	9 May 2002 02:31:46 -0000
>@@ -240,6 +240,7 @@
> 
> 
> #define MAX_LIST_SIZE 100
>+#define MAX_CHILD_ACCESSIBLES 1000000
> 
> class RootAccessible: public DocAccessible, public nsIAccessibleEventListener
> {
Attachment #82883 - Flags: superreview+

Comment 35

16 years ago
Created attachment 83314 [details] [diff] [review]
Final version that was checked in

jst, Thanks for your comment, I've updated the patch by following your
suggestions.

>- In accessible.properties, add a newline at the end of the file.
>
Done

>- In nsGenericAccessible::GetAccId(), don't you want to assert if this
>no-yet-implemented method is ever called? Or at least set the out param to
>something (0?) to get consisten behavior if this was ever called.
>

nsGenericAccessible is not a real implementation for accessibility. It defines
all the methods of nsIAccessible interface and just keep them
"no-yet-implemented".
Please see:
http://lxr.mozilla.org/seamonkey/source/accessible/src/base/nsGenericAccessible.cpp


>- In nsRootAccessible.cpp:
>
>+	 accessible = new nsXULTreeitemAccessible(accessible, targetNode,
>weakShell, treeIndex);
>
>add some OOM protection after the new.

Added OOM protection for all new allocations.

>
>- In nsXULTreeAccessible::GetAccFirstChild():
>
>+	*aAccFirstChild = new nsXULTreeitemAccessible(this, mDOMNode,
>mPresShell, 0);
>+	if (! *aAccFirstChild)
>+	 return NS_ERROR_FAILURE;
>
>Wouldn't it make more sense to return NS_ERROR_OUT_OF_MEMORY here?
>
>Same thing in nsXULTreeAccessible::GetAccLastChild().
>

Changed the return value from NS_ERROR_FAILURE to NS_ERROR_OUT_OF_MEMORY for
all OOM situations.

>- In nsXULTreeAccessible::GetSelectedChildren():
>
>+  NS_NewISupportsArray(getter_AddRefs(selectedAccessibles));
>+  if (!selection || !selectedAccessibles)
>+    return NS_ERROR_FAILURE;
>
>I'm not sure what !selection means, but !selectedAccessibles means you're OOM,

>so return the proper error code in that case.
>

Splited into two parts:
  if (!selection)
    return NS_ERROR_FAILURE;
  ...
  if (!selectedAccessibles)
    return NS_ERROR_OUT_OF_MEMORY;

>- Why does nsXULTreeAccessible::GetTreeBoxObject() return an error code if it
>doesn't find a tree boxobject? Isn't returning null as the box object enough?
>Think of returning error codes as throwing exceptions, is this really an
>exceptional case?
>

Actually, I didn't use the return value of GetTreeBoxObject(). 
Changed GetTreeBoxObject's return type to void.

>- In nsXULTreeitemAccessible::AccGetBounds():
>
>+    boxObject->GetElement(getter_AddRefs(boxElement));
>+    if (boxElement) {
>+	nsCOMPtr<nsIDOMNode> boxNode(do_QueryInterface(boxElement));
>+	if (boxNode) {
>
>You can loose the if (boxElement) check here, do_QueryInterface() is null
safe.
>

Deleted redundant if (pointer) checking, if the pointer was only used as
do_QueryInterface's parameter.

>Also:
>
>+	       nsCOMPtr<nsIDOMXULElement>
>xulElement(do_QueryInterface(childNode));
>+	       if (xulElement) {
>+		 nsCOMPtr<nsIBoxObject> box(do_QueryInterface(xulElement));
>+		 xulElement->GetBoxObject(getter_AddRefs(box));
>
>Why QI xulElement into box when you're immediately after that getting a box
>object from xulElement into box? Loose the do_QueryInterface in the
initializer
>of box.
>

nsCOMPtr<nsIBoxObject> box(do_QueryInterface(xulElement)); is wrong, should be:

nsCOMPtr<nsIBoxObject> box;

>- In nsXULTreeColumnsAccessible::GetAccNextSibling(), return the proper error
>code if OOM.
>
>- In nsXULTreeColumnsAccessible::GetAccPreviousSibling(), don't you want to
>return the return value from the call into the inherited method?
>

Returned the return value of inherited method.

>- In nsTreeBoxObject::GetColumnID(), truncate the out string if there's no
>body.
>
>- In nsTreeBoxObject::GetKeyColumnIndex() default the out param to something
>(0?) if there's no body.
>

Assigned a default value for out parameter.

Comment 36

16 years ago
checked in by pete.zha@sun.com
Status: ASSIGNED → RESOLVED
Last Resolved: 16 years ago
Resolution: --- → FIXED

Updated

16 years ago
Component: Browser-General → Accessibility APIs
You need to log in before you can comment on or make changes to this bug.