gecko-dev/layout/base/nsFrameTraversal.cpp

288 lines
5.5 KiB
C++
Raw Normal View History

#include "nsFrameTraversal.h"
#include "nsFrameList.h"
static NS_DEFINE_IID(kIEnumeratorIID, NS_IENUMERATOR_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
class nsFrameIterator: public nsIEnumerator
{
public:
NS_DECL_ISUPPORTS
virtual nsresult First();
virtual nsresult Last();
virtual nsresult Next()=0;
virtual nsresult Prev()=0;
virtual nsresult CurrentItem(nsISupports **aItem);
virtual nsresult IsDone();//what does this mean??off edge? yes
nsFrameIterator();
protected:
void setCurrent(nsIFrame *aFrame){mCurrent = aFrame;}
nsIFrame *getCurrent(){return mCurrent;}
void setStart(nsIFrame *aFrame){mStart = aFrame;}
nsIFrame *getStart(){return mStart;}
nsIFrame *getLast(){return mLast;}
void setLast(nsIFrame *aFrame){mLast = aFrame;}
PRInt8 getOffEdge(){return mOffEdge;}
void setOffEdge(PRInt8 aOffEdge){mOffEdge = aOffEdge;}
private:
nsIFrame *mStart;
nsIFrame *mCurrent;
nsIFrame *mLast; //the last one that was in current;
PRInt8 mOffEdge; //0= no -1 to far prev, 1 to far next;
};
/*
class nsFastFrameIterator: public nsFrameIterator
{
nsFastFrameIterator(nsIFrame *start);
private :
virtual nsresult Next();
virtual nsresult Prev();
}
*/
class nsLeafIterator: public nsFrameIterator
{
public:
nsLeafIterator(nsIFrame *start);
private :
virtual nsresult Next();
virtual nsresult Prev();
};
/************IMPLEMENTATIONS**************/
nsresult
NS_NewFrameTraversal(nsIEnumerator **aEnumerator, nsTraversalType aType, nsIFrame *aStart)
{
if (!aEnumerator || !aStart)
return NS_ERROR_NULL_POINTER;
switch(aType)
{
case LEAF: {
nsLeafIterator *trav = new nsLeafIterator(aStart);
if (!trav)
return NS_ERROR_OUT_OF_MEMORY;
*aEnumerator = (nsIEnumerator *)trav;
NS_ADDREF(trav);
}
break;
#if 0
case EXTENSIVE:{
nsExtensiveTraversal *trav = new nsExtensiveTraversal(aStart);
if (!trav)
return NS_ERROR_NOMEMORY;
*aEnumerator = (nsIEnumerator *)trav;
NS_ADDREF(trav);
}
break;
case FASTEST:{
nsFastestTraversal *trav = new nsFastestTraversal(aStart);
if (!trav)
return NS_ERROR_NOMEMORY;
*aEnumerator = (nsIEnumerator *)trav;
NS_ADDREF(trav);
}
#endif
default:
return NS_ERROR_NOT_IMPLEMENTED;
break;
}
return NS_OK;
}
/*********nsFrameIterator************/
NS_IMPL_ADDREF(nsFrameIterator)
NS_IMPL_RELEASE(nsFrameIterator)
nsFrameIterator::nsFrameIterator()
{
mOffEdge = 0;
mLast = nsnull;
mCurrent = nsnull;
mStart = nsnull;
NS_INIT_REFCNT();
}
nsresult
nsFrameIterator::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void *)(nsISupports *)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIEnumeratorIID)) {
*aInstancePtr = (void*)(nsIEnumerator*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
nsresult
nsFrameIterator::CurrentItem(nsISupports **aItem)
{
if (!aItem)
return NS_ERROR_NULL_POINTER;
*aItem = mCurrent;
return NS_OK;
}
nsresult
nsFrameIterator::IsDone()//what does this mean??off edge? yes
{
if (mOffEdge != 0)
return NS_OK;
return NS_COMFALSE;
}
nsresult
nsFrameIterator::First()
{
mCurrent = mStart;
return NS_OK;
}
nsresult
nsFrameIterator::Last()
{
return NS_ERROR_FAILURE;
}
/*********LEAFITERATOR**********/
nsLeafIterator::nsLeafIterator(nsIFrame *aStart)
{
setStart(aStart);
setCurrent(aStart);
setLast(aStart);
}
nsresult
nsLeafIterator::Next()
{
//recursive-oid method to get next frame
nsIFrame *result;
nsIFrame *parent = getCurrent();
if (!parent)
parent = getLast();
while(NS_SUCCEEDED(parent->FirstChild(nsnull,&result)) && result)
{
parent = result;
}
if (parent != getCurrent())
{
result = parent;
}
else {
while(parent){
if (NS_SUCCEEDED(parent->GetNextSibling(&result)) && result){
parent = result;
while(NS_SUCCEEDED(parent->FirstChild(nsnull,&result)) && result)
{
parent = result;
}
result = parent;
break;
}
else
if (NS_FAILED(parent->GetParent(&result)) || !result){
result = nsnull;
break;
}
else
parent = result;
}
}
setCurrent(result);
if (!result)
setOffEdge(1);
return nsnull;
}
nsresult
nsLeafIterator::Prev()
{
//recursive-oid method to get prev frame
nsIFrame *result;
nsIFrame *parent = getCurrent();
if (!parent)
return NS_ERROR_FAILURE;
parent = getLast();
while(parent){
nsIFrame *grandParent;
if (NS_SUCCEEDED(parent->GetParent(&grandParent)) && grandParent){
nsIFrame * grandFchild;
if (NS_SUCCEEDED(grandParent->FirstChild(nsnull,&grandFchild)) && grandFchild){
nsFrameList list(grandFchild);
if (result = list.GetPrevSiblingFor(parent) ){
parent = result;
while(NS_SUCCEEDED(parent->FirstChild(nsnull,&result)) && result){
parent = result;
while(NS_SUCCEEDED(parent->GetNextSibling(&result)) && result){
parent = result;
}
}
result = parent;
break;
}
else
if (NS_FAILED(parent->GetParent(&result)) || !result){
result = nsnull;
break;
}
else
parent = result;
}
}
}
setCurrent(result);
if (!result)
setOffEdge(-1);
return nsnull;
}