1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 2003
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Aaron Leventhal <aaronleventhal@moonset.net> (original author)
24 : * Alexander Surkov <surkov.alexander@gmail.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "nsAccTreeWalker.h"
41 :
42 : #include "nsAccessible.h"
43 : #include "nsAccessibilityService.h"
44 : #include "nsDocAccessible.h"
45 :
46 : #include "nsINodeList.h"
47 :
48 : ////////////////////////////////////////////////////////////////////////////////
49 : // WalkState
50 : ////////////////////////////////////////////////////////////////////////////////
51 :
52 : struct WalkState
53 0 : {
54 0 : WalkState(nsIContent *aContent) :
55 0 : content(aContent), childIdx(0), prevState(nsnull) {}
56 :
57 : nsCOMPtr<nsIContent> content;
58 : nsCOMPtr<nsINodeList> childList;
59 : PRUint32 childIdx;
60 : WalkState *prevState;
61 : };
62 :
63 : ////////////////////////////////////////////////////////////////////////////////
64 : // nsAccTreeWalker
65 : ////////////////////////////////////////////////////////////////////////////////
66 :
67 0 : nsAccTreeWalker::
68 : nsAccTreeWalker(nsDocAccessible* aDoc, nsIContent* aContent,
69 : bool aWalkAnonContent, bool aWalkCache) :
70 0 : mDoc(aDoc), mWalkCache(aWalkCache), mState(nsnull)
71 : {
72 0 : NS_ASSERTION(aContent, "No node for the accessible tree walker!");
73 :
74 0 : if (aContent)
75 0 : mState = new WalkState(aContent);
76 :
77 : mChildFilter = aWalkAnonContent ? nsIContent::eAllChildren :
78 0 : nsIContent::eAllButXBL;
79 :
80 0 : mChildFilter |= nsIContent::eSkipPlaceholderContent;
81 :
82 0 : MOZ_COUNT_CTOR(nsAccTreeWalker);
83 0 : }
84 :
85 0 : nsAccTreeWalker::~nsAccTreeWalker()
86 : {
87 : // Clear state stack from memory
88 0 : while (mState)
89 0 : PopState();
90 :
91 0 : MOZ_COUNT_DTOR(nsAccTreeWalker);
92 0 : }
93 :
94 : ////////////////////////////////////////////////////////////////////////////////
95 : // nsAccTreeWalker: private
96 :
97 : nsAccessible*
98 0 : nsAccTreeWalker::NextChildInternal(bool aNoWalkUp)
99 : {
100 0 : if (!mState || !mState->content)
101 0 : return nsnull;
102 :
103 0 : if (!mState->childList)
104 0 : mState->childList = mState->content->GetChildren(mChildFilter);
105 :
106 0 : PRUint32 length = 0;
107 0 : if (mState->childList)
108 0 : mState->childList->GetLength(&length);
109 :
110 0 : while (mState->childIdx < length) {
111 0 : nsIContent* childNode = mState->childList->GetNodeAt(mState->childIdx);
112 0 : mState->childIdx++;
113 :
114 0 : bool isSubtreeHidden = false;
115 0 : nsAccessible* accessible = mWalkCache ? mDoc->GetAccessible(childNode) :
116 0 : GetAccService()->GetOrCreateAccessible(childNode, mDoc, &isSubtreeHidden);
117 :
118 0 : if (accessible)
119 0 : return accessible;
120 :
121 : // Walk down into subtree to find accessibles.
122 0 : if (!isSubtreeHidden) {
123 0 : if (!PushState(childNode))
124 0 : break;
125 :
126 0 : accessible = NextChildInternal(true);
127 0 : if (accessible)
128 0 : return accessible;
129 : }
130 : }
131 :
132 : // No more children, get back to the parent.
133 0 : PopState();
134 :
135 0 : return aNoWalkUp ? nsnull : NextChildInternal(false);
136 : }
137 :
138 : void
139 0 : nsAccTreeWalker::PopState()
140 : {
141 0 : WalkState* prevToLastState = mState->prevState;
142 0 : delete mState;
143 0 : mState = prevToLastState;
144 0 : }
145 :
146 : bool
147 0 : nsAccTreeWalker::PushState(nsIContent* aContent)
148 : {
149 0 : WalkState* nextToLastState = new WalkState(aContent);
150 0 : if (!nextToLastState)
151 0 : return false;
152 :
153 0 : nextToLastState->prevState = mState;
154 0 : mState = nextToLastState;
155 :
156 0 : return true;
157 : }
|