diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index c0b46665c6a7..c846ff664103 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -21,6 +21,7 @@ #include "nsLineLayout.h" #include "nsInlineReflow.h" #include "nsCSSLayout.h" +#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" @@ -2008,16 +2009,11 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext, PRBool isBlock = nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition); -// XXX yikes! this has to be here because otherwise we bust...why? -#if 1 - // See if the element wants to be floated - if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) { - // Create a placeholder frame that will serve as the anchor point. - nsPlaceholderFrame* placeholder = - CreatePlaceholderFrame(aPresContext, frame); - - // Remove the floated element from the flow, and replace it with the - // placeholder frame + // See if we need to move the frame outside of the flow, and insert in + // its place a placeholder frame + nsIFrame* placeholder; + if (MoveFrameOutOfFlow(aPresContext, frame, kidDisplay, kidPosition, placeholder)) { + // Remove 'frame' from the flow, and replace it with 'placeholder' if (nsnull != prevFrame) { prevFrame->SetNextSibling(placeholder); } @@ -2026,58 +2022,17 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext, placeholder->SetNextSibling(nextSibling); frame->SetNextSibling(nsnull); - // If the floated element can contain children then wrap it in a - // BODY frame before floating it - nsIContent* content; - PRBool isContainer; - - frame->GetContent(content); - content->CanContainChildren(isContainer); - if (isContainer) { - // Wrap the floated element in a BODY frame. - nsIFrame* wrapperFrame; - NS_NewBodyFrame(content, this, wrapperFrame); - - // The body wrapper frame gets the original style context, and the floated - // frame gets a pseudo style context - nsIStyleContext* kidStyle; - frame->GetStyleContext(&aPresContext, kidStyle); - wrapperFrame->SetStyleContext(&aPresContext, kidStyle); - NS_RELEASE(kidStyle); - - nsIStyleContext* pseudoStyle; - pseudoStyle = aPresContext.ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo, - wrapperFrame); - frame->SetStyleContext(&aPresContext, pseudoStyle); - NS_RELEASE(pseudoStyle); - - // Init the body frame - wrapperFrame->Init(aPresContext, frame); - - // Bind the wrapper frame to the placeholder - placeholder->SetAnchoredItem(wrapperFrame); - } - NS_RELEASE(content); - // The placeholder frame is always inline frame = placeholder; isBlock = PR_FALSE; } -#endif - // XXX CONSTRUCTION See if it wants to be absolutely positioned or scrolled - // if overflows... + // XXX CONSTRUCTION See if it wants to be scrolled if overflows... #if 0 nsIFrame* kidFrame = nsnull; nsresult rv; - if (NS_STYLE_POSITION_ABSOLUTE == kidPosition->mPosition) { - rv = nsAbsoluteFrame::NewFrame(&kidFrame, aKid, aParentFrame); - if (NS_OK == rv) { - kidFrame->SetStyleContext(aPresContext, kidSC); - } - } - else if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) || - (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) { + if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) || + (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) { rv = NS_NewScrollFrame(&kidFrame, aKid, aParentFrame); if (NS_OK == rv) { kidFrame->SetStyleContext(aPresContext, kidSC); @@ -3446,6 +3401,8 @@ nsBlockFrame::DrainOverflowLines() return drained; } +// XXX This code doesn't handle floating elements or absolutely positioned +// elements... nsresult nsBlockFrame::InsertNewFrame(nsBlockFrame* aParentFrame, nsIFrame* aNewFrame, diff --git a/layout/generic/nsBlockReflowState.cpp b/layout/generic/nsBlockReflowState.cpp index c0b46665c6a7..c846ff664103 100644 --- a/layout/generic/nsBlockReflowState.cpp +++ b/layout/generic/nsBlockReflowState.cpp @@ -21,6 +21,7 @@ #include "nsLineLayout.h" #include "nsInlineReflow.h" #include "nsCSSLayout.h" +#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" @@ -2008,16 +2009,11 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext, PRBool isBlock = nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition); -// XXX yikes! this has to be here because otherwise we bust...why? -#if 1 - // See if the element wants to be floated - if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) { - // Create a placeholder frame that will serve as the anchor point. - nsPlaceholderFrame* placeholder = - CreatePlaceholderFrame(aPresContext, frame); - - // Remove the floated element from the flow, and replace it with the - // placeholder frame + // See if we need to move the frame outside of the flow, and insert in + // its place a placeholder frame + nsIFrame* placeholder; + if (MoveFrameOutOfFlow(aPresContext, frame, kidDisplay, kidPosition, placeholder)) { + // Remove 'frame' from the flow, and replace it with 'placeholder' if (nsnull != prevFrame) { prevFrame->SetNextSibling(placeholder); } @@ -2026,58 +2022,17 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext, placeholder->SetNextSibling(nextSibling); frame->SetNextSibling(nsnull); - // If the floated element can contain children then wrap it in a - // BODY frame before floating it - nsIContent* content; - PRBool isContainer; - - frame->GetContent(content); - content->CanContainChildren(isContainer); - if (isContainer) { - // Wrap the floated element in a BODY frame. - nsIFrame* wrapperFrame; - NS_NewBodyFrame(content, this, wrapperFrame); - - // The body wrapper frame gets the original style context, and the floated - // frame gets a pseudo style context - nsIStyleContext* kidStyle; - frame->GetStyleContext(&aPresContext, kidStyle); - wrapperFrame->SetStyleContext(&aPresContext, kidStyle); - NS_RELEASE(kidStyle); - - nsIStyleContext* pseudoStyle; - pseudoStyle = aPresContext.ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo, - wrapperFrame); - frame->SetStyleContext(&aPresContext, pseudoStyle); - NS_RELEASE(pseudoStyle); - - // Init the body frame - wrapperFrame->Init(aPresContext, frame); - - // Bind the wrapper frame to the placeholder - placeholder->SetAnchoredItem(wrapperFrame); - } - NS_RELEASE(content); - // The placeholder frame is always inline frame = placeholder; isBlock = PR_FALSE; } -#endif - // XXX CONSTRUCTION See if it wants to be absolutely positioned or scrolled - // if overflows... + // XXX CONSTRUCTION See if it wants to be scrolled if overflows... #if 0 nsIFrame* kidFrame = nsnull; nsresult rv; - if (NS_STYLE_POSITION_ABSOLUTE == kidPosition->mPosition) { - rv = nsAbsoluteFrame::NewFrame(&kidFrame, aKid, aParentFrame); - if (NS_OK == rv) { - kidFrame->SetStyleContext(aPresContext, kidSC); - } - } - else if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) || - (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) { + if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) || + (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) { rv = NS_NewScrollFrame(&kidFrame, aKid, aParentFrame); if (NS_OK == rv) { kidFrame->SetStyleContext(aPresContext, kidSC); @@ -3446,6 +3401,8 @@ nsBlockFrame::DrainOverflowLines() return drained; } +// XXX This code doesn't handle floating elements or absolutely positioned +// elements... nsresult nsBlockFrame::InsertNewFrame(nsBlockFrame* aParentFrame, nsIFrame* aNewFrame, diff --git a/layout/generic/nsBlockReflowState.h b/layout/generic/nsBlockReflowState.h index c0b46665c6a7..c846ff664103 100644 --- a/layout/generic/nsBlockReflowState.h +++ b/layout/generic/nsBlockReflowState.h @@ -21,6 +21,7 @@ #include "nsLineLayout.h" #include "nsInlineReflow.h" #include "nsCSSLayout.h" +#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" @@ -2008,16 +2009,11 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext, PRBool isBlock = nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition); -// XXX yikes! this has to be here because otherwise we bust...why? -#if 1 - // See if the element wants to be floated - if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) { - // Create a placeholder frame that will serve as the anchor point. - nsPlaceholderFrame* placeholder = - CreatePlaceholderFrame(aPresContext, frame); - - // Remove the floated element from the flow, and replace it with the - // placeholder frame + // See if we need to move the frame outside of the flow, and insert in + // its place a placeholder frame + nsIFrame* placeholder; + if (MoveFrameOutOfFlow(aPresContext, frame, kidDisplay, kidPosition, placeholder)) { + // Remove 'frame' from the flow, and replace it with 'placeholder' if (nsnull != prevFrame) { prevFrame->SetNextSibling(placeholder); } @@ -2026,58 +2022,17 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext, placeholder->SetNextSibling(nextSibling); frame->SetNextSibling(nsnull); - // If the floated element can contain children then wrap it in a - // BODY frame before floating it - nsIContent* content; - PRBool isContainer; - - frame->GetContent(content); - content->CanContainChildren(isContainer); - if (isContainer) { - // Wrap the floated element in a BODY frame. - nsIFrame* wrapperFrame; - NS_NewBodyFrame(content, this, wrapperFrame); - - // The body wrapper frame gets the original style context, and the floated - // frame gets a pseudo style context - nsIStyleContext* kidStyle; - frame->GetStyleContext(&aPresContext, kidStyle); - wrapperFrame->SetStyleContext(&aPresContext, kidStyle); - NS_RELEASE(kidStyle); - - nsIStyleContext* pseudoStyle; - pseudoStyle = aPresContext.ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo, - wrapperFrame); - frame->SetStyleContext(&aPresContext, pseudoStyle); - NS_RELEASE(pseudoStyle); - - // Init the body frame - wrapperFrame->Init(aPresContext, frame); - - // Bind the wrapper frame to the placeholder - placeholder->SetAnchoredItem(wrapperFrame); - } - NS_RELEASE(content); - // The placeholder frame is always inline frame = placeholder; isBlock = PR_FALSE; } -#endif - // XXX CONSTRUCTION See if it wants to be absolutely positioned or scrolled - // if overflows... + // XXX CONSTRUCTION See if it wants to be scrolled if overflows... #if 0 nsIFrame* kidFrame = nsnull; nsresult rv; - if (NS_STYLE_POSITION_ABSOLUTE == kidPosition->mPosition) { - rv = nsAbsoluteFrame::NewFrame(&kidFrame, aKid, aParentFrame); - if (NS_OK == rv) { - kidFrame->SetStyleContext(aPresContext, kidSC); - } - } - else if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) || - (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) { + if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) || + (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) { rv = NS_NewScrollFrame(&kidFrame, aKid, aParentFrame); if (NS_OK == rv) { kidFrame->SetStyleContext(aPresContext, kidSC); @@ -3446,6 +3401,8 @@ nsBlockFrame::DrainOverflowLines() return drained; } +// XXX This code doesn't handle floating elements or absolutely positioned +// elements... nsresult nsBlockFrame::InsertNewFrame(nsBlockFrame* aParentFrame, nsIFrame* aNewFrame, diff --git a/layout/generic/nsHTMLContainerFrame.cpp b/layout/generic/nsHTMLContainerFrame.cpp index 0e8be59e74e7..4031b89a1d02 100644 --- a/layout/generic/nsHTMLContainerFrame.cpp +++ b/layout/generic/nsHTMLContainerFrame.cpp @@ -160,6 +160,105 @@ nsHTMLContainerFrame::CreatePlaceholderFrame(nsIPresContext& aPresContext, return placeholder; } +nsAbsoluteFrame* +nsHTMLContainerFrame::CreateAbsolutePlaceholderFrame(nsIPresContext& aPresContext, + nsIFrame* aAbsoluteFrame) +{ + nsIContent* content; + aAbsoluteFrame->GetContent(content); + + nsAbsoluteFrame* placeholder; + nsAbsoluteFrame::NewFrame((nsIFrame**)&placeholder, content, this, aAbsoluteFrame); + NS_IF_RELEASE(content); + + // Let the placeholder share the same style context as the floated element + nsIStyleContext* kidSC; + aAbsoluteFrame->GetStyleContext(&aPresContext, kidSC); + placeholder->SetStyleContext(&aPresContext, kidSC); + NS_RELEASE(kidSC); + + return placeholder; +} + +PRBool +nsHTMLContainerFrame::CreateWrapperFrame(nsIPresContext& aPresContext, + nsIFrame* aFrame, + nsIFrame*& aWrapperFrame) +{ + // If the floated element can contain children then wrap it in a + // BODY frame before floating it + nsIContent* content; + PRBool isContainer; + + aFrame->GetContent(content); + content->CanContainChildren(isContainer); + if (isContainer) { + // Wrap the floated element in a BODY frame. + NS_NewBodyFrame(content, this, aWrapperFrame); + + // The body wrapper frame gets the original style context, and the floated + // frame gets a pseudo style context + nsIStyleContext* kidStyle; + aFrame->GetStyleContext(&aPresContext, kidStyle); + aWrapperFrame->SetStyleContext(&aPresContext, kidStyle); + NS_RELEASE(kidStyle); + + nsIStyleContext* pseudoStyle; + pseudoStyle = aPresContext.ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo, + aWrapperFrame); + aFrame->SetStyleContext(&aPresContext, pseudoStyle); + NS_RELEASE(pseudoStyle); + + // Init the body frame + aWrapperFrame->Init(aPresContext, aFrame); + } + + NS_RELEASE(content); + return isContainer; +} + +PRBool +nsHTMLContainerFrame::MoveFrameOutOfFlow(nsIPresContext& aPresContext, + nsIFrame* aFrame, + const nsStyleDisplay* aDisplay, + const nsStylePosition* aPosition, + nsIFrame*& aPlaceholderFrame) +{ + aPlaceholderFrame = nsnull; + + // See if the element wants to be floated or absolutely positioned + if (NS_STYLE_FLOAT_NONE != aDisplay->mFloats) { + // Create a placeholder frame that will serve as the anchor point. + nsPlaceholderFrame* placeholder = + CreatePlaceholderFrame(aPresContext, aFrame); + + // See if we need to wrap the frame in a BODY frame + nsIFrame* wrapperFrame; + if (CreateWrapperFrame(aPresContext, aFrame, wrapperFrame)) { + // Bind the wrapper frame to the placeholder + placeholder->SetAnchoredItem(wrapperFrame); + } + + aPlaceholderFrame = placeholder; + + } else if (NS_STYLE_POSITION_ABSOLUTE == aPosition->mPosition) { + // Create a placeholder frame that will serve as the anchor point. + nsAbsoluteFrame* placeholder = + CreateAbsolutePlaceholderFrame(aPresContext, aFrame); + + // See if we need to wrap the frame in a BODY frame + nsIFrame* wrapperFrame; + if (CreateWrapperFrame(aPresContext, aFrame, wrapperFrame)) { + // Bind the wrapper frame to the placeholder + placeholder->SetAbsoluteFrame(wrapperFrame); + } + + aPlaceholderFrame = placeholder; + } + + return aPlaceholderFrame != nsnull; +} + /** * Create a next-in-flow for aFrame. Will return the newly created * frame in aNextInFlowResult if and only if a new frame is diff --git a/layout/generic/nsHTMLContainerFrame.h b/layout/generic/nsHTMLContainerFrame.h index f7b3241f985b..aaf21664fb34 100644 --- a/layout/generic/nsHTMLContainerFrame.h +++ b/layout/generic/nsHTMLContainerFrame.h @@ -20,7 +20,10 @@ #include "nsContainerFrame.h" class nsString; +class nsAbsoluteFrame; class nsPlaceholderFrame; +struct nsStyleDisplay; +struct nsStylePosition; // Base class for html container frames that provides common // functionality. @@ -51,6 +54,17 @@ public: nsPlaceholderFrame* CreatePlaceholderFrame(nsIPresContext& aPresContext, nsIFrame* aFloatedFrame); + nsAbsoluteFrame* CreateAbsolutePlaceholderFrame(nsIPresContext& aPresContext, + nsIFrame* aAbsoluteFrame); + PRBool CreateWrapperFrame(nsIPresContext& aPresContext, + nsIFrame* aFrame, + nsIFrame*& aWrapperFrame); + + PRBool MoveFrameOutOfFlow(nsIPresContext& aPresContext, + nsIFrame* aFrame, + const nsStyleDisplay* aDisplay, + const nsStylePosition* aPosition, + nsIFrame*& aPlaceholderFrame); // Helper method to create next-in-flows if necessary static nsresult CreateNextInFlow(nsIPresContext& aPresContext, diff --git a/layout/html/base/src/nsAbsoluteFrame.cpp b/layout/html/base/src/nsAbsoluteFrame.cpp index 77441c4a81a3..8bfe9d5b57cf 100644 --- a/layout/html/base/src/nsAbsoluteFrame.cpp +++ b/layout/html/base/src/nsAbsoluteFrame.cpp @@ -25,13 +25,14 @@ nsresult nsAbsoluteFrame::NewFrame(nsIFrame** aInstancePtrResult, nsIContent* aContent, - nsIFrame* aParent) + nsIFrame* aParent, + nsIFrame* aAbsoluteFrame) { NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); if (nsnull == aInstancePtrResult) { return NS_ERROR_NULL_POINTER; } - nsIFrame* it = new nsAbsoluteFrame(aContent, aParent); + nsIFrame* it = new nsAbsoluteFrame(aContent, aParent, aAbsoluteFrame); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } @@ -39,9 +40,12 @@ nsAbsoluteFrame::NewFrame(nsIFrame** aInstancePtrResult, return NS_OK; } -nsAbsoluteFrame::nsAbsoluteFrame(nsIContent* aContent, nsIFrame* aParent) +nsAbsoluteFrame::nsAbsoluteFrame(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame* aAbsoluteFrame) : nsFrame(aContent, aParent) { + mFrame = aAbsoluteFrame; } nsAbsoluteFrame::~nsAbsoluteFrame() @@ -53,31 +57,10 @@ NS_IMETHODIMP nsAbsoluteFrame::Reflow(nsIPresContext& aPresContext, const nsReflowState& aReflowState, nsReflowStatus& aStatus) { - // Have we created the absolutely positioned item yet? - if (nsnull == mFrame) { - // If the content object is a container then wrap it in a body pseudo-frame - PRBool canHaveKids; - mContent->CanContainChildren(canHaveKids); - if (canHaveKids) { - nsBodyFrame::NewFrame(&mFrame, mContent, this); - - // Use our style context for the pseudo-frame - mFrame->SetStyleContext(&aPresContext, mStyleContext); - - } else { - // XXX CONSTRUCTION -#if 0 - // Ask the content delegate to create the frame - nsIContentDelegate* delegate = mContent->GetDelegate(&aPresContext); - - nsresult rv = delegate->CreateFrame(&aPresContext, mContent, this, - mStyleContext, mFrame); - NS_RELEASE(delegate); - if (NS_OK != rv) { - return rv; - } -#endif - } + if (eReflowReason_Initial == aReflowState.reason) { + // By this point we expect to have been told which absolute frame we're + // associated with + NS_ASSERTION(nsnull != mFrame, "no absolute frame"); // Get the containing block nsIFrame* containingBlock = GetContainingBlock(); diff --git a/layout/html/base/src/nsAbsoluteFrame.h b/layout/html/base/src/nsAbsoluteFrame.h index 90ded94b3ff6..ece43bdce50e 100644 --- a/layout/html/base/src/nsAbsoluteFrame.h +++ b/layout/html/base/src/nsAbsoluteFrame.h @@ -32,10 +32,12 @@ public: */ static nsresult NewFrame(nsIFrame** aInstancePtrResult, nsIContent* aContent, - nsIFrame* aParent); + nsIFrame* aParent, + nsIFrame* aAbsoluteFrame = nsnull); // Returns the associated anchored item nsIFrame* GetAbsoluteFrame() const {return mFrame;} + void SetAbsoluteFrame(nsIFrame* aAbsoluteFrame) {mFrame = aAbsoluteFrame;} // nsIFrame overrides NS_IMETHOD Reflow(nsIPresContext& aPresContext, @@ -55,7 +57,7 @@ protected: // Constructor. Takes as arguments the content object, the index in parent, // and the Frame for the content parent - nsAbsoluteFrame(nsIContent* aContent, nsIFrame* aParent); + nsAbsoluteFrame(nsIContent* aContent, nsIFrame* aParent, nsIFrame* aAbsoluteFrame); virtual ~nsAbsoluteFrame(); diff --git a/layout/html/base/src/nsBlockFrame.cpp b/layout/html/base/src/nsBlockFrame.cpp index c0b46665c6a7..c846ff664103 100644 --- a/layout/html/base/src/nsBlockFrame.cpp +++ b/layout/html/base/src/nsBlockFrame.cpp @@ -21,6 +21,7 @@ #include "nsLineLayout.h" #include "nsInlineReflow.h" #include "nsCSSLayout.h" +#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" @@ -2008,16 +2009,11 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext, PRBool isBlock = nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition); -// XXX yikes! this has to be here because otherwise we bust...why? -#if 1 - // See if the element wants to be floated - if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) { - // Create a placeholder frame that will serve as the anchor point. - nsPlaceholderFrame* placeholder = - CreatePlaceholderFrame(aPresContext, frame); - - // Remove the floated element from the flow, and replace it with the - // placeholder frame + // See if we need to move the frame outside of the flow, and insert in + // its place a placeholder frame + nsIFrame* placeholder; + if (MoveFrameOutOfFlow(aPresContext, frame, kidDisplay, kidPosition, placeholder)) { + // Remove 'frame' from the flow, and replace it with 'placeholder' if (nsnull != prevFrame) { prevFrame->SetNextSibling(placeholder); } @@ -2026,58 +2022,17 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext, placeholder->SetNextSibling(nextSibling); frame->SetNextSibling(nsnull); - // If the floated element can contain children then wrap it in a - // BODY frame before floating it - nsIContent* content; - PRBool isContainer; - - frame->GetContent(content); - content->CanContainChildren(isContainer); - if (isContainer) { - // Wrap the floated element in a BODY frame. - nsIFrame* wrapperFrame; - NS_NewBodyFrame(content, this, wrapperFrame); - - // The body wrapper frame gets the original style context, and the floated - // frame gets a pseudo style context - nsIStyleContext* kidStyle; - frame->GetStyleContext(&aPresContext, kidStyle); - wrapperFrame->SetStyleContext(&aPresContext, kidStyle); - NS_RELEASE(kidStyle); - - nsIStyleContext* pseudoStyle; - pseudoStyle = aPresContext.ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo, - wrapperFrame); - frame->SetStyleContext(&aPresContext, pseudoStyle); - NS_RELEASE(pseudoStyle); - - // Init the body frame - wrapperFrame->Init(aPresContext, frame); - - // Bind the wrapper frame to the placeholder - placeholder->SetAnchoredItem(wrapperFrame); - } - NS_RELEASE(content); - // The placeholder frame is always inline frame = placeholder; isBlock = PR_FALSE; } -#endif - // XXX CONSTRUCTION See if it wants to be absolutely positioned or scrolled - // if overflows... + // XXX CONSTRUCTION See if it wants to be scrolled if overflows... #if 0 nsIFrame* kidFrame = nsnull; nsresult rv; - if (NS_STYLE_POSITION_ABSOLUTE == kidPosition->mPosition) { - rv = nsAbsoluteFrame::NewFrame(&kidFrame, aKid, aParentFrame); - if (NS_OK == rv) { - kidFrame->SetStyleContext(aPresContext, kidSC); - } - } - else if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) || - (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) { + if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) || + (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) { rv = NS_NewScrollFrame(&kidFrame, aKid, aParentFrame); if (NS_OK == rv) { kidFrame->SetStyleContext(aPresContext, kidSC); @@ -3446,6 +3401,8 @@ nsBlockFrame::DrainOverflowLines() return drained; } +// XXX This code doesn't handle floating elements or absolutely positioned +// elements... nsresult nsBlockFrame::InsertNewFrame(nsBlockFrame* aParentFrame, nsIFrame* aNewFrame, diff --git a/layout/html/base/src/nsBlockReflowState.cpp b/layout/html/base/src/nsBlockReflowState.cpp index c0b46665c6a7..c846ff664103 100644 --- a/layout/html/base/src/nsBlockReflowState.cpp +++ b/layout/html/base/src/nsBlockReflowState.cpp @@ -21,6 +21,7 @@ #include "nsLineLayout.h" #include "nsInlineReflow.h" #include "nsCSSLayout.h" +#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" @@ -2008,16 +2009,11 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext, PRBool isBlock = nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition); -// XXX yikes! this has to be here because otherwise we bust...why? -#if 1 - // See if the element wants to be floated - if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) { - // Create a placeholder frame that will serve as the anchor point. - nsPlaceholderFrame* placeholder = - CreatePlaceholderFrame(aPresContext, frame); - - // Remove the floated element from the flow, and replace it with the - // placeholder frame + // See if we need to move the frame outside of the flow, and insert in + // its place a placeholder frame + nsIFrame* placeholder; + if (MoveFrameOutOfFlow(aPresContext, frame, kidDisplay, kidPosition, placeholder)) { + // Remove 'frame' from the flow, and replace it with 'placeholder' if (nsnull != prevFrame) { prevFrame->SetNextSibling(placeholder); } @@ -2026,58 +2022,17 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext, placeholder->SetNextSibling(nextSibling); frame->SetNextSibling(nsnull); - // If the floated element can contain children then wrap it in a - // BODY frame before floating it - nsIContent* content; - PRBool isContainer; - - frame->GetContent(content); - content->CanContainChildren(isContainer); - if (isContainer) { - // Wrap the floated element in a BODY frame. - nsIFrame* wrapperFrame; - NS_NewBodyFrame(content, this, wrapperFrame); - - // The body wrapper frame gets the original style context, and the floated - // frame gets a pseudo style context - nsIStyleContext* kidStyle; - frame->GetStyleContext(&aPresContext, kidStyle); - wrapperFrame->SetStyleContext(&aPresContext, kidStyle); - NS_RELEASE(kidStyle); - - nsIStyleContext* pseudoStyle; - pseudoStyle = aPresContext.ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo, - wrapperFrame); - frame->SetStyleContext(&aPresContext, pseudoStyle); - NS_RELEASE(pseudoStyle); - - // Init the body frame - wrapperFrame->Init(aPresContext, frame); - - // Bind the wrapper frame to the placeholder - placeholder->SetAnchoredItem(wrapperFrame); - } - NS_RELEASE(content); - // The placeholder frame is always inline frame = placeholder; isBlock = PR_FALSE; } -#endif - // XXX CONSTRUCTION See if it wants to be absolutely positioned or scrolled - // if overflows... + // XXX CONSTRUCTION See if it wants to be scrolled if overflows... #if 0 nsIFrame* kidFrame = nsnull; nsresult rv; - if (NS_STYLE_POSITION_ABSOLUTE == kidPosition->mPosition) { - rv = nsAbsoluteFrame::NewFrame(&kidFrame, aKid, aParentFrame); - if (NS_OK == rv) { - kidFrame->SetStyleContext(aPresContext, kidSC); - } - } - else if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) || - (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) { + if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) || + (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) { rv = NS_NewScrollFrame(&kidFrame, aKid, aParentFrame); if (NS_OK == rv) { kidFrame->SetStyleContext(aPresContext, kidSC); @@ -3446,6 +3401,8 @@ nsBlockFrame::DrainOverflowLines() return drained; } +// XXX This code doesn't handle floating elements or absolutely positioned +// elements... nsresult nsBlockFrame::InsertNewFrame(nsBlockFrame* aParentFrame, nsIFrame* aNewFrame, diff --git a/layout/html/base/src/nsBlockReflowState.h b/layout/html/base/src/nsBlockReflowState.h index c0b46665c6a7..c846ff664103 100644 --- a/layout/html/base/src/nsBlockReflowState.h +++ b/layout/html/base/src/nsBlockReflowState.h @@ -21,6 +21,7 @@ #include "nsLineLayout.h" #include "nsInlineReflow.h" #include "nsCSSLayout.h" +#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" @@ -2008,16 +2009,11 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext, PRBool isBlock = nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition); -// XXX yikes! this has to be here because otherwise we bust...why? -#if 1 - // See if the element wants to be floated - if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) { - // Create a placeholder frame that will serve as the anchor point. - nsPlaceholderFrame* placeholder = - CreatePlaceholderFrame(aPresContext, frame); - - // Remove the floated element from the flow, and replace it with the - // placeholder frame + // See if we need to move the frame outside of the flow, and insert in + // its place a placeholder frame + nsIFrame* placeholder; + if (MoveFrameOutOfFlow(aPresContext, frame, kidDisplay, kidPosition, placeholder)) { + // Remove 'frame' from the flow, and replace it with 'placeholder' if (nsnull != prevFrame) { prevFrame->SetNextSibling(placeholder); } @@ -2026,58 +2022,17 @@ nsBlockFrame::AppendNewFrames(nsIPresContext& aPresContext, placeholder->SetNextSibling(nextSibling); frame->SetNextSibling(nsnull); - // If the floated element can contain children then wrap it in a - // BODY frame before floating it - nsIContent* content; - PRBool isContainer; - - frame->GetContent(content); - content->CanContainChildren(isContainer); - if (isContainer) { - // Wrap the floated element in a BODY frame. - nsIFrame* wrapperFrame; - NS_NewBodyFrame(content, this, wrapperFrame); - - // The body wrapper frame gets the original style context, and the floated - // frame gets a pseudo style context - nsIStyleContext* kidStyle; - frame->GetStyleContext(&aPresContext, kidStyle); - wrapperFrame->SetStyleContext(&aPresContext, kidStyle); - NS_RELEASE(kidStyle); - - nsIStyleContext* pseudoStyle; - pseudoStyle = aPresContext.ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo, - wrapperFrame); - frame->SetStyleContext(&aPresContext, pseudoStyle); - NS_RELEASE(pseudoStyle); - - // Init the body frame - wrapperFrame->Init(aPresContext, frame); - - // Bind the wrapper frame to the placeholder - placeholder->SetAnchoredItem(wrapperFrame); - } - NS_RELEASE(content); - // The placeholder frame is always inline frame = placeholder; isBlock = PR_FALSE; } -#endif - // XXX CONSTRUCTION See if it wants to be absolutely positioned or scrolled - // if overflows... + // XXX CONSTRUCTION See if it wants to be scrolled if overflows... #if 0 nsIFrame* kidFrame = nsnull; nsresult rv; - if (NS_STYLE_POSITION_ABSOLUTE == kidPosition->mPosition) { - rv = nsAbsoluteFrame::NewFrame(&kidFrame, aKid, aParentFrame); - if (NS_OK == rv) { - kidFrame->SetStyleContext(aPresContext, kidSC); - } - } - else if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) || - (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) { + if ((NS_STYLE_OVERFLOW_SCROLL == kidDisplay->mOverflow) || + (NS_STYLE_OVERFLOW_AUTO == kidDisplay->mOverflow)) { rv = NS_NewScrollFrame(&kidFrame, aKid, aParentFrame); if (NS_OK == rv) { kidFrame->SetStyleContext(aPresContext, kidSC); @@ -3446,6 +3401,8 @@ nsBlockFrame::DrainOverflowLines() return drained; } +// XXX This code doesn't handle floating elements or absolutely positioned +// elements... nsresult nsBlockFrame::InsertNewFrame(nsBlockFrame* aParentFrame, nsIFrame* aNewFrame, diff --git a/layout/html/base/src/nsHTMLContainerFrame.cpp b/layout/html/base/src/nsHTMLContainerFrame.cpp index 0e8be59e74e7..4031b89a1d02 100644 --- a/layout/html/base/src/nsHTMLContainerFrame.cpp +++ b/layout/html/base/src/nsHTMLContainerFrame.cpp @@ -160,6 +160,105 @@ nsHTMLContainerFrame::CreatePlaceholderFrame(nsIPresContext& aPresContext, return placeholder; } +nsAbsoluteFrame* +nsHTMLContainerFrame::CreateAbsolutePlaceholderFrame(nsIPresContext& aPresContext, + nsIFrame* aAbsoluteFrame) +{ + nsIContent* content; + aAbsoluteFrame->GetContent(content); + + nsAbsoluteFrame* placeholder; + nsAbsoluteFrame::NewFrame((nsIFrame**)&placeholder, content, this, aAbsoluteFrame); + NS_IF_RELEASE(content); + + // Let the placeholder share the same style context as the floated element + nsIStyleContext* kidSC; + aAbsoluteFrame->GetStyleContext(&aPresContext, kidSC); + placeholder->SetStyleContext(&aPresContext, kidSC); + NS_RELEASE(kidSC); + + return placeholder; +} + +PRBool +nsHTMLContainerFrame::CreateWrapperFrame(nsIPresContext& aPresContext, + nsIFrame* aFrame, + nsIFrame*& aWrapperFrame) +{ + // If the floated element can contain children then wrap it in a + // BODY frame before floating it + nsIContent* content; + PRBool isContainer; + + aFrame->GetContent(content); + content->CanContainChildren(isContainer); + if (isContainer) { + // Wrap the floated element in a BODY frame. + NS_NewBodyFrame(content, this, aWrapperFrame); + + // The body wrapper frame gets the original style context, and the floated + // frame gets a pseudo style context + nsIStyleContext* kidStyle; + aFrame->GetStyleContext(&aPresContext, kidStyle); + aWrapperFrame->SetStyleContext(&aPresContext, kidStyle); + NS_RELEASE(kidStyle); + + nsIStyleContext* pseudoStyle; + pseudoStyle = aPresContext.ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo, + aWrapperFrame); + aFrame->SetStyleContext(&aPresContext, pseudoStyle); + NS_RELEASE(pseudoStyle); + + // Init the body frame + aWrapperFrame->Init(aPresContext, aFrame); + } + + NS_RELEASE(content); + return isContainer; +} + +PRBool +nsHTMLContainerFrame::MoveFrameOutOfFlow(nsIPresContext& aPresContext, + nsIFrame* aFrame, + const nsStyleDisplay* aDisplay, + const nsStylePosition* aPosition, + nsIFrame*& aPlaceholderFrame) +{ + aPlaceholderFrame = nsnull; + + // See if the element wants to be floated or absolutely positioned + if (NS_STYLE_FLOAT_NONE != aDisplay->mFloats) { + // Create a placeholder frame that will serve as the anchor point. + nsPlaceholderFrame* placeholder = + CreatePlaceholderFrame(aPresContext, aFrame); + + // See if we need to wrap the frame in a BODY frame + nsIFrame* wrapperFrame; + if (CreateWrapperFrame(aPresContext, aFrame, wrapperFrame)) { + // Bind the wrapper frame to the placeholder + placeholder->SetAnchoredItem(wrapperFrame); + } + + aPlaceholderFrame = placeholder; + + } else if (NS_STYLE_POSITION_ABSOLUTE == aPosition->mPosition) { + // Create a placeholder frame that will serve as the anchor point. + nsAbsoluteFrame* placeholder = + CreateAbsolutePlaceholderFrame(aPresContext, aFrame); + + // See if we need to wrap the frame in a BODY frame + nsIFrame* wrapperFrame; + if (CreateWrapperFrame(aPresContext, aFrame, wrapperFrame)) { + // Bind the wrapper frame to the placeholder + placeholder->SetAbsoluteFrame(wrapperFrame); + } + + aPlaceholderFrame = placeholder; + } + + return aPlaceholderFrame != nsnull; +} + /** * Create a next-in-flow for aFrame. Will return the newly created * frame in aNextInFlowResult if and only if a new frame is diff --git a/layout/html/base/src/nsHTMLContainerFrame.h b/layout/html/base/src/nsHTMLContainerFrame.h index f7b3241f985b..aaf21664fb34 100644 --- a/layout/html/base/src/nsHTMLContainerFrame.h +++ b/layout/html/base/src/nsHTMLContainerFrame.h @@ -20,7 +20,10 @@ #include "nsContainerFrame.h" class nsString; +class nsAbsoluteFrame; class nsPlaceholderFrame; +struct nsStyleDisplay; +struct nsStylePosition; // Base class for html container frames that provides common // functionality. @@ -51,6 +54,17 @@ public: nsPlaceholderFrame* CreatePlaceholderFrame(nsIPresContext& aPresContext, nsIFrame* aFloatedFrame); + nsAbsoluteFrame* CreateAbsolutePlaceholderFrame(nsIPresContext& aPresContext, + nsIFrame* aAbsoluteFrame); + PRBool CreateWrapperFrame(nsIPresContext& aPresContext, + nsIFrame* aFrame, + nsIFrame*& aWrapperFrame); + + PRBool MoveFrameOutOfFlow(nsIPresContext& aPresContext, + nsIFrame* aFrame, + const nsStyleDisplay* aDisplay, + const nsStylePosition* aPosition, + nsIFrame*& aPlaceholderFrame); // Helper method to create next-in-flows if necessary static nsresult CreateNextInFlow(nsIPresContext& aPresContext,