diff -r 000000000000 -r 6474c204b198 accessible/src/base/AccIterator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/accessible/src/base/AccIterator.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,398 @@ +/* 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/. */ + +#include "AccIterator.h" + +#include "AccGroupInfo.h" +#ifdef MOZ_XUL +#include "XULTreeAccessible.h" +#endif + +#include "mozilla/dom/Element.h" + +using namespace mozilla; +using namespace mozilla::a11y; + +//////////////////////////////////////////////////////////////////////////////// +// AccIterator +//////////////////////////////////////////////////////////////////////////////// + +AccIterator::AccIterator(Accessible* aAccessible, + filters::FilterFuncPtr aFilterFunc) : + mFilterFunc(aFilterFunc) +{ + mState = new IteratorState(aAccessible); +} + +AccIterator::~AccIterator() +{ + while (mState) { + IteratorState *tmp = mState; + mState = tmp->mParentState; + delete tmp; + } +} + +Accessible* +AccIterator::Next() +{ + while (mState) { + Accessible* child = mState->mParent->GetChildAt(mState->mIndex++); + if (!child) { + IteratorState* tmp = mState; + mState = mState->mParentState; + delete tmp; + + continue; + } + + uint32_t result = mFilterFunc(child); + if (result & filters::eMatch) + return child; + + if (!(result & filters::eSkipSubtree)) { + IteratorState* childState = new IteratorState(child, mState); + mState = childState; + } + } + + return nullptr; +} + +//////////////////////////////////////////////////////////////////////////////// +// nsAccIterator::IteratorState + +AccIterator::IteratorState::IteratorState(Accessible* aParent, + IteratorState *mParentState) : + mParent(aParent), mIndex(0), mParentState(mParentState) +{ +} + + +//////////////////////////////////////////////////////////////////////////////// +// RelatedAccIterator +//////////////////////////////////////////////////////////////////////////////// + +RelatedAccIterator:: + RelatedAccIterator(DocAccessible* aDocument, nsIContent* aDependentContent, + nsIAtom* aRelAttr) : + mDocument(aDocument), mRelAttr(aRelAttr), mProviders(nullptr), + mBindingParent(nullptr), mIndex(0) +{ + mBindingParent = aDependentContent->GetBindingParent(); + nsIAtom* IDAttr = mBindingParent ? + nsGkAtoms::anonid : aDependentContent->GetIDAttributeName(); + + nsAutoString id; + if (aDependentContent->GetAttr(kNameSpaceID_None, IDAttr, id)) + mProviders = mDocument->mDependentIDsHash.Get(id); +} + +Accessible* +RelatedAccIterator::Next() +{ + if (!mProviders) + return nullptr; + + while (mIndex < mProviders->Length()) { + DocAccessible::AttrRelProvider* provider = (*mProviders)[mIndex++]; + + // Return related accessible for the given attribute and if the provider + // content is in the same binding in the case of XBL usage. + if (provider->mRelAttr == mRelAttr) { + nsIContent* bindingParent = provider->mContent->GetBindingParent(); + bool inScope = mBindingParent == bindingParent || + mBindingParent == provider->mContent; + + if (inScope) { + Accessible* related = mDocument->GetAccessible(provider->mContent); + if (related) + return related; + + // If the document content is pointed by relation then return the document + // itself. + if (provider->mContent == mDocument->GetContent()) + return mDocument; + } + } + } + + return nullptr; +} + + +//////////////////////////////////////////////////////////////////////////////// +// HTMLLabelIterator +//////////////////////////////////////////////////////////////////////////////// + +HTMLLabelIterator:: + HTMLLabelIterator(DocAccessible* aDocument, const Accessible* aAccessible, + LabelFilter aFilter) : + mRelIter(aDocument, aAccessible->GetContent(), nsGkAtoms::_for), + mAcc(aAccessible), mLabelFilter(aFilter) +{ +} + +Accessible* +HTMLLabelIterator::Next() +{ + // Get either