nsTableFrame can now incrementally insert, append, and delete colgroups

This commit is contained in:
buster%netscape.com 1998-10-14 22:51:50 +00:00
Родитель cee140ae96
Коммит 2a254f6de9
9 изменённых файлов: 608 добавлений и 228 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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 (aColumnIndex<mNumColumns)
{
case eStyleUnit_Auto:
if (nsnull==mColIndexes[eColWidthType_Auto])
mColIndexes[eColWidthType_Auto] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Auto][mColCounts[eColWidthType_Auto]] = aColumnIndex;
mColCounts[eColWidthType_Auto]++;
break;
switch (aType)
{
case eStyleUnit_Auto:
if (nsnull==mColIndexes[eColWidthType_Auto])
mColIndexes[eColWidthType_Auto] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Auto][mColCounts[eColWidthType_Auto]] = aColumnIndex;
mColCounts[eColWidthType_Auto]++;
break;
case eStyleUnit_Percent:
if (nsnull==mColIndexes[eColWidthType_Percent])
mColIndexes[eColWidthType_Percent] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Percent][mColCounts[eColWidthType_Percent]] = aColumnIndex;
mColCounts[eColWidthType_Percent]++;
break;
case eStyleUnit_Percent:
if (nsnull==mColIndexes[eColWidthType_Percent])
mColIndexes[eColWidthType_Percent] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Percent][mColCounts[eColWidthType_Percent]] = aColumnIndex;
mColCounts[eColWidthType_Percent]++;
break;
case eStyleUnit_Coord:
if (nsnull==mColIndexes[eColWidthType_Coord])
mColIndexes[eColWidthType_Coord] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Coord][mColCounts[eColWidthType_Coord]] = aColumnIndex;
mColCounts[eColWidthType_Coord]++;
break;
case eStyleUnit_Coord:
if (nsnull==mColIndexes[eColWidthType_Coord])
mColIndexes[eColWidthType_Coord] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Coord][mColCounts[eColWidthType_Coord]] = aColumnIndex;
mColCounts[eColWidthType_Coord]++;
break;
case eStyleUnit_Proportional:
if (nsnull==mColIndexes[eColWidthType_Proportional])
mColIndexes[eColWidthType_Proportional] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Proportional][mColCounts[eColWidthType_Proportional]] = aColumnIndex;
mColCounts[eColWidthType_Proportional]++;
break;
case eStyleUnit_Proportional:
if (nsnull==mColIndexes[eColWidthType_Proportional])
mColIndexes[eColWidthType_Proportional] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Proportional][mColCounts[eColWidthType_Proportional]] = aColumnIndex;
mColCounts[eColWidthType_Proportional]++;
break;
}
}
}
@ -270,6 +271,7 @@ nsTableFrame::nsTableFrame(nsIContent* aContent, nsIFrame* aParentFrame)
mColCache(nsnull),
mTableLayoutStrategy(nsnull),
mFirstPassValid(PR_FALSE),
mColumnCacheValid(PR_FALSE),
mCellMapValid(PR_TRUE),
mIsInvariantWidth(PR_FALSE)
{
@ -1560,10 +1562,10 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
if (PR_TRUE==NeedsReflow(aReflowState, aReflowState.maxSize))
{
PRBool needsRecalc=PR_FALSE;
if (PR_TRUE==gsDebug) printf("TF Reflow: needs reflow\n");
if (PR_TRUE==gsDebug) printf("TIF Reflow: needs reflow\n");
if (eReflowReason_Initial!=aReflowState.reason && PR_FALSE==IsCellMapValid())
{
if (PR_TRUE==gsDebug) printf("TF Reflow: not initial reflow, so resetting cell map.\n");
if (PR_TRUE==gsDebug) printf("TIF Reflow: not initial reflow, so resetting cell map.\n");
if (nsnull!=mCellMap)
delete mCellMap;
mCellMap = new nsCellMap(0,0);
@ -1572,19 +1574,21 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
}
if (PR_FALSE==IsFirstPassValid())
{
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TF Reflow: first pass is invalid\n");
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: first pass is invalid\n");
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, aStatus);
if (NS_FAILED(rv))
return rv;
needsRecalc=PR_TRUE;
}
if (PR_FALSE==IsColumnCacheValid())
needsRecalc=PR_TRUE;
if (PR_TRUE==needsRecalc)
{
if (PR_TRUE==gsDebugIR) printf("TF Reflow: needs recalc.\n");
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("TF Reflow: Re-init layout strategy\n");
if (PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
mTableLayoutStrategy->Initialize(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 (0<colGroupCount)
{
aAppendedFrame->FirstChild(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; colGroupIndex<colGroupCount; colGroupIndex++)
nsTableColGroupFrame *colGroup = (nsTableColGroupFrame *)(colGroupList.ElementAt(colGroupCount-1));
if (PR_TRUE==colGroup->IsManufactured())
{ // 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();

Просмотреть файл

@ -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

Просмотреть файл

@ -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 <type> found
<br>
<INPUT TYPE="button" NAME="Ins ColGroup" VALUE="InsertCG" onClick="insertColGroup()" width=100>
<INPUT TYPE="button" NAME="App ColGroup" VALUE="AppendCG" onClick="appendColGroup()" width=100>
<INPUT TYPE="button" NAME="Del ColGroup" VALUE="DeleteCG" onClick="deleteColGroup()" width=100>
<br>
<INPUT TYPE="button" NAME="Ins Col" VALUE="InsertCol" onClick="insertCol()" width=100>
<INPUT TYPE="button" NAME="App Col" VALUE="AppendCol" onClick="appendCol()" width=100>
<INPUT TYPE="button" NAME="Del Col" VALUE="DeleteCol" onClick="deleteCol()" width=100>
<br>
<INPUT TYPE="button" NAME="Ins RowGroup" VALUE="InsertRG" onClick="insertRowGroup()" width=100>
<INPUT TYPE="button" NAME="App RowGroup" VALUE="AppendRG" onClick="appendRowGroup()" width=100>
<INPUT TYPE="button" NAME="Del RowGroup" VALUE="DeleteRG" onClick="deleteRowGroup()" width=100>
<br>
<INPUT TYPE="button" NAME="Ins Row" VALUE="InsertRow" onClick="insertRowGroup()" width=100>
<INPUT TYPE="button" NAME="Del Row" VALUE="DeleteRow" onClick="deleteRowGroup()" width=100>
<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>
<br>
</form>

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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 (aColumnIndex<mNumColumns)
{
case eStyleUnit_Auto:
if (nsnull==mColIndexes[eColWidthType_Auto])
mColIndexes[eColWidthType_Auto] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Auto][mColCounts[eColWidthType_Auto]] = aColumnIndex;
mColCounts[eColWidthType_Auto]++;
break;
switch (aType)
{
case eStyleUnit_Auto:
if (nsnull==mColIndexes[eColWidthType_Auto])
mColIndexes[eColWidthType_Auto] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Auto][mColCounts[eColWidthType_Auto]] = aColumnIndex;
mColCounts[eColWidthType_Auto]++;
break;
case eStyleUnit_Percent:
if (nsnull==mColIndexes[eColWidthType_Percent])
mColIndexes[eColWidthType_Percent] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Percent][mColCounts[eColWidthType_Percent]] = aColumnIndex;
mColCounts[eColWidthType_Percent]++;
break;
case eStyleUnit_Percent:
if (nsnull==mColIndexes[eColWidthType_Percent])
mColIndexes[eColWidthType_Percent] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Percent][mColCounts[eColWidthType_Percent]] = aColumnIndex;
mColCounts[eColWidthType_Percent]++;
break;
case eStyleUnit_Coord:
if (nsnull==mColIndexes[eColWidthType_Coord])
mColIndexes[eColWidthType_Coord] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Coord][mColCounts[eColWidthType_Coord]] = aColumnIndex;
mColCounts[eColWidthType_Coord]++;
break;
case eStyleUnit_Coord:
if (nsnull==mColIndexes[eColWidthType_Coord])
mColIndexes[eColWidthType_Coord] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Coord][mColCounts[eColWidthType_Coord]] = aColumnIndex;
mColCounts[eColWidthType_Coord]++;
break;
case eStyleUnit_Proportional:
if (nsnull==mColIndexes[eColWidthType_Proportional])
mColIndexes[eColWidthType_Proportional] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Proportional][mColCounts[eColWidthType_Proportional]] = aColumnIndex;
mColCounts[eColWidthType_Proportional]++;
break;
case eStyleUnit_Proportional:
if (nsnull==mColIndexes[eColWidthType_Proportional])
mColIndexes[eColWidthType_Proportional] = new PRInt32[mNumColumns]; // TODO : be much more efficient
mColIndexes[eColWidthType_Proportional][mColCounts[eColWidthType_Proportional]] = aColumnIndex;
mColCounts[eColWidthType_Proportional]++;
break;
}
}
}
@ -270,6 +271,7 @@ nsTableFrame::nsTableFrame(nsIContent* aContent, nsIFrame* aParentFrame)
mColCache(nsnull),
mTableLayoutStrategy(nsnull),
mFirstPassValid(PR_FALSE),
mColumnCacheValid(PR_FALSE),
mCellMapValid(PR_TRUE),
mIsInvariantWidth(PR_FALSE)
{
@ -1560,10 +1562,10 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
if (PR_TRUE==NeedsReflow(aReflowState, aReflowState.maxSize))
{
PRBool needsRecalc=PR_FALSE;
if (PR_TRUE==gsDebug) printf("TF Reflow: needs reflow\n");
if (PR_TRUE==gsDebug) printf("TIF Reflow: needs reflow\n");
if (eReflowReason_Initial!=aReflowState.reason && PR_FALSE==IsCellMapValid())
{
if (PR_TRUE==gsDebug) printf("TF Reflow: not initial reflow, so resetting cell map.\n");
if (PR_TRUE==gsDebug) printf("TIF Reflow: not initial reflow, so resetting cell map.\n");
if (nsnull!=mCellMap)
delete mCellMap;
mCellMap = new nsCellMap(0,0);
@ -1572,19 +1574,21 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
}
if (PR_FALSE==IsFirstPassValid())
{
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TF Reflow: first pass is invalid\n");
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: first pass is invalid\n");
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, aStatus);
if (NS_FAILED(rv))
return rv;
needsRecalc=PR_TRUE;
}
if (PR_FALSE==IsColumnCacheValid())
needsRecalc=PR_TRUE;
if (PR_TRUE==needsRecalc)
{
if (PR_TRUE==gsDebugIR) printf("TF Reflow: needs recalc.\n");
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("TF Reflow: Re-init layout strategy\n");
if (PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
mTableLayoutStrategy->Initialize(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 (0<colGroupCount)
{
aAppendedFrame->FirstChild(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; colGroupIndex<colGroupCount; colGroupIndex++)
nsTableColGroupFrame *colGroup = (nsTableColGroupFrame *)(colGroupList.ElementAt(colGroupCount-1));
if (PR_TRUE==colGroup->IsManufactured())
{ // 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();

Просмотреть файл

@ -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