rows can now be incrementally inserted, appended, and deleted.

This commit is contained in:
buster%netscape.com 1998-10-19 23:43:06 +00:00
parent da133d64f2
commit 7cb1f39626
19 changed files with 690 additions and 460 deletions

View File

@ -103,25 +103,21 @@ PRBool BasicTableLayoutStrategy::IsFixedWidth(const nsStylePosition* aStylePosit
}
BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame, PRInt32 aNumCols)
BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame)
{
NS_ASSERTION(nsnull!=aFrame, "bad frame arg");
mTableFrame = aFrame;
mNumCols = aNumCols;
mMinTableWidth=0;
mMaxTableWidth=0;
mFixedTableWidth=0;
//cache the value of the cols attribute
mCols = mTableFrame->GetEffectiveCOLSAttribute();
}
BasicTableLayoutStrategy::~BasicTableLayoutStrategy()
{
}
PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize)
PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols)
{
#ifdef NS_DEBUG
nsIFrame *tablePIF=nsnull;
@ -132,9 +128,11 @@ PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize)
PRBool result = PR_TRUE;
// re-init instance variables
mNumCols = aNumCols;
mMinTableWidth=0;
mMaxTableWidth=0;
mFixedTableWidth=0;
mCols = mTableFrame->GetEffectiveCOLSAttribute();
// Step 1 - assign the width of all fixed-width columns
AssignPreliminaryColumnWidths();

View File

@ -76,15 +76,17 @@ public:
/** Public constructor.
* @paran aFrame the table frame for which this delegate will do layout
* @param aNumCols the total number of columns in the table
*/
BasicTableLayoutStrategy(nsTableFrame *aFrame, PRInt32 aNumCols);
BasicTableLayoutStrategy(nsTableFrame *aFrame);
/** destructor */
virtual ~BasicTableLayoutStrategy();
/** call once every time any table thing changes (content, structure, or style) */
virtual PRBool Initialize(nsSize* aMaxElementSize);
/** call once every time any table thing changes (content, structure, or style)
* @param aMaxElementSize [OUT] if not null, the max element size is computed and returned in this param
* @param aNumCols the total number of columns in the table
*/
virtual PRBool Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols);
virtual void SetMaxElementSize(nsSize* aMaxElementSize);

View File

@ -35,8 +35,8 @@ static PRBool gsDebug = PR_FALSE;
static const PRBool gsDebug = PR_FALSE;
#endif
FixedTableLayoutStrategy::FixedTableLayoutStrategy(nsTableFrame *aFrame, PRInt32 aNumCols)
: BasicTableLayoutStrategy(aFrame, aNumCols)
FixedTableLayoutStrategy::FixedTableLayoutStrategy(nsTableFrame *aFrame)
: BasicTableLayoutStrategy(aFrame)
{
}

View File

@ -44,19 +44,16 @@ public:
* @paran aFrame the table frame for which this delegate will do layout
* @param aNumCols the total number of columns in the table
*/
FixedTableLayoutStrategy(nsTableFrame *aFrame, PRInt32 aNumCols);
FixedTableLayoutStrategy(nsTableFrame *aFrame);
/** destructor */
virtual ~FixedTableLayoutStrategy();
/** no need to override Initialize since it calls our AssignPreliminaryColumnWidths */
// virtual PRBool Initialize(nsSize* aMaxElementSize);
/** Called during resize reflow to determine the new column widths
* @param aTableStyle - the resolved style for mTableFrame
* @param aReflowState - the reflow state for mTableFrame
* @param aMaxWidth - the computed max width for columns to fit into
*/
* @param aReflowState - the reflow state for mTableFrame
* @param aMaxWidth - the computed max width for columns to fit into
*/
virtual PRBool BalanceColumnWidths(nsIStyleContext * aTableStyle,
const nsHTMLReflowState& aReflowState,
nscoord aMaxWidth);

View File

@ -30,9 +30,10 @@ class nsITableLayoutStrategy
public:
/** call once every time any table thing changes (content, structure, or style)
* @param aMaxElementSize [OUT] the min possible size of the table
* @param aMaxElementSize [OUT] if not null, the max element size is computed and returned in this param
* @param aNumCols the total number of columns in the table
*/
virtual PRBool Initialize(nsSize* aMaxElementSize)=0;
virtual PRBool Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols)=0;
/** compute the max-element-size for the table
* @param aMaxElementSize [OUT] width field set to the min legal width of the table

View File

@ -928,7 +928,8 @@ void nsTableFrame::SetMinColSpanForTable()
{ // XXX: must be called ONLY on first-in-flow
// set the minColSpan for each column
PRInt32 rowCount = mCellMap->GetRowCount();
for (PRInt32 colIndex=0; colIndex<mColCount; colIndex++)
PRInt32 colCount = mCellMap->GetColCount();
for (PRInt32 colIndex=0; colIndex<colCount; colIndex++)
{
PRInt32 minColSpan;
for (PRInt32 rowIndex=0; rowIndex<rowCount; rowIndex++)
@ -999,6 +1000,7 @@ void nsTableFrame::AddCellToTable (nsTableRowFrame *aRowFrame,
NS_METHOD nsTableFrame::ReBuildCellMap()
{
if (PR_TRUE==gsDebugIR) printf("TIF: ReBuildCellMap.\n");
nsresult rv=NS_OK;
nsIFrame *rowGroupFrame=mFirstChild;
for ( ; nsnull!=rowGroupFrame; rowGroupFrame->GetNextSibling(rowGroupFrame))
@ -1022,6 +1024,7 @@ NS_METHOD nsTableFrame::ReBuildCellMap()
}
}
}
mCellMapValid=PR_TRUE;
return rv;
}
@ -1562,10 +1565,10 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
if (PR_TRUE==NeedsReflow(aReflowState, aReflowState.maxSize))
{
PRBool needsRecalc=PR_FALSE;
if (PR_TRUE==gsDebug) printf("TIF Reflow: needs reflow\n");
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: needs reflow\n");
if (eReflowReason_Initial!=aReflowState.reason && PR_FALSE==IsCellMapValid())
{
if (PR_TRUE==gsDebug) printf("TIF Reflow: cell map invalid, rebuilding...\n");
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: cell map invalid, rebuilding...\n");
if (nsnull!=mCellMap)
delete mCellMap;
mCellMap = new nsCellMap(0,0);
@ -1575,7 +1578,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
if (PR_FALSE==IsFirstPassValid())
{
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: first pass is invalid, rebuilding...\n");
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, aStatus, nsnull, aReflowState.reason);
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, aStatus, nsnull, aReflowState.reason, PR_TRUE);
if (NS_FAILED(rv))
return rv;
needsRecalc=PR_TRUE;
@ -1587,23 +1590,23 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
}
if (PR_TRUE==needsRecalc)
{
if (PR_TRUE==gsDebugIR) printf("TIF Reflow: needs recalc.\n");
// if we need to recalc, the data stored in the layout strategy is invalid
if (nsnull!=mTableLayoutStrategy)
{
if (PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize);
mColumnWidthsValid=PR_TRUE;
}
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: needs recalc. Calling BuildColumnCache...\n");
BuildColumnCache(aPresContext, aDesiredSize, aReflowState, aStatus);
RecalcLayoutData(); // Recalculate Layout Dependencies
// if we needed to rebuild the column cache, the data stored in the layout strategy is invalid
if (nsnull!=mTableLayoutStrategy)
{
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, mCellMap->GetColCount());
mColumnWidthsValid=PR_TRUE; //so we don't do this a second time below
}
}
if (PR_FALSE==IsColumnWidthsValid())
{
if (PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
if (nsnull!=mTableLayoutStrategy)
{
mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize);
mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, mCellMap->GetColCount());
mColumnWidthsValid=PR_TRUE;
}
}
@ -1658,7 +1661,8 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus,
nsTableRowGroupFrame * aStartingFrame,
nsReflowReason aReason)
nsReflowReason aReason,
PRBool aDoSiblingFrames)
{
NS_PRECONDITION(aReflowState.frame == this, "bad reflow state");
NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent,
@ -1719,7 +1723,7 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext,
PRInt32 yCoord = y;
if (NS_UNCONSTRAINEDSIZE!=yCoord)
yCoord+= topInset;
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: Reflow Pass 1 of frame %p\n", kidFrame);
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: Reflow Pass 1 of frame %p with reason=%d\n", kidFrame, aReason);
ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus);
// Place the child since some of its content fit in us.
@ -1744,6 +1748,8 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext,
// up all of our available space (or needs us to split).
break;
}
if (PR_FALSE==aDoSiblingFrames)
break;
}
}
@ -2185,14 +2191,18 @@ NS_METHOD nsTableFrame::IR_RowGroupInserted(nsIPresContext& aPresContext,
{
nsresult rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState,
aStatus, (nsIFrame*)aInsertedFrame, aReplace);
// inserting the rowgroup only effects reflow if the rowgroup includes at least one row
PRInt32 rowCount;
aInsertedFrame->GetRowCount(rowCount);
if (0>rowCount)
{ // for now we will assume that if there are rows, then there are cells and we need to recalc table info
InvalidateCellMap();
InvalidateColumnCache();
}
if (NS_FAILED(rv))
return rv;
// do a pass-1 layout of all the cells in all the rows of the rowgroup
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.reflowState, aStatus,
aInsertedFrame, eReflowReason_Initial, PR_FALSE);
if (NS_FAILED(rv))
return rv;
InvalidateCellMap();
InvalidateColumnCache();
return rv;
}
@ -2212,10 +2222,12 @@ NS_METHOD nsTableFrame::IR_RowGroupAppended(nsIPresContext& aPresContext,
// account for the cells in the rows that are children of aAppendedFrame
// this will add the content of the rowgroup to the cell map
rv = DidAppendRowGroup((nsTableRowGroupFrame*)aAppendedFrame);
if (NS_FAILED(rv))
return rv;
// do a pass-1 layout of all the cells in all the rows of the rowgroup
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.reflowState, aStatus,
aAppendedFrame, eReflowReason_Initial);
aAppendedFrame, eReflowReason_Initial, PR_TRUE);
if (NS_FAILED(rv))
return rv;
@ -2232,17 +2244,11 @@ NS_METHOD nsTableFrame::IR_RowGroupRemoved(nsIPresContext& aPresContext,
nsReflowStatus& aStatus,
nsTableRowGroupFrame * aDeletedFrame)
{
nsresult rv;
nsresult rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
aDeletedFrame);
InvalidateCellMap();
InvalidateColumnCache();
rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
aDeletedFrame);
PRInt32 rowCount=0;
aDeletedFrame->GetRowCount(rowCount);
if (0>rowCount)
{ // for now we will assume that if there are rows, then there are cells and we need to recalc table info
InvalidateCellMap();
InvalidateColumnCache();
}
// if any column widths have to change due to this, rebalance column widths
//XXX need to calculate this, but for now just do it
InvalidateColumnWidths();
@ -2292,9 +2298,7 @@ NS_METHOD nsTableFrame::IR_UnknownFrameInserted(nsIPresContext& aPresCont
}
else
{
nsIFrame *nextSibling=nsnull;
if (nsnull!=mFirstChild)
mFirstChild->GetNextSibling(nextSibling);
nsIFrame *nextSibling = mFirstChild;
mFirstChild = aInsertedFrame;
aInsertedFrame->SetNextSibling(nextSibling);
}
@ -2555,7 +2559,7 @@ PRBool nsTableFrame::ReflowMappedChildren( nsIPresContext& aPresContext,
nscoord x = aState.leftInset + kidMargin.left;
nscoord y = aState.topInset + aState.y + topMargin;
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: Reflow Pass 2 of frame %p\n", kidFrame);
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: Reflow Pass 2 of frame %p with reason=%d\n", kidFrame, reason);
ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, status);
// Did the child fit?
if ((kidFrame != mFirstChild) && (desiredSize.height > kidAvailSize.height))
@ -2834,10 +2838,10 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext& aPresContext,
nsStyleTable* tableStyle;
GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
if (NS_STYLE_TABLE_LAYOUT_FIXED==tableStyle->mLayoutStrategy)
mTableLayoutStrategy = new FixedTableLayoutStrategy(this, numCols);
mTableLayoutStrategy = new FixedTableLayoutStrategy(this);
else
mTableLayoutStrategy = new BasicTableLayoutStrategy(this, numCols);
mTableLayoutStrategy->Initialize(aMaxElementSize);
mTableLayoutStrategy = new BasicTableLayoutStrategy(this);
mTableLayoutStrategy->Initialize(aMaxElementSize, mCellMap->GetColCount());
mColumnWidthsValid=PR_TRUE;
}
mTableLayoutStrategy->BalanceColumnWidths(mStyleContext, aReflowState, maxWidth);
@ -3070,13 +3074,12 @@ void nsTableFrame::BuildColumnCache( nsIPresContext& aPresContext,
{
NS_ASSERTION(nsnull==mPrevInFlow, "never ever call me on a continuing frame!");
NS_ASSERTION(nsnull!=mCellMap, "never ever call me until the cell map is built!");
NS_ASSERTION(PR_FALSE==mColumnCacheValid, "column cache valid state should be PR_FALSE");
nsStyleTable* tableStyle;
GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
EnsureColumns(aPresContext);
if (nsnull!=mColCache)
{
if (PR_TRUE==gsDebugIR) printf("TIF BCB: clearing column cache and cell map column frame cache.\n");
if (PR_TRUE==gsDebugIR) printf("TIF BCC: clearing column cache and cell map column frame cache.\n");
mCellMap->ClearColumnCache();
delete mColCache;
}
@ -3159,6 +3162,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext& aPresContext,
}
childFrame->GetNextSibling(childFrame);
}
if (PR_TRUE==gsDebugIR) printf("TIF BCC: mColumnCacheValid=PR_TRUE.\n");
mColumnCacheValid=PR_TRUE;
}
@ -3167,6 +3171,7 @@ void nsTableFrame::InvalidateColumnWidths()
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
firstInFlow->mColumnWidthsValid=PR_FALSE;
if (PR_TRUE==gsDebugIR) printf("TIF: ColWidths invalidated.\n");
}
PRBool nsTableFrame::IsColumnWidthsValid() const
@ -3188,6 +3193,7 @@ void nsTableFrame::InvalidateFirstPassCache()
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
firstInFlow->mFirstPassValid=PR_FALSE;
if (PR_TRUE==gsDebugIR) printf("TIF: FirstPass invalidated.\n");
}
PRBool nsTableFrame::IsColumnCacheValid() const
@ -3202,6 +3208,7 @@ void nsTableFrame::InvalidateColumnCache()
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
firstInFlow->mColumnCacheValid=PR_FALSE;
if (PR_TRUE==gsDebugIR) printf("TIF: ColCache invalidated.\n");
}
PRBool nsTableFrame::IsCellMapValid() const
@ -3237,6 +3244,7 @@ void nsTableFrame::InvalidateCellMap()
}
}
}
if (PR_TRUE==gsDebugIR) printf("TIF: CellMap invalidated.\n");
}
NS_METHOD

View File

@ -281,7 +281,8 @@ protected:
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus,
nsTableRowGroupFrame * aStartingFrame,
nsReflowReason aReason);
nsReflowReason aReason,
PRBool aDoSiblings);
/** second pass of ResizeReflow.
* lays out all table content with aMaxSize(computed_table_width, given_table_height)

View File

@ -59,7 +59,7 @@ struct RowGroupReflowState {
// Running y-offset
nscoord y;
// Flag used to set aMaxElementSize to my first row
// Flag used to set maxElementSize to my first row
PRBool firstRow;
// Remember the height of the first row, because it's our maxElementHeight (plus header/footers)
@ -188,7 +188,7 @@ void nsTableRowGroupFrame::PaintChildren(nsIPresContext& aPresContext,
// Collapse child's top margin with previous bottom margin
nscoord nsTableRowGroupFrame::GetTopMarginFor(nsIPresContext* aCX,
RowGroupReflowState& aState,
RowGroupReflowState& aReflowState,
const nsMargin& aKidMargin)
{
nscoord margin;
@ -200,8 +200,8 @@ nscoord nsTableRowGroupFrame::GetTopMarginFor(nsIPresContext* aCX,
maxPosTopMargin = margin;
}
nscoord maxPos = PR_MAX(aState.prevMaxPosBottomMargin, maxPosTopMargin);
nscoord maxNeg = PR_MAX(aState.prevMaxNegBottomMargin, maxNegTopMargin);
nscoord maxPos = PR_MAX(aReflowState.prevMaxPosBottomMargin, maxPosTopMargin);
nscoord maxNeg = PR_MAX(aReflowState.prevMaxNegBottomMargin, maxNegTopMargin);
margin = maxPos - maxNeg;
return margin;
@ -210,12 +210,12 @@ nscoord nsTableRowGroupFrame::GetTopMarginFor(nsIPresContext* aCX,
// Position and size aKidFrame and update our reflow state. The origin of
// aKidRect is relative to the upper-left origin of our frame, and includes
// any left/top margin.
void nsTableRowGroupFrame::PlaceChild( nsIPresContext* aPresContext,
RowGroupReflowState& aState,
nsIFrame* aKidFrame,
const nsRect& aKidRect,
nsSize* aMaxElementSize,
nsSize& aKidMaxElementSize)
void nsTableRowGroupFrame::PlaceChild(nsIPresContext& aPresContext,
RowGroupReflowState& aReflowState,
nsIFrame* aKidFrame,
const nsRect& aKidRect,
nsSize* aMaxElementSize,
nsSize& aKidMaxElementSize)
{
if (PR_TRUE==gsDebug)
printf ("rowgroup %p: placing row at %d, %d, %d, %d\n",
@ -225,18 +225,18 @@ void nsTableRowGroupFrame::PlaceChild( nsIPresContext* aPresContext,
aKidFrame->SetRect(aKidRect);
// Adjust the running y-offset
aState.y += aKidRect.height;
aReflowState.y += aKidRect.height;
// If our height is constrained then update the available height
if (PR_FALSE == aState.unconstrainedHeight) {
aState.availSize.height -= aKidRect.height;
if (PR_FALSE == aReflowState.unconstrainedHeight) {
aReflowState.availSize.height -= aKidRect.height;
}
// Update the maximum element size
if (PR_TRUE==aState.firstRow)
if (PR_TRUE==aReflowState.firstRow)
{
aState.firstRow = PR_FALSE;
aState.firstRowHeight = aKidRect.height;
aReflowState.firstRow = PR_FALSE;
aReflowState.firstRowHeight = aKidRect.height;
if (nsnull != aMaxElementSize) {
aMaxElementSize->width = aKidMaxElementSize.width;
aMaxElementSize->height = aKidMaxElementSize.height;
@ -254,61 +254,64 @@ void nsTableRowGroupFrame::PlaceChild( nsIPresContext* aPresContext,
* Reflow the frames we've already created
*
* @param aPresContext presentation context to use
* @param aState current inline state
* @param aReflowState 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 nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresContext,
RowGroupReflowState& aState,
nsSize* aMaxElementSize)
NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsTableRowFrame * aStartFrame,
nsReflowReason aReason,
PRBool aDoSiblings)
{
NS_PRECONDITION(nsnull != mFirstChild, "no children");
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: ReflowMappedChildren\n");
nsIFrame* prevKidFrame = nsnull;
nsSize kidMaxElementSize;
nsSize* pKidMaxElementSize = (nsnull != aMaxElementSize) ? &kidMaxElementSize : nsnull;
PRBool result = PR_TRUE;
PRInt32 debugCounter=0;
for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) {
nsSize kidAvailSize(aState.availSize);
nsSize* pKidMaxElementSize = (nsnull != aDesiredSize.maxElementSize) ? &kidMaxElementSize : nsnull;
nsresult rv = NS_OK;
nsIFrame* kidFrame;
if (nsnull==aStartFrame)
kidFrame = mFirstChild;
else
kidFrame = aStartFrame;
for ( ; nsnull != kidFrame; )
{
nsSize kidAvailSize(aReflowState.availSize);
if (0>=kidAvailSize.height)
kidAvailSize.height = 1; // XXX: HaCk - we don't handle negative heights yet
nsHTMLReflowMetrics desiredSize(pKidMaxElementSize);
desiredSize.width=desiredSize.height=desiredSize.ascent=desiredSize.descent=0;
nsReflowStatus status;
// Get top margin for this kid
nsIContentPtr kid;
kidFrame->GetContent(kid.AssignRef());
nsIStyleContextPtr kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
const nsStyleSpacing* kidSpacing = (const nsStyleSpacing*)
kidSC->GetStyleData(eStyleStruct_Spacing);
const nsStyleSpacing* kidSpacing;
kidFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)kidSpacing);
nsMargin kidMargin;
kidSpacing->CalcMarginFor(this, kidMargin);
nscoord topMargin = GetTopMarginFor(aPresContext, aState, kidMargin);
nscoord topMargin = GetTopMarginFor(&aPresContext, aReflowState, kidMargin);
nscoord bottomMargin = kidMargin.bottom;
// Figure out the amount of available size for the child (subtract
// off the top margin we are going to apply to it)
if (PR_FALSE == aState.unconstrainedHeight) {
if (PR_FALSE == aReflowState.unconstrainedHeight) {
kidAvailSize.height -= topMargin;
}
// Subtract off for left and right margin
if (PR_FALSE == aState.unconstrainedWidth) {
if (PR_FALSE == aReflowState.unconstrainedWidth) {
kidAvailSize.width -= kidMargin.left + kidMargin.right;
}
// Reflow the child into the available space
nsHTMLReflowState kidReflowState(*aPresContext, kidFrame,
aState.reflowState, kidAvailSize);
nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState.reflowState,
kidAvailSize, aReason);
if (gsDebug) printf("%p RG reflowing child %d (frame=%p) with avail width = %d\n",
this, debugCounter, kidFrame, kidAvailSize.width);
ReflowChild(kidFrame, *aPresContext, desiredSize, kidReflowState, status);
if (gsDebug) printf("%p RG child %d (frame=%p) returned desired width = %d\n",
this, debugCounter, kidFrame, desiredSize.width);
if ((PR_TRUE==gsDebug) || (PR_TRUE==gsDebugIR))
printf("%p RG reflowing child %p with avail width = %d, reason = %d\n",
this, kidFrame, kidAvailSize.width, aReason);
rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus);
if (gsDebug) printf("%p RG child %p returned desired width = %d\n",
this, kidFrame, desiredSize.width);
// Did the child fit?
if ((kidFrame != mFirstChild) &&
@ -321,18 +324,17 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
// Note that if the width is too big that's okay and we allow the
// child to extend horizontally outside of the reflow area
PushChildren(kidFrame, prevKidFrame);
result = PR_FALSE;
break;
}
// Place the child after taking into account it's margin
nsRect kidRect (kidMargin.left, aState.y, desiredSize.width, desiredSize.height);
PlaceChild(aPresContext, aState, kidFrame, kidRect, aMaxElementSize,
nsRect kidRect (kidMargin.left, aReflowState.y, desiredSize.width, desiredSize.height);
PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize,
kidMaxElementSize);
if (bottomMargin < 0) {
aState.prevMaxNegBottomMargin = -bottomMargin;
aReflowState.prevMaxNegBottomMargin = -bottomMargin;
} else {
aState.prevMaxPosBottomMargin = bottomMargin;
aReflowState.prevMaxPosBottomMargin = bottomMargin;
}
// Remember where we just were in case we end up pushing children
@ -344,7 +346,7 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
* otherwise PushChildren and bail.
*/
// Special handling for incomplete children
if (NS_FRAME_IS_NOT_COMPLETE(status)) {
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
// XXX It's good to assume that we might still have room
// even if the child didn't complete (floaters will want this)
nsIFrame* kidNextInFlow;
@ -355,8 +357,8 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
// create a continuing frame. This hooks the child into the flow.
nsIFrame* continuingFrame;
nsIStyleContext* kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC);
kidFrame->CreateContinuingFrame(*aPresContext, this, kidSC,
kidFrame->GetStyleContext(&aPresContext, kidSC);
kidFrame->CreateContinuingFrame(aPresContext, this, kidSC,
continuingFrame);
NS_RELEASE(kidSC);
@ -375,47 +377,47 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
if (nsnull != nextSibling) {
PushChildren(nextSibling, kidFrame);
}
result = PR_FALSE;
break;
}
// Add back in the left and right margins, because one row does not
// impact another row's width
if (PR_FALSE == aState.unconstrainedWidth) {
if (PR_FALSE == aReflowState.unconstrainedWidth) {
kidAvailSize.width += kidMargin.left + kidMargin.right;
}
if (PR_FALSE==aDoSiblings)
break;
// Get the next child
kidFrame->GetNextSibling(kidFrame);
debugCounter++;
}
// Update the child count
return result;
return rv;
}
/**
* Try and pull-up frames from our next-in-flow
*
* @param aPresContext presentation context to use
* @param aState current inline state
* @param aReflowState current inline state
* @return true if we successfully pulled-up all the children and false
* otherwise, e.g. child didn't fit
*/
PRBool nsTableRowGroupFrame::PullUpChildren(nsIPresContext* aPresContext,
RowGroupReflowState& aState,
nsSize* aMaxElementSize)
NS_METHOD nsTableRowGroupFrame::PullUpChildren(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsTableRowGroupFrame* nextInFlow = (nsTableRowGroupFrame*)mNextInFlow;
nsSize kidMaxElementSize;
nsSize* pKidMaxElementSize = (nsnull != aMaxElementSize) ? &kidMaxElementSize : nsnull;
nsSize* pKidMaxElementSize = (nsnull != aDesiredSize.maxElementSize) ? &kidMaxElementSize : nsnull;
nsIFrame* prevKidFrame = LastFrame(mFirstChild);
PRBool result = PR_TRUE;
nsresult rv = NS_OK;
while (nsnull != nextInFlow) {
nsHTMLReflowMetrics kidSize(pKidMaxElementSize);
kidSize.width=kidSize.height=kidSize.ascent=kidSize.descent=0;
nsReflowStatus status;
// Get the next child
nsIFrame* kidFrame = nextInFlow->mFirstChild;
@ -444,31 +446,30 @@ PRBool nsTableRowGroupFrame::PullUpChildren(nsIPresContext* aPresContext,
kidFrame->GetSize(kidFrameSize);
kidFrame->IsSplittable(kidIsSplittable);
if ((kidFrameSize.height > aState.availSize.height) &&
if ((kidFrameSize.height > aReflowState.availSize.height) &&
NS_FRAME_IS_NOT_SPLITTABLE(kidIsSplittable)) {
result = PR_FALSE;
break;
}
nsHTMLReflowState kidReflowState(*aPresContext, kidFrame,
aState.reflowState, aState.availSize,
nsHTMLReflowState kidReflowState(aPresContext, kidFrame,
aReflowState.reflowState, aReflowState.availSize,
eReflowReason_Resize);
ReflowChild(kidFrame, *aPresContext, kidSize, kidReflowState, status);
rv = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus);
// Did the child fit?
if ((kidSize.height > aState.availSize.height) && (nsnull != mFirstChild)) {
if ((kidSize.height > aReflowState.availSize.height) && (nsnull != mFirstChild)) {
// The child is too wide to fit in the available space, and it's
// not our first child
result = PR_FALSE;
//result = PR_FALSE;
break;
}
// Place the child
//aState.y += topMargin;
//aReflowState.y += topMargin;
nsRect kidRect (0, 0, kidSize.width, kidSize.height);
//kidRect.x += kidMol->margin.left;
kidRect.y += aState.y;
PlaceChild(aPresContext, aState, kidFrame, kidRect, aMaxElementSize, *pKidMaxElementSize);
kidRect.y += aReflowState.y;
PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize, *pKidMaxElementSize);
// Remove the frame from its current parent
kidFrame->GetNextSibling(nextInFlow->mFirstChild);
@ -492,7 +493,7 @@ PRBool nsTableRowGroupFrame::PullUpChildren(nsIPresContext* aPresContext,
prevKidFrame = kidFrame;
// Is the child we just pulled up complete?
if (NS_FRAME_IS_NOT_COMPLETE(status)) {
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
// No the child isn't complete
nsIFrame* kidNextInFlow;
@ -503,8 +504,8 @@ PRBool nsTableRowGroupFrame::PullUpChildren(nsIPresContext* aPresContext,
// prepares it for reflow.
nsIFrame* continuingFrame;
nsIStyleContext* kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC);
kidFrame->CreateContinuingFrame(*aPresContext, this, kidSC,
kidFrame->GetStyleContext(&aPresContext, kidSC);
kidFrame->CreateContinuingFrame(aPresContext, this, kidSC,
continuingFrame);
NS_RELEASE(kidSC);
NS_ASSERTION(nsnull != continuingFrame, "frame creation failed");
@ -521,12 +522,12 @@ PRBool nsTableRowGroupFrame::PullUpChildren(nsIPresContext* aPresContext,
// If the child isn't complete then it means that we've used up
// all of our available space.
result = PR_FALSE;
//result = PR_FALSE;
break;
}
}
return result;
return rv;
}
/**
@ -691,10 +692,11 @@ void nsTableRowGroupFrame::ShrinkWrapChildren(nsIPresContext* aPresContext,
}
nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aPresContext,
RowGroupReflowState& aState,
RowGroupReflowState& aReflowState,
nsIFrame* aKidFrame,
nscoord aDeltaY)
{
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: AdjustSiblingsAfterReflow\n");
nsIFrame* lastKidFrame = aKidFrame;
if (aDeltaY != 0) {
@ -731,7 +733,7 @@ nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aP
// Update our running y-offset to reflect the bottommost child
nsRect rect;
lastKidFrame->GetRect(rect);
aState.y = rect.YMost();
aReflowState.y = rect.YMost();
return NS_OK;
}
@ -771,24 +773,18 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext,
// Reflow the existing frames
if (nsnull != mFirstChild) {
reflowMappedOK = ReflowMappedChildren(&aPresContext, state, aDesiredSize.maxElementSize);
if (PR_FALSE == reflowMappedOK) {
aStatus = NS_FRAME_NOT_COMPLETE;
}
rv = ReflowMappedChildren(aPresContext, aDesiredSize, state, aStatus,
nsnull, aReflowState.reason, PR_TRUE);
}
// Did we successfully reflow our mapped children?
if (PR_TRUE == reflowMappedOK) {
if (NS_FRAME_COMPLETE==aStatus) {
// Any space left?
PRInt32 numKids;
mContent->ChildCount(numKids);
if (state.availSize.height > 0) {
// Try and pull-up some children from a next-in-flow
if (!PullUpChildren(&aPresContext, state, aDesiredSize.maxElementSize)) {
// We were unable to pull-up all the existing frames from the
// next in flow
aStatus = NS_FRAME_NOT_COMPLETE;
}
rv = PullUpChildren(aPresContext, aDesiredSize, state, aStatus);
}
}
@ -803,8 +799,6 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext,
}
// Return our desired rect
//NS_ASSERTION(0<state.firstRowHeight, "illegal firstRowHeight after reflow");
//NS_ASSERTION(0<state.y, "illegal height after reflow");
aDesiredSize.width = aReflowState.maxSize.width;
aDesiredSize.height = state.y;
@ -824,9 +818,7 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext,
this, NS_FRAME_IS_COMPLETE(aStatus)?"Complete":"Not Complete",
aDesiredSize.width, aDesiredSize.height);
}
return rv;
}
@ -874,14 +866,14 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
aReflowState.reflowState.reflowCommand->GetChildFrame(objectFrame);
const nsStyleDisplay *childDisplay;
objectFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
if (PR_TRUE==gsDebugIR) printf("TRGF IR: IncrementalReflow_TargetIsMe with type=%d\n", type);
if (PR_TRUE==gsDebugIR) printf("TRGF IR: TargetIsMe with type=%d\n", type);
switch (type)
{
case nsIReflowCommand::FrameInserted :
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
rv = IR_RowInserted(aPresContext, aDesiredSize, aReflowState, aStatus,
objectFrame, PR_FALSE);
(nsTableRowFrame *)objectFrame, PR_FALSE);
}
else
{
@ -893,7 +885,8 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
case nsIReflowCommand::FrameAppended :
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
rv = IR_RowAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame);
rv = IR_RowAppended(aPresContext, aDesiredSize, aReflowState, aStatus,
(nsTableRowFrame *)objectFrame);
}
else
{ // no optimization to be done for Unknown frame types, so just reuse the Inserted method
@ -911,7 +904,7 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
rv = IR_RowRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
objectFrame);
(nsTableRowFrame *)objectFrame);
}
else
{
@ -948,16 +941,35 @@ NS_METHOD nsTableRowGroupFrame::IR_RowInserted(nsIPresContext& aPresContext
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aInsertedFrame,
nsTableRowFrame * aInsertedFrame,
PRBool aReplace)
{
nsresult rv=NS_OK;
// inserting the rowgroup only effects reflow if the rowgroup includes at least one row
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_RowInserted\n");
nsresult rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState,
aStatus, (nsIFrame*)aInsertedFrame, aReplace);
if (NS_FAILED(rv))
return rv;
// do a pass-1 layout of all the cells in the inserted row
//XXX: check the table frame to see if we can skip this
rv = ReflowMappedChildren(aPresContext, aDesiredSize, aReflowState, aStatus,
aInsertedFrame, eReflowReason_Initial, PR_FALSE);
if (NS_FAILED(rv))
return rv;
nsTableFrame *tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (NS_FAILED(rv) || nsnull==tableFrame)
return rv;
tableFrame->InvalidateCellMap();
tableFrame->InvalidateColumnCache();
return rv;
}
NS_METHOD nsTableRowGroupFrame::IR_DidAppendRow(nsTableRowFrame *aRowFrame)
NS_METHOD nsTableRowGroupFrame::DidAppendRow(nsTableRowFrame *aRowFrame)
{
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: DidAppendRow\n");
nsresult rv=NS_OK;
/* need to make space in the cell map. Remeber that row spans can't cross row groups
once the space is made, tell the row to initizalize its children.
@ -969,56 +981,97 @@ NS_METHOD nsTableRowGroupFrame::IR_DidAppendRow(nsTableRowFrame *aRowFrame)
return rv;
}
// support method that tells us if there are any rows in the table after our rows
// returns PR_TRUE if there are no rows after ours
PRBool nsTableRowGroupFrame::NoRowsFollow()
{
PRBool result = PR_TRUE;
nsIFrame *nextSib=nsnull;
GetNextSibling(nextSib);
while (nsnull!=nextSib)
{
const nsStyleDisplay *sibDisplay;
nextSib->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)sibDisplay));
if ((NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == sibDisplay->mDisplay) ||
(NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == sibDisplay->mDisplay) ||
(NS_STYLE_DISPLAY_TABLE_ROW_GROUP == sibDisplay->mDisplay))
{
nsIFrame *childFrame=nsnull;
nextSib->FirstChild(childFrame);
while (nsnull!=childFrame)
{
const nsStyleDisplay *childDisplay;
childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{ // found a row
result = PR_FALSE;
break;
}
}
}
nextSib->GetNextSibling(nextSib);
}
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: NoRowsFollow returning %d\n", result);
return result;
}
// since we know we're doing an append here, we can optimize
NS_METHOD nsTableRowGroupFrame::IR_RowAppended(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aAppendedFrame)
nsTableRowFrame * aAppendedFrame)
{
nsresult rv=NS_OK;
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_RowAppended\n");
// hook aAppendedFrame into the child list
nsIFrame *lastChild = mFirstChild;
nsIFrame *nextChild = lastChild;
nsIFrame *lastRow = nsnull;
while (nsnull!=nextChild)
{
// remember the last child that is really a row
const nsStyleDisplay *childDisplay;
nextChild->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
lastRow = nextChild;
lastChild = nextChild;
nextChild->GetNextSibling(nextChild);
}
if (nsnull==lastChild)
mFirstChild = aAppendedFrame;
else
lastChild->SetNextSibling(aAppendedFrame);
nsTableFrame *tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (NS_FAILED(rv) || nsnull==tableFrame)
nsresult rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState,
aStatus, (nsIFrame*)aAppendedFrame, PR_FALSE);
if (NS_FAILED(rv))
return rv;
tableFrame->InvalidateFirstPassCache();
// the table will see that it's cached info is bogus and rebuild the cell map,
// and do a reflow
#if 0
// find the row index of the new row
PRInt32 newRowIndex=-1;
if (nsnull!=
/* we have 2 paths to choose from. If we know that aAppendedFrame is
* the last row in the table, we can optimize. Otherwise, we have to
* treat it like an insert
*/
if (PR_TRUE==NoRowsFollow())
{ // aAppendedRow is the last row, so do the optimized route
// account for the cells in the row aAppendedFrame
// this will add the content of the rowgroup to the cell map
rv = DidAppendRow(aAppendedFrame);
if (NS_FAILED(rv))
return rv;
lastChild=mFirstChild;
nextChild=lastChild;
while (nsnull!=nextChild)
{
// do a pass1 reflow of the new row
//XXX: check the table frame to see if we can skip this
rv = ReflowMappedChildren(aPresContext, aDesiredSize, aReflowState, aStatus,
aAppendedFrame, eReflowReason_Initial, PR_FALSE);
if (NS_FAILED(rv))
return rv;
// if any column widths have to change due to this, rebalance column widths
//XXX need to calculate this, but for now just do it
nsTableFrame *tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (NS_FAILED(rv) || nsnull==tableFrame)
return rv;
tableFrame->InvalidateColumnWidths();
}
// account for the cells in aAppendedFrame
nsresult rv = DidAppendRow((nsTableRowFrame*)aAppendedFrame, newRowIndex);
else
{
// do a pass1 reflow of the new row
//XXX: check the table frame to see if we can skip this
rv = ReflowMappedChildren(aPresContext, aDesiredSize, aReflowState, aStatus,
aAppendedFrame, eReflowReason_Initial, PR_FALSE);
if (NS_FAILED(rv))
return rv;
// need to increment the row index of all subsequent rows
#endif
nsTableFrame *tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (NS_FAILED(rv) || nsnull==tableFrame)
return rv;
tableFrame->InvalidateCellMap();
tableFrame->InvalidateColumnCache();
}
return rv;
}
@ -1027,9 +1080,25 @@ NS_METHOD nsTableRowGroupFrame::IR_RowRemoved(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aDeletedFrame)
nsTableRowFrame * aDeletedFrame)
{
nsresult rv;
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_RowRemoved\n");
nsresult rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
aDeletedFrame);
if (NS_SUCCEEDED(rv))
{
nsTableFrame *tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (NS_FAILED(rv) || nsnull==tableFrame)
return rv;
tableFrame->InvalidateCellMap();
tableFrame->InvalidateColumnCache();
// if any column widths have to change due to this, rebalance column widths
//XXX need to calculate this, but for now just do it
tableFrame->InvalidateColumnWidths();
}
return rv;
}
@ -1041,6 +1110,7 @@ NS_METHOD nsTableRowGroupFrame::IR_UnknownFrameInserted(nsIPresContext& aPr
nsIFrame * aInsertedFrame,
PRBool aReplace)
{
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_UnknownFrameInserted\n");
nsIReflowCommand::ReflowType type;
aReflowState.reflowState.reflowCommand->GetType(type);
// we have a generic frame that gets inserted but doesn't effect reflow
@ -1075,9 +1145,7 @@ NS_METHOD nsTableRowGroupFrame::IR_UnknownFrameInserted(nsIPresContext& aPr
}
else
{
nsIFrame *nextSibling=nsnull;
if (nsnull!=mFirstChild)
mFirstChild->GetNextSibling(nextSibling);
nsIFrame *nextSibling=mFirstChild;
mFirstChild = aInsertedFrame;
aInsertedFrame->SetNextSibling(nextSibling);
}
@ -1091,6 +1159,7 @@ NS_METHOD nsTableRowGroupFrame::IR_UnknownFrameRemoved(nsIPresContext& aPre
nsReflowStatus& aStatus,
nsIFrame * aRemovedFrame)
{
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_UnknownFrameRemoved\n");
// we have a generic frame that gets removed but doesn't effect reflow
// unhook it then ignore it
if (PR_TRUE==gsDebugIR) printf("TRGF IR: FrameRemoved removing unknown frame type.\n");

View File

@ -107,22 +107,20 @@ public:
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aInsertedFrame,
nsTableRowFrame * aInsertedFrame,
PRBool aReplace);
NS_IMETHOD IR_RowAppended(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aAppendedFrame);
NS_IMETHOD IR_DidAppendRow(nsTableRowFrame *aRowFrame);
nsTableRowFrame * aAppendedFrame);
NS_IMETHOD IR_RowRemoved(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aDeletedFrame);
nsTableRowFrame * aDeletedFrame);
NS_IMETHOD IR_UnknownFrameInserted(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
@ -138,6 +136,9 @@ public:
nsIFrame * aDeletedFrame);
NS_IMETHOD DidAppendRow(nsTableRowFrame *aRowFrame);
PRBool NoRowsFollow();
/** @see nsContainerFrame::CreateContinuingFrame */
NS_IMETHOD CreateContinuingFrame(nsIPresContext& aPresContext,
@ -174,7 +175,7 @@ protected:
RowGroupReflowState& aReflowState,
const nsMargin& aKidMargin);
void PlaceChild( nsIPresContext* aPresContext,
void PlaceChild( nsIPresContext& aPresContext,
RowGroupReflowState& aReflowState,
nsIFrame* aKidFrame,
const nsRect& aKidRect,
@ -197,9 +198,13 @@ protected:
* @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,
NS_METHOD ReflowMappedChildren(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsSize* aMaxElementSize);
nsReflowStatus& aStatus,
nsTableRowFrame * aStartFrame,
nsReflowReason aReason,
PRBool aDoSiblings);
/**
* Try and pull-up frames from our next-in-flow
@ -209,9 +214,10 @@ protected:
* @return true if we successfully pulled-up all the children and false
* otherwise, e.g. child didn't fit
*/
PRBool PullUpChildren(nsIPresContext* aPresContext,
NS_METHOD PullUpChildren(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsSize* aMaxElementSize);
nsReflowStatus& aStatus);
private:
nsIAtom *mType;

View File

@ -6,7 +6,7 @@
function insertCaption() {
var table = document.getElementsByTagName("TABLE")[0];
var caption = document.createElement("CAPTION", null);
var text = document.createTextNode("here is the new caption text");
var text = document.createTextNode("here is the new caption text\n");
caption.appendChild(text);
table.appendChild(caption);
}
@ -25,7 +25,7 @@ function insertColGroup() {
colGroup.width=200;
colGroup.span=1;
table.insertBefore(colGroup, refColGroup);
dump("inserted COLGROUP with span=1 width=200 as first colgroup in table");
dump("SCRIPT: inserted COLGROUP with span=1 width=200 as first colgroup in table\n");
}
function appendColGroup() {
@ -34,13 +34,14 @@ function appendColGroup() {
colGroup.width=300;
colGroup.span=1;
table.appendChild(colGroup);
dump("appended COLGROUP with span=1 width=300");
dump("SCRIPT: appended COLGROUP with span=1 width=300\n");
}
function deleteColGroup() {
var table = document.getElementsByTagName("TABLE")[0];
var colGroup = document.getElementsByTagName("COLGROUP")[0];
table.removeChild(colGroup);
dump("SCRIPT: deleted first COLGROUP\n");
}
@ -51,20 +52,21 @@ function insertCol() {
col.width=200;
col.span=1;
table.insertBefore(col, refCol);
dump("inserted COL with span=1 width=200 as first col in first col group");
dump("SCRIPT: inserted COL with span=1 width=200 as first col in first col group\n");
}
function appendCol() {
var table = document.getElementsByTagName("TABLE")[0];
var col = document.createElement("COL", null);
table.appendChild(col);
dump("appended COL with span=1 width=300");
dump("SCRIPT: appended COL with span=1 width=300\n");
}
function deleteCol() {
var table = document.getElementsByTagName("TABLE")[0];
var col = document.getElementsByTagName("COL")[0];
table.removeChild(col);
dump("SCRIPT: deleted first COL in first COLGROUP\n");
}
@ -73,52 +75,110 @@ function insertRowGroup() {
var refRowGroup = document.getElementsByTagName("TBODY")[0];
var rowGroup = document.createElement("TBODY", null);
table.insertBefore(rowGroup, refRowGroup);
dump("inserted empty ROWGROUP as first rowgroup in table");
dump("SCRIPT: inserted empty ROWGROUP as first rowgroup in table\n");
}
function appendRowGroup() {
var table = document.getElementsByTagName("TABLE")[0];
var rowGroup = document.createElement("TBODY", null);
table.appendChild(rowGroup);
dump("appended empty ROWGROUP");
dump("SCRIPT: appended empty ROWGROUP\n");
}
function appendRowGroupWithContent() {
dump("\nSCRIPT: starting appendRowGroupWithContent\n");
var table = document.getElementsByTagName("TABLE")[0];
var rowGroup = document.createElement("TBODY", null);
var row = document.createElement("TR", null);
var cell = document.createElement("TD", null);
var text = document.createTextNode("here is content in the cell from the script");
var text = document.createTextNode("here is content in the cell from the script appendRowGroupWithContent\n");
cell.appendChild(text);
row.appendChild(cell);
rowGroup.appendChild(row);
table.appendChild(rowGroup);
dump("appended ROWGROUP with 1 row and 1 cell");
dump("SCRIPT: appended ROWGROUP with 1 row and 1 cell\n");
}
function deleteRowGroup() {
var table = document.getElementsByTagName("TABLE")[0];
var rowGroup = document.getElementsByTagName("TBODY")[0];
table.removeChild(rowGroup);
dump("SCRIPT: deleted first ROWGROUP\n");
}
function insertRow() {
var table = document.getElementsByTagName("TABLE")[0];
var rg = document.getElementsByTagName("TBODY")[0];
var refRow = document.getElementsByTagName("TR")[0];
var row = document.createElement("TR", null);
table.appendChild(row);
rg.insertBefore(row, refRow);
dump("SCRIPT: inserted empty ROW as first row in first rowgroup in table\n");
}
function appendRow() {
var rg = document.getElementsByTagName("TBODY")[0];
var row = document.createElement("TR", null);
rg.appendChild(row);
dump("SCRIPT: appended empty ROW in first ROWGROUP\n");
}
function appendRowWithContent() {
dump("\nSCRIPT: starting appendRowWithContent\n");
var rg = document.getElementsByTagName("TBODY")[0];
var row = document.createElement("TR", null);
var cell = document.createElement("TD", null);
var text = document.createTextNode("here is content in the cell from the script appendRowWithContent\n");
cell.appendChild(text);
row.appendChild(cell);
rg.appendChild(row);
dump("SCRIPT: appended ROW with 1 cell in first ROWGROUP\n");
}
function deleteRow() {
var table = document.getElementsByTagName("TABLE")[0];
var rg = document.getElementsByTagName("TBODY")[0];
var row = document.getElementsByTagName("TR")[0];
table.removeChild(row);
rg.removeChild(row);
dump("SCRIPT: deleted first ROW in first ROWGROUP\n");
}
function insertCell() {
var row = document.getElementsByTagName("TR")[0];
var refCell = document.getElementsByTagName("TD")[0];
var cell = document.createElement("TD", null);
row.insertBefore(cell, refCell);
dump("SCRIPT: inserted empty Cell as first cell in first row\n");
}
function appendCell() {
var row = document.getElementsByTagName("TR")[0];
var cell = document.createElement("TD", null);
row.appendChild(cell);
dump("SCRIPT: appended empty CELL in first ROW\n");
}
function appendCellWithContent() {
var row = document.getElementsByTagName("TR")[0];
var cell = document.createElement("TD", null);
var text = document.createTextNode("here is content in the cell from the script appendRowWithContent\n");
cell.appendChild(text);
row.appendChild(cell);
dump("SCRIPT: appended CELL with text content in first ROW\n");
}
function deleteCell() {
var row = document.getElementsByTagName("TR")[0];
var cell = document.getElementsByTagName("TD")[0];
row.removeChild(cell);
dump("SCRIPT: deleted first CELL in first ROW\n");
}
</SCRIPT>
</HEAD>
<BODY>
all insert buttons currently do an append
all delete buttons currently remove the first item of <type> found
<table border>
<tbody>
@ -150,6 +210,12 @@ all delete buttons currently remove the first item of <type> found
<INPUT TYPE="button" NAME="Ins Row" VALUE="InsertRow" onClick="insertRow()" width=100>
<INPUT TYPE="button" NAME="App Row" VALUE="AppendRow" onClick="appendRow()" width=100>
<INPUT TYPE="button" NAME="Del Row" VALUE="DeleteRow" onClick="deleteRow()" width=100>
<INPUT TYPE="button" NAME="App Row with content" VALUE="AppendRow with content" onClick="appendRowWithContent()" width=100>
<br>
<INPUT TYPE="button" NAME="Ins Cell" VALUE="InsertCell" onClick="insertCell()" width=100>
<INPUT TYPE="button" NAME="App Cell" VALUE="AppendCell" onClick="appendCell()" width=100>
<INPUT TYPE="button" NAME="Del Cell" VALUE="DeleteCell" onClick="deleteCell()" width=100>
<INPUT TYPE="button" NAME="App Cell with content" VALUE="AppendCell with content" onClick="appendCellWithContent()" width=100>
<br>
</form>

View File

@ -103,25 +103,21 @@ PRBool BasicTableLayoutStrategy::IsFixedWidth(const nsStylePosition* aStylePosit
}
BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame, PRInt32 aNumCols)
BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame)
{
NS_ASSERTION(nsnull!=aFrame, "bad frame arg");
mTableFrame = aFrame;
mNumCols = aNumCols;
mMinTableWidth=0;
mMaxTableWidth=0;
mFixedTableWidth=0;
//cache the value of the cols attribute
mCols = mTableFrame->GetEffectiveCOLSAttribute();
}
BasicTableLayoutStrategy::~BasicTableLayoutStrategy()
{
}
PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize)
PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols)
{
#ifdef NS_DEBUG
nsIFrame *tablePIF=nsnull;
@ -132,9 +128,11 @@ PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize)
PRBool result = PR_TRUE;
// re-init instance variables
mNumCols = aNumCols;
mMinTableWidth=0;
mMaxTableWidth=0;
mFixedTableWidth=0;
mCols = mTableFrame->GetEffectiveCOLSAttribute();
// Step 1 - assign the width of all fixed-width columns
AssignPreliminaryColumnWidths();

View File

@ -76,15 +76,17 @@ public:
/** Public constructor.
* @paran aFrame the table frame for which this delegate will do layout
* @param aNumCols the total number of columns in the table
*/
BasicTableLayoutStrategy(nsTableFrame *aFrame, PRInt32 aNumCols);
BasicTableLayoutStrategy(nsTableFrame *aFrame);
/** destructor */
virtual ~BasicTableLayoutStrategy();
/** call once every time any table thing changes (content, structure, or style) */
virtual PRBool Initialize(nsSize* aMaxElementSize);
/** call once every time any table thing changes (content, structure, or style)
* @param aMaxElementSize [OUT] if not null, the max element size is computed and returned in this param
* @param aNumCols the total number of columns in the table
*/
virtual PRBool Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols);
virtual void SetMaxElementSize(nsSize* aMaxElementSize);

View File

@ -35,8 +35,8 @@ static PRBool gsDebug = PR_FALSE;
static const PRBool gsDebug = PR_FALSE;
#endif
FixedTableLayoutStrategy::FixedTableLayoutStrategy(nsTableFrame *aFrame, PRInt32 aNumCols)
: BasicTableLayoutStrategy(aFrame, aNumCols)
FixedTableLayoutStrategy::FixedTableLayoutStrategy(nsTableFrame *aFrame)
: BasicTableLayoutStrategy(aFrame)
{
}

View File

@ -44,19 +44,16 @@ public:
* @paran aFrame the table frame for which this delegate will do layout
* @param aNumCols the total number of columns in the table
*/
FixedTableLayoutStrategy(nsTableFrame *aFrame, PRInt32 aNumCols);
FixedTableLayoutStrategy(nsTableFrame *aFrame);
/** destructor */
virtual ~FixedTableLayoutStrategy();
/** no need to override Initialize since it calls our AssignPreliminaryColumnWidths */
// virtual PRBool Initialize(nsSize* aMaxElementSize);
/** Called during resize reflow to determine the new column widths
* @param aTableStyle - the resolved style for mTableFrame
* @param aReflowState - the reflow state for mTableFrame
* @param aMaxWidth - the computed max width for columns to fit into
*/
* @param aReflowState - the reflow state for mTableFrame
* @param aMaxWidth - the computed max width for columns to fit into
*/
virtual PRBool BalanceColumnWidths(nsIStyleContext * aTableStyle,
const nsHTMLReflowState& aReflowState,
nscoord aMaxWidth);

View File

@ -30,9 +30,10 @@ class nsITableLayoutStrategy
public:
/** call once every time any table thing changes (content, structure, or style)
* @param aMaxElementSize [OUT] the min possible size of the table
* @param aMaxElementSize [OUT] if not null, the max element size is computed and returned in this param
* @param aNumCols the total number of columns in the table
*/
virtual PRBool Initialize(nsSize* aMaxElementSize)=0;
virtual PRBool Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols)=0;
/** compute the max-element-size for the table
* @param aMaxElementSize [OUT] width field set to the min legal width of the table

View File

@ -928,7 +928,8 @@ void nsTableFrame::SetMinColSpanForTable()
{ // XXX: must be called ONLY on first-in-flow
// set the minColSpan for each column
PRInt32 rowCount = mCellMap->GetRowCount();
for (PRInt32 colIndex=0; colIndex<mColCount; colIndex++)
PRInt32 colCount = mCellMap->GetColCount();
for (PRInt32 colIndex=0; colIndex<colCount; colIndex++)
{
PRInt32 minColSpan;
for (PRInt32 rowIndex=0; rowIndex<rowCount; rowIndex++)
@ -999,6 +1000,7 @@ void nsTableFrame::AddCellToTable (nsTableRowFrame *aRowFrame,
NS_METHOD nsTableFrame::ReBuildCellMap()
{
if (PR_TRUE==gsDebugIR) printf("TIF: ReBuildCellMap.\n");
nsresult rv=NS_OK;
nsIFrame *rowGroupFrame=mFirstChild;
for ( ; nsnull!=rowGroupFrame; rowGroupFrame->GetNextSibling(rowGroupFrame))
@ -1022,6 +1024,7 @@ NS_METHOD nsTableFrame::ReBuildCellMap()
}
}
}
mCellMapValid=PR_TRUE;
return rv;
}
@ -1562,10 +1565,10 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
if (PR_TRUE==NeedsReflow(aReflowState, aReflowState.maxSize))
{
PRBool needsRecalc=PR_FALSE;
if (PR_TRUE==gsDebug) printf("TIF Reflow: needs reflow\n");
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: needs reflow\n");
if (eReflowReason_Initial!=aReflowState.reason && PR_FALSE==IsCellMapValid())
{
if (PR_TRUE==gsDebug) printf("TIF Reflow: cell map invalid, rebuilding...\n");
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: cell map invalid, rebuilding...\n");
if (nsnull!=mCellMap)
delete mCellMap;
mCellMap = new nsCellMap(0,0);
@ -1575,7 +1578,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
if (PR_FALSE==IsFirstPassValid())
{
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: first pass is invalid, rebuilding...\n");
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, aStatus, nsnull, aReflowState.reason);
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, aStatus, nsnull, aReflowState.reason, PR_TRUE);
if (NS_FAILED(rv))
return rv;
needsRecalc=PR_TRUE;
@ -1587,23 +1590,23 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
}
if (PR_TRUE==needsRecalc)
{
if (PR_TRUE==gsDebugIR) printf("TIF Reflow: needs recalc.\n");
// if we need to recalc, the data stored in the layout strategy is invalid
if (nsnull!=mTableLayoutStrategy)
{
if (PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize);
mColumnWidthsValid=PR_TRUE;
}
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: needs recalc. Calling BuildColumnCache...\n");
BuildColumnCache(aPresContext, aDesiredSize, aReflowState, aStatus);
RecalcLayoutData(); // Recalculate Layout Dependencies
// if we needed to rebuild the column cache, the data stored in the layout strategy is invalid
if (nsnull!=mTableLayoutStrategy)
{
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, mCellMap->GetColCount());
mColumnWidthsValid=PR_TRUE; //so we don't do this a second time below
}
}
if (PR_FALSE==IsColumnWidthsValid())
{
if (PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
if (nsnull!=mTableLayoutStrategy)
{
mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize);
mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, mCellMap->GetColCount());
mColumnWidthsValid=PR_TRUE;
}
}
@ -1658,7 +1661,8 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus,
nsTableRowGroupFrame * aStartingFrame,
nsReflowReason aReason)
nsReflowReason aReason,
PRBool aDoSiblingFrames)
{
NS_PRECONDITION(aReflowState.frame == this, "bad reflow state");
NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent,
@ -1719,7 +1723,7 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext,
PRInt32 yCoord = y;
if (NS_UNCONSTRAINEDSIZE!=yCoord)
yCoord+= topInset;
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: Reflow Pass 1 of frame %p\n", kidFrame);
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: Reflow Pass 1 of frame %p with reason=%d\n", kidFrame, aReason);
ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus);
// Place the child since some of its content fit in us.
@ -1744,6 +1748,8 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext,
// up all of our available space (or needs us to split).
break;
}
if (PR_FALSE==aDoSiblingFrames)
break;
}
}
@ -2185,14 +2191,18 @@ NS_METHOD nsTableFrame::IR_RowGroupInserted(nsIPresContext& aPresContext,
{
nsresult rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState,
aStatus, (nsIFrame*)aInsertedFrame, aReplace);
// inserting the rowgroup only effects reflow if the rowgroup includes at least one row
PRInt32 rowCount;
aInsertedFrame->GetRowCount(rowCount);
if (0>rowCount)
{ // for now we will assume that if there are rows, then there are cells and we need to recalc table info
InvalidateCellMap();
InvalidateColumnCache();
}
if (NS_FAILED(rv))
return rv;
// do a pass-1 layout of all the cells in all the rows of the rowgroup
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.reflowState, aStatus,
aInsertedFrame, eReflowReason_Initial, PR_FALSE);
if (NS_FAILED(rv))
return rv;
InvalidateCellMap();
InvalidateColumnCache();
return rv;
}
@ -2212,10 +2222,12 @@ NS_METHOD nsTableFrame::IR_RowGroupAppended(nsIPresContext& aPresContext,
// account for the cells in the rows that are children of aAppendedFrame
// this will add the content of the rowgroup to the cell map
rv = DidAppendRowGroup((nsTableRowGroupFrame*)aAppendedFrame);
if (NS_FAILED(rv))
return rv;
// do a pass-1 layout of all the cells in all the rows of the rowgroup
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.reflowState, aStatus,
aAppendedFrame, eReflowReason_Initial);
aAppendedFrame, eReflowReason_Initial, PR_TRUE);
if (NS_FAILED(rv))
return rv;
@ -2232,17 +2244,11 @@ NS_METHOD nsTableFrame::IR_RowGroupRemoved(nsIPresContext& aPresContext,
nsReflowStatus& aStatus,
nsTableRowGroupFrame * aDeletedFrame)
{
nsresult rv;
nsresult rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
aDeletedFrame);
InvalidateCellMap();
InvalidateColumnCache();
rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
aDeletedFrame);
PRInt32 rowCount=0;
aDeletedFrame->GetRowCount(rowCount);
if (0>rowCount)
{ // for now we will assume that if there are rows, then there are cells and we need to recalc table info
InvalidateCellMap();
InvalidateColumnCache();
}
// if any column widths have to change due to this, rebalance column widths
//XXX need to calculate this, but for now just do it
InvalidateColumnWidths();
@ -2292,9 +2298,7 @@ NS_METHOD nsTableFrame::IR_UnknownFrameInserted(nsIPresContext& aPresCont
}
else
{
nsIFrame *nextSibling=nsnull;
if (nsnull!=mFirstChild)
mFirstChild->GetNextSibling(nextSibling);
nsIFrame *nextSibling = mFirstChild;
mFirstChild = aInsertedFrame;
aInsertedFrame->SetNextSibling(nextSibling);
}
@ -2555,7 +2559,7 @@ PRBool nsTableFrame::ReflowMappedChildren( nsIPresContext& aPresContext,
nscoord x = aState.leftInset + kidMargin.left;
nscoord y = aState.topInset + aState.y + topMargin;
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: Reflow Pass 2 of frame %p\n", kidFrame);
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: Reflow Pass 2 of frame %p with reason=%d\n", kidFrame, reason);
ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, status);
// Did the child fit?
if ((kidFrame != mFirstChild) && (desiredSize.height > kidAvailSize.height))
@ -2834,10 +2838,10 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext& aPresContext,
nsStyleTable* tableStyle;
GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
if (NS_STYLE_TABLE_LAYOUT_FIXED==tableStyle->mLayoutStrategy)
mTableLayoutStrategy = new FixedTableLayoutStrategy(this, numCols);
mTableLayoutStrategy = new FixedTableLayoutStrategy(this);
else
mTableLayoutStrategy = new BasicTableLayoutStrategy(this, numCols);
mTableLayoutStrategy->Initialize(aMaxElementSize);
mTableLayoutStrategy = new BasicTableLayoutStrategy(this);
mTableLayoutStrategy->Initialize(aMaxElementSize, mCellMap->GetColCount());
mColumnWidthsValid=PR_TRUE;
}
mTableLayoutStrategy->BalanceColumnWidths(mStyleContext, aReflowState, maxWidth);
@ -3070,13 +3074,12 @@ void nsTableFrame::BuildColumnCache( nsIPresContext& aPresContext,
{
NS_ASSERTION(nsnull==mPrevInFlow, "never ever call me on a continuing frame!");
NS_ASSERTION(nsnull!=mCellMap, "never ever call me until the cell map is built!");
NS_ASSERTION(PR_FALSE==mColumnCacheValid, "column cache valid state should be PR_FALSE");
nsStyleTable* tableStyle;
GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
EnsureColumns(aPresContext);
if (nsnull!=mColCache)
{
if (PR_TRUE==gsDebugIR) printf("TIF BCB: clearing column cache and cell map column frame cache.\n");
if (PR_TRUE==gsDebugIR) printf("TIF BCC: clearing column cache and cell map column frame cache.\n");
mCellMap->ClearColumnCache();
delete mColCache;
}
@ -3159,6 +3162,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext& aPresContext,
}
childFrame->GetNextSibling(childFrame);
}
if (PR_TRUE==gsDebugIR) printf("TIF BCC: mColumnCacheValid=PR_TRUE.\n");
mColumnCacheValid=PR_TRUE;
}
@ -3167,6 +3171,7 @@ void nsTableFrame::InvalidateColumnWidths()
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
firstInFlow->mColumnWidthsValid=PR_FALSE;
if (PR_TRUE==gsDebugIR) printf("TIF: ColWidths invalidated.\n");
}
PRBool nsTableFrame::IsColumnWidthsValid() const
@ -3188,6 +3193,7 @@ void nsTableFrame::InvalidateFirstPassCache()
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
firstInFlow->mFirstPassValid=PR_FALSE;
if (PR_TRUE==gsDebugIR) printf("TIF: FirstPass invalidated.\n");
}
PRBool nsTableFrame::IsColumnCacheValid() const
@ -3202,6 +3208,7 @@ void nsTableFrame::InvalidateColumnCache()
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
firstInFlow->mColumnCacheValid=PR_FALSE;
if (PR_TRUE==gsDebugIR) printf("TIF: ColCache invalidated.\n");
}
PRBool nsTableFrame::IsCellMapValid() const
@ -3237,6 +3244,7 @@ void nsTableFrame::InvalidateCellMap()
}
}
}
if (PR_TRUE==gsDebugIR) printf("TIF: CellMap invalidated.\n");
}
NS_METHOD

View File

@ -281,7 +281,8 @@ protected:
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus,
nsTableRowGroupFrame * aStartingFrame,
nsReflowReason aReason);
nsReflowReason aReason,
PRBool aDoSiblings);
/** second pass of ResizeReflow.
* lays out all table content with aMaxSize(computed_table_width, given_table_height)

View File

@ -59,7 +59,7 @@ struct RowGroupReflowState {
// Running y-offset
nscoord y;
// Flag used to set aMaxElementSize to my first row
// Flag used to set maxElementSize to my first row
PRBool firstRow;
// Remember the height of the first row, because it's our maxElementHeight (plus header/footers)
@ -188,7 +188,7 @@ void nsTableRowGroupFrame::PaintChildren(nsIPresContext& aPresContext,
// Collapse child's top margin with previous bottom margin
nscoord nsTableRowGroupFrame::GetTopMarginFor(nsIPresContext* aCX,
RowGroupReflowState& aState,
RowGroupReflowState& aReflowState,
const nsMargin& aKidMargin)
{
nscoord margin;
@ -200,8 +200,8 @@ nscoord nsTableRowGroupFrame::GetTopMarginFor(nsIPresContext* aCX,
maxPosTopMargin = margin;
}
nscoord maxPos = PR_MAX(aState.prevMaxPosBottomMargin, maxPosTopMargin);
nscoord maxNeg = PR_MAX(aState.prevMaxNegBottomMargin, maxNegTopMargin);
nscoord maxPos = PR_MAX(aReflowState.prevMaxPosBottomMargin, maxPosTopMargin);
nscoord maxNeg = PR_MAX(aReflowState.prevMaxNegBottomMargin, maxNegTopMargin);
margin = maxPos - maxNeg;
return margin;
@ -210,12 +210,12 @@ nscoord nsTableRowGroupFrame::GetTopMarginFor(nsIPresContext* aCX,
// Position and size aKidFrame and update our reflow state. The origin of
// aKidRect is relative to the upper-left origin of our frame, and includes
// any left/top margin.
void nsTableRowGroupFrame::PlaceChild( nsIPresContext* aPresContext,
RowGroupReflowState& aState,
nsIFrame* aKidFrame,
const nsRect& aKidRect,
nsSize* aMaxElementSize,
nsSize& aKidMaxElementSize)
void nsTableRowGroupFrame::PlaceChild(nsIPresContext& aPresContext,
RowGroupReflowState& aReflowState,
nsIFrame* aKidFrame,
const nsRect& aKidRect,
nsSize* aMaxElementSize,
nsSize& aKidMaxElementSize)
{
if (PR_TRUE==gsDebug)
printf ("rowgroup %p: placing row at %d, %d, %d, %d\n",
@ -225,18 +225,18 @@ void nsTableRowGroupFrame::PlaceChild( nsIPresContext* aPresContext,
aKidFrame->SetRect(aKidRect);
// Adjust the running y-offset
aState.y += aKidRect.height;
aReflowState.y += aKidRect.height;
// If our height is constrained then update the available height
if (PR_FALSE == aState.unconstrainedHeight) {
aState.availSize.height -= aKidRect.height;
if (PR_FALSE == aReflowState.unconstrainedHeight) {
aReflowState.availSize.height -= aKidRect.height;
}
// Update the maximum element size
if (PR_TRUE==aState.firstRow)
if (PR_TRUE==aReflowState.firstRow)
{
aState.firstRow = PR_FALSE;
aState.firstRowHeight = aKidRect.height;
aReflowState.firstRow = PR_FALSE;
aReflowState.firstRowHeight = aKidRect.height;
if (nsnull != aMaxElementSize) {
aMaxElementSize->width = aKidMaxElementSize.width;
aMaxElementSize->height = aKidMaxElementSize.height;
@ -254,61 +254,64 @@ void nsTableRowGroupFrame::PlaceChild( nsIPresContext* aPresContext,
* Reflow the frames we've already created
*
* @param aPresContext presentation context to use
* @param aState current inline state
* @param aReflowState 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 nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresContext,
RowGroupReflowState& aState,
nsSize* aMaxElementSize)
NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsTableRowFrame * aStartFrame,
nsReflowReason aReason,
PRBool aDoSiblings)
{
NS_PRECONDITION(nsnull != mFirstChild, "no children");
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: ReflowMappedChildren\n");
nsIFrame* prevKidFrame = nsnull;
nsSize kidMaxElementSize;
nsSize* pKidMaxElementSize = (nsnull != aMaxElementSize) ? &kidMaxElementSize : nsnull;
PRBool result = PR_TRUE;
PRInt32 debugCounter=0;
for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) {
nsSize kidAvailSize(aState.availSize);
nsSize* pKidMaxElementSize = (nsnull != aDesiredSize.maxElementSize) ? &kidMaxElementSize : nsnull;
nsresult rv = NS_OK;
nsIFrame* kidFrame;
if (nsnull==aStartFrame)
kidFrame = mFirstChild;
else
kidFrame = aStartFrame;
for ( ; nsnull != kidFrame; )
{
nsSize kidAvailSize(aReflowState.availSize);
if (0>=kidAvailSize.height)
kidAvailSize.height = 1; // XXX: HaCk - we don't handle negative heights yet
nsHTMLReflowMetrics desiredSize(pKidMaxElementSize);
desiredSize.width=desiredSize.height=desiredSize.ascent=desiredSize.descent=0;
nsReflowStatus status;
// Get top margin for this kid
nsIContentPtr kid;
kidFrame->GetContent(kid.AssignRef());
nsIStyleContextPtr kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
const nsStyleSpacing* kidSpacing = (const nsStyleSpacing*)
kidSC->GetStyleData(eStyleStruct_Spacing);
const nsStyleSpacing* kidSpacing;
kidFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)kidSpacing);
nsMargin kidMargin;
kidSpacing->CalcMarginFor(this, kidMargin);
nscoord topMargin = GetTopMarginFor(aPresContext, aState, kidMargin);
nscoord topMargin = GetTopMarginFor(&aPresContext, aReflowState, kidMargin);
nscoord bottomMargin = kidMargin.bottom;
// Figure out the amount of available size for the child (subtract
// off the top margin we are going to apply to it)
if (PR_FALSE == aState.unconstrainedHeight) {
if (PR_FALSE == aReflowState.unconstrainedHeight) {
kidAvailSize.height -= topMargin;
}
// Subtract off for left and right margin
if (PR_FALSE == aState.unconstrainedWidth) {
if (PR_FALSE == aReflowState.unconstrainedWidth) {
kidAvailSize.width -= kidMargin.left + kidMargin.right;
}
// Reflow the child into the available space
nsHTMLReflowState kidReflowState(*aPresContext, kidFrame,
aState.reflowState, kidAvailSize);
nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState.reflowState,
kidAvailSize, aReason);
if (gsDebug) printf("%p RG reflowing child %d (frame=%p) with avail width = %d\n",
this, debugCounter, kidFrame, kidAvailSize.width);
ReflowChild(kidFrame, *aPresContext, desiredSize, kidReflowState, status);
if (gsDebug) printf("%p RG child %d (frame=%p) returned desired width = %d\n",
this, debugCounter, kidFrame, desiredSize.width);
if ((PR_TRUE==gsDebug) || (PR_TRUE==gsDebugIR))
printf("%p RG reflowing child %p with avail width = %d, reason = %d\n",
this, kidFrame, kidAvailSize.width, aReason);
rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus);
if (gsDebug) printf("%p RG child %p returned desired width = %d\n",
this, kidFrame, desiredSize.width);
// Did the child fit?
if ((kidFrame != mFirstChild) &&
@ -321,18 +324,17 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
// Note that if the width is too big that's okay and we allow the
// child to extend horizontally outside of the reflow area
PushChildren(kidFrame, prevKidFrame);
result = PR_FALSE;
break;
}
// Place the child after taking into account it's margin
nsRect kidRect (kidMargin.left, aState.y, desiredSize.width, desiredSize.height);
PlaceChild(aPresContext, aState, kidFrame, kidRect, aMaxElementSize,
nsRect kidRect (kidMargin.left, aReflowState.y, desiredSize.width, desiredSize.height);
PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize,
kidMaxElementSize);
if (bottomMargin < 0) {
aState.prevMaxNegBottomMargin = -bottomMargin;
aReflowState.prevMaxNegBottomMargin = -bottomMargin;
} else {
aState.prevMaxPosBottomMargin = bottomMargin;
aReflowState.prevMaxPosBottomMargin = bottomMargin;
}
// Remember where we just were in case we end up pushing children
@ -344,7 +346,7 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
* otherwise PushChildren and bail.
*/
// Special handling for incomplete children
if (NS_FRAME_IS_NOT_COMPLETE(status)) {
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
// XXX It's good to assume that we might still have room
// even if the child didn't complete (floaters will want this)
nsIFrame* kidNextInFlow;
@ -355,8 +357,8 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
// create a continuing frame. This hooks the child into the flow.
nsIFrame* continuingFrame;
nsIStyleContext* kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC);
kidFrame->CreateContinuingFrame(*aPresContext, this, kidSC,
kidFrame->GetStyleContext(&aPresContext, kidSC);
kidFrame->CreateContinuingFrame(aPresContext, this, kidSC,
continuingFrame);
NS_RELEASE(kidSC);
@ -375,47 +377,47 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
if (nsnull != nextSibling) {
PushChildren(nextSibling, kidFrame);
}
result = PR_FALSE;
break;
}
// Add back in the left and right margins, because one row does not
// impact another row's width
if (PR_FALSE == aState.unconstrainedWidth) {
if (PR_FALSE == aReflowState.unconstrainedWidth) {
kidAvailSize.width += kidMargin.left + kidMargin.right;
}
if (PR_FALSE==aDoSiblings)
break;
// Get the next child
kidFrame->GetNextSibling(kidFrame);
debugCounter++;
}
// Update the child count
return result;
return rv;
}
/**
* Try and pull-up frames from our next-in-flow
*
* @param aPresContext presentation context to use
* @param aState current inline state
* @param aReflowState current inline state
* @return true if we successfully pulled-up all the children and false
* otherwise, e.g. child didn't fit
*/
PRBool nsTableRowGroupFrame::PullUpChildren(nsIPresContext* aPresContext,
RowGroupReflowState& aState,
nsSize* aMaxElementSize)
NS_METHOD nsTableRowGroupFrame::PullUpChildren(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsTableRowGroupFrame* nextInFlow = (nsTableRowGroupFrame*)mNextInFlow;
nsSize kidMaxElementSize;
nsSize* pKidMaxElementSize = (nsnull != aMaxElementSize) ? &kidMaxElementSize : nsnull;
nsSize* pKidMaxElementSize = (nsnull != aDesiredSize.maxElementSize) ? &kidMaxElementSize : nsnull;
nsIFrame* prevKidFrame = LastFrame(mFirstChild);
PRBool result = PR_TRUE;
nsresult rv = NS_OK;
while (nsnull != nextInFlow) {
nsHTMLReflowMetrics kidSize(pKidMaxElementSize);
kidSize.width=kidSize.height=kidSize.ascent=kidSize.descent=0;
nsReflowStatus status;
// Get the next child
nsIFrame* kidFrame = nextInFlow->mFirstChild;
@ -444,31 +446,30 @@ PRBool nsTableRowGroupFrame::PullUpChildren(nsIPresContext* aPresContext,
kidFrame->GetSize(kidFrameSize);
kidFrame->IsSplittable(kidIsSplittable);
if ((kidFrameSize.height > aState.availSize.height) &&
if ((kidFrameSize.height > aReflowState.availSize.height) &&
NS_FRAME_IS_NOT_SPLITTABLE(kidIsSplittable)) {
result = PR_FALSE;
break;
}
nsHTMLReflowState kidReflowState(*aPresContext, kidFrame,
aState.reflowState, aState.availSize,
nsHTMLReflowState kidReflowState(aPresContext, kidFrame,
aReflowState.reflowState, aReflowState.availSize,
eReflowReason_Resize);
ReflowChild(kidFrame, *aPresContext, kidSize, kidReflowState, status);
rv = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus);
// Did the child fit?
if ((kidSize.height > aState.availSize.height) && (nsnull != mFirstChild)) {
if ((kidSize.height > aReflowState.availSize.height) && (nsnull != mFirstChild)) {
// The child is too wide to fit in the available space, and it's
// not our first child
result = PR_FALSE;
//result = PR_FALSE;
break;
}
// Place the child
//aState.y += topMargin;
//aReflowState.y += topMargin;
nsRect kidRect (0, 0, kidSize.width, kidSize.height);
//kidRect.x += kidMol->margin.left;
kidRect.y += aState.y;
PlaceChild(aPresContext, aState, kidFrame, kidRect, aMaxElementSize, *pKidMaxElementSize);
kidRect.y += aReflowState.y;
PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize, *pKidMaxElementSize);
// Remove the frame from its current parent
kidFrame->GetNextSibling(nextInFlow->mFirstChild);
@ -492,7 +493,7 @@ PRBool nsTableRowGroupFrame::PullUpChildren(nsIPresContext* aPresContext,
prevKidFrame = kidFrame;
// Is the child we just pulled up complete?
if (NS_FRAME_IS_NOT_COMPLETE(status)) {
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
// No the child isn't complete
nsIFrame* kidNextInFlow;
@ -503,8 +504,8 @@ PRBool nsTableRowGroupFrame::PullUpChildren(nsIPresContext* aPresContext,
// prepares it for reflow.
nsIFrame* continuingFrame;
nsIStyleContext* kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC);
kidFrame->CreateContinuingFrame(*aPresContext, this, kidSC,
kidFrame->GetStyleContext(&aPresContext, kidSC);
kidFrame->CreateContinuingFrame(aPresContext, this, kidSC,
continuingFrame);
NS_RELEASE(kidSC);
NS_ASSERTION(nsnull != continuingFrame, "frame creation failed");
@ -521,12 +522,12 @@ PRBool nsTableRowGroupFrame::PullUpChildren(nsIPresContext* aPresContext,
// If the child isn't complete then it means that we've used up
// all of our available space.
result = PR_FALSE;
//result = PR_FALSE;
break;
}
}
return result;
return rv;
}
/**
@ -691,10 +692,11 @@ void nsTableRowGroupFrame::ShrinkWrapChildren(nsIPresContext* aPresContext,
}
nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aPresContext,
RowGroupReflowState& aState,
RowGroupReflowState& aReflowState,
nsIFrame* aKidFrame,
nscoord aDeltaY)
{
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: AdjustSiblingsAfterReflow\n");
nsIFrame* lastKidFrame = aKidFrame;
if (aDeltaY != 0) {
@ -731,7 +733,7 @@ nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext& aP
// Update our running y-offset to reflect the bottommost child
nsRect rect;
lastKidFrame->GetRect(rect);
aState.y = rect.YMost();
aReflowState.y = rect.YMost();
return NS_OK;
}
@ -771,24 +773,18 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext,
// Reflow the existing frames
if (nsnull != mFirstChild) {
reflowMappedOK = ReflowMappedChildren(&aPresContext, state, aDesiredSize.maxElementSize);
if (PR_FALSE == reflowMappedOK) {
aStatus = NS_FRAME_NOT_COMPLETE;
}
rv = ReflowMappedChildren(aPresContext, aDesiredSize, state, aStatus,
nsnull, aReflowState.reason, PR_TRUE);
}
// Did we successfully reflow our mapped children?
if (PR_TRUE == reflowMappedOK) {
if (NS_FRAME_COMPLETE==aStatus) {
// Any space left?
PRInt32 numKids;
mContent->ChildCount(numKids);
if (state.availSize.height > 0) {
// Try and pull-up some children from a next-in-flow
if (!PullUpChildren(&aPresContext, state, aDesiredSize.maxElementSize)) {
// We were unable to pull-up all the existing frames from the
// next in flow
aStatus = NS_FRAME_NOT_COMPLETE;
}
rv = PullUpChildren(aPresContext, aDesiredSize, state, aStatus);
}
}
@ -803,8 +799,6 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext,
}
// Return our desired rect
//NS_ASSERTION(0<state.firstRowHeight, "illegal firstRowHeight after reflow");
//NS_ASSERTION(0<state.y, "illegal height after reflow");
aDesiredSize.width = aReflowState.maxSize.width;
aDesiredSize.height = state.y;
@ -824,9 +818,7 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext,
this, NS_FRAME_IS_COMPLETE(aStatus)?"Complete":"Not Complete",
aDesiredSize.width, aDesiredSize.height);
}
return rv;
}
@ -874,14 +866,14 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
aReflowState.reflowState.reflowCommand->GetChildFrame(objectFrame);
const nsStyleDisplay *childDisplay;
objectFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
if (PR_TRUE==gsDebugIR) printf("TRGF IR: IncrementalReflow_TargetIsMe with type=%d\n", type);
if (PR_TRUE==gsDebugIR) printf("TRGF IR: TargetIsMe with type=%d\n", type);
switch (type)
{
case nsIReflowCommand::FrameInserted :
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
rv = IR_RowInserted(aPresContext, aDesiredSize, aReflowState, aStatus,
objectFrame, PR_FALSE);
(nsTableRowFrame *)objectFrame, PR_FALSE);
}
else
{
@ -893,7 +885,8 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
case nsIReflowCommand::FrameAppended :
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
rv = IR_RowAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame);
rv = IR_RowAppended(aPresContext, aDesiredSize, aReflowState, aStatus,
(nsTableRowFrame *)objectFrame);
}
else
{ // no optimization to be done for Unknown frame types, so just reuse the Inserted method
@ -911,7 +904,7 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
rv = IR_RowRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
objectFrame);
(nsTableRowFrame *)objectFrame);
}
else
{
@ -948,16 +941,35 @@ NS_METHOD nsTableRowGroupFrame::IR_RowInserted(nsIPresContext& aPresContext
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aInsertedFrame,
nsTableRowFrame * aInsertedFrame,
PRBool aReplace)
{
nsresult rv=NS_OK;
// inserting the rowgroup only effects reflow if the rowgroup includes at least one row
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_RowInserted\n");
nsresult rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState,
aStatus, (nsIFrame*)aInsertedFrame, aReplace);
if (NS_FAILED(rv))
return rv;
// do a pass-1 layout of all the cells in the inserted row
//XXX: check the table frame to see if we can skip this
rv = ReflowMappedChildren(aPresContext, aDesiredSize, aReflowState, aStatus,
aInsertedFrame, eReflowReason_Initial, PR_FALSE);
if (NS_FAILED(rv))
return rv;
nsTableFrame *tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (NS_FAILED(rv) || nsnull==tableFrame)
return rv;
tableFrame->InvalidateCellMap();
tableFrame->InvalidateColumnCache();
return rv;
}
NS_METHOD nsTableRowGroupFrame::IR_DidAppendRow(nsTableRowFrame *aRowFrame)
NS_METHOD nsTableRowGroupFrame::DidAppendRow(nsTableRowFrame *aRowFrame)
{
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: DidAppendRow\n");
nsresult rv=NS_OK;
/* need to make space in the cell map. Remeber that row spans can't cross row groups
once the space is made, tell the row to initizalize its children.
@ -969,56 +981,97 @@ NS_METHOD nsTableRowGroupFrame::IR_DidAppendRow(nsTableRowFrame *aRowFrame)
return rv;
}
// support method that tells us if there are any rows in the table after our rows
// returns PR_TRUE if there are no rows after ours
PRBool nsTableRowGroupFrame::NoRowsFollow()
{
PRBool result = PR_TRUE;
nsIFrame *nextSib=nsnull;
GetNextSibling(nextSib);
while (nsnull!=nextSib)
{
const nsStyleDisplay *sibDisplay;
nextSib->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)sibDisplay));
if ((NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == sibDisplay->mDisplay) ||
(NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == sibDisplay->mDisplay) ||
(NS_STYLE_DISPLAY_TABLE_ROW_GROUP == sibDisplay->mDisplay))
{
nsIFrame *childFrame=nsnull;
nextSib->FirstChild(childFrame);
while (nsnull!=childFrame)
{
const nsStyleDisplay *childDisplay;
childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{ // found a row
result = PR_FALSE;
break;
}
}
}
nextSib->GetNextSibling(nextSib);
}
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: NoRowsFollow returning %d\n", result);
return result;
}
// since we know we're doing an append here, we can optimize
NS_METHOD nsTableRowGroupFrame::IR_RowAppended(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aAppendedFrame)
nsTableRowFrame * aAppendedFrame)
{
nsresult rv=NS_OK;
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_RowAppended\n");
// hook aAppendedFrame into the child list
nsIFrame *lastChild = mFirstChild;
nsIFrame *nextChild = lastChild;
nsIFrame *lastRow = nsnull;
while (nsnull!=nextChild)
{
// remember the last child that is really a row
const nsStyleDisplay *childDisplay;
nextChild->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
lastRow = nextChild;
lastChild = nextChild;
nextChild->GetNextSibling(nextChild);
}
if (nsnull==lastChild)
mFirstChild = aAppendedFrame;
else
lastChild->SetNextSibling(aAppendedFrame);
nsTableFrame *tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (NS_FAILED(rv) || nsnull==tableFrame)
nsresult rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState,
aStatus, (nsIFrame*)aAppendedFrame, PR_FALSE);
if (NS_FAILED(rv))
return rv;
tableFrame->InvalidateFirstPassCache();
// the table will see that it's cached info is bogus and rebuild the cell map,
// and do a reflow
#if 0
// find the row index of the new row
PRInt32 newRowIndex=-1;
if (nsnull!=
/* we have 2 paths to choose from. If we know that aAppendedFrame is
* the last row in the table, we can optimize. Otherwise, we have to
* treat it like an insert
*/
if (PR_TRUE==NoRowsFollow())
{ // aAppendedRow is the last row, so do the optimized route
// account for the cells in the row aAppendedFrame
// this will add the content of the rowgroup to the cell map
rv = DidAppendRow(aAppendedFrame);
if (NS_FAILED(rv))
return rv;
lastChild=mFirstChild;
nextChild=lastChild;
while (nsnull!=nextChild)
{
// do a pass1 reflow of the new row
//XXX: check the table frame to see if we can skip this
rv = ReflowMappedChildren(aPresContext, aDesiredSize, aReflowState, aStatus,
aAppendedFrame, eReflowReason_Initial, PR_FALSE);
if (NS_FAILED(rv))
return rv;
// if any column widths have to change due to this, rebalance column widths
//XXX need to calculate this, but for now just do it
nsTableFrame *tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (NS_FAILED(rv) || nsnull==tableFrame)
return rv;
tableFrame->InvalidateColumnWidths();
}
// account for the cells in aAppendedFrame
nsresult rv = DidAppendRow((nsTableRowFrame*)aAppendedFrame, newRowIndex);
else
{
// do a pass1 reflow of the new row
//XXX: check the table frame to see if we can skip this
rv = ReflowMappedChildren(aPresContext, aDesiredSize, aReflowState, aStatus,
aAppendedFrame, eReflowReason_Initial, PR_FALSE);
if (NS_FAILED(rv))
return rv;
// need to increment the row index of all subsequent rows
#endif
nsTableFrame *tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (NS_FAILED(rv) || nsnull==tableFrame)
return rv;
tableFrame->InvalidateCellMap();
tableFrame->InvalidateColumnCache();
}
return rv;
}
@ -1027,9 +1080,25 @@ NS_METHOD nsTableRowGroupFrame::IR_RowRemoved(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aDeletedFrame)
nsTableRowFrame * aDeletedFrame)
{
nsresult rv;
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_RowRemoved\n");
nsresult rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
aDeletedFrame);
if (NS_SUCCEEDED(rv))
{
nsTableFrame *tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (NS_FAILED(rv) || nsnull==tableFrame)
return rv;
tableFrame->InvalidateCellMap();
tableFrame->InvalidateColumnCache();
// if any column widths have to change due to this, rebalance column widths
//XXX need to calculate this, but for now just do it
tableFrame->InvalidateColumnWidths();
}
return rv;
}
@ -1041,6 +1110,7 @@ NS_METHOD nsTableRowGroupFrame::IR_UnknownFrameInserted(nsIPresContext& aPr
nsIFrame * aInsertedFrame,
PRBool aReplace)
{
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_UnknownFrameInserted\n");
nsIReflowCommand::ReflowType type;
aReflowState.reflowState.reflowCommand->GetType(type);
// we have a generic frame that gets inserted but doesn't effect reflow
@ -1075,9 +1145,7 @@ NS_METHOD nsTableRowGroupFrame::IR_UnknownFrameInserted(nsIPresContext& aPr
}
else
{
nsIFrame *nextSibling=nsnull;
if (nsnull!=mFirstChild)
mFirstChild->GetNextSibling(nextSibling);
nsIFrame *nextSibling=mFirstChild;
mFirstChild = aInsertedFrame;
aInsertedFrame->SetNextSibling(nextSibling);
}
@ -1091,6 +1159,7 @@ NS_METHOD nsTableRowGroupFrame::IR_UnknownFrameRemoved(nsIPresContext& aPre
nsReflowStatus& aStatus,
nsIFrame * aRemovedFrame)
{
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_UnknownFrameRemoved\n");
// we have a generic frame that gets removed but doesn't effect reflow
// unhook it then ignore it
if (PR_TRUE==gsDebugIR) printf("TRGF IR: FrameRemoved removing unknown frame type.\n");

View File

@ -107,22 +107,20 @@ public:
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aInsertedFrame,
nsTableRowFrame * aInsertedFrame,
PRBool aReplace);
NS_IMETHOD IR_RowAppended(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aAppendedFrame);
NS_IMETHOD IR_DidAppendRow(nsTableRowFrame *aRowFrame);
nsTableRowFrame * aAppendedFrame);
NS_IMETHOD IR_RowRemoved(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aDeletedFrame);
nsTableRowFrame * aDeletedFrame);
NS_IMETHOD IR_UnknownFrameInserted(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
@ -138,6 +136,9 @@ public:
nsIFrame * aDeletedFrame);
NS_IMETHOD DidAppendRow(nsTableRowFrame *aRowFrame);
PRBool NoRowsFollow();
/** @see nsContainerFrame::CreateContinuingFrame */
NS_IMETHOD CreateContinuingFrame(nsIPresContext& aPresContext,
@ -174,7 +175,7 @@ protected:
RowGroupReflowState& aReflowState,
const nsMargin& aKidMargin);
void PlaceChild( nsIPresContext* aPresContext,
void PlaceChild( nsIPresContext& aPresContext,
RowGroupReflowState& aReflowState,
nsIFrame* aKidFrame,
const nsRect& aKidRect,
@ -197,9 +198,13 @@ protected:
* @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,
NS_METHOD ReflowMappedChildren(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsSize* aMaxElementSize);
nsReflowStatus& aStatus,
nsTableRowFrame * aStartFrame,
nsReflowReason aReason,
PRBool aDoSiblings);
/**
* Try and pull-up frames from our next-in-flow
@ -209,9 +214,10 @@ protected:
* @return true if we successfully pulled-up all the children and false
* otherwise, e.g. child didn't fit
*/
PRBool PullUpChildren(nsIPresContext* aPresContext,
NS_METHOD PullUpChildren(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsSize* aMaxElementSize);
nsReflowStatus& aStatus);
private:
nsIAtom *mType;