2010-02-20 16:55:04 -08:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2012-05-21 04:12:37 -07:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2010-02-20 16:55:04 -08:00
|
|
|
|
|
|
|
#include "nsAccTreeWalker.h"
|
|
|
|
|
2012-05-28 18:18:45 -07:00
|
|
|
#include "Accessible.h"
|
2010-02-20 16:55:04 -08:00
|
|
|
#include "nsAccessibilityService.h"
|
2012-05-27 02:01:40 -07:00
|
|
|
#include "DocAccessible.h"
|
2010-02-20 16:55:04 -08:00
|
|
|
|
2010-06-08 09:39:58 -07:00
|
|
|
#include "nsINodeList.h"
|
|
|
|
|
2010-02-20 16:55:04 -08:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// WalkState
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
struct WalkState
|
|
|
|
{
|
|
|
|
WalkState(nsIContent *aContent) :
|
2012-07-30 07:20:58 -07:00
|
|
|
content(aContent), childIdx(0), prevState(nullptr) {}
|
2010-02-20 16:55:04 -08:00
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> content;
|
|
|
|
nsCOMPtr<nsINodeList> childList;
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t childIdx;
|
2010-02-20 16:55:04 -08:00
|
|
|
WalkState *prevState;
|
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// nsAccTreeWalker
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
nsAccTreeWalker::
|
2012-05-27 02:01:40 -07:00
|
|
|
nsAccTreeWalker(DocAccessible* aDoc, nsIContent* aContent,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aWalkAnonContent, bool aWalkCache) :
|
2012-07-30 07:20:58 -07:00
|
|
|
mDoc(aDoc), mWalkCache(aWalkCache), mState(nullptr)
|
2010-02-20 16:55:04 -08:00
|
|
|
{
|
|
|
|
NS_ASSERTION(aContent, "No node for the accessible tree walker!");
|
|
|
|
|
|
|
|
if (aContent)
|
|
|
|
mState = new WalkState(aContent);
|
|
|
|
|
2010-10-15 08:34:35 -07:00
|
|
|
mChildFilter = aWalkAnonContent ? nsIContent::eAllChildren :
|
2010-02-20 16:55:04 -08:00
|
|
|
nsIContent::eAllButXBL;
|
|
|
|
|
2010-10-15 08:34:35 -07:00
|
|
|
mChildFilter |= nsIContent::eSkipPlaceholderContent;
|
|
|
|
|
2010-02-20 16:55:04 -08:00
|
|
|
MOZ_COUNT_CTOR(nsAccTreeWalker);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAccTreeWalker::~nsAccTreeWalker()
|
|
|
|
{
|
|
|
|
// Clear state stack from memory
|
|
|
|
while (mState)
|
|
|
|
PopState();
|
|
|
|
|
|
|
|
MOZ_COUNT_DTOR(nsAccTreeWalker);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// nsAccTreeWalker: private
|
|
|
|
|
2012-05-28 18:18:45 -07:00
|
|
|
Accessible*
|
2011-03-31 02:30:58 -07:00
|
|
|
nsAccTreeWalker::NextChildInternal(bool aNoWalkUp)
|
2010-02-20 16:55:04 -08:00
|
|
|
{
|
|
|
|
if (!mState || !mState->content)
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2010-02-20 16:55:04 -08:00
|
|
|
|
|
|
|
if (!mState->childList)
|
2010-10-15 08:34:35 -07:00
|
|
|
mState->childList = mState->content->GetChildren(mChildFilter);
|
2010-02-20 16:55:04 -08:00
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t length = 0;
|
2010-02-20 16:55:04 -08:00
|
|
|
if (mState->childList)
|
|
|
|
mState->childList->GetLength(&length);
|
|
|
|
|
2010-02-20 17:31:07 -08:00
|
|
|
while (mState->childIdx < length) {
|
2012-10-13 05:50:24 -07:00
|
|
|
nsIContent* childNode = mState->childList->Item(mState->childIdx);
|
2010-02-20 16:55:04 -08:00
|
|
|
mState->childIdx++;
|
|
|
|
|
2010-11-13 09:49:26 -08:00
|
|
|
bool isSubtreeHidden = false;
|
2012-05-28 18:18:45 -07:00
|
|
|
Accessible* accessible = mWalkCache ? mDoc->GetAccessible(childNode) :
|
2012-02-09 08:49:17 -08:00
|
|
|
GetAccService()->GetOrCreateAccessible(childNode, mDoc, &isSubtreeHidden);
|
2010-02-20 16:55:04 -08:00
|
|
|
|
|
|
|
if (accessible)
|
2011-03-31 02:30:58 -07:00
|
|
|
return accessible;
|
2010-02-20 16:55:04 -08:00
|
|
|
|
|
|
|
// Walk down into subtree to find accessibles.
|
2010-11-13 09:49:26 -08:00
|
|
|
if (!isSubtreeHidden) {
|
2010-02-20 16:55:04 -08:00
|
|
|
if (!PushState(childNode))
|
|
|
|
break;
|
|
|
|
|
2011-03-31 02:30:58 -07:00
|
|
|
accessible = NextChildInternal(true);
|
2010-02-20 16:55:04 -08:00
|
|
|
if (accessible)
|
2011-03-31 02:30:58 -07:00
|
|
|
return accessible;
|
2010-02-20 16:55:04 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// No more children, get back to the parent.
|
|
|
|
PopState();
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
return aNoWalkUp ? nullptr : NextChildInternal(false);
|
2010-02-20 16:55:04 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsAccTreeWalker::PopState()
|
|
|
|
{
|
|
|
|
WalkState* prevToLastState = mState->prevState;
|
|
|
|
delete mState;
|
|
|
|
mState = prevToLastState;
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2010-02-20 16:55:04 -08:00
|
|
|
nsAccTreeWalker::PushState(nsIContent* aContent)
|
|
|
|
{
|
|
|
|
WalkState* nextToLastState = new WalkState(aContent);
|
|
|
|
if (!nextToLastState)
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-02-20 16:55:04 -08:00
|
|
|
|
|
|
|
nextToLastState->prevState = mState;
|
|
|
|
mState = nextToLastState;
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-02-20 16:55:04 -08:00
|
|
|
}
|