mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
table header and footer rowgroups placed properly, replicated across continuing tables
some pagination fixes, including a hack to make negative available heights = 1.
This commit is contained in:
parent
ac6d7c116e
commit
9481637fae
@ -145,6 +145,30 @@ PRInt32 nsTableCellFrame::GetRowSpan()
|
||||
return result;
|
||||
}
|
||||
|
||||
/** helper method to get the col span of this frame's content (which must be a cell) */
|
||||
PRInt32 nsTableCellFrame::GetColSpan()
|
||||
{
|
||||
PRInt32 result = 0;
|
||||
nsTableCell *cellContent = (nsTableCell *)mContent;
|
||||
if (nsnull!=cellContent)
|
||||
{
|
||||
result = cellContent->GetColSpan();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** helper method to get the col index of this frame's content (which must be a cell) */
|
||||
PRInt32 nsTableCellFrame::GetColIndex()
|
||||
{
|
||||
PRInt32 result = 0;
|
||||
nsTableCell *cellContent = (nsTableCell *)mContent;
|
||||
if (nsnull!=cellContent)
|
||||
{
|
||||
result = cellContent->GetColIndex();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void nsTableCellFrame::CreatePsuedoFrame(nsIPresContext* aPresContext)
|
||||
{
|
||||
// Do we have a prev-in-flow?
|
||||
@ -229,6 +253,8 @@ NS_METHOD nsTableCellFrame::ResizeReflow(nsIPresContext* aPresContext,
|
||||
|
||||
// Try to reflow the child into the available space. It might not
|
||||
// fit or might need continuing.
|
||||
if (availSize.height < 0)
|
||||
availSize.height = 1;
|
||||
nsSize maxKidElementSize;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" nsTableCellFrame::ResizeReflow calling ReflowChild with availSize=%d,%d\n",
|
||||
|
@ -63,8 +63,15 @@ public:
|
||||
|
||||
void VerticallyAlignChild(nsIPresContext* aPresContext);
|
||||
|
||||
/** return the mapped cell's row span. Always >= 1. */
|
||||
virtual PRInt32 GetRowSpan();
|
||||
|
||||
/** return the mapped cell's col span. Always >= 1. */
|
||||
virtual PRInt32 GetColSpan();
|
||||
|
||||
/** return the mapped cell's column index (starting at 0 for the first column) */
|
||||
virtual PRInt32 GetColIndex();
|
||||
|
||||
virtual ~nsTableCellFrame();
|
||||
|
||||
protected:
|
||||
|
@ -90,6 +90,12 @@ struct InnerTableReflowState {
|
||||
// Flag for whether we're dealing with the first interior row group
|
||||
PRBool firstRowGroup;
|
||||
|
||||
// a list of the footers in this table frame, for quick access when inserting bodies
|
||||
nsVoidArray *footerList;
|
||||
|
||||
// cache the total height of the footers for placing body rows
|
||||
nscoord footerHeight;
|
||||
|
||||
InnerTableReflowState(nsIPresContext* aPresContext,
|
||||
const nsSize& aMaxSize,
|
||||
nsStyleMolecule* aMol)
|
||||
@ -103,9 +109,13 @@ struct InnerTableReflowState {
|
||||
unconstrainedWidth = PRBool(aMaxSize.width == NS_UNCONSTRAINEDSIZE);
|
||||
unconstrainedHeight = PRBool(aMaxSize.height == NS_UNCONSTRAINEDSIZE);
|
||||
firstRowGroup = PR_TRUE;
|
||||
footerHeight = 0;
|
||||
footerList = nsnull;
|
||||
}
|
||||
|
||||
~InnerTableReflowState() {
|
||||
if (nsnull!=footerList)
|
||||
delete footerList;
|
||||
}
|
||||
};
|
||||
|
||||
@ -712,7 +722,7 @@ nsIFrame::ReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresCont
|
||||
nsIFrame* prevKidFrame = nsnull;/* XXX incremental reflow! */
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PreReflowCheck();
|
||||
//PreReflowCheck();
|
||||
#endif
|
||||
|
||||
// Initialize out parameter
|
||||
@ -775,7 +785,7 @@ nsIFrame::ReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresCont
|
||||
}
|
||||
|
||||
// Return our desired rect
|
||||
NS_ASSERTION(0<state.y, "illegal height after reflow");
|
||||
//NS_ASSERTION(0<state.y, "illegal height after reflow");
|
||||
aDesiredSize.width = aMaxSize.width;
|
||||
aDesiredSize.height = state.y;
|
||||
|
||||
@ -798,7 +808,7 @@ nsIFrame::ReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresCont
|
||||
mPass = kPASS_UNDEFINED; // we're no longer in-process
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PostReflowCheck(status);
|
||||
//PostReflowCheck(status);
|
||||
#endif
|
||||
|
||||
return status;
|
||||
@ -850,6 +860,48 @@ void nsTableFrame::PlaceChild(nsIPresContext* aPresContext,
|
||||
aState.availSize.height -= aKidRect.height;
|
||||
}
|
||||
|
||||
// If this is a footer row group, add it to the list of footer row groups
|
||||
nsIAtom * tFootTag = NS_NewAtom(nsTablePart::kRowGroupFootTagString); // tFootTag: REFCNT++
|
||||
nsIAtom *kidType=nsnull;
|
||||
((nsTableRowGroupFrame *)aKidFrame)->GetRowGroupType(kidType);
|
||||
if (tFootTag==kidType)
|
||||
{
|
||||
if (nsnull==aState.footerList)
|
||||
aState.footerList = new nsVoidArray();
|
||||
aState.footerList->AppendElement((void *)aKidFrame);
|
||||
aState.footerHeight += aKidRect.height;
|
||||
}
|
||||
// else if this is a body row group, push down all the footer row groups
|
||||
else
|
||||
{
|
||||
// don't bother unless there are footers to push down
|
||||
if (nsnull!=aState.footerList && 0!=aState.footerList->Count())
|
||||
{
|
||||
nsPoint origin;
|
||||
aKidFrame->GetOrigin(origin);
|
||||
origin.y -= aState.footerHeight;
|
||||
aKidFrame->MoveTo(origin.x, origin.y);
|
||||
nsIAtom * tBodyTag = NS_NewAtom(nsTablePart::kRowGroupBodyTagString); // tBodyTag: REFCNT++
|
||||
if (tBodyTag==kidType)
|
||||
{
|
||||
PRInt32 numFooters = aState.footerList->Count();
|
||||
for (PRInt32 footerIndex = 0; footerIndex < numFooters; footerIndex++)
|
||||
{
|
||||
nsTableRowGroupFrame * footer = (nsTableRowGroupFrame *)(aState.footerList->ElementAt(footerIndex));
|
||||
NS_ASSERTION(nsnull!=footer, "bad footer list in table inner frame.");
|
||||
if (nsnull!=footer)
|
||||
{
|
||||
footer->GetOrigin(origin);
|
||||
origin.y += aKidRect.height;
|
||||
footer->MoveTo(origin.x, origin.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_RELEASE(tBodyTag);
|
||||
}
|
||||
}
|
||||
NS_RELEASE(tFootTag);
|
||||
|
||||
// Update the maximum element size
|
||||
if (PR_TRUE==aState.firstRowGroup)
|
||||
{
|
||||
@ -1284,8 +1336,8 @@ PRBool nsTableFrame::PullUpChildren(nsIPresContext* aPresContext,
|
||||
*/
|
||||
nsIFrame::ReflowStatus
|
||||
nsTableFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
|
||||
InnerTableReflowState& aState,
|
||||
nsSize* aMaxElementSize)
|
||||
InnerTableReflowState& aState,
|
||||
nsSize* aMaxElementSize)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
VerifyLastIsComplete();
|
||||
@ -2441,16 +2493,53 @@ NS_METHOD nsTableFrame::CreateContinuingFrame(nsIPresContext* aPresContext,
|
||||
cf->SetRect(nsRect(0, 0, mRect.width, 0));
|
||||
// add headers and footers to cf
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
PRInt32 childCount;
|
||||
|
||||
firstInFlow->ChildCount(childCount);
|
||||
PRInt32 childIndex = 0;
|
||||
for (; childIndex < childCount; childIndex++)
|
||||
nsIFrame * rg = nsnull;
|
||||
firstInFlow->ChildAt(0, rg);
|
||||
NS_ASSERTION (nsnull!=rg, "previous frame has no children");
|
||||
nsIAtom * tHeadTag = NS_NewAtom(nsTablePart::kRowGroupHeadTagString); // tHeadTag: REFCNT++
|
||||
nsIAtom * tFootTag = NS_NewAtom(nsTablePart::kRowGroupFootTagString); // tFootTag: REFCNT++
|
||||
PRInt32 index = 0;
|
||||
nsIFrame * bodyRowGroupFromOverflow = mOverflowList;
|
||||
nsIFrame * lastSib = nsnull;
|
||||
for ( ; nsnull!=rg; index++)
|
||||
{
|
||||
// TODO: place copies of the header and footer row groups here
|
||||
// maybe need to do this in ResizeReflow at the beginning, when we determine we are a continuing frame
|
||||
nsIContent *content = nsnull;
|
||||
rg->GetContent(content); // content: REFCNT++
|
||||
NS_ASSERTION(nsnull!=content, "bad frame, returned null content.");
|
||||
nsIAtom * rgTag = content->GetTag();
|
||||
// if we've found a header or a footer, replicate it
|
||||
if (tHeadTag==rgTag || tFootTag==rgTag)
|
||||
{
|
||||
printf("found a head or foot in continuing frame\n");
|
||||
// Resolve style for the child
|
||||
nsIStyleContext* kidStyleContext =
|
||||
aPresContext->ResolveStyleContextFor(content, cf); // kidStyleContext: REFCNT++
|
||||
nsStyleMolecule* kidMol =
|
||||
(nsStyleMolecule*)kidStyleContext->GetData(kStyleMoleculeSID);
|
||||
nsIContentDelegate* kidDel = nsnull;
|
||||
kidDel = content->GetDelegate(aPresContext); // kidDel: REFCNT++
|
||||
nsIFrame * duplicateFrame = kidDel->CreateFrame(aPresContext, content, index, cf);
|
||||
NS_RELEASE(kidDel); // kidDel: REFCNT--
|
||||
duplicateFrame->SetStyleContext(kidStyleContext);
|
||||
NS_RELEASE(kidStyleContext); // kidStyleContenxt: REFCNT--
|
||||
|
||||
if (nsnull==lastSib)
|
||||
{
|
||||
mOverflowList = duplicateFrame;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastSib->SetNextSibling(duplicateFrame);
|
||||
}
|
||||
duplicateFrame->SetNextSibling(bodyRowGroupFromOverflow);
|
||||
lastSib = duplicateFrame;
|
||||
}
|
||||
NS_RELEASE(content); // content: REFCNT--
|
||||
// get the next row group
|
||||
rg->GetNextSibling(rg);
|
||||
}
|
||||
|
||||
NS_RELEASE(tFootTag); // tHeadTag: REFCNT --
|
||||
NS_RELEASE(tHeadTag); // tFootTag: REFCNT --
|
||||
aContinuingFrame = cf;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -305,7 +305,13 @@ NS_METHOD nsTableOuterFrame::ResizeReflow(nsIPresContext* aPresContext,
|
||||
//NS_ASSERTION(0<state.y, "illegal height after reflow");
|
||||
//NS_ASSERTION(0<state.innerTableMaxSize.width, "illegal width after reflow");
|
||||
aDesiredSize.width = state.innerTableMaxSize.width;
|
||||
aDesiredSize.height = state.y;
|
||||
/* if we're incomplete, take up all the remaining height so we don't waste time
|
||||
* trying to lay out in a slot that we know isn't tall enough to fit our minimum.
|
||||
* otherwise, we're as tall as our kids want us to be */
|
||||
if (frNotComplete == aStatus)
|
||||
aDesiredSize.height = aMaxSize.height;
|
||||
else
|
||||
aDesiredSize.height = state.y;
|
||||
|
||||
if (gsDebug==PR_TRUE)
|
||||
{
|
||||
@ -486,7 +492,7 @@ PRBool nsTableOuterFrame::ReflowMappedChildren( nsIPresContext* aPresContex
|
||||
|
||||
// Did the child fit?
|
||||
if ((kidSize.height > aState.availSize.height) && (kidFrame != mFirstChild)) {
|
||||
// The child is too wide to fit in the available space, and it's
|
||||
// The child is too tall to fit in the available space, and it's
|
||||
// not our first child
|
||||
|
||||
// Since we are giving the next-in-flow our last child, we
|
||||
@ -518,8 +524,6 @@ PRBool nsTableOuterFrame::ReflowMappedChildren( nsIPresContext* aPresContex
|
||||
// Update mLastContentIsComplete now that this kid fits
|
||||
mLastContentIsComplete = PRBool(status == frComplete);
|
||||
|
||||
// Is the child complete?
|
||||
mLastContentIsComplete = PRBool(status == frComplete);
|
||||
if (frNotComplete == status) {
|
||||
// No, the child isn't complete
|
||||
nsIFrame* kidNextInFlow;
|
||||
@ -555,6 +559,21 @@ PRBool nsTableOuterFrame::ReflowMappedChildren( nsIPresContext* aPresContex
|
||||
kidFrame->GetNextSibling(nextSibling);
|
||||
if (nsnull != nextSibling) {
|
||||
PushChildren(nextSibling, kidFrame, lastContentIsComplete);
|
||||
/* debug */
|
||||
/*
|
||||
printf ("having just pushed children, here is the frame hierarchy.\n");
|
||||
nsIFrame *p;
|
||||
GetGeometricParent(p);
|
||||
nsIFrame *root;
|
||||
while (nsnull!=p)
|
||||
{
|
||||
root = p;
|
||||
p->GetGeometricParent(p);
|
||||
}
|
||||
root->List();
|
||||
fflush(stdout);
|
||||
*/
|
||||
/* end debug */
|
||||
SetLastContentOffset(prevKidFrame);
|
||||
}
|
||||
result = PR_FALSE;
|
||||
|
@ -593,7 +593,7 @@ PRBool nsTablePart::AppendRowGroup (nsTableRowGroup *aContent)
|
||||
// if aContent is a body and the current child is a footer, stop, we've found the spot
|
||||
else if (tBodyTag==rowGroupTag && tFootTag==tableChildTag)
|
||||
{
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
// if aContent is a body and we've gotten this far, keep going
|
||||
else if (tBodyTag==rowGroupTag)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,8 @@
|
||||
#include "nscore.h"
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
struct RowReflowState;
|
||||
|
||||
|
||||
/**
|
||||
* nsTableRowFrame is the frame that maps table rows
|
||||
@ -110,12 +112,60 @@ protected:
|
||||
/** protected constructor.
|
||||
* @see NewFrame
|
||||
*/
|
||||
nsTableRowFrame(nsIContent* aContent,
|
||||
PRInt32 aIndexInParent,
|
||||
nsIFrame* aParentFrame);
|
||||
nsTableRowFrame(nsIContent* aContent,
|
||||
PRInt32 aIndexInParent,
|
||||
nsIFrame* aParentFrame);
|
||||
|
||||
/** destructor */
|
||||
virtual ~nsTableRowFrame();
|
||||
|
||||
nscoord GetTopMarginFor(nsIPresContext* aCX,
|
||||
RowReflowState& aState,
|
||||
nsStyleMolecule* aKidMol);
|
||||
|
||||
void PlaceChild( nsIPresContext* aPresContext,
|
||||
RowReflowState& aState,
|
||||
nsIFrame* aKidFrame,
|
||||
const nsRect& aKidRect,
|
||||
nsSize* aMaxElementSize,
|
||||
nsSize& aKidMaxElementSize);
|
||||
|
||||
/**
|
||||
* Reflow the frames we've already created
|
||||
*
|
||||
* @param aPresContext presentation context to use
|
||||
* @param aState current inline state
|
||||
* @return true if we successfully reflowed all the mapped children and false
|
||||
* otherwise, e.g. we pushed children to the next in flow
|
||||
*/
|
||||
PRBool ReflowMappedChildren(nsIPresContext* aPresContext,
|
||||
RowReflowState& aState,
|
||||
nsSize* aMaxElementSize);
|
||||
|
||||
/**
|
||||
* Try and pull-up frames from our next-in-flow
|
||||
*
|
||||
* @param aPresContext presentation context to use
|
||||
* @param aState current inline state
|
||||
* @return true if we successfully pulled-up all the children and false
|
||||
* otherwise, e.g. child didn't fit
|
||||
*/
|
||||
PRBool PullUpChildren(nsIPresContext* aPresContext,
|
||||
RowReflowState& aState,
|
||||
nsSize* aMaxElementSize);
|
||||
|
||||
/**
|
||||
* Create new frames for content we haven't yet mapped
|
||||
*
|
||||
* @param aPresContext presentation context to use
|
||||
* @param aState current inline state
|
||||
* @return frComplete if all content has been mapped and frNotComplete
|
||||
* if we should be continued
|
||||
*/
|
||||
ReflowStatus ReflowUnmappedChildren(nsIPresContext* aPresContext,
|
||||
RowReflowState& aState,
|
||||
nsSize* aMaxElementSize);
|
||||
|
||||
/** destructor */
|
||||
virtual ~nsTableRowFrame();
|
||||
|
||||
private:
|
||||
PRInt32 mTallestCell; // not my height, but the height of my tallest child
|
||||
|
@ -95,14 +95,24 @@ struct RowGroupReflowState {
|
||||
/* ----------- nsTableRowGroupFrame ---------- */
|
||||
|
||||
nsTableRowGroupFrame::nsTableRowGroupFrame(nsIContent* aContent,
|
||||
PRInt32 aIndexInParent,
|
||||
nsIFrame* aParentFrame)
|
||||
PRInt32 aIndexInParent,
|
||||
nsIFrame* aParentFrame)
|
||||
: nsContainerFrame(aContent, aIndexInParent, aParentFrame)
|
||||
{
|
||||
mType = aContent->GetTag(); // mType: REFCNT++
|
||||
}
|
||||
|
||||
nsTableRowGroupFrame::~nsTableRowGroupFrame()
|
||||
{
|
||||
if (nsnull!=mType)
|
||||
NS_RELEASE(mType); // mType: REFCNT--
|
||||
}
|
||||
|
||||
NS_METHOD nsTableRowGroupFrame::GetRowGroupType(nsIAtom *& aType)
|
||||
{
|
||||
NS_ADDREF(mType);
|
||||
aType=mType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -264,6 +274,8 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
|
||||
|
||||
for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) {
|
||||
nsSize kidAvailSize(aState.availSize);
|
||||
if (0>=kidAvailSize.height)
|
||||
kidAvailSize.height = 1; // XXX: HaCk - we don't handle negative heights yet
|
||||
nsReflowMetrics desiredSize;
|
||||
nsIFrame::ReflowStatus status;
|
||||
|
||||
@ -290,7 +302,7 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
|
||||
|
||||
// Reflow the child into the available space
|
||||
status = ReflowChild(kidFrame, aPresContext, desiredSize,
|
||||
kidAvailSize, pKidMaxElementSize);
|
||||
kidAvailSize, pKidMaxElementSize);
|
||||
|
||||
// Did the child fit?
|
||||
if ((kidFrame != mFirstChild) &&
|
||||
@ -381,6 +393,12 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
|
||||
break;
|
||||
}
|
||||
|
||||
// Add back in the left and right margins, because one row does not
|
||||
// impact another row's width
|
||||
if (PR_FALSE == aState.unconstrainedWidth) {
|
||||
kidAvailSize.width += kidMol->margin.left + kidMol->margin.right;
|
||||
}
|
||||
|
||||
// Get the next child
|
||||
kidFrame->GetNextSibling(kidFrame);
|
||||
|
||||
@ -868,10 +886,10 @@ nsTableRowGroupFrame::ResizeReflow( nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
// Return our desired rect
|
||||
NS_ASSERTION(0<state.firstRowHeight, "illegal firstRowHeight after reflow");
|
||||
NS_ASSERTION(0<state.y, "illegal height after reflow");
|
||||
//NS_ASSERTION(0<state.firstRowHeight, "illegal firstRowHeight after reflow");
|
||||
//NS_ASSERTION(0<state.y, "illegal height after reflow");
|
||||
aDesiredSize.width = aMaxSize.width;
|
||||
aDesiredSize.height = state.y;
|
||||
aDesiredSize.height = state.y;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PostReflowCheck(aStatus);
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsIAtom.h"
|
||||
|
||||
struct RowGroupReflowState;
|
||||
struct nsStyleMolecule;
|
||||
@ -90,6 +91,15 @@ public:
|
||||
nsIFrame* aParent,
|
||||
nsIFrame*& aContinuingFrame);
|
||||
|
||||
/** returns the type of the mapped row group content in aType.
|
||||
* caller MUST call release on the returned object if it is not null.
|
||||
*
|
||||
* @param aType out param filled with the type of the mapped content, or null if none.
|
||||
*
|
||||
* @return NS_OK
|
||||
*/
|
||||
NS_IMETHOD GetRowGroupType(nsIAtom *& aType);
|
||||
|
||||
protected:
|
||||
|
||||
/** protected constructor.
|
||||
@ -149,6 +159,9 @@ protected:
|
||||
RowGroupReflowState& aState,
|
||||
nsSize* aMaxElementSize);
|
||||
|
||||
private:
|
||||
nsIAtom *mType;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -145,6 +145,30 @@ PRInt32 nsTableCellFrame::GetRowSpan()
|
||||
return result;
|
||||
}
|
||||
|
||||
/** helper method to get the col span of this frame's content (which must be a cell) */
|
||||
PRInt32 nsTableCellFrame::GetColSpan()
|
||||
{
|
||||
PRInt32 result = 0;
|
||||
nsTableCell *cellContent = (nsTableCell *)mContent;
|
||||
if (nsnull!=cellContent)
|
||||
{
|
||||
result = cellContent->GetColSpan();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** helper method to get the col index of this frame's content (which must be a cell) */
|
||||
PRInt32 nsTableCellFrame::GetColIndex()
|
||||
{
|
||||
PRInt32 result = 0;
|
||||
nsTableCell *cellContent = (nsTableCell *)mContent;
|
||||
if (nsnull!=cellContent)
|
||||
{
|
||||
result = cellContent->GetColIndex();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void nsTableCellFrame::CreatePsuedoFrame(nsIPresContext* aPresContext)
|
||||
{
|
||||
// Do we have a prev-in-flow?
|
||||
@ -229,6 +253,8 @@ NS_METHOD nsTableCellFrame::ResizeReflow(nsIPresContext* aPresContext,
|
||||
|
||||
// Try to reflow the child into the available space. It might not
|
||||
// fit or might need continuing.
|
||||
if (availSize.height < 0)
|
||||
availSize.height = 1;
|
||||
nsSize maxKidElementSize;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" nsTableCellFrame::ResizeReflow calling ReflowChild with availSize=%d,%d\n",
|
||||
|
@ -63,8 +63,15 @@ public:
|
||||
|
||||
void VerticallyAlignChild(nsIPresContext* aPresContext);
|
||||
|
||||
/** return the mapped cell's row span. Always >= 1. */
|
||||
virtual PRInt32 GetRowSpan();
|
||||
|
||||
/** return the mapped cell's col span. Always >= 1. */
|
||||
virtual PRInt32 GetColSpan();
|
||||
|
||||
/** return the mapped cell's column index (starting at 0 for the first column) */
|
||||
virtual PRInt32 GetColIndex();
|
||||
|
||||
virtual ~nsTableCellFrame();
|
||||
|
||||
protected:
|
||||
|
@ -90,6 +90,12 @@ struct InnerTableReflowState {
|
||||
// Flag for whether we're dealing with the first interior row group
|
||||
PRBool firstRowGroup;
|
||||
|
||||
// a list of the footers in this table frame, for quick access when inserting bodies
|
||||
nsVoidArray *footerList;
|
||||
|
||||
// cache the total height of the footers for placing body rows
|
||||
nscoord footerHeight;
|
||||
|
||||
InnerTableReflowState(nsIPresContext* aPresContext,
|
||||
const nsSize& aMaxSize,
|
||||
nsStyleMolecule* aMol)
|
||||
@ -103,9 +109,13 @@ struct InnerTableReflowState {
|
||||
unconstrainedWidth = PRBool(aMaxSize.width == NS_UNCONSTRAINEDSIZE);
|
||||
unconstrainedHeight = PRBool(aMaxSize.height == NS_UNCONSTRAINEDSIZE);
|
||||
firstRowGroup = PR_TRUE;
|
||||
footerHeight = 0;
|
||||
footerList = nsnull;
|
||||
}
|
||||
|
||||
~InnerTableReflowState() {
|
||||
if (nsnull!=footerList)
|
||||
delete footerList;
|
||||
}
|
||||
};
|
||||
|
||||
@ -712,7 +722,7 @@ nsIFrame::ReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresCont
|
||||
nsIFrame* prevKidFrame = nsnull;/* XXX incremental reflow! */
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PreReflowCheck();
|
||||
//PreReflowCheck();
|
||||
#endif
|
||||
|
||||
// Initialize out parameter
|
||||
@ -775,7 +785,7 @@ nsIFrame::ReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresCont
|
||||
}
|
||||
|
||||
// Return our desired rect
|
||||
NS_ASSERTION(0<state.y, "illegal height after reflow");
|
||||
//NS_ASSERTION(0<state.y, "illegal height after reflow");
|
||||
aDesiredSize.width = aMaxSize.width;
|
||||
aDesiredSize.height = state.y;
|
||||
|
||||
@ -798,7 +808,7 @@ nsIFrame::ReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresCont
|
||||
mPass = kPASS_UNDEFINED; // we're no longer in-process
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PostReflowCheck(status);
|
||||
//PostReflowCheck(status);
|
||||
#endif
|
||||
|
||||
return status;
|
||||
@ -850,6 +860,48 @@ void nsTableFrame::PlaceChild(nsIPresContext* aPresContext,
|
||||
aState.availSize.height -= aKidRect.height;
|
||||
}
|
||||
|
||||
// If this is a footer row group, add it to the list of footer row groups
|
||||
nsIAtom * tFootTag = NS_NewAtom(nsTablePart::kRowGroupFootTagString); // tFootTag: REFCNT++
|
||||
nsIAtom *kidType=nsnull;
|
||||
((nsTableRowGroupFrame *)aKidFrame)->GetRowGroupType(kidType);
|
||||
if (tFootTag==kidType)
|
||||
{
|
||||
if (nsnull==aState.footerList)
|
||||
aState.footerList = new nsVoidArray();
|
||||
aState.footerList->AppendElement((void *)aKidFrame);
|
||||
aState.footerHeight += aKidRect.height;
|
||||
}
|
||||
// else if this is a body row group, push down all the footer row groups
|
||||
else
|
||||
{
|
||||
// don't bother unless there are footers to push down
|
||||
if (nsnull!=aState.footerList && 0!=aState.footerList->Count())
|
||||
{
|
||||
nsPoint origin;
|
||||
aKidFrame->GetOrigin(origin);
|
||||
origin.y -= aState.footerHeight;
|
||||
aKidFrame->MoveTo(origin.x, origin.y);
|
||||
nsIAtom * tBodyTag = NS_NewAtom(nsTablePart::kRowGroupBodyTagString); // tBodyTag: REFCNT++
|
||||
if (tBodyTag==kidType)
|
||||
{
|
||||
PRInt32 numFooters = aState.footerList->Count();
|
||||
for (PRInt32 footerIndex = 0; footerIndex < numFooters; footerIndex++)
|
||||
{
|
||||
nsTableRowGroupFrame * footer = (nsTableRowGroupFrame *)(aState.footerList->ElementAt(footerIndex));
|
||||
NS_ASSERTION(nsnull!=footer, "bad footer list in table inner frame.");
|
||||
if (nsnull!=footer)
|
||||
{
|
||||
footer->GetOrigin(origin);
|
||||
origin.y += aKidRect.height;
|
||||
footer->MoveTo(origin.x, origin.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_RELEASE(tBodyTag);
|
||||
}
|
||||
}
|
||||
NS_RELEASE(tFootTag);
|
||||
|
||||
// Update the maximum element size
|
||||
if (PR_TRUE==aState.firstRowGroup)
|
||||
{
|
||||
@ -1284,8 +1336,8 @@ PRBool nsTableFrame::PullUpChildren(nsIPresContext* aPresContext,
|
||||
*/
|
||||
nsIFrame::ReflowStatus
|
||||
nsTableFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
|
||||
InnerTableReflowState& aState,
|
||||
nsSize* aMaxElementSize)
|
||||
InnerTableReflowState& aState,
|
||||
nsSize* aMaxElementSize)
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
VerifyLastIsComplete();
|
||||
@ -2441,16 +2493,53 @@ NS_METHOD nsTableFrame::CreateContinuingFrame(nsIPresContext* aPresContext,
|
||||
cf->SetRect(nsRect(0, 0, mRect.width, 0));
|
||||
// add headers and footers to cf
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
PRInt32 childCount;
|
||||
|
||||
firstInFlow->ChildCount(childCount);
|
||||
PRInt32 childIndex = 0;
|
||||
for (; childIndex < childCount; childIndex++)
|
||||
nsIFrame * rg = nsnull;
|
||||
firstInFlow->ChildAt(0, rg);
|
||||
NS_ASSERTION (nsnull!=rg, "previous frame has no children");
|
||||
nsIAtom * tHeadTag = NS_NewAtom(nsTablePart::kRowGroupHeadTagString); // tHeadTag: REFCNT++
|
||||
nsIAtom * tFootTag = NS_NewAtom(nsTablePart::kRowGroupFootTagString); // tFootTag: REFCNT++
|
||||
PRInt32 index = 0;
|
||||
nsIFrame * bodyRowGroupFromOverflow = mOverflowList;
|
||||
nsIFrame * lastSib = nsnull;
|
||||
for ( ; nsnull!=rg; index++)
|
||||
{
|
||||
// TODO: place copies of the header and footer row groups here
|
||||
// maybe need to do this in ResizeReflow at the beginning, when we determine we are a continuing frame
|
||||
nsIContent *content = nsnull;
|
||||
rg->GetContent(content); // content: REFCNT++
|
||||
NS_ASSERTION(nsnull!=content, "bad frame, returned null content.");
|
||||
nsIAtom * rgTag = content->GetTag();
|
||||
// if we've found a header or a footer, replicate it
|
||||
if (tHeadTag==rgTag || tFootTag==rgTag)
|
||||
{
|
||||
printf("found a head or foot in continuing frame\n");
|
||||
// Resolve style for the child
|
||||
nsIStyleContext* kidStyleContext =
|
||||
aPresContext->ResolveStyleContextFor(content, cf); // kidStyleContext: REFCNT++
|
||||
nsStyleMolecule* kidMol =
|
||||
(nsStyleMolecule*)kidStyleContext->GetData(kStyleMoleculeSID);
|
||||
nsIContentDelegate* kidDel = nsnull;
|
||||
kidDel = content->GetDelegate(aPresContext); // kidDel: REFCNT++
|
||||
nsIFrame * duplicateFrame = kidDel->CreateFrame(aPresContext, content, index, cf);
|
||||
NS_RELEASE(kidDel); // kidDel: REFCNT--
|
||||
duplicateFrame->SetStyleContext(kidStyleContext);
|
||||
NS_RELEASE(kidStyleContext); // kidStyleContenxt: REFCNT--
|
||||
|
||||
if (nsnull==lastSib)
|
||||
{
|
||||
mOverflowList = duplicateFrame;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastSib->SetNextSibling(duplicateFrame);
|
||||
}
|
||||
duplicateFrame->SetNextSibling(bodyRowGroupFromOverflow);
|
||||
lastSib = duplicateFrame;
|
||||
}
|
||||
NS_RELEASE(content); // content: REFCNT--
|
||||
// get the next row group
|
||||
rg->GetNextSibling(rg);
|
||||
}
|
||||
|
||||
NS_RELEASE(tFootTag); // tHeadTag: REFCNT --
|
||||
NS_RELEASE(tHeadTag); // tFootTag: REFCNT --
|
||||
aContinuingFrame = cf;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -305,7 +305,13 @@ NS_METHOD nsTableOuterFrame::ResizeReflow(nsIPresContext* aPresContext,
|
||||
//NS_ASSERTION(0<state.y, "illegal height after reflow");
|
||||
//NS_ASSERTION(0<state.innerTableMaxSize.width, "illegal width after reflow");
|
||||
aDesiredSize.width = state.innerTableMaxSize.width;
|
||||
aDesiredSize.height = state.y;
|
||||
/* if we're incomplete, take up all the remaining height so we don't waste time
|
||||
* trying to lay out in a slot that we know isn't tall enough to fit our minimum.
|
||||
* otherwise, we're as tall as our kids want us to be */
|
||||
if (frNotComplete == aStatus)
|
||||
aDesiredSize.height = aMaxSize.height;
|
||||
else
|
||||
aDesiredSize.height = state.y;
|
||||
|
||||
if (gsDebug==PR_TRUE)
|
||||
{
|
||||
@ -486,7 +492,7 @@ PRBool nsTableOuterFrame::ReflowMappedChildren( nsIPresContext* aPresContex
|
||||
|
||||
// Did the child fit?
|
||||
if ((kidSize.height > aState.availSize.height) && (kidFrame != mFirstChild)) {
|
||||
// The child is too wide to fit in the available space, and it's
|
||||
// The child is too tall to fit in the available space, and it's
|
||||
// not our first child
|
||||
|
||||
// Since we are giving the next-in-flow our last child, we
|
||||
@ -518,8 +524,6 @@ PRBool nsTableOuterFrame::ReflowMappedChildren( nsIPresContext* aPresContex
|
||||
// Update mLastContentIsComplete now that this kid fits
|
||||
mLastContentIsComplete = PRBool(status == frComplete);
|
||||
|
||||
// Is the child complete?
|
||||
mLastContentIsComplete = PRBool(status == frComplete);
|
||||
if (frNotComplete == status) {
|
||||
// No, the child isn't complete
|
||||
nsIFrame* kidNextInFlow;
|
||||
@ -555,6 +559,21 @@ PRBool nsTableOuterFrame::ReflowMappedChildren( nsIPresContext* aPresContex
|
||||
kidFrame->GetNextSibling(nextSibling);
|
||||
if (nsnull != nextSibling) {
|
||||
PushChildren(nextSibling, kidFrame, lastContentIsComplete);
|
||||
/* debug */
|
||||
/*
|
||||
printf ("having just pushed children, here is the frame hierarchy.\n");
|
||||
nsIFrame *p;
|
||||
GetGeometricParent(p);
|
||||
nsIFrame *root;
|
||||
while (nsnull!=p)
|
||||
{
|
||||
root = p;
|
||||
p->GetGeometricParent(p);
|
||||
}
|
||||
root->List();
|
||||
fflush(stdout);
|
||||
*/
|
||||
/* end debug */
|
||||
SetLastContentOffset(prevKidFrame);
|
||||
}
|
||||
result = PR_FALSE;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,8 @@
|
||||
#include "nscore.h"
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
struct RowReflowState;
|
||||
|
||||
|
||||
/**
|
||||
* nsTableRowFrame is the frame that maps table rows
|
||||
@ -110,12 +112,60 @@ protected:
|
||||
/** protected constructor.
|
||||
* @see NewFrame
|
||||
*/
|
||||
nsTableRowFrame(nsIContent* aContent,
|
||||
PRInt32 aIndexInParent,
|
||||
nsIFrame* aParentFrame);
|
||||
nsTableRowFrame(nsIContent* aContent,
|
||||
PRInt32 aIndexInParent,
|
||||
nsIFrame* aParentFrame);
|
||||
|
||||
/** destructor */
|
||||
virtual ~nsTableRowFrame();
|
||||
|
||||
nscoord GetTopMarginFor(nsIPresContext* aCX,
|
||||
RowReflowState& aState,
|
||||
nsStyleMolecule* aKidMol);
|
||||
|
||||
void PlaceChild( nsIPresContext* aPresContext,
|
||||
RowReflowState& aState,
|
||||
nsIFrame* aKidFrame,
|
||||
const nsRect& aKidRect,
|
||||
nsSize* aMaxElementSize,
|
||||
nsSize& aKidMaxElementSize);
|
||||
|
||||
/**
|
||||
* Reflow the frames we've already created
|
||||
*
|
||||
* @param aPresContext presentation context to use
|
||||
* @param aState current inline state
|
||||
* @return true if we successfully reflowed all the mapped children and false
|
||||
* otherwise, e.g. we pushed children to the next in flow
|
||||
*/
|
||||
PRBool ReflowMappedChildren(nsIPresContext* aPresContext,
|
||||
RowReflowState& aState,
|
||||
nsSize* aMaxElementSize);
|
||||
|
||||
/**
|
||||
* Try and pull-up frames from our next-in-flow
|
||||
*
|
||||
* @param aPresContext presentation context to use
|
||||
* @param aState current inline state
|
||||
* @return true if we successfully pulled-up all the children and false
|
||||
* otherwise, e.g. child didn't fit
|
||||
*/
|
||||
PRBool PullUpChildren(nsIPresContext* aPresContext,
|
||||
RowReflowState& aState,
|
||||
nsSize* aMaxElementSize);
|
||||
|
||||
/**
|
||||
* Create new frames for content we haven't yet mapped
|
||||
*
|
||||
* @param aPresContext presentation context to use
|
||||
* @param aState current inline state
|
||||
* @return frComplete if all content has been mapped and frNotComplete
|
||||
* if we should be continued
|
||||
*/
|
||||
ReflowStatus ReflowUnmappedChildren(nsIPresContext* aPresContext,
|
||||
RowReflowState& aState,
|
||||
nsSize* aMaxElementSize);
|
||||
|
||||
/** destructor */
|
||||
virtual ~nsTableRowFrame();
|
||||
|
||||
private:
|
||||
PRInt32 mTallestCell; // not my height, but the height of my tallest child
|
||||
|
@ -95,14 +95,24 @@ struct RowGroupReflowState {
|
||||
/* ----------- nsTableRowGroupFrame ---------- */
|
||||
|
||||
nsTableRowGroupFrame::nsTableRowGroupFrame(nsIContent* aContent,
|
||||
PRInt32 aIndexInParent,
|
||||
nsIFrame* aParentFrame)
|
||||
PRInt32 aIndexInParent,
|
||||
nsIFrame* aParentFrame)
|
||||
: nsContainerFrame(aContent, aIndexInParent, aParentFrame)
|
||||
{
|
||||
mType = aContent->GetTag(); // mType: REFCNT++
|
||||
}
|
||||
|
||||
nsTableRowGroupFrame::~nsTableRowGroupFrame()
|
||||
{
|
||||
if (nsnull!=mType)
|
||||
NS_RELEASE(mType); // mType: REFCNT--
|
||||
}
|
||||
|
||||
NS_METHOD nsTableRowGroupFrame::GetRowGroupType(nsIAtom *& aType)
|
||||
{
|
||||
NS_ADDREF(mType);
|
||||
aType=mType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -264,6 +274,8 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
|
||||
|
||||
for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) {
|
||||
nsSize kidAvailSize(aState.availSize);
|
||||
if (0>=kidAvailSize.height)
|
||||
kidAvailSize.height = 1; // XXX: HaCk - we don't handle negative heights yet
|
||||
nsReflowMetrics desiredSize;
|
||||
nsIFrame::ReflowStatus status;
|
||||
|
||||
@ -290,7 +302,7 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
|
||||
|
||||
// Reflow the child into the available space
|
||||
status = ReflowChild(kidFrame, aPresContext, desiredSize,
|
||||
kidAvailSize, pKidMaxElementSize);
|
||||
kidAvailSize, pKidMaxElementSize);
|
||||
|
||||
// Did the child fit?
|
||||
if ((kidFrame != mFirstChild) &&
|
||||
@ -381,6 +393,12 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
|
||||
break;
|
||||
}
|
||||
|
||||
// Add back in the left and right margins, because one row does not
|
||||
// impact another row's width
|
||||
if (PR_FALSE == aState.unconstrainedWidth) {
|
||||
kidAvailSize.width += kidMol->margin.left + kidMol->margin.right;
|
||||
}
|
||||
|
||||
// Get the next child
|
||||
kidFrame->GetNextSibling(kidFrame);
|
||||
|
||||
@ -868,10 +886,10 @@ nsTableRowGroupFrame::ResizeReflow( nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
// Return our desired rect
|
||||
NS_ASSERTION(0<state.firstRowHeight, "illegal firstRowHeight after reflow");
|
||||
NS_ASSERTION(0<state.y, "illegal height after reflow");
|
||||
//NS_ASSERTION(0<state.firstRowHeight, "illegal firstRowHeight after reflow");
|
||||
//NS_ASSERTION(0<state.y, "illegal height after reflow");
|
||||
aDesiredSize.width = aMaxSize.width;
|
||||
aDesiredSize.height = state.y;
|
||||
aDesiredSize.height = state.y;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PostReflowCheck(aStatus);
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsIAtom.h"
|
||||
|
||||
struct RowGroupReflowState;
|
||||
struct nsStyleMolecule;
|
||||
@ -90,6 +91,15 @@ public:
|
||||
nsIFrame* aParent,
|
||||
nsIFrame*& aContinuingFrame);
|
||||
|
||||
/** returns the type of the mapped row group content in aType.
|
||||
* caller MUST call release on the returned object if it is not null.
|
||||
*
|
||||
* @param aType out param filled with the type of the mapped content, or null if none.
|
||||
*
|
||||
* @return NS_OK
|
||||
*/
|
||||
NS_IMETHOD GetRowGroupType(nsIAtom *& aType);
|
||||
|
||||
protected:
|
||||
|
||||
/** protected constructor.
|
||||
@ -149,6 +159,9 @@ protected:
|
||||
RowGroupReflowState& aState,
|
||||
nsSize* aMaxElementSize);
|
||||
|
||||
private:
|
||||
nsIAtom *mType;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user