diff --git a/layout/html/table/src/nsTableFrame.cpp b/layout/html/table/src/nsTableFrame.cpp index bf18ff472bd0..fbc069f03d45 100644 --- a/layout/html/table/src/nsTableFrame.cpp +++ b/layout/html/table/src/nsTableFrame.cpp @@ -1703,6 +1703,9 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, nsSize maxKidElementSize(0,0); nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState, availSize, aReason); + // Note: we don't bother checking here for whether we should clear the + // isTopOfPage reflow state flag, because we're dealing with an unconstrained + // height and it isn't an issue... PRInt32 yCoord = y; if (NS_UNCONSTRAINEDSIZE!=yCoord) yCoord+= topInset; @@ -2440,7 +2443,8 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, reason = eReflowReason_Resize; // this never passes reflows down to colgroups - for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) + nsIFrame* firstRowGroupFrame = nsnull; + for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) { nsSize kidAvailSize(aReflowState.availSize); nsHTMLReflowMetrics desiredSize(pKidMaxElementSize); @@ -2449,7 +2453,15 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, const nsStyleDisplay *childDisplay; kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay)); if (PR_TRUE==IsRowGroup(childDisplay->mDisplay)) - { // for all colgroups and rowgroups... + { + // Keep track of the first row group frame: we need this to correctly clear + // the isTopOfPage flag and when pushing frames + if (nsnull == firstRowGroupFrame) { + if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay) { + firstRowGroupFrame = kidFrame; + } + } + const nsStyleSpacing* kidSpacing; kidFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)kidSpacing)); nsMargin kidMargin; @@ -2472,20 +2484,25 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState.reflowState, kidAvailSize, reason); + if ((nsnull != firstRowGroupFrame) && (kidFrame != firstRowGroupFrame)) { + // If this isn't the first row group frame or the header or footer, then + // we can't be at the top of the page anymore... + kidReflowState.isTopOfPage = PR_FALSE; + } nscoord x = aReflowState.leftInset + kidMargin.left; nscoord y = aReflowState.topInset + aReflowState.y + topMargin; if (PR_TRUE==gsDebugIR) printf("\nTIF IR: Reflow Pass 2 of frame %p with reason=%d\n", kidFrame, reason); rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus); // Did the child fit? - if ((kidFrame != mFirstChild) && (desiredSize.height > kidAvailSize.height)) - { - // The child is too tall to fit in the available space, and it's - // not our first child - // XXX TROY: checking mFirstChild here is probably wrong. Should check to see if its the first row group? - PushChildren(kidFrame, prevKidFrame); - //XXX TROY: set aStatus? - break; + if (desiredSize.height > kidAvailSize.height) { + if ((nsnull != firstRowGroupFrame) && (kidFrame != firstRowGroupFrame)) { + // The child is too tall to fit in the available space, and it's + // not our first row grpup frame + PushChildren(kidFrame, prevKidFrame); + aStatus = NS_FRAME_NOT_COMPLETE; + break; + } } // Place the child after taking into account it's margin diff --git a/layout/html/table/src/nsTableRowGroupFrame.cpp b/layout/html/table/src/nsTableRowGroupFrame.cpp index a12271ea9cc0..3cfbe5394cfe 100644 --- a/layout/html/table/src/nsTableRowGroupFrame.cpp +++ b/layout/html/table/src/nsTableRowGroupFrame.cpp @@ -356,8 +356,19 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC } // Reflow the child into the available space +#if 1 + // XXX Give it as much room as it wants. We'll deal with splitting later + // after we've computed the row heights taking into account cells with + // row spans... + kidAvailSize.height = NS_UNCONSTRAINEDSIZE; +#endif nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState.reflowState, kidAvailSize, aReason); + if (kidFrame != mFirstChild) { + // If this isn't the first row frame, then we can't be at the top of + // the page anymore... + kidReflowState.isTopOfPage = PR_FALSE; + } if ((PR_TRUE==gsDebug) || (PR_TRUE==gsDebugIR)) printf("%p RG reflowing child %p with avail width = %d, reason = %d\n", @@ -366,6 +377,7 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC if (gsDebug) printf("%p RG child %p returned desired width = %d\n", this, kidFrame, desiredSize.width); +#if 0 // Did the child fit? if ((kidFrame != mFirstChild) && ((kidAvailSize.height <= 0) || @@ -380,6 +392,7 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC aStatus = NS_FRAME_NOT_COMPLETE; break; } +#endif // Place the child after taking into account its margin nsRect kidRect (kidMargin.left, aReflowState.y, desiredSize.width, desiredSize.height); @@ -394,6 +407,7 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC // Remember where we just were in case we end up pushing children prevKidFrame = kidFrame; +#if 0 /* Row groups should not create continuing frames for rows * unless they absolutely have to! * check to see if this is absolutely necessary (with new params from troy) @@ -433,6 +447,7 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC } break; } +#endif // Add back in the left and right margins, because one row does not // impact another row's width @@ -828,6 +843,74 @@ nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aP return NS_OK; } +nsresult +nsTableRowGroupFrame::SplitRowGroup(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + nsIFrame* prevKidFrame = nsnull; + + // Walk each of the row frames looking for the first row frame that + // doesn't fit in the available space + for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) { + nsRect bounds; + + kidFrame->GetRect(bounds); + if (bounds.YMost() > aReflowState.maxSize.height) { + // If this is the first row frame then we need to split it + if (nsnull == prevKidFrame) { + // Reflow the row in the available space and have it split + // XXX Account for horizontal margins... +#if 0 + nsSize kidAvailSize(aReflowState.maxSize.width, + aReflowState.maxSize.height - bounds.y); + nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState, + kidAvailSize, eReflowReason_Resize); + nsReflowMetrics desiredSize; + + rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus); + kidFrame->SizeTo(desiredSize.width, desiredSize.height); + NS_ASSERTION(NS_FRAME_IS_NOT_COMPLETE(aStatus), "unexpected status"); + + // Create a continuing frame, add it to the child list, and then push it + // and the frames that follow + // XXX Check whether it already has a next-in-flow + nsIFrame* continuingFrame; + nsIStyleContext* kidSC; + + kidFrame->GetStyleContext(kidSC); + kidFrame->CreateContinuingFrame(aPresContext, this, kidSC, continuingFrame); + NS_RELEASE(kidSC); + + // Add it to the child list + nsIFrame* nextSibling; + + kidFrame->GetNextSibling(nextSibling); + continuingFrame->SetNextSibling(nextSibling); + kidFrame->SetNextSibling(continuingFrame); + + // Push it and the frames that follow + PushChildren(continuingFrame, kidFrame); + aDesiredSize.height = bounds.y; +#endif + + } else { + // See whether the row frame has cells that span into it or across it + PushChildren(kidFrame, prevKidFrame); + aDesiredSize.height = bounds.y; + } + + aStatus = NS_FRAME_NOT_COMPLETE; + break; + } + + prevKidFrame = kidFrame; + } + + return NS_OK; +} + /** Layout the entire row group. * This method stacks rows vertically according to HTML 4.0 rules. * Rows are responsible for layout of their children. @@ -874,11 +957,14 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext, nsnull, aReflowState.reason, PR_TRUE); } + // XXX We need to figure out what to do about this... +#if 0 // Did we successfully reflow our mapped children? if (NS_FRAME_COMPLETE==aStatus) { // Try and pull-up some children from a next-in-flow rv = PullUpChildren(aPresContext, aDesiredSize, state, aStatus); } +#endif if (NS_FRAME_IS_COMPLETE(aStatus)) { // Don't forget to add in the bottom margin from our last child. @@ -898,6 +984,12 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext, if (eReflowReason_Initial != aReflowState.reason) { CalculateRowHeights(aPresContext, aDesiredSize, aReflowState); } + + // See if all the frames fit + if (aDesiredSize.height > aReflowState.maxSize.height) { + // Nope, find a place to split the row group + SplitRowGroup(aPresContext, aDesiredSize, aReflowState, aStatus); + } } if (gsDebug==PR_TRUE) diff --git a/layout/html/table/src/nsTableRowGroupFrame.h b/layout/html/table/src/nsTableRowGroupFrame.h index 28106d2bcff8..520e22e7791b 100644 --- a/layout/html/table/src/nsTableRowGroupFrame.h +++ b/layout/html/table/src/nsTableRowGroupFrame.h @@ -33,8 +33,6 @@ struct RowGroupReflowState; * * @see nsTableFrame * @see nsTableRowFrame - * - * @author sclark */ class nsTableRowGroupFrame : public nsHTMLContainerFrame { @@ -109,12 +107,12 @@ protected: RowGroupReflowState& aReflowState, const nsMargin& aKidMargin); - void PlaceChild( nsIPresContext& aPresContext, - RowGroupReflowState& aReflowState, - nsIFrame* aKidFrame, - const nsRect& aKidRect, - nsSize* aMaxElementSize, - nsSize& aKidMaxElementSize); + void PlaceChild(nsIPresContext& aPresContext, + RowGroupReflowState& aReflowState, + nsIFrame* aKidFrame, + const nsRect& aKidRect, + nsSize* aMaxElementSize, + nsSize& aKidMaxElementSize); void CalculateRowHeights(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -212,6 +210,11 @@ protected: RowGroupReflowState& aReflowState, nsReflowStatus& aStatus); + nsresult SplitRowGroup(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus); + private: nsIAtom *mType; diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index bf18ff472bd0..fbc069f03d45 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -1703,6 +1703,9 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, nsSize maxKidElementSize(0,0); nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState, availSize, aReason); + // Note: we don't bother checking here for whether we should clear the + // isTopOfPage reflow state flag, because we're dealing with an unconstrained + // height and it isn't an issue... PRInt32 yCoord = y; if (NS_UNCONSTRAINEDSIZE!=yCoord) yCoord+= topInset; @@ -2440,7 +2443,8 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, reason = eReflowReason_Resize; // this never passes reflows down to colgroups - for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) + nsIFrame* firstRowGroupFrame = nsnull; + for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) { nsSize kidAvailSize(aReflowState.availSize); nsHTMLReflowMetrics desiredSize(pKidMaxElementSize); @@ -2449,7 +2453,15 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, const nsStyleDisplay *childDisplay; kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay)); if (PR_TRUE==IsRowGroup(childDisplay->mDisplay)) - { // for all colgroups and rowgroups... + { + // Keep track of the first row group frame: we need this to correctly clear + // the isTopOfPage flag and when pushing frames + if (nsnull == firstRowGroupFrame) { + if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay) { + firstRowGroupFrame = kidFrame; + } + } + const nsStyleSpacing* kidSpacing; kidFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)kidSpacing)); nsMargin kidMargin; @@ -2472,20 +2484,25 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState.reflowState, kidAvailSize, reason); + if ((nsnull != firstRowGroupFrame) && (kidFrame != firstRowGroupFrame)) { + // If this isn't the first row group frame or the header or footer, then + // we can't be at the top of the page anymore... + kidReflowState.isTopOfPage = PR_FALSE; + } nscoord x = aReflowState.leftInset + kidMargin.left; nscoord y = aReflowState.topInset + aReflowState.y + topMargin; if (PR_TRUE==gsDebugIR) printf("\nTIF IR: Reflow Pass 2 of frame %p with reason=%d\n", kidFrame, reason); rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus); // Did the child fit? - if ((kidFrame != mFirstChild) && (desiredSize.height > kidAvailSize.height)) - { - // The child is too tall to fit in the available space, and it's - // not our first child - // XXX TROY: checking mFirstChild here is probably wrong. Should check to see if its the first row group? - PushChildren(kidFrame, prevKidFrame); - //XXX TROY: set aStatus? - break; + if (desiredSize.height > kidAvailSize.height) { + if ((nsnull != firstRowGroupFrame) && (kidFrame != firstRowGroupFrame)) { + // The child is too tall to fit in the available space, and it's + // not our first row grpup frame + PushChildren(kidFrame, prevKidFrame); + aStatus = NS_FRAME_NOT_COMPLETE; + break; + } } // Place the child after taking into account it's margin diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index a12271ea9cc0..3cfbe5394cfe 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -356,8 +356,19 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC } // Reflow the child into the available space +#if 1 + // XXX Give it as much room as it wants. We'll deal with splitting later + // after we've computed the row heights taking into account cells with + // row spans... + kidAvailSize.height = NS_UNCONSTRAINEDSIZE; +#endif nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState.reflowState, kidAvailSize, aReason); + if (kidFrame != mFirstChild) { + // If this isn't the first row frame, then we can't be at the top of + // the page anymore... + kidReflowState.isTopOfPage = PR_FALSE; + } if ((PR_TRUE==gsDebug) || (PR_TRUE==gsDebugIR)) printf("%p RG reflowing child %p with avail width = %d, reason = %d\n", @@ -366,6 +377,7 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC if (gsDebug) printf("%p RG child %p returned desired width = %d\n", this, kidFrame, desiredSize.width); +#if 0 // Did the child fit? if ((kidFrame != mFirstChild) && ((kidAvailSize.height <= 0) || @@ -380,6 +392,7 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC aStatus = NS_FRAME_NOT_COMPLETE; break; } +#endif // Place the child after taking into account its margin nsRect kidRect (kidMargin.left, aReflowState.y, desiredSize.width, desiredSize.height); @@ -394,6 +407,7 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC // Remember where we just were in case we end up pushing children prevKidFrame = kidFrame; +#if 0 /* Row groups should not create continuing frames for rows * unless they absolutely have to! * check to see if this is absolutely necessary (with new params from troy) @@ -433,6 +447,7 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC } break; } +#endif // Add back in the left and right margins, because one row does not // impact another row's width @@ -828,6 +843,74 @@ nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aP return NS_OK; } +nsresult +nsTableRowGroupFrame::SplitRowGroup(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + nsIFrame* prevKidFrame = nsnull; + + // Walk each of the row frames looking for the first row frame that + // doesn't fit in the available space + for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) { + nsRect bounds; + + kidFrame->GetRect(bounds); + if (bounds.YMost() > aReflowState.maxSize.height) { + // If this is the first row frame then we need to split it + if (nsnull == prevKidFrame) { + // Reflow the row in the available space and have it split + // XXX Account for horizontal margins... +#if 0 + nsSize kidAvailSize(aReflowState.maxSize.width, + aReflowState.maxSize.height - bounds.y); + nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState, + kidAvailSize, eReflowReason_Resize); + nsReflowMetrics desiredSize; + + rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus); + kidFrame->SizeTo(desiredSize.width, desiredSize.height); + NS_ASSERTION(NS_FRAME_IS_NOT_COMPLETE(aStatus), "unexpected status"); + + // Create a continuing frame, add it to the child list, and then push it + // and the frames that follow + // XXX Check whether it already has a next-in-flow + nsIFrame* continuingFrame; + nsIStyleContext* kidSC; + + kidFrame->GetStyleContext(kidSC); + kidFrame->CreateContinuingFrame(aPresContext, this, kidSC, continuingFrame); + NS_RELEASE(kidSC); + + // Add it to the child list + nsIFrame* nextSibling; + + kidFrame->GetNextSibling(nextSibling); + continuingFrame->SetNextSibling(nextSibling); + kidFrame->SetNextSibling(continuingFrame); + + // Push it and the frames that follow + PushChildren(continuingFrame, kidFrame); + aDesiredSize.height = bounds.y; +#endif + + } else { + // See whether the row frame has cells that span into it or across it + PushChildren(kidFrame, prevKidFrame); + aDesiredSize.height = bounds.y; + } + + aStatus = NS_FRAME_NOT_COMPLETE; + break; + } + + prevKidFrame = kidFrame; + } + + return NS_OK; +} + /** Layout the entire row group. * This method stacks rows vertically according to HTML 4.0 rules. * Rows are responsible for layout of their children. @@ -874,11 +957,14 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext, nsnull, aReflowState.reason, PR_TRUE); } + // XXX We need to figure out what to do about this... +#if 0 // Did we successfully reflow our mapped children? if (NS_FRAME_COMPLETE==aStatus) { // Try and pull-up some children from a next-in-flow rv = PullUpChildren(aPresContext, aDesiredSize, state, aStatus); } +#endif if (NS_FRAME_IS_COMPLETE(aStatus)) { // Don't forget to add in the bottom margin from our last child. @@ -898,6 +984,12 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext, if (eReflowReason_Initial != aReflowState.reason) { CalculateRowHeights(aPresContext, aDesiredSize, aReflowState); } + + // See if all the frames fit + if (aDesiredSize.height > aReflowState.maxSize.height) { + // Nope, find a place to split the row group + SplitRowGroup(aPresContext, aDesiredSize, aReflowState, aStatus); + } } if (gsDebug==PR_TRUE) diff --git a/layout/tables/nsTableRowGroupFrame.h b/layout/tables/nsTableRowGroupFrame.h index 28106d2bcff8..520e22e7791b 100644 --- a/layout/tables/nsTableRowGroupFrame.h +++ b/layout/tables/nsTableRowGroupFrame.h @@ -33,8 +33,6 @@ struct RowGroupReflowState; * * @see nsTableFrame * @see nsTableRowFrame - * - * @author sclark */ class nsTableRowGroupFrame : public nsHTMLContainerFrame { @@ -109,12 +107,12 @@ protected: RowGroupReflowState& aReflowState, const nsMargin& aKidMargin); - void PlaceChild( nsIPresContext& aPresContext, - RowGroupReflowState& aReflowState, - nsIFrame* aKidFrame, - const nsRect& aKidRect, - nsSize* aMaxElementSize, - nsSize& aKidMaxElementSize); + void PlaceChild(nsIPresContext& aPresContext, + RowGroupReflowState& aReflowState, + nsIFrame* aKidFrame, + const nsRect& aKidRect, + nsSize* aMaxElementSize, + nsSize& aKidMaxElementSize); void CalculateRowHeights(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -212,6 +210,11 @@ protected: RowGroupReflowState& aReflowState, nsReflowStatus& aStatus); + nsresult SplitRowGroup(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus); + private: nsIAtom *mType;