Use frame bit to indicate if frame has a decendant with a view and use this to optimize nsContainerFrame::PositionChildViews; bug 70211; sr=attinasi@netscape.com r=karnaze@netscape.com

This commit is contained in:
kmcclusk%netscape.com 2001-03-30 05:25:49 +00:00
parent 90751f7ac7
commit 572c81e29b
8 changed files with 110 additions and 144 deletions

View File

@ -193,6 +193,9 @@ typedef PRUint32 nsFrameState;
#define NS_FRAME_IS_BIDI 0x00020000
#endif
// If this bit is set the frame has descendant with a view
#define NS_FRAME_HAS_CHILD_WITH_VIEW 0x00040000
// The lower 20 bits of the frame state word are reserved by this API.
#define NS_FRAME_RESERVED 0x000FFFFF

View File

@ -737,84 +737,47 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
return result;
}
PRBool nsContainerFrame::IsDescendant(nsIFrame* aAncestor,
nsIFrame *aFrame,
nsIFrame *aStopFrame)
{
// Walk up the frame's parent's until either aAncestor or aStopFrame is found
// If aAncestor is found return PR_TRUE, otherwide return PR_FALSE.
nsIFrame* currentFrame = aFrame;
while (currentFrame != nsnull) {
if (currentFrame == aStopFrame) {
return PR_FALSE;
}
if (currentFrame == aAncestor) {
return PR_TRUE;
}
currentFrame->GetParent(&currentFrame);
}
// Neither aAncestor or aStopFrame was found.
return PR_FALSE;
}
void
nsContainerFrame::PositionChildViews(nsIPresContext* aPresContext,
nsIFrame* aFrame)
{
// Look at only the views which are direct descendants of the frame's view.
// If the frame owns a view then all we need to do is reposition the frame's
// associated with the view children. If the frame does not own the view then
// we also need to check to see if the child view's frame is a descendant of this
// frame. In most cases the view will have no children at all and this method returns
// almost immediately.
// Check to see if this frame owns a view
nsIFrame* frameWithView = aFrame;
nsIView* framesView = nsnull;
aFrame->GetView(aPresContext, &framesView);
if (nsnull == framesView) {
// this frame doesn't own a view so we need to find the ancestor frame that
// has a view.
aFrame->GetParentWithView(aPresContext, &frameWithView);
if (frameWithView) {
frameWithView->GetView(aPresContext, &framesView);
}
}
if (nsnull == framesView ) {
NS_ASSERTION(PR_FALSE, "Could not find any view");
nsFrameState frameState;
aFrame->GetFrameState(&frameState);
if (! ((frameState & NS_FRAME_HAS_CHILD_WITH_VIEW) == NS_FRAME_HAS_CHILD_WITH_VIEW)) {
return;
}
// Cycle through all of the children of the frame's view.
nsIView * childView = nsnull;
for (framesView->GetChild(0, childView); nsnull != childView; childView->GetNextSibling(childView))
{
void *data = nsnull;
nsIFrame *childFrame = nsnull;
childView->GetClientData(data);
NS_ASSERTION(data != nsnull, "The view does not contain a frame pointer");
childFrame = (nsIFrame*) data;
if (childFrame) {
nsFrameState kidState;
childFrame->GetFrameState(&kidState);
// Position the frame only if flag is set to synchronize them.
if (NS_FRAME_SYNC_FRAME_AND_VIEW & kidState) {
if (aFrame == frameWithView) {
PositionFrameView(aPresContext, childFrame, childView);
} else {
// Need to check to see if the view's frame is a
// descendant of this frame.
if (IsDescendant(aFrame, childFrame, frameWithView)) {
PositionFrameView(aPresContext, childFrame, childView);
}
}
nsIAtom* childListName = nsnull;
PRInt32 childListIndex = 0;
do {
// Recursively walk aFrame's child frames
nsIFrame* childFrame;
aFrame->FirstChild(aPresContext, childListName, &childFrame);
while (childFrame) {
nsIView* view;
// See if the child frame has a view
childFrame->GetView(aPresContext, &view);
if (view) {
// Position the view. Because any child views are relative to their
// parent, there's no need to recurse
PositionFrameView(aPresContext, childFrame, view);
} else {
// Recursively examine its child frames
PositionChildViews(aPresContext, childFrame);
}
// Get the next sibling child frame
childFrame->GetNextSibling(&childFrame);
}
}
NS_IF_RELEASE(childListName);
aFrame->GetAdditionalChildListName(childListIndex++, &childListName);
} while (childListName);
}
/**

View File

@ -148,10 +148,6 @@ public:
nscoord aY,
PRUint32 aFlags);
static PRBool IsDescendant(nsIFrame* aAncestor,
nsIFrame *aFrame,
nsIFrame *aStopFrame);
static void PositionChildViews(nsIPresContext* aPresContext,
nsIFrame* aFrame);

View File

@ -1994,6 +1994,27 @@ NS_IMETHODIMP nsFrame::SetView(nsIPresContext* aPresContext, nsIView* aView)
// Set the frame state bit that says the frame has a view
mState |= NS_FRAME_HAS_VIEW;
// Let all of the containing frames know they have a child
// with a view until a frame is hit that has the
// NS_FRAME_HAS_CHILD_WITH_VIEW bit set already or a we
// reached the top of the frame tree.
PRBool isSet = PR_FALSE;
nsIFrame* parent = nsnull;
GetParent(&parent);
while ((parent != nsnull) && (! isSet)) {
nsFrameState frameState;
parent->GetFrameState(&frameState);
isSet = ((frameState & NS_FRAME_HAS_CHILD_WITH_VIEW) == NS_FRAME_HAS_CHILD_WITH_VIEW
);
if (! isSet) {
frameState |= NS_FRAME_HAS_CHILD_WITH_VIEW;
parent->SetFrameState(frameState);
}
parent->GetParent(&parent);
}
}
return NS_OK;

View File

@ -193,6 +193,9 @@ typedef PRUint32 nsFrameState;
#define NS_FRAME_IS_BIDI 0x00020000
#endif
// If this bit is set the frame has descendant with a view
#define NS_FRAME_HAS_CHILD_WITH_VIEW 0x00040000
// The lower 20 bits of the frame state word are reserved by this API.
#define NS_FRAME_RESERVED 0x000FFFFF

View File

@ -737,84 +737,47 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
return result;
}
PRBool nsContainerFrame::IsDescendant(nsIFrame* aAncestor,
nsIFrame *aFrame,
nsIFrame *aStopFrame)
{
// Walk up the frame's parent's until either aAncestor or aStopFrame is found
// If aAncestor is found return PR_TRUE, otherwide return PR_FALSE.
nsIFrame* currentFrame = aFrame;
while (currentFrame != nsnull) {
if (currentFrame == aStopFrame) {
return PR_FALSE;
}
if (currentFrame == aAncestor) {
return PR_TRUE;
}
currentFrame->GetParent(&currentFrame);
}
// Neither aAncestor or aStopFrame was found.
return PR_FALSE;
}
void
nsContainerFrame::PositionChildViews(nsIPresContext* aPresContext,
nsIFrame* aFrame)
{
// Look at only the views which are direct descendants of the frame's view.
// If the frame owns a view then all we need to do is reposition the frame's
// associated with the view children. If the frame does not own the view then
// we also need to check to see if the child view's frame is a descendant of this
// frame. In most cases the view will have no children at all and this method returns
// almost immediately.
// Check to see if this frame owns a view
nsIFrame* frameWithView = aFrame;
nsIView* framesView = nsnull;
aFrame->GetView(aPresContext, &framesView);
if (nsnull == framesView) {
// this frame doesn't own a view so we need to find the ancestor frame that
// has a view.
aFrame->GetParentWithView(aPresContext, &frameWithView);
if (frameWithView) {
frameWithView->GetView(aPresContext, &framesView);
}
}
if (nsnull == framesView ) {
NS_ASSERTION(PR_FALSE, "Could not find any view");
nsFrameState frameState;
aFrame->GetFrameState(&frameState);
if (! ((frameState & NS_FRAME_HAS_CHILD_WITH_VIEW) == NS_FRAME_HAS_CHILD_WITH_VIEW)) {
return;
}
// Cycle through all of the children of the frame's view.
nsIView * childView = nsnull;
for (framesView->GetChild(0, childView); nsnull != childView; childView->GetNextSibling(childView))
{
void *data = nsnull;
nsIFrame *childFrame = nsnull;
childView->GetClientData(data);
NS_ASSERTION(data != nsnull, "The view does not contain a frame pointer");
childFrame = (nsIFrame*) data;
if (childFrame) {
nsFrameState kidState;
childFrame->GetFrameState(&kidState);
// Position the frame only if flag is set to synchronize them.
if (NS_FRAME_SYNC_FRAME_AND_VIEW & kidState) {
if (aFrame == frameWithView) {
PositionFrameView(aPresContext, childFrame, childView);
} else {
// Need to check to see if the view's frame is a
// descendant of this frame.
if (IsDescendant(aFrame, childFrame, frameWithView)) {
PositionFrameView(aPresContext, childFrame, childView);
}
}
nsIAtom* childListName = nsnull;
PRInt32 childListIndex = 0;
do {
// Recursively walk aFrame's child frames
nsIFrame* childFrame;
aFrame->FirstChild(aPresContext, childListName, &childFrame);
while (childFrame) {
nsIView* view;
// See if the child frame has a view
childFrame->GetView(aPresContext, &view);
if (view) {
// Position the view. Because any child views are relative to their
// parent, there's no need to recurse
PositionFrameView(aPresContext, childFrame, view);
} else {
// Recursively examine its child frames
PositionChildViews(aPresContext, childFrame);
}
// Get the next sibling child frame
childFrame->GetNextSibling(&childFrame);
}
}
NS_IF_RELEASE(childListName);
aFrame->GetAdditionalChildListName(childListIndex++, &childListName);
} while (childListName);
}
/**

View File

@ -148,10 +148,6 @@ public:
nscoord aY,
PRUint32 aFlags);
static PRBool IsDescendant(nsIFrame* aAncestor,
nsIFrame *aFrame,
nsIFrame *aStopFrame);
static void PositionChildViews(nsIPresContext* aPresContext,
nsIFrame* aFrame);

View File

@ -1994,6 +1994,27 @@ NS_IMETHODIMP nsFrame::SetView(nsIPresContext* aPresContext, nsIView* aView)
// Set the frame state bit that says the frame has a view
mState |= NS_FRAME_HAS_VIEW;
// Let all of the containing frames know they have a child
// with a view until a frame is hit that has the
// NS_FRAME_HAS_CHILD_WITH_VIEW bit set already or a we
// reached the top of the frame tree.
PRBool isSet = PR_FALSE;
nsIFrame* parent = nsnull;
GetParent(&parent);
while ((parent != nsnull) && (! isSet)) {
nsFrameState frameState;
parent->GetFrameState(&frameState);
isSet = ((frameState & NS_FRAME_HAS_CHILD_WITH_VIEW) == NS_FRAME_HAS_CHILD_WITH_VIEW
);
if (! isSet) {
frameState |= NS_FRAME_HAS_CHILD_WITH_VIEW;
parent->SetFrameState(frameState);
}
parent->GetParent(&parent);
}
}
return NS_OK;