diff --git a/layout/html/table/src/nsTableColGroupFrame.cpp b/layout/html/table/src/nsTableColGroupFrame.cpp index ffd056193bdd..454d90839d2d 100644 --- a/layout/html/table/src/nsTableColGroupFrame.cpp +++ b/layout/html/table/src/nsTableColGroupFrame.cpp @@ -316,6 +316,32 @@ int nsTableColGroupFrame::GetColumnCount () return mColCount; } +nsTableColFrame * nsTableColGroupFrame::GetFirstColumn() +{ + return GetNextColumn(nsnull); +} + +nsTableColFrame * nsTableColGroupFrame::GetNextColumn(nsIFrame *aChildFrame) +{ + nsTableColFrame *result = nsnull; + nsIFrame *childFrame = aChildFrame; + if (nsnull==childFrame) + childFrame = mFirstChild; + while (nsnull!=childFrame) + { + const nsStyleDisplay *childDisplay; + childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay)); + if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay) + { + result = (nsTableColFrame *)childFrame; + break; + } + childFrame->GetNextSibling(childFrame); + } + return result; +} + + nsTableColFrame * nsTableColGroupFrame::GetColumnAt (PRInt32 aColIndex) { nsTableColFrame *result = nsnull; @@ -349,6 +375,34 @@ PRInt32 nsTableColGroupFrame::GetSpan() return span; } +/* this may be needed when IsSynthetic is properly implemented +PRBool nsTableColGroupFrame::IsManufactured() +{ + PRBool result = PR_FALSE; + nsIFrame *firstCol = GetFirstColumn(); + if (nsTableFrame::IsSynthetic(this) && + ((nsnull==firstCol) || nsTableFrame::IsSynthetic(firstCol))) + result = PR_TRUE; + return result; +} +*/ + +/** returns colcount because it is frequently used in the context of + * shuffling relative colgroup order, and it's convenient to not have to + * call GetColumnCount redundantly. + */ +PRInt32 nsTableColGroupFrame::SetStartColumnIndex (int aIndex) +{ + PRInt32 result = mColCount; + if (aIndex != mStartColIndex) + { + mStartColIndex = aIndex; + mColCount=0; + result = GetColumnCount(); // has the side effect of setting each column index based on new start index + } + return result; +} + /* ----- global methods ----- */ nsresult diff --git a/layout/html/table/src/nsTableColGroupFrame.h b/layout/html/table/src/nsTableColGroupFrame.h index b8f0936703e3..7ee4e26d830b 100644 --- a/layout/html/table/src/nsTableColGroupFrame.h +++ b/layout/html/table/src/nsTableColGroupFrame.h @@ -66,18 +66,31 @@ public: * if there are col children, count them (taking into account the span of each) * else, check my own span attribute. */ - virtual PRInt32 GetColumnCount (); + virtual PRInt32 GetColumnCount(); - virtual nsTableColFrame * GetColumnAt (PRInt32 aColIndex); + virtual nsTableColFrame * GetFirstColumn(); - virtual PRInt32 GetStartColumnIndex (); + virtual nsTableColFrame * GetNextColumn(nsIFrame *aChildFrame); + + virtual nsTableColFrame * GetColumnAt(PRInt32 aColIndex); + + virtual PRInt32 GetStartColumnIndex(); - virtual void SetStartColumnIndex (PRInt32 aIndex); + /** sets mStartColIndex to aIndex. + * @return the col count + * has the side effect of setting all child COL indexes + */ + virtual PRInt32 SetStartColumnIndex(PRInt32 aIndex); /** helper method to get the span attribute for this colgroup */ PRInt32 GetSpan(); - NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0, nsIListFilter *aFilter = nsnull) const; + /** helper method returns PR_TRUE if this colgroup exists without any + * colgroup or col content in the table backing it. + */ + //PRBool IsManufactured(); + + NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0, nsIListFilter *aFilter = nsnull) const; protected: @@ -104,11 +117,4 @@ protected: inline int nsTableColGroupFrame::GetStartColumnIndex () { return mStartColIndex;} -inline void nsTableColGroupFrame::SetStartColumnIndex (int aIndex) -{ - if (aIndex != mStartColIndex) - mColCount = 0; // our index is being changed, trigger reset of col indicies, don't propogate back to table - mStartColIndex = aIndex; -} - #endif diff --git a/layout/html/table/src/nsTableFrame.cpp b/layout/html/table/src/nsTableFrame.cpp index 64e775c30a16..3c14a479f3b5 100644 --- a/layout/html/table/src/nsTableFrame.cpp +++ b/layout/html/table/src/nsTableFrame.cpp @@ -47,9 +47,6 @@ static PRBool gsDebug = PR_FALSE; static PRBool gsDebugCLD = PR_FALSE; static PRBool gsDebugNT = PR_FALSE; static PRBool gsDebugIR = PR_FALSE; -//#define NOISY -//#define NOISY_FLOW -//#ifdef NOISY_STYLE #else static const PRBool gsDebug = PR_FALSE; static const PRBool gsDebugCLD = PR_FALSE; @@ -197,35 +194,39 @@ ColumnInfoCache::~ColumnInfoCache() void ColumnInfoCache::AddColumnInfo(const nsStyleUnit aType, PRInt32 aColumnIndex) { - switch (aType) + // a table may have more COLs than actual columns, so we guard against that here + if (aColumnIndexInitialize(aDesiredSize.maxElementSize); } BuildColumnCache(aPresContext, aDesiredSize, aReflowState, aStatus); @@ -1882,12 +1886,12 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext& aPresContext, if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay) { rv = IR_ColGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus, - objectFrame, PR_FALSE); + (nsTableColGroupFrame*)objectFrame, PR_FALSE); } else if (IsRowGroup(childDisplay->mDisplay)) { rv = IR_RowGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus, - objectFrame, PR_FALSE); + (nsTableRowGroupFrame*)objectFrame, PR_FALSE); } else { @@ -1899,11 +1903,13 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext& aPresContext, case nsIReflowCommand::FrameAppended : if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay) { - rv = IR_ColGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame); + rv = IR_ColGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus, + (nsTableColGroupFrame*)objectFrame); } else if (IsRowGroup(childDisplay->mDisplay)) { - rv = IR_RowGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame); + rv = IR_RowGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus, + (nsTableRowGroupFrame*)objectFrame); } else { // no optimization to be done for Unknown frame types, so just reuse the Inserted method @@ -1921,18 +1927,18 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext& aPresContext, if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay) { rv = IR_ColGroupRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, - objectFrame); + (nsTableColGroupFrame*)objectFrame); } else if (IsRowGroup(childDisplay->mDisplay)) { rv = IR_RowGroupRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, - objectFrame); + (nsTableRowGroupFrame*)objectFrame); } else { rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, - objectFrame); + objectFrame); } break; @@ -1964,38 +1970,75 @@ NS_METHOD nsTableFrame::IR_ColGroupInserted(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aInsertedFrame, + nsTableColGroupFrame * aInsertedFrame, PRBool aReplace) { - nsresult rv; - /* - find where to place colgroup (skipping implicit children?) - for every col in the colgroup (including implicit cols due to span attribute) - an implicit col from the first implicit colgroup is removed - when an implicit colgroups col count goes to 0, it is removed - */ - /* need to really verify that issynthetic is specified on implicit colgroups and cols */ + nsresult rv=NS_OK; + PRBool adjustStartingColIndex=PR_FALSE; + PRInt32 startingColIndex=0; + // find out what frame to insert aInsertedFrame after + nsIFrame *frameToInsertAfter=nsnull; + rv = aReflowState.reflowState.reflowCommand->GetPrevSiblingFrame(frameToInsertAfter); + // insert aInsertedFrame as the first child. Set its start col index to 0 + if (nsnull==frameToInsertAfter) + { + aInsertedFrame->SetNextSibling(mFirstChild); + mFirstChild=aInsertedFrame; + startingColIndex += aInsertedFrame->SetStartColumnIndex(0); + adjustStartingColIndex=PR_TRUE; + } + nsIFrame *childFrame=mFirstChild; + nsIFrame *prevSib=nsnull; + while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame)) + { + if ((nsnull!=frameToInsertAfter) && (childFrame==frameToInsertAfter)) + { + nsIFrame *nextSib=nsnull; + frameToInsertAfter->GetNextSibling(nextSib); + aInsertedFrame->SetNextSibling(nextSib); + frameToInsertAfter->SetNextSibling(aInsertedFrame); + // account for childFrame being a COLGROUP now + const nsStyleDisplay *display; + childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display); + if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) + { + if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet + startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount(); + } + // skip ahead to aInsertedFrame, since we just handled the frame we inserted after + childFrame=aInsertedFrame; + adjustStartingColIndex=PR_TRUE; // now that we've inserted aInsertedFrame, + // start adjusting subsequent col groups' starting col index including aInsertedFrame + } + const nsStyleDisplay *display; + childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display); + if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) + { + if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet + startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount(); + else // we've removed aDeletedFrame, now adjust the starting col index of all subsequent col groups + startingColIndex += ((nsTableColGroupFrame *)childFrame)->SetStartColumnIndex(startingColIndex); + } + prevSib=childFrame; + rv = childFrame->GetNextSibling(childFrame); + } + + InvalidateColumnCache(); + //XXX: what we want to do here is determine if the new COL information changes anything about layout + // if not, skip invalidating the first passs + // if so, and we can fix the first pass info return rv; + } NS_METHOD nsTableFrame::IR_ColGroupAppended(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aAppendedFrame) + nsTableColGroupFrame * aAppendedFrame) { nsresult rv=NS_OK; - /* - find where to place colgroup (skipping implicit children?) - for every col in the colgroup (including implicit cols due to span attribute) - an implicit col from the first implicit colgroup is removed - when an implicit colgroups col count goes to 0, it is removed - */ - /* need to really verify that issynthetic is specified on implicit colgroups and cols */ - - - // build a vector of colgroups. XXX might want to do this as a class thing, so we don't have to rebuild it each time - nsVoidArray colGroupList; + PRInt32 startingColIndex=0; nsIFrame *childFrame=mFirstChild; nsIFrame *lastChild=mFirstChild; while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame)) @@ -2004,7 +2047,7 @@ NS_METHOD nsTableFrame::IR_ColGroupAppended(nsIPresContext& aPresContext, childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display); if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) { - colGroupList.AppendElement((void*)childFrame); + startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount(); } lastChild=childFrame; rv = childFrame->GetNextSibling(childFrame); @@ -2015,36 +2058,54 @@ NS_METHOD nsTableFrame::IR_ColGroupAppended(nsIPresContext& aPresContext, else mFirstChild = aAppendedFrame; - /* go through the list of colgroups, sucking out implicit columns that are not the result of a span attribute - * and replacing them with columns in aAppendedFrame - * if the column had an attribute from a cell, be sure to preserve that - * if any implicit colgroup becomes empty, destroy it - * if any real colgroup becomes empty, we have to keep it - * factor the new cols into the column cache - * this means having a flag that says whether the col cache needs to be rebuilt or not - */ - PRInt32 colGroupCount = colGroupList.Count(); + aAppendedFrame->SetStartColumnIndex(startingColIndex); + +#if 0 + +we would only want to do this if manufactured col groups were invisible to the DOM. Since they +currently are visible, they should behave just as if they were content-backed "real" colgroups +If this decision is changed, the code below is a half-finished attempt to rationalize the situation. +It requires having built a list of the colGroups before we get to this point. + + // look at the last col group. If it is implicit, and it's cols are implicit, then + // it and its cols were manufactured for table layout. + // Delete it if possible, otherwise move it to the end of the list + if (0FirstChild(childFrame); - while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame)) - { - const nsStyleDisplay *colDisplay; - childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)colDisplay); - if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay) - { // find an implicit column that is not from a span attribute if there is one and remove it - for (PRInt32 colGroupIndex=0; colGroupIndexIsManufactured()) + { // account for the new COLs that were added in aAppendedFrame + // first, try to delete the implicit colgroup + + // if we couldn't delete it, move the implicit colgroup to the end of the list + // and adjust it's col indexes + nsIFrame *colGroupNextSib; + colGroup->GetNextSibling(colGroupNextSib); + childFrame=mFirstChild; + nsIFrame * prevSib=nsnull; + rv = NS_OK; + while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame)) + { + if (childFrame==colGroup) { - nsTableColGroupFrame *colGroup = (nsTableColGroupFrame *)(colGroupList.ElementAt(colGroupIndex)); - // XXX: here's where we yank colGroups if necessary + if (nsnull!=prevSib) // colGroup is in the middle of the list, remove it + prevSib->SetNextSibling(colGroupNextSib); + else // colGroup was the first child, so set it's next sib to first child + mFirstChild = colGroupNextSib; + aAppendedFrame->SetNextSibling(colGroup); // place colGroup at the end of the list + colGroup->SetNextSibling(nsnull); + break; } + prevSib=childFrame; + rv = childFrame->GetNextSibling(childFrame); } } } +#endif - //InvalidateFirstPassCache(); // for now, redo the first pass reflow - // could probably just get away with mTableLayoutStrategy->Initialize(aMaxElementSize); - mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize); + + InvalidateColumnCache(); //XXX: what we want to do here is determine if the new COL information changes anything about layout // if not, skip invalidating the first passs // if so, and we can fix the first pass info @@ -2056,14 +2117,45 @@ NS_METHOD nsTableFrame::IR_ColGroupRemoved(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aDeletedFrame) + nsTableColGroupFrame * aDeletedFrame) { - nsresult rv; - /* - for every col in the colgroup (including implicit cols due to span attribute) - an implicit col is created in the last implicit colgroup - if there is no implicit colgroup, one is created at the end of the colgroup list - */ + nsresult rv=NS_OK; + PRBool adjustStartingColIndex=PR_FALSE; + PRInt32 startingColIndex=0; + nsIFrame *childFrame=mFirstChild; + nsIFrame *prevSib=nsnull; + while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame)) + { + if (childFrame==aDeletedFrame) + { + nsIFrame *deleteFrameNextSib=nsnull; + aDeletedFrame->GetNextSibling(deleteFrameNextSib); + if (nsnull!=prevSib) + prevSib->SetNextSibling(deleteFrameNextSib); + else + mFirstChild = deleteFrameNextSib; + childFrame=deleteFrameNextSib; + if (nsnull==childFrame) + break; + adjustStartingColIndex=PR_TRUE; // now that we've removed aDeletedFrame, start adjusting subsequent col groups' starting col index + } + const nsStyleDisplay *display; + childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display); + if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) + { + if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet + startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount(); + else // we've removed aDeletedFrame, now adjust the starting col index of all subsequent col groups + startingColIndex += ((nsTableColGroupFrame *)childFrame)->SetStartColumnIndex(startingColIndex); + } + prevSib=childFrame; + rv = childFrame->GetNextSibling(childFrame); + } + + InvalidateColumnCache(); + //XXX: what we want to do here is determine if the new COL information changes anything about layout + // if not, skip invalidating the first passs + // if so, and we can fix the first pass info return rv; } @@ -2071,7 +2163,7 @@ NS_METHOD nsTableFrame::IR_RowGroupInserted(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aInsertedFrame, + nsTableRowGroupFrame * aInsertedFrame, PRBool aReplace) { nsresult rv; @@ -2084,7 +2176,7 @@ NS_METHOD nsTableFrame::IR_RowGroupAppended(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aAppendedFrame) + nsTableRowGroupFrame * aAppendedFrame) { // hook aAppendedFrame into the child list nsIFrame *lastChild = mFirstChild; @@ -2115,7 +2207,7 @@ NS_METHOD nsTableFrame::IR_RowGroupRemoved(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aDeletedFrame) + nsTableRowGroupFrame * aDeletedFrame) { nsresult rv; return rv; @@ -2940,6 +3032,7 @@ 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); @@ -3028,6 +3121,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext& aPresContext, } childFrame->GetNextSibling(childFrame); } + mColumnCacheValid=PR_TRUE; } PRBool nsTableFrame::IsFirstPassValid() const @@ -3044,6 +3138,20 @@ void nsTableFrame::InvalidateFirstPassCache() firstInFlow->mFirstPassValid=PR_FALSE; } +PRBool nsTableFrame::IsColumnCacheValid() const +{ + nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow(); + NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow"); + return firstInFlow->mColumnCacheValid; +} + +void nsTableFrame::InvalidateColumnCache() +{ + nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow(); + NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow"); + firstInFlow->mColumnCacheValid=PR_FALSE; +} + PRBool nsTableFrame::IsCellMapValid() const { nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow(); diff --git a/layout/html/table/src/nsTableFrame.h b/layout/html/table/src/nsTableFrame.h index cd8cbc57e5d4..05aacc6df15a 100644 --- a/layout/html/table/src/nsTableFrame.h +++ b/layout/html/table/src/nsTableFrame.h @@ -29,6 +29,7 @@ class nsTableCellFrame; class nsTableColFrame; class nsTableRowGroupFrame; class nsTableRowFrame; +class nsTableColGroupFrame; class nsITableLayoutStrategy; class nsHTMLValue; class ColumnInfoCache; @@ -317,39 +318,39 @@ protected: nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aInsertedFrame, + nsTableColGroupFrame * aInsertedFrame, PRBool aReplace); - NS_IMETHOD IR_ColGroupAppended(nsIPresContext& aPresContext, + NS_IMETHOD IR_ColGroupAppended(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aAppendedFrame); + nsTableColGroupFrame * aAppendedFrame); NS_IMETHOD IR_ColGroupRemoved(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aDeletedFrame); + nsTableColGroupFrame * aDeletedFrame); NS_IMETHOD IR_RowGroupInserted(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aInsertedFrame, + nsTableRowGroupFrame * aInsertedFrame, PRBool aReplace); NS_IMETHOD IR_RowGroupAppended(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aAppendedFrame); + nsTableRowGroupFrame * aAppendedFrame); NS_IMETHOD IR_RowGroupRemoved(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aDeletedFrame); + nsTableRowGroupFrame * aDeletedFrame); NS_IMETHOD IR_UnknownFrameInserted(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -437,9 +438,14 @@ protected: /** returns PR_TRUE if the cached pass 1 data is still valid */ virtual PRBool IsFirstPassValid() const; + /** returns PR_TRUE if the cached column info is still valid */ + virtual PRBool IsColumnCacheValid() const; + public: virtual void InvalidateFirstPassCache(); + virtual void InvalidateColumnCache(); + protected: /** do post processing to setting up style information for the frame */ NS_IMETHOD DidSetStyleContext(nsIPresContext& aPresContext); @@ -589,6 +595,7 @@ private: PRInt32 mColumnWidthsLength; // the number of column lengths this frame has allocated PRBool mColumnWidthsSet; // PR_TRUE if column widths have been set at least once PRBool mFirstPassValid; // PR_TRUE if first pass data is still legit + PRBool mColumnCacheValid; // PR_TRUE if column cache info is still legit PRBool mCellMapValid; // PR_TRUE if cell map data is still legit PRBool mIsInvariantWidth; // PR_TRUE if table width cannot change PRInt32 mColCount; // the number of columns in this table diff --git a/layout/html/tests/TableIncrementalReflow.html b/layout/html/tests/TableIncrementalReflow.html index 661966d27417..e363cda487b6 100644 --- a/layout/html/tests/TableIncrementalReflow.html +++ b/layout/html/tests/TableIncrementalReflow.html @@ -17,10 +17,24 @@ function deleteCaption() { table.removeChild(caption); } + function insertColGroup() { var table = document.getElementsByTagName("TABLE")[0]; + var refColGroup = document.getElementsByTagName("COLGROUP")[0]; var colGroup = document.createElement("COLGROUP", null); + colGroup.width=200; + colGroup.span=1; + table.insertBefore(colGroup, refColGroup); + dump("inserted COLGROUP with span=1 width=200 as first colgroup in table"); +} + +function appendColGroup() { + var table = document.getElementsByTagName("TABLE")[0]; + var colGroup = document.createElement("COLGROUP", null); + colGroup.width=300; + colGroup.span=1; table.appendChild(colGroup); + dump("appended COLGROUP with span=1 width=300"); } function deleteColGroup() { @@ -29,10 +43,22 @@ function deleteColGroup() { table.removeChild(colGroup); } + function insertCol() { + var table = document.getElementsByTagName("TABLE")[0]; + var refCol = table.getElementsByTagName("COL")[0]; + var col = document.createElement("COL", null); + 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"); +} + +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"); } function deleteCol() { @@ -86,16 +112,20 @@ all delete buttons currently remove the first item of found
+
+
+
- - + + +
diff --git a/layout/tables/nsTableColGroupFrame.cpp b/layout/tables/nsTableColGroupFrame.cpp index ffd056193bdd..454d90839d2d 100644 --- a/layout/tables/nsTableColGroupFrame.cpp +++ b/layout/tables/nsTableColGroupFrame.cpp @@ -316,6 +316,32 @@ int nsTableColGroupFrame::GetColumnCount () return mColCount; } +nsTableColFrame * nsTableColGroupFrame::GetFirstColumn() +{ + return GetNextColumn(nsnull); +} + +nsTableColFrame * nsTableColGroupFrame::GetNextColumn(nsIFrame *aChildFrame) +{ + nsTableColFrame *result = nsnull; + nsIFrame *childFrame = aChildFrame; + if (nsnull==childFrame) + childFrame = mFirstChild; + while (nsnull!=childFrame) + { + const nsStyleDisplay *childDisplay; + childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay)); + if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay) + { + result = (nsTableColFrame *)childFrame; + break; + } + childFrame->GetNextSibling(childFrame); + } + return result; +} + + nsTableColFrame * nsTableColGroupFrame::GetColumnAt (PRInt32 aColIndex) { nsTableColFrame *result = nsnull; @@ -349,6 +375,34 @@ PRInt32 nsTableColGroupFrame::GetSpan() return span; } +/* this may be needed when IsSynthetic is properly implemented +PRBool nsTableColGroupFrame::IsManufactured() +{ + PRBool result = PR_FALSE; + nsIFrame *firstCol = GetFirstColumn(); + if (nsTableFrame::IsSynthetic(this) && + ((nsnull==firstCol) || nsTableFrame::IsSynthetic(firstCol))) + result = PR_TRUE; + return result; +} +*/ + +/** returns colcount because it is frequently used in the context of + * shuffling relative colgroup order, and it's convenient to not have to + * call GetColumnCount redundantly. + */ +PRInt32 nsTableColGroupFrame::SetStartColumnIndex (int aIndex) +{ + PRInt32 result = mColCount; + if (aIndex != mStartColIndex) + { + mStartColIndex = aIndex; + mColCount=0; + result = GetColumnCount(); // has the side effect of setting each column index based on new start index + } + return result; +} + /* ----- global methods ----- */ nsresult diff --git a/layout/tables/nsTableColGroupFrame.h b/layout/tables/nsTableColGroupFrame.h index b8f0936703e3..7ee4e26d830b 100644 --- a/layout/tables/nsTableColGroupFrame.h +++ b/layout/tables/nsTableColGroupFrame.h @@ -66,18 +66,31 @@ public: * if there are col children, count them (taking into account the span of each) * else, check my own span attribute. */ - virtual PRInt32 GetColumnCount (); + virtual PRInt32 GetColumnCount(); - virtual nsTableColFrame * GetColumnAt (PRInt32 aColIndex); + virtual nsTableColFrame * GetFirstColumn(); - virtual PRInt32 GetStartColumnIndex (); + virtual nsTableColFrame * GetNextColumn(nsIFrame *aChildFrame); + + virtual nsTableColFrame * GetColumnAt(PRInt32 aColIndex); + + virtual PRInt32 GetStartColumnIndex(); - virtual void SetStartColumnIndex (PRInt32 aIndex); + /** sets mStartColIndex to aIndex. + * @return the col count + * has the side effect of setting all child COL indexes + */ + virtual PRInt32 SetStartColumnIndex(PRInt32 aIndex); /** helper method to get the span attribute for this colgroup */ PRInt32 GetSpan(); - NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0, nsIListFilter *aFilter = nsnull) const; + /** helper method returns PR_TRUE if this colgroup exists without any + * colgroup or col content in the table backing it. + */ + //PRBool IsManufactured(); + + NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0, nsIListFilter *aFilter = nsnull) const; protected: @@ -104,11 +117,4 @@ protected: inline int nsTableColGroupFrame::GetStartColumnIndex () { return mStartColIndex;} -inline void nsTableColGroupFrame::SetStartColumnIndex (int aIndex) -{ - if (aIndex != mStartColIndex) - mColCount = 0; // our index is being changed, trigger reset of col indicies, don't propogate back to table - mStartColIndex = aIndex; -} - #endif diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 64e775c30a16..3c14a479f3b5 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -47,9 +47,6 @@ static PRBool gsDebug = PR_FALSE; static PRBool gsDebugCLD = PR_FALSE; static PRBool gsDebugNT = PR_FALSE; static PRBool gsDebugIR = PR_FALSE; -//#define NOISY -//#define NOISY_FLOW -//#ifdef NOISY_STYLE #else static const PRBool gsDebug = PR_FALSE; static const PRBool gsDebugCLD = PR_FALSE; @@ -197,35 +194,39 @@ ColumnInfoCache::~ColumnInfoCache() void ColumnInfoCache::AddColumnInfo(const nsStyleUnit aType, PRInt32 aColumnIndex) { - switch (aType) + // a table may have more COLs than actual columns, so we guard against that here + if (aColumnIndexInitialize(aDesiredSize.maxElementSize); } BuildColumnCache(aPresContext, aDesiredSize, aReflowState, aStatus); @@ -1882,12 +1886,12 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext& aPresContext, if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay) { rv = IR_ColGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus, - objectFrame, PR_FALSE); + (nsTableColGroupFrame*)objectFrame, PR_FALSE); } else if (IsRowGroup(childDisplay->mDisplay)) { rv = IR_RowGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus, - objectFrame, PR_FALSE); + (nsTableRowGroupFrame*)objectFrame, PR_FALSE); } else { @@ -1899,11 +1903,13 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext& aPresContext, case nsIReflowCommand::FrameAppended : if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay) { - rv = IR_ColGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame); + rv = IR_ColGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus, + (nsTableColGroupFrame*)objectFrame); } else if (IsRowGroup(childDisplay->mDisplay)) { - rv = IR_RowGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame); + rv = IR_RowGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus, + (nsTableRowGroupFrame*)objectFrame); } else { // no optimization to be done for Unknown frame types, so just reuse the Inserted method @@ -1921,18 +1927,18 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext& aPresContext, if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay) { rv = IR_ColGroupRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, - objectFrame); + (nsTableColGroupFrame*)objectFrame); } else if (IsRowGroup(childDisplay->mDisplay)) { rv = IR_RowGroupRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, - objectFrame); + (nsTableRowGroupFrame*)objectFrame); } else { rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, - objectFrame); + objectFrame); } break; @@ -1964,38 +1970,75 @@ NS_METHOD nsTableFrame::IR_ColGroupInserted(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aInsertedFrame, + nsTableColGroupFrame * aInsertedFrame, PRBool aReplace) { - nsresult rv; - /* - find where to place colgroup (skipping implicit children?) - for every col in the colgroup (including implicit cols due to span attribute) - an implicit col from the first implicit colgroup is removed - when an implicit colgroups col count goes to 0, it is removed - */ - /* need to really verify that issynthetic is specified on implicit colgroups and cols */ + nsresult rv=NS_OK; + PRBool adjustStartingColIndex=PR_FALSE; + PRInt32 startingColIndex=0; + // find out what frame to insert aInsertedFrame after + nsIFrame *frameToInsertAfter=nsnull; + rv = aReflowState.reflowState.reflowCommand->GetPrevSiblingFrame(frameToInsertAfter); + // insert aInsertedFrame as the first child. Set its start col index to 0 + if (nsnull==frameToInsertAfter) + { + aInsertedFrame->SetNextSibling(mFirstChild); + mFirstChild=aInsertedFrame; + startingColIndex += aInsertedFrame->SetStartColumnIndex(0); + adjustStartingColIndex=PR_TRUE; + } + nsIFrame *childFrame=mFirstChild; + nsIFrame *prevSib=nsnull; + while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame)) + { + if ((nsnull!=frameToInsertAfter) && (childFrame==frameToInsertAfter)) + { + nsIFrame *nextSib=nsnull; + frameToInsertAfter->GetNextSibling(nextSib); + aInsertedFrame->SetNextSibling(nextSib); + frameToInsertAfter->SetNextSibling(aInsertedFrame); + // account for childFrame being a COLGROUP now + const nsStyleDisplay *display; + childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display); + if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) + { + if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet + startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount(); + } + // skip ahead to aInsertedFrame, since we just handled the frame we inserted after + childFrame=aInsertedFrame; + adjustStartingColIndex=PR_TRUE; // now that we've inserted aInsertedFrame, + // start adjusting subsequent col groups' starting col index including aInsertedFrame + } + const nsStyleDisplay *display; + childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display); + if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) + { + if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet + startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount(); + else // we've removed aDeletedFrame, now adjust the starting col index of all subsequent col groups + startingColIndex += ((nsTableColGroupFrame *)childFrame)->SetStartColumnIndex(startingColIndex); + } + prevSib=childFrame; + rv = childFrame->GetNextSibling(childFrame); + } + + InvalidateColumnCache(); + //XXX: what we want to do here is determine if the new COL information changes anything about layout + // if not, skip invalidating the first passs + // if so, and we can fix the first pass info return rv; + } NS_METHOD nsTableFrame::IR_ColGroupAppended(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aAppendedFrame) + nsTableColGroupFrame * aAppendedFrame) { nsresult rv=NS_OK; - /* - find where to place colgroup (skipping implicit children?) - for every col in the colgroup (including implicit cols due to span attribute) - an implicit col from the first implicit colgroup is removed - when an implicit colgroups col count goes to 0, it is removed - */ - /* need to really verify that issynthetic is specified on implicit colgroups and cols */ - - - // build a vector of colgroups. XXX might want to do this as a class thing, so we don't have to rebuild it each time - nsVoidArray colGroupList; + PRInt32 startingColIndex=0; nsIFrame *childFrame=mFirstChild; nsIFrame *lastChild=mFirstChild; while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame)) @@ -2004,7 +2047,7 @@ NS_METHOD nsTableFrame::IR_ColGroupAppended(nsIPresContext& aPresContext, childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display); if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) { - colGroupList.AppendElement((void*)childFrame); + startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount(); } lastChild=childFrame; rv = childFrame->GetNextSibling(childFrame); @@ -2015,36 +2058,54 @@ NS_METHOD nsTableFrame::IR_ColGroupAppended(nsIPresContext& aPresContext, else mFirstChild = aAppendedFrame; - /* go through the list of colgroups, sucking out implicit columns that are not the result of a span attribute - * and replacing them with columns in aAppendedFrame - * if the column had an attribute from a cell, be sure to preserve that - * if any implicit colgroup becomes empty, destroy it - * if any real colgroup becomes empty, we have to keep it - * factor the new cols into the column cache - * this means having a flag that says whether the col cache needs to be rebuilt or not - */ - PRInt32 colGroupCount = colGroupList.Count(); + aAppendedFrame->SetStartColumnIndex(startingColIndex); + +#if 0 + +we would only want to do this if manufactured col groups were invisible to the DOM. Since they +currently are visible, they should behave just as if they were content-backed "real" colgroups +If this decision is changed, the code below is a half-finished attempt to rationalize the situation. +It requires having built a list of the colGroups before we get to this point. + + // look at the last col group. If it is implicit, and it's cols are implicit, then + // it and its cols were manufactured for table layout. + // Delete it if possible, otherwise move it to the end of the list + if (0FirstChild(childFrame); - while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame)) - { - const nsStyleDisplay *colDisplay; - childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)colDisplay); - if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay) - { // find an implicit column that is not from a span attribute if there is one and remove it - for (PRInt32 colGroupIndex=0; colGroupIndexIsManufactured()) + { // account for the new COLs that were added in aAppendedFrame + // first, try to delete the implicit colgroup + + // if we couldn't delete it, move the implicit colgroup to the end of the list + // and adjust it's col indexes + nsIFrame *colGroupNextSib; + colGroup->GetNextSibling(colGroupNextSib); + childFrame=mFirstChild; + nsIFrame * prevSib=nsnull; + rv = NS_OK; + while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame)) + { + if (childFrame==colGroup) { - nsTableColGroupFrame *colGroup = (nsTableColGroupFrame *)(colGroupList.ElementAt(colGroupIndex)); - // XXX: here's where we yank colGroups if necessary + if (nsnull!=prevSib) // colGroup is in the middle of the list, remove it + prevSib->SetNextSibling(colGroupNextSib); + else // colGroup was the first child, so set it's next sib to first child + mFirstChild = colGroupNextSib; + aAppendedFrame->SetNextSibling(colGroup); // place colGroup at the end of the list + colGroup->SetNextSibling(nsnull); + break; } + prevSib=childFrame; + rv = childFrame->GetNextSibling(childFrame); } } } +#endif - //InvalidateFirstPassCache(); // for now, redo the first pass reflow - // could probably just get away with mTableLayoutStrategy->Initialize(aMaxElementSize); - mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize); + + InvalidateColumnCache(); //XXX: what we want to do here is determine if the new COL information changes anything about layout // if not, skip invalidating the first passs // if so, and we can fix the first pass info @@ -2056,14 +2117,45 @@ NS_METHOD nsTableFrame::IR_ColGroupRemoved(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aDeletedFrame) + nsTableColGroupFrame * aDeletedFrame) { - nsresult rv; - /* - for every col in the colgroup (including implicit cols due to span attribute) - an implicit col is created in the last implicit colgroup - if there is no implicit colgroup, one is created at the end of the colgroup list - */ + nsresult rv=NS_OK; + PRBool adjustStartingColIndex=PR_FALSE; + PRInt32 startingColIndex=0; + nsIFrame *childFrame=mFirstChild; + nsIFrame *prevSib=nsnull; + while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame)) + { + if (childFrame==aDeletedFrame) + { + nsIFrame *deleteFrameNextSib=nsnull; + aDeletedFrame->GetNextSibling(deleteFrameNextSib); + if (nsnull!=prevSib) + prevSib->SetNextSibling(deleteFrameNextSib); + else + mFirstChild = deleteFrameNextSib; + childFrame=deleteFrameNextSib; + if (nsnull==childFrame) + break; + adjustStartingColIndex=PR_TRUE; // now that we've removed aDeletedFrame, start adjusting subsequent col groups' starting col index + } + const nsStyleDisplay *display; + childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display); + if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) + { + if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet + startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount(); + else // we've removed aDeletedFrame, now adjust the starting col index of all subsequent col groups + startingColIndex += ((nsTableColGroupFrame *)childFrame)->SetStartColumnIndex(startingColIndex); + } + prevSib=childFrame; + rv = childFrame->GetNextSibling(childFrame); + } + + InvalidateColumnCache(); + //XXX: what we want to do here is determine if the new COL information changes anything about layout + // if not, skip invalidating the first passs + // if so, and we can fix the first pass info return rv; } @@ -2071,7 +2163,7 @@ NS_METHOD nsTableFrame::IR_RowGroupInserted(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aInsertedFrame, + nsTableRowGroupFrame * aInsertedFrame, PRBool aReplace) { nsresult rv; @@ -2084,7 +2176,7 @@ NS_METHOD nsTableFrame::IR_RowGroupAppended(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aAppendedFrame) + nsTableRowGroupFrame * aAppendedFrame) { // hook aAppendedFrame into the child list nsIFrame *lastChild = mFirstChild; @@ -2115,7 +2207,7 @@ NS_METHOD nsTableFrame::IR_RowGroupRemoved(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aDeletedFrame) + nsTableRowGroupFrame * aDeletedFrame) { nsresult rv; return rv; @@ -2940,6 +3032,7 @@ 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); @@ -3028,6 +3121,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext& aPresContext, } childFrame->GetNextSibling(childFrame); } + mColumnCacheValid=PR_TRUE; } PRBool nsTableFrame::IsFirstPassValid() const @@ -3044,6 +3138,20 @@ void nsTableFrame::InvalidateFirstPassCache() firstInFlow->mFirstPassValid=PR_FALSE; } +PRBool nsTableFrame::IsColumnCacheValid() const +{ + nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow(); + NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow"); + return firstInFlow->mColumnCacheValid; +} + +void nsTableFrame::InvalidateColumnCache() +{ + nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow(); + NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow"); + firstInFlow->mColumnCacheValid=PR_FALSE; +} + PRBool nsTableFrame::IsCellMapValid() const { nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow(); diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index cd8cbc57e5d4..05aacc6df15a 100644 --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -29,6 +29,7 @@ class nsTableCellFrame; class nsTableColFrame; class nsTableRowGroupFrame; class nsTableRowFrame; +class nsTableColGroupFrame; class nsITableLayoutStrategy; class nsHTMLValue; class ColumnInfoCache; @@ -317,39 +318,39 @@ protected: nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aInsertedFrame, + nsTableColGroupFrame * aInsertedFrame, PRBool aReplace); - NS_IMETHOD IR_ColGroupAppended(nsIPresContext& aPresContext, + NS_IMETHOD IR_ColGroupAppended(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aAppendedFrame); + nsTableColGroupFrame * aAppendedFrame); NS_IMETHOD IR_ColGroupRemoved(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aDeletedFrame); + nsTableColGroupFrame * aDeletedFrame); NS_IMETHOD IR_RowGroupInserted(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aInsertedFrame, + nsTableRowGroupFrame * aInsertedFrame, PRBool aReplace); NS_IMETHOD IR_RowGroupAppended(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aAppendedFrame); + nsTableRowGroupFrame * aAppendedFrame); NS_IMETHOD IR_RowGroupRemoved(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, InnerTableReflowState& aReflowState, nsReflowStatus& aStatus, - nsIFrame * aDeletedFrame); + nsTableRowGroupFrame * aDeletedFrame); NS_IMETHOD IR_UnknownFrameInserted(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -437,9 +438,14 @@ protected: /** returns PR_TRUE if the cached pass 1 data is still valid */ virtual PRBool IsFirstPassValid() const; + /** returns PR_TRUE if the cached column info is still valid */ + virtual PRBool IsColumnCacheValid() const; + public: virtual void InvalidateFirstPassCache(); + virtual void InvalidateColumnCache(); + protected: /** do post processing to setting up style information for the frame */ NS_IMETHOD DidSetStyleContext(nsIPresContext& aPresContext); @@ -589,6 +595,7 @@ private: PRInt32 mColumnWidthsLength; // the number of column lengths this frame has allocated PRBool mColumnWidthsSet; // PR_TRUE if column widths have been set at least once PRBool mFirstPassValid; // PR_TRUE if first pass data is still legit + PRBool mColumnCacheValid; // PR_TRUE if column cache info is still legit PRBool mCellMapValid; // PR_TRUE if cell map data is still legit PRBool mIsInvariantWidth; // PR_TRUE if table width cannot change PRInt32 mColCount; // the number of columns in this table