incremental cell map, columns. Bugs 12122, 21544. r=troy,hyatt a=hofmann

This commit is contained in:
karnaze%netscape.com 1999-12-13 22:56:31 +00:00
parent e6c401cb3e
commit 2eb4655c2e
43 changed files with 5214 additions and 3047 deletions

View File

@ -37,6 +37,7 @@
#include "nsILinkHandler.h"
#include "nsIDocument.h"
#include "nsIHTMLTableCellElement.h"
#include "nsTableColGroupFrame.h"
#include "nsTableColFrame.h"
#include "nsHTMLIIDs.h"
#include "nsIStyleFrameConstruction.h"
@ -1175,7 +1176,7 @@ nsCSSFrameConstructor::ConstructAnonymousTableFrame(nsIPresShell* aPresSh
nsTableCreator& aTableCreator)
{
nsresult rv = NS_OK;
NS_WARNING("an anonymous table frame was created. \n");
//NS_WARNING("an anonymous table frame was created. \n");
nsCOMPtr<nsIStyleContext> parentStyleContext;
aParentFrame->GetStyleContext(getter_AddRefs(parentStyleContext));
const nsStyleDisplay* parentDisplay =
@ -1326,7 +1327,7 @@ nsCSSFrameConstructor::ConstructTableCaptionFrame(nsIPresShell* aPres
// the caller is responsible for calling SetInitialChildList on the outer, inner frames
aNewTopFrame = aNewCaptionFrame;
} else { // parent is not a table, need to create a new table
NS_WARNING("a non table contains a table caption child. \n");
//NS_WARNING("a non table contains a table caption child. \n");
nsIFrame* outerFrame;
ConstructAnonymousTableFrame(aPresShell, aPresContext, aState, aContent, aParentFrame,
aNewTopFrame, outerFrame, innerFrame, aTableCreator);
@ -1418,7 +1419,7 @@ nsCSSFrameConstructor::ConstructTableGroupFrame(nsIPresShell* aPresShell,
styleContext, aIsRowGroup, aNewTopFrame, aNewGroupFrame,
aTableCreator, contentDisplayIsGroup);
} else { // construct anonymous frames
NS_WARNING("a non table contains a table row or col group child. \n");
//NS_WARNING("a non table contains a table row or col group child. \n");
nsIFrame* innerFrame;
nsIFrame* outerFrame;
@ -1639,9 +1640,8 @@ nsCSSFrameConstructor::ConstructTableRowFrameOnly(nsIPresShell* aPresShel
return rv;
}
nsresult
nsCSSFrameConstructor::ConstructTableColFrame(nsIPresShell* aPresShell,
nsCSSFrameConstructor::ConstructTableColFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,
nsIContent* aContent,
@ -1673,6 +1673,7 @@ nsCSSFrameConstructor::ConstructTableColFrame(nsIPresShell* aPresShell,
rv = ConstructTableColFrameOnly(aPresShell, aPresContext, aState, aContent, groupFrame,
styleContext, aNewColFrame, aTableCreator);
if (NS_FAILED(rv)) return rv;
aState.mFrameManager->SetPrimaryFrameFor(aContent, aNewColFrame);
groupFrame->SetInitialChildList(aPresContext, nsnull, aNewColFrame);
// if an anoymous table got created, then set its initial child list
@ -1747,7 +1748,7 @@ nsCSSFrameConstructor::ConstructTableCellFrame(nsIPresShell* aPresShell,
aTableCreator, aProcessChildren);
aNewTopFrame = aNewCellFrame;
} else { // the cell needs some ancestors to be fabricated
NS_WARNING("WARNING - a non table row contains a table cell child. \n");
//NS_WARNING("WARNING - a non table row contains a table cell child. \n");
nsTableList toDo;
nsIFrame* rowFrame;
rv = ConstructTableRowFrame(aPresShell, aPresContext, aState, aContent, aParentFrame,
@ -5484,6 +5485,35 @@ nsCSSFrameConstructor::AppendFrames(nsIPresContext* aPresContext,
aFrameList);
}
// a col group or col appended to a table may result in an insert rather than an append
nsIAtom* parentType;
aParentFrame->GetFrameType(&parentType);
if (nsLayoutAtoms::tableFrame == parentType) {
nsTableFrame* tableFrame = (nsTableFrame *)aParentFrame;
nsIAtom* childType;
aFrameList->GetFrameType(&childType);
if (nsLayoutAtoms::tableColFrame == childType) {
nsIFrame* parentFrame = aParentFrame;
aFrameList->GetParent(&parentFrame);
return aFrameManager->AppendFrames(aPresContext, *aPresShell, parentFrame,
nsLayoutAtoms::colGroupList, aFrameList);
}
else if (nsLayoutAtoms::tableColGroupFrame == childType) {
nsIFrame* prevSibling;
PRBool doAppend = nsTableColGroupFrame::GetLastRealColGroup(tableFrame, &prevSibling);
if (doAppend) {
return aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame,
nsLayoutAtoms::colGroupList, aFrameList);
}
else {
return aFrameManager->InsertFrames(aPresContext, *aPresShell, aParentFrame,
nsLayoutAtoms::colGroupList, prevSibling, aFrameList);
}
}
NS_IF_RELEASE(childType);
}
NS_IF_RELEASE(parentType);
// Append the frames to the end of the parent's child list
return aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame,
nsnull, aFrameList);

View File

@ -675,7 +675,10 @@ nsGfxScrollFrame::GetSkipSides() const
NS_IMETHODIMP
nsGfxScrollFrame::GetFrameType(nsIAtom** aType) const
{
return nsHTMLContainerFrame::GetFrameType(aType);
NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer");
*aType = nsLayoutAtoms::scrollFrame;
NS_ADDREF(*aType);
return NS_OK;
}
#ifdef NS_DEBUG

View File

@ -675,7 +675,10 @@ nsGfxScrollFrame::GetSkipSides() const
NS_IMETHODIMP
nsGfxScrollFrame::GetFrameType(nsIAtom** aType) const
{
return nsHTMLContainerFrame::GetFrameType(aType);
NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer");
*aType = nsLayoutAtoms::scrollFrame;
NS_ADDREF(*aType);
return NS_OK;
}
#ifdef NS_DEBUG

View File

@ -37,6 +37,7 @@
#include "nsILinkHandler.h"
#include "nsIDocument.h"
#include "nsIHTMLTableCellElement.h"
#include "nsTableColGroupFrame.h"
#include "nsTableColFrame.h"
#include "nsHTMLIIDs.h"
#include "nsIStyleFrameConstruction.h"
@ -1175,7 +1176,7 @@ nsCSSFrameConstructor::ConstructAnonymousTableFrame(nsIPresShell* aPresSh
nsTableCreator& aTableCreator)
{
nsresult rv = NS_OK;
NS_WARNING("an anonymous table frame was created. \n");
//NS_WARNING("an anonymous table frame was created. \n");
nsCOMPtr<nsIStyleContext> parentStyleContext;
aParentFrame->GetStyleContext(getter_AddRefs(parentStyleContext));
const nsStyleDisplay* parentDisplay =
@ -1326,7 +1327,7 @@ nsCSSFrameConstructor::ConstructTableCaptionFrame(nsIPresShell* aPres
// the caller is responsible for calling SetInitialChildList on the outer, inner frames
aNewTopFrame = aNewCaptionFrame;
} else { // parent is not a table, need to create a new table
NS_WARNING("a non table contains a table caption child. \n");
//NS_WARNING("a non table contains a table caption child. \n");
nsIFrame* outerFrame;
ConstructAnonymousTableFrame(aPresShell, aPresContext, aState, aContent, aParentFrame,
aNewTopFrame, outerFrame, innerFrame, aTableCreator);
@ -1418,7 +1419,7 @@ nsCSSFrameConstructor::ConstructTableGroupFrame(nsIPresShell* aPresShell,
styleContext, aIsRowGroup, aNewTopFrame, aNewGroupFrame,
aTableCreator, contentDisplayIsGroup);
} else { // construct anonymous frames
NS_WARNING("a non table contains a table row or col group child. \n");
//NS_WARNING("a non table contains a table row or col group child. \n");
nsIFrame* innerFrame;
nsIFrame* outerFrame;
@ -1639,9 +1640,8 @@ nsCSSFrameConstructor::ConstructTableRowFrameOnly(nsIPresShell* aPresShel
return rv;
}
nsresult
nsCSSFrameConstructor::ConstructTableColFrame(nsIPresShell* aPresShell,
nsCSSFrameConstructor::ConstructTableColFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,
nsIContent* aContent,
@ -1673,6 +1673,7 @@ nsCSSFrameConstructor::ConstructTableColFrame(nsIPresShell* aPresShell,
rv = ConstructTableColFrameOnly(aPresShell, aPresContext, aState, aContent, groupFrame,
styleContext, aNewColFrame, aTableCreator);
if (NS_FAILED(rv)) return rv;
aState.mFrameManager->SetPrimaryFrameFor(aContent, aNewColFrame);
groupFrame->SetInitialChildList(aPresContext, nsnull, aNewColFrame);
// if an anoymous table got created, then set its initial child list
@ -1747,7 +1748,7 @@ nsCSSFrameConstructor::ConstructTableCellFrame(nsIPresShell* aPresShell,
aTableCreator, aProcessChildren);
aNewTopFrame = aNewCellFrame;
} else { // the cell needs some ancestors to be fabricated
NS_WARNING("WARNING - a non table row contains a table cell child. \n");
//NS_WARNING("WARNING - a non table row contains a table cell child. \n");
nsTableList toDo;
nsIFrame* rowFrame;
rv = ConstructTableRowFrame(aPresShell, aPresContext, aState, aContent, aParentFrame,
@ -5484,6 +5485,35 @@ nsCSSFrameConstructor::AppendFrames(nsIPresContext* aPresContext,
aFrameList);
}
// a col group or col appended to a table may result in an insert rather than an append
nsIAtom* parentType;
aParentFrame->GetFrameType(&parentType);
if (nsLayoutAtoms::tableFrame == parentType) {
nsTableFrame* tableFrame = (nsTableFrame *)aParentFrame;
nsIAtom* childType;
aFrameList->GetFrameType(&childType);
if (nsLayoutAtoms::tableColFrame == childType) {
nsIFrame* parentFrame = aParentFrame;
aFrameList->GetParent(&parentFrame);
return aFrameManager->AppendFrames(aPresContext, *aPresShell, parentFrame,
nsLayoutAtoms::colGroupList, aFrameList);
}
else if (nsLayoutAtoms::tableColGroupFrame == childType) {
nsIFrame* prevSibling;
PRBool doAppend = nsTableColGroupFrame::GetLastRealColGroup(tableFrame, &prevSibling);
if (doAppend) {
return aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame,
nsLayoutAtoms::colGroupList, aFrameList);
}
else {
return aFrameManager->InsertFrames(aPresContext, *aPresShell, aParentFrame,
nsLayoutAtoms::colGroupList, prevSibling, aFrameList);
}
}
NS_IF_RELEASE(childType);
}
NS_IF_RELEASE(parentType);
// Append the frames to the end of the parent's child list
return aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame,
nsnull, aFrameList);

View File

@ -59,17 +59,6 @@ PRBool CanAllocate(PRInt32 aTypeToAllocate,
/* ---------- BasicTableLayoutStrategy ---------- */
/* return true if the style indicates that the width is fixed
* for the purposes of column width determination
*/
inline
PRBool BasicTableLayoutStrategy::IsFixedWidth(const nsStylePosition* aStylePosition,
const nsStyleTable* aStyleTable)
{
return PRBool ((eStyleUnit_Coord==aStylePosition->mWidth.GetUnit()) ||
(eStyleUnit_Coord==aStyleTable->mSpanWidth.GetUnit()));
}
MOZ_DECL_CTOR_COUNTER(BasicTableLayoutStrategy);
@ -90,8 +79,7 @@ BasicTableLayoutStrategy::~BasicTableLayoutStrategy()
MOZ_COUNT_DTOR(BasicTableLayoutStrategy);
}
PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize,
PRInt32 aNumCols,
PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize,
nscoord aMaxWidth)
{
ContinuingFrameCheck();
@ -99,12 +87,10 @@ PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize,
PRBool result = PR_TRUE;
// re-init instance variables
mNumCols = aNumCols;
mMinTableContentWidth = 0;
mMaxTableContentWidth = 0;
mCellSpacingTotal = 0;
mCols = mTableFrame->GetEffectiveCOLSAttribute();
// assign the width of all fixed-width columns
AssignPreliminaryColumnWidths(aMaxWidth);
@ -157,7 +143,7 @@ PRBool BCW_Wrapup(BasicTableLayoutStrategy* aStrategy,
{
if (aAllocTypes)
delete [] aAllocTypes;
if (gsDebugBalance) {printf("BalanceColumnWidths ex \n"); aTableFrame->Dump(PR_TRUE, PR_FALSE);}
if (gsDebugBalance) {printf("BalanceColumnWidths ex \n"); aTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE);}
return PR_TRUE;
}
@ -176,7 +162,7 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
const nsHTMLReflowState& aReflowState,
nscoord aMaxWidthIn)
{
if (gsDebugBalance) {printf("BalanceColumnWidths en max=%d\n", aMaxWidthIn); mTableFrame->Dump(PR_TRUE, PR_FALSE);}
if (gsDebugBalance) {printf("BalanceColumnWidths en max=%d\n", aMaxWidthIn); mTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE);}
ContinuingFrameCheck();
if (!aTableStyle) {
@ -184,6 +170,8 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
return PR_FALSE;
}
PRInt32 numCols = mTableFrame->GetColCount();
// determine if the table is auto/fixed and get the fixed width if available
nscoord maxWidth = aMaxWidthIn;
nscoord specifiedTableWidth = 0;
@ -204,7 +192,7 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
}
// initialize the col percent and cell percent values to 0.
PRInt32 colX;
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
colFrame->SetWidth(PCT, WIDTH_NOT_SET);
colFrame->SetWidth(PCT_ADJ, WIDTH_NOT_SET);
@ -220,7 +208,7 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
PRBool recomputedAdjMin = RecomputeAdjMinIfNecessary();
// set the table's columns to the min width
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord colMinWidth = colFrame->GetMinWidth();
mTableFrame->SetColumnWidth(colX, colMinWidth);
@ -257,10 +245,10 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
nscoord totalAllocated = totalWidths[MIN_CON] + cellSpacingTotal;
// allocate and initialize arrays indicating what col gets set
PRInt32* allocTypes = new PRInt32[mNumCols];
PRInt32* allocTypes = new PRInt32[numCols];
if (!allocTypes) return PR_FALSE;
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
allocTypes[colX] = -1;
}
@ -330,9 +318,9 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
PRBool skip0Proportional = totalCounts[DES_CON] > num0Proportional;
if ( (tableIsAutoWidth && (perAdjTableWidth - totalAllocated > 0)) ||
(!tableIsAutoWidth && (totalAllocated < maxWidth)) ) {
if (totalCounts[PCT] != mNumCols) {
if (totalCounts[PCT] != numCols) {
//PRBool onlyAuto = (totalCounts[DES_CON] > 0) && !mIsNavQuirksMode;
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
if (PCT == allocTypes[colX]) {
allocTypes[colX] = -1;
}
@ -350,7 +338,7 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
}
// give the proportional cols the rest up to the max width in quirks mode
else if (tableIsAutoWidth && mIsNavQuirksMode && (totalCounts[MIN_PRO] > 0)) {
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
if (DES_CON != allocTypes[colX]) {
allocTypes[colX] = -1;
}
@ -369,7 +357,8 @@ void BasicTableLayoutStrategy::AllocateFully(nscoord& aTotalAllocated,
PRInt32 aWidthType,
PRBool aMarkAllocated)
{
for (PRInt32 colX = 0; colX < mNumCols; colX++) {
PRInt32 numCols = mTableFrame->GetColCount();
for (PRInt32 colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord oldWidth = mTableFrame->GetColumnWidth(colX);
nscoord newWidth = colFrame->GetWidth(aWidthType);
@ -408,13 +397,14 @@ void BasicTableLayoutStrategy::AllocateUnconstrained(PRInt32 aAllocAmount,
PRInt32 numColsAllocated = 0;
PRInt32 totalAllocated = 0;
PRInt32 colX;
for (colX = 0; colX < mNumCols; colX++) {
PRInt32 numCols = mTableFrame->GetColCount();
for (colX = 0; colX < numCols; colX++) {
if (-1 != aAllocTypes[colX]) {
divisor += mTableFrame->GetColumnWidth(colX);
numColsAllocated++;
}
}
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
if (-1 != aAllocTypes[colX]) {
if (aSkip0Proportional) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
@ -703,9 +693,10 @@ BasicTableLayoutStrategy::ComputeColspanWidths(PRInt32 aWidthIndex,
// and calculate min/max table width
PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth)
{
if (gsDebugAssign) {printf("AssignPrelimColWidths en max=%d\n", aMaxWidth); mTableFrame->Dump(PR_TRUE, PR_FALSE);}
if (gsDebugAssign) {printf("AssignPrelimColWidths en max=%d\n", aMaxWidth); mTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE);}
PRBool rv = PR_FALSE;
PRInt32 numRows = mTableFrame->GetRowCount();
PRInt32 numCols = mTableFrame->GetColCount();
nscoord spacingX = mTableFrame->GetCellSpacingX();
PRInt32 colX, rowX;
mCellSpacingTotal = 0;
@ -713,12 +704,12 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
PRInt32 propTotal = 0; // total of numbers of the type 1*, 2*, etc
PRInt32 numColsForColsAttr = 0; // Nav Quirks cols attribute for equal width cols
if (NS_STYLE_TABLE_COLS_NONE != mCols) {
numColsForColsAttr = (NS_STYLE_TABLE_COLS_ALL == mCols) ? mNumCols : mCols;
numColsForColsAttr = (NS_STYLE_TABLE_COLS_ALL == mCols) ? numCols : mCols;
}
// For every column, determine it's min and desired width based on cell style
// base on cells which do not span cols. Also, determine mCellSpacingTotal
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nscoord minWidth = 0;
nscoord desWidth = 0;
nscoord fixWidth = WIDTH_NOT_SET;
@ -794,6 +785,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
// proportional width on a col or Nav Quirks cols attr
if (fixWidth <= 0) {
nscoord proportion = WIDTH_NOT_SET;
#ifdef foobar
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)colPosition);
if (eStyleUnit_Proportional == colPosition->mWidth.GetUnit()) {
@ -806,6 +798,19 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
proportion = WIDTH_NOT_SET;
}
}
#else
nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
if (eStyleUnit_Proportional == colStyleWidth.GetUnit()) {
proportion = colStyleWidth.GetIntValue();
}
else if (colX < numColsForColsAttr) {
proportion = 1;
if ((eStyleUnit_Percent == colStyleWidth.GetUnit()) &&
(colStyleWidth.GetPercentValue() > 0.0f)) {
proportion = WIDTH_NOT_SET;
}
}
#endif
if (proportion >= 0) {
colFrame->SetWidth(MIN_PRO, proportion);
if (proportion > 0) {
@ -831,7 +836,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
nscoord minPropTotal = 0;
nscoord desPropTotal = 0;
// figure the totals of all proportional cols which support every min and desired width
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord colProp = colFrame->GetWidth(MIN_PRO);
if (colProp > 0) {
@ -846,7 +851,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
mMinToDesProportionRatio = ((float)desPropTotal) / ((float)minPropTotal);
}
// figure the cols proportional min width based on the new totals
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord colProp = colFrame->GetWidth(MIN_PRO);
if (colProp > 0) {
@ -861,7 +866,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
// Adjust the cols that each cell spans if necessary. Iterate backwards
// so that nested and/or overlaping col spans handle the inner ones first,
// ensuring more accurated calculations.
for (colX = mNumCols - 1; colX >= 0; colX--) {
for (colX = numCols - 1; colX >= 0; colX--) {
for (rowX = 0; rowX < numRows; rowX++) {
PRBool originates;
PRInt32 colSpan;
@ -878,11 +883,12 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
// Set the col's fixed width if present
// Set the table col width for each col to the content min.
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord fixColWidth = colFrame->GetWidth(FIX);
// use the style width of a col only if the col hasn't gotten a fixed width from any cell
if (fixColWidth <= 0) {
#ifdef foobar
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)colPosition);
if (eStyleUnit_Coord == colPosition->mWidth.GetUnit()) {
@ -891,13 +897,22 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
colFrame->SetWidth(FIX, fixColWidth);
}
}
#else
nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
if (eStyleUnit_Coord == colStyleWidth.GetUnit()) {
fixColWidth = colStyleWidth.GetCoordValue();
if (fixColWidth > 0) {
colFrame->SetWidth(FIX, fixColWidth);
}
}
#endif
}
nscoord minWidth = colFrame->GetMinWidth();
mTableFrame->SetColumnWidth(colX, minWidth);
}
SetMinAndMaxTableContentWidths();
if (gsDebugAssign) {printf("AssignPrelimColWidths ex\n"); mTableFrame->Dump(PR_TRUE, PR_FALSE);}
if (gsDebugAssign) {printf("AssignPrelimColWidths ex\n"); mTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE);}
return rv;
}
@ -906,6 +921,7 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
PRBool aTableIsAutoWidth)
{
PRInt32 numRows = mTableFrame->GetRowCount();
PRInt32 numCols = mTableFrame->GetColCount();
nscoord spacingX = mTableFrame->GetCellSpacingX();
PRInt32 colX, rowX;
nscoord basis = aBasisIn;
@ -918,7 +934,7 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
PRInt32 numPerCols = 0; // number of colums that have percentage constraints
nscoord prefWidthTotal = 0;// total of des/fix widths of cols that don't have percentage constraints
basis = 0; // basis to use for percentages, computed considering percentage values
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord colBasis = -1;
// Scan the cells in the col
@ -950,6 +966,7 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
}
if (-1 == colBasis) {
// see if the col has a style percent width specified
#ifdef foobar
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)colPosition);
if (eStyleUnit_Percent == colPosition->mWidth.GetUnit()) {
@ -960,6 +977,17 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
colBasis = NSToCoordRound((float)desWidth / percent);
}
}
#else
nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
if (eStyleUnit_Percent == colStyleWidth.GetUnit()) {
float percent = colStyleWidth.GetPercentValue();
colBasis = 0;
if (percent > 0.0f) {
nscoord desWidth = colFrame->GetDesWidth();
colBasis = NSToCoordRound((float)desWidth / percent);
}
}
#endif
}
basis = PR_MAX(basis, colBasis);
nscoord fixWidth = colFrame->GetFixWidth();
@ -976,7 +1004,7 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
return 0;
}
// If there is only one col and it is % based, it won't affect anything
if ((1 == mNumCols) && (mNumCols == numPerCols)) {
if ((1 == numCols) && (numCols == numPerCols)) {
return 0;
}
// compute a basis considering total percentages and the desired width of everything else
@ -995,12 +1023,12 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
}
nscoord colPctTotal = 0;
nscoord* colPcts = new nscoord[mNumCols];
nscoord* colPcts = new nscoord[numCols];
if (!colPcts) return 0;
// Determine the percentage contribution for cols and for cells with colspan = 1
// Iterate backwards, similarly to the reasoning in AssignPreliminaryColumnWidths
for (colX = mNumCols - 1; colX >= 0; colX--) {
for (colX = numCols - 1; colX >= 0; colX--) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord maxColPctWidth = WIDTH_NOT_SET;
float maxColPct = 0.0f;
@ -1039,12 +1067,20 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
}
if (WIDTH_NOT_SET == maxColPctWidth) {
// see if the col has a style percent width specified
#ifdef foobar
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)colPosition);
if (eStyleUnit_Percent == colPosition->mWidth.GetUnit()) {
maxColPct = colPosition->mWidth.GetPercentValue();
maxColPctWidth = NSToCoordRound( ((float)basis) * maxColPct );
}
#else
nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
if (eStyleUnit_Percent == colStyleWidth.GetUnit()) {
maxColPct = colStyleWidth.GetPercentValue();
maxColPctWidth = NSToCoordRound( ((float)basis) * maxColPct );
}
#endif
}
// conflicting pct/fixed widths are recorded. Nav 4.x may be changing the
// fixed width value if it exceeds the pct value and not recording the pct
@ -1066,7 +1102,7 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
// For each col, consider the cells originating in it with colspans > 1.
// Adjust the cols that each cell spans if necessary.
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
for (rowX = 0; rowX < numRows; rowX++) {
PRBool originates;
PRInt32 colSpan;
@ -1162,7 +1198,7 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
// if the percent total went over 100%, adjustments need to be made to right most cols
if (colPctTotal > 100) {
for (colX = mNumCols - 1; colX >= 0; colX--) {
for (colX = numCols - 1; colX >= 0; colX--) {
if (colPcts[colX] > 0) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord newPct = colPcts[colX] - (colPctTotal - 100);
@ -1197,10 +1233,11 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
PRBool BasicTableLayoutStrategy::RecomputeAdjMinIfNecessary()
{
PRInt32 numRows = mTableFrame->GetRowCount();
PRInt32 numCols = mTableFrame->GetColCount();
PRInt32 colX, rowX, spanX;
PRBool spansPercent = PR_FALSE;
for (colX = mNumCols - 1; colX >= 0; colX--) {
for (colX = numCols - 1; colX >= 0; colX--) {
for (rowX = 0; rowX < numRows; rowX++) {
PRBool originates;
PRInt32 colSpan;
@ -1233,7 +1270,7 @@ PRBool BasicTableLayoutStrategy::RecomputeAdjMinIfNecessary()
nscoord spacingX = mTableFrame->GetCellSpacingX();
for (colX = mNumCols - 1; colX >= 0; colX--) {
for (colX = numCols - 1; colX >= 0; colX--) {
for (rowX = 0; rowX < numRows; rowX++) {
PRBool originates;
PRInt32 colSpan;
@ -1267,7 +1304,8 @@ void BasicTableLayoutStrategy::SetMinAndMaxTableContentWidths()
mMaxTableContentWidth = 0;
nscoord spacingX = mTableFrame->GetCellSpacingX();
for (PRInt32 colX = 0; colX < mNumCols; colX++) {
PRInt32 numCols = mTableFrame->GetColCount();
for (PRInt32 colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
mMinTableContentWidth += colFrame->GetMinWidth();
mMaxTableContentWidth += PR_MAX(colFrame->GetDesWidth(), colFrame->GetFixWidth());
@ -1302,7 +1340,8 @@ void BasicTableLayoutStrategy::CalculateTotals(PRInt32& aCellSpacing,
a0ProportionalCount = 0;
nscoord spacingX = mTableFrame->GetCellSpacingX();
for (PRInt32 colX = 0; colX < mNumCols; colX++) {
PRInt32 numCols = mTableFrame->GetColCount();
for (PRInt32 colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
if (mTableFrame->GetNumCellsOriginatingInCol(colX) > 0) {
aCellSpacing += spacingX;
@ -1387,7 +1426,7 @@ void BasicTableLayoutStrategy::CalculateTotals(PRInt32& aCellSpacing,
aMinWidths[DES_CON] += minCol;
}
// if it is not a degenerate table, add the last spacing on the right
if (mNumCols > 0) {
if (numCols > 0) {
aCellSpacing += spacingX;
}
}
@ -1508,11 +1547,12 @@ void BasicTableLayoutStrategy::AllocateConstrained(PRInt32 aAvailWidth,
return;
}
PRInt32 numCols = mTableFrame->GetColCount();
PRInt32 numConstrainedCols = 0;
nscoord sumMaxConstraints = 0;
PRBool useAdj = PR_TRUE;
PRInt32 colX;
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame, useAdj)) {
if (-1 != aAllocTypes[colX]) {
@ -1539,7 +1579,7 @@ void BasicTableLayoutStrategy::AllocateConstrained(PRInt32 aAvailWidth,
PRInt32 maxMinDiff = 0;
PRInt32 constrColX = 0;
// set the col info entries for each constrained col
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame, useAdj)) {
if (-1 != aAllocTypes[colX]) {
@ -1810,11 +1850,16 @@ PRBool BasicTableLayoutStrategy::ColIsSpecifiedAsMinimumWidth(PRInt32 aColIndex)
PRBool result = PR_FALSE;
nsTableColFrame* colFrame;
mTableFrame->GetColumnFrame(aColIndex, colFrame);
#ifdef foobar
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)colPosition);
switch (colPosition->mWidth.GetUnit()) {
#else
nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
switch (colStyleWidth.GetUnit()) {
#endif
case eStyleUnit_Coord:
if (0 == colPosition->mWidth.GetCoordValue()) {
if (0 == colStyleWidth.GetCoordValue()) {
result = PR_TRUE;
}
break;
@ -1823,14 +1868,14 @@ PRBool BasicTableLayoutStrategy::ColIsSpecifiedAsMinimumWidth(PRInt32 aColIndex)
// total hack for now for 0% and 1% specifications
// should compare percent to available parent width and see that it is below minimum
// for this column
float percent = colPosition->mWidth.GetPercentValue();
float percent = colStyleWidth.GetPercentValue();
if (0.0f == percent || 0.01f == percent) {
result = PR_TRUE;
}
break;
}
case eStyleUnit_Proportional:
if (0 == colPosition->mWidth.GetIntValue()) {
if (0 == colStyleWidth.GetIntValue()) {
result = PR_TRUE;
}
@ -1849,8 +1894,8 @@ void BasicTableLayoutStrategy::Dump(PRInt32 aIndent)
}
indent[aIndent] = 0;
printf("%s**START BASIC STRATEGY DUMP** table=%p cols=%X numCols=%d",
indent, mTableFrame, mCols, mNumCols);
printf("%s**START BASIC STRATEGY DUMP** table=%p cols=%X",
indent, mTableFrame, mCols);
printf("\n%s minConWidth=%d maxConWidth=%d cellSpacing=%d propRatio=%.2f navQuirks=%d",
indent, mMinTableContentWidth, mMaxTableContentWidth, mCellSpacingTotal, mMinToDesProportionRatio, mIsNavQuirksMode);
printf(" **END BASIC STRATEGY DUMP** \n");

View File

@ -57,11 +57,9 @@ public:
/** call every time any table thing changes that might effect the width of any column
* in the table (content, structure, or style)
* @param aMaxElementSize [OUT] if not null, the max element size is computed and returned in this param
* @param aNumCols the total number of columns in the table
*/
virtual PRBool Initialize(nsSize* aMaxElementSize,
PRInt32 aNumCols,
nscoord aMaxSize);
virtual PRBool Initialize(nsSize* aMaxElementSize,
nscoord aMaxSize);
/** compute the max element size of the table.
* assumes that Initialize has been called
@ -83,7 +81,6 @@ public:
nscoord GetTableMinContentWidth() const;
nscoord GetTableMaxContentWidth() const;
nscoord GetCOLSAttribute() const;
nscoord GetNumCols() const;
void Dump(PRInt32 aIndent);
protected:
@ -159,13 +156,6 @@ protected:
PRInt32* aAllocTypes,
PRBool aSkip0Proportional);
/** return true if the style indicates that the width is a specific width
* for the purposes of column width determination.
* return false if the width changes based on content, parent size, etc.
*/
static PRBool IsFixedWidth(const nsStylePosition* aStylePosition,
const nsStyleTable* aStyleTable);
/** return true if the colIndex is in the list of colIndexes */
virtual PRBool IsColumnInList(const PRInt32 colIndex,
PRInt32 *colIndexes,
@ -214,7 +204,6 @@ protected:
protected:
nsTableFrame * mTableFrame;
PRInt32 mCols;
PRInt32 mNumCols;
// cached data
nscoord mMinTableContentWidth; // the smallest size for the table (excluding border and padding)
nscoord mMaxTableContentWidth; // the "natural" size for the table, if unconstrained (excluding border and padding)
@ -233,9 +222,6 @@ inline nscoord BasicTableLayoutStrategy::GetTableMaxContentWidth() const
inline nscoord BasicTableLayoutStrategy::GetCOLSAttribute() const
{ return mCols; };
inline nscoord BasicTableLayoutStrategy::GetNumCols() const
{ return mNumCols; };
#endif

View File

@ -59,7 +59,6 @@ PRBool FixedTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aT
PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputedWidth)
{
// NS_ASSERTION(aComputedWidth != NS_UNCONSTRAINEDSIZE, "bad computed width");
const nsStylePosition* tablePosition;
mTableFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)tablePosition);
PRBool tableIsFixedWidth = eStyleUnit_Coord == tablePosition->mWidth.GetUnit() ||
@ -70,24 +69,25 @@ PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputed
nsMargin borderPadding;
tableSpacing->CalcBorderPaddingFor(mTableFrame, borderPadding);
PRInt32 numCols = mTableFrame->GetColCount();
PRInt32 colX;
// availWidth is used as the basis for percentage width columns. It is aComputedWidth
// minus table border, padding, & cellspacing
nscoord availWidth = aComputedWidth - borderPadding.left - borderPadding.right -
((mNumCols + 1) * mTableFrame->GetCellSpacingX());
((numCols + 1) * mTableFrame->GetCellSpacingX());
PRInt32 specifiedCols = 0; // the number of columns whose width is given
nscoord totalColWidth = 0; // the sum of the widths of the columns
nscoord* colWidths = new PRBool[mNumCols];
nsCRT::memset(colWidths, WIDTH_NOT_SET, mNumCols*sizeof(nscoord));
nscoord* colWidths = new PRBool[numCols];
nsCRT::memset(colWidths, WIDTH_NOT_SET, numCols*sizeof(nscoord));
nscoord* propInfo = new PRBool[mNumCols];
nsCRT::memset(propInfo, 0, mNumCols*sizeof(nscoord));
nscoord* propInfo = new PRBool[numCols];
nsCRT::memset(propInfo, 0, numCols*sizeof(nscoord));
nscoord propTotal = 0;
// for every column, determine its specified width
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
// Get column information
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
if (!colFrame) {
@ -115,6 +115,7 @@ PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputed
propTotal += propInfo[colX];
}
else { // get width from the cell
nsTableCellFrame* cellFrame = mTableFrame->GetCellFrameAt(0, colX);
if (nsnull != cellFrame) {
// Get the cell's style
@ -148,7 +149,7 @@ PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputed
if (0 < remainingWidth) {
if (propTotal > 0) {
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
if (propInfo[colX] > 0) {
// We're proportional
float percent = ((float)propInfo[colX])/((float)propTotal);
@ -159,10 +160,10 @@ PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputed
}
}
else if (tableIsFixedWidth) {
if (mNumCols > specifiedCols) {
if (numCols > specifiedCols) {
// allocate the extra space to the columns which have no width specified
nscoord colAlloc = NSToCoordRound( ((float)remainingWidth) / (((float)mNumCols) - ((float)specifiedCols)));
for (colX = 0; colX < mNumCols; colX++) {
nscoord colAlloc = NSToCoordRound( ((float)remainingWidth) / (((float)numCols) - ((float)specifiedCols)));
for (colX = 0; colX < numCols; colX++) {
if (-1 == colWidths[colX]) {
colWidths[colX] = colAlloc;
totalColWidth += colAlloc;
@ -172,7 +173,7 @@ PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputed
}
else { // allocate the extra space to the columns which have width specified
float divisor = (float)totalColWidth;
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
if (colWidths[colX] > 0) {
nscoord colAlloc = NSToCoordRound(remainingWidth * colWidths[colX] / divisor);
colWidths[colX] += colAlloc;
@ -187,7 +188,7 @@ PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputed
nscoord overAllocation = (availWidth >= 0)
? totalColWidth - availWidth : 0;
// set the column widths
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
if (colWidths[colX] < 0)
colWidths[colX] = 0;
// if there was too much allocated due to rounding, remove it from the last col

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,22 @@
#include "nsVoidArray.h"
class nsTableColFrame;
class nsTableCellFrame;
class nsIPresContext;
// XXX the collapsing row and col data structures need to be moved
// into nsTableFrame. Collapsing cols are broken due to the recent
// incremental cell map methods which don't attempt to update
// collapsing col info here.
struct nsColInfo
{
PRInt32 mNumCellsOrig; // number of cells originating in the col
PRInt32 mNumCellsSpan; // number of cells spanning into the col via colspans (not rowspans)
nsColInfo();
nsColInfo(PRInt32 aNumCellsOrig,
PRInt32 aNumCellsSpan);
};
/** nsCellMap is a support class for nsTablePart.
* It maintains an Rows x Columns grid onto which the cells of the table are mapped.
@ -60,23 +76,29 @@ public:
CellData* GetCellAt(PRInt32 aRowIndex,
PRInt32 aColIndex) const;
/** insert a new row into the map
makes a blank row and adjusts spans
*/
void InsertRowIntoMap(PRInt32 aRowIndex);
/** removes a row from the map and adjusts spans
*/
void RemoveRowFromMap(PRInt32 aRowIndex);
void AppendCol();
/** append the cellFrame at the end of the row at aRowIndex and return the col index
*/
PRInt32 AppendCell(nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
PRInt32 aRowIndex,
PRBool aRebuildIfNecessary);
void InsertCells(nsVoidArray& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndexBefore);
void RemoveCell(nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
void InsertRows(nsVoidArray& aRows,
PRInt32 aFirstRowIndex,
PRBool aConsiderSpans);
void RemoveRows(PRInt32 aFirstRowIndex,
PRInt32 aNumRowsToRemove,
PRBool aConsiderSpans);
PRInt32 GetNextAvailRowIndex();
PRInt32 GetEffectiveColSpan(nsTableCellFrame* aCell) const;
@ -102,17 +124,6 @@ public:
/** return the actual number of rows in the table represented by this CellMap */
PRInt32 GetRowCount() const;
/** return the column frame associated with aColIndex */
nsTableColFrame* GetColumnFrame(PRInt32 aColIndex) const;
/** add a column frame to the list of column frames
* column frames must be added in order
*/
void AppendColumnFrame(nsTableColFrame *aColFrame);
/** empty the column frame cache */
void ClearColumnCache();
// temporary until nsTableFrame::GetCellData uses GetCellFrameAt
nsTableCellFrame* GetCellFrameOriginatingAt(PRInt32 aRowX,
PRInt32 aColX) const;
@ -123,6 +134,7 @@ public:
PRInt32* aColSpan = nsnull) const;
void AddColsAtEnd(PRUint32 aNumCols);
PRInt32 RemoveUnusedCols(PRInt32 aMaxNumToRemove);
PRBool RowIsSpannedInto(PRInt32 aRowIndex) const;
PRBool RowHasSpanningCells(PRInt32 aRowIndex) const;
@ -156,23 +168,48 @@ protected:
CellData* GetMapCellAt(PRInt32 aMapRowIndex,
PRInt32 aColIndex) const;
PRInt32 GetNumCellsIn(PRInt32 aColIndex,
PRBool aOriginating) const;
PRInt32 GetNumCellsIn(PRInt32 aColIndex) const;
void ExpandWithRows(nsVoidArray& aRowFrames,
PRInt32 aStartRowIndex);
void ExpandWithCells(nsVoidArray& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRInt32 aRowSpan);
void ShrinkWithoutRows(PRInt32 aFirstRowIndex,
PRInt32 aNumRowsToRemove);
void ShrinkWithoutCell(nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex,
PRInt32 aColIndex);
void RebuildConsideringRows(PRInt32 aStartRowIndex,
nsVoidArray* aRowsToInsert,
PRInt32 aNumRowsToRemove = 0);
void RebuildConsideringCells(nsVoidArray* aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool aInsert);
PRBool CellsSpanOut(nsVoidArray& aNewRows);
PRBool CellsSpanInOrOut(PRInt32 aStartRowIndex,
PRInt32 aEndRowIndex,
PRInt32 aStartColIndex,
PRInt32 aEndColIndex);
PRBool CreateEmptyRow(PRInt32 aRowIndex,
PRInt32 aNumCols);
/** an array containing col array. It can be larger than mRowCount due to
* row spans extending beyond the table */
nsVoidArray mRows;
/** an array of col frames. It is as large as mRowCount */
nsVoidArray mColFrames;
/** an array of PRInt32 indexed by row and giving the number of cells originating
* in each row. */
nsVoidArray mNumCellsOrigInRow;
/** an array of PRInt32 indexed by col and giving the number of cells originating
* in each col. */
nsVoidArray mNumCellsOrigInCol;
/** an array of nsColInfo indexed by col and giving the number of
* cells originating and spanning each col. */
nsVoidArray mCols;
// an array of booleans where the ith element indicates if the ith row is collapsed
PRPackedBool* mIsCollapsedRows;
@ -196,7 +233,7 @@ inline CellData* nsCellMap::GetCellAt(PRInt32 aRowIndex,
PRInt32 aColIndex) const
{
if ((0 > aRowIndex) || (aRowIndex >= mRowCount) ||
(0 > aColIndex) || (aColIndex >= mNumCellsOrigInCol.Count())) {
(0 > aColIndex) || (aColIndex >= mCols.Count())) {
//bug 9024 tickled this
//printf("%s \n", "nsCellMap::GetCellAt called with invalid row or col index"); // XXX look at this when bug 10911 get fixed
return nsnull;
@ -213,7 +250,7 @@ inline CellData* nsCellMap::GetMapCellAt(PRInt32 aMapRowIndex,
PRInt32 aColIndex) const
{
if ((0 > aMapRowIndex) || (aMapRowIndex >= mRows.Count()) ||
(0 > aColIndex) || (aColIndex >= mNumCellsOrigInCol.Count())) {
(0 > aColIndex) || (aColIndex >= mCols.Count())) {
//see bug 9024 comments above
//printf("%s \n", "nsCellMap::GetMapCellAt called with invalid row or col index"); // XXX look at this when bug 10911 get fixed
return nsnull;
@ -228,7 +265,7 @@ inline CellData* nsCellMap::GetMapCellAt(PRInt32 aMapRowIndex,
inline PRInt32 nsCellMap::GetColCount() const
{
return mNumCellsOrigInCol.Count();
return mCols.Count();
}
inline PRInt32 nsCellMap::GetRowCount() const
@ -236,15 +273,16 @@ inline PRInt32 nsCellMap::GetRowCount() const
return mRowCount;
}
inline void nsCellMap::AppendColumnFrame(nsTableColFrame *aColFrame)
{
mColFrames.AppendElement(aColFrame);
}
// nsColInfo
inline void nsCellMap::ClearColumnCache()
{
mColFrames.Clear();
}
inline nsColInfo::nsColInfo()
:mNumCellsOrig(0), mNumCellsSpan(0)
{}
inline nsColInfo::nsColInfo(PRInt32 aNumCellsOrig,
PRInt32 aNumCellsSpan)
:mNumCellsOrig(aNumCellsOrig), mNumCellsSpan(aNumCellsSpan)
{}
#endif

View File

@ -38,11 +38,9 @@ public:
/** call once every time any table thing changes (content, structure, or style)
* @param aMaxElementSize [OUT] if not null, the max element size is computed and returned in this param
* @param aNumCols the total number of columns in the table
* @param aComputedWidth the computed size of the table
*/
virtual PRBool Initialize(nsSize* aMaxElementSize,
PRInt32 aNumCols,
nscoord aComputedWidth)=0;
/** compute the max-element-size for the table
@ -80,9 +78,6 @@ public:
/** return the value of the COLS attribute, used for balancing column widths */
virtual nscoord GetCOLSAttribute() const = 0;
/** return the total number of columns in the table */
virtual nscoord GetNumCols() const = 0;
// see nsTableFrame::ColumnsCanBeInvalidatedBy
virtual PRBool ColumnsCanBeInvalidatedBy(nsStyleCoord* aPrevStyleWidth,
const nsTableCellFrame& aCellFrame) const = 0;

View File

@ -146,8 +146,6 @@ void nsTableBorderCollapser::ComputeVerticalBorders(nsIPresContext* aPresContext
//if (nsnull == cellMap)
// return; // no info yet, so nothing useful to do
mTableFrame.CacheColFrames(aPresContext); // XXX why here?
// compute all the collapsing border values for the entire table
// XXX: we have to make this more incremental!
@ -305,7 +303,7 @@ void nsTableBorderCollapser::ComputeRightBorderForEdgeAt(nsIPresContext* aPresCo
styles.AppendElement((void*)spacing);
}
// 2. colgroup //XXX: need to test if we're really on a colgroup border
nsTableColFrame* colFrame = cellMap->GetColumnFrame(aColIndex);
nsTableColFrame* colFrame = mTableFrame.GetColFrame(aColIndex);
nsIFrame* colGroupFrame;
colFrame->GetParent(&colGroupFrame);
colGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
@ -402,7 +400,7 @@ void nsTableBorderCollapser::ComputeTopBorderForEdgeAt(nsIPresContext* aPresCont
mTableFrame.GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 2. colgroup
nsTableColFrame* colFrame = cellMap->GetColumnFrame(aColIndex);
nsTableColFrame* colFrame = mTableFrame.GetColFrame(aColIndex);
nsIFrame* colGroupFrame;
colFrame->GetParent(&colGroupFrame);
colGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
@ -521,7 +519,7 @@ void nsTableBorderCollapser::ComputeBottomBorderForEdgeAt(nsIPresContext* aPresC
styles.AppendElement((void*)spacing);
// 2. colgroup // XXX: need to deterine if we're on a colgroup boundary
nsTableColFrame* colFrame = cellMap->GetColumnFrame(aColIndex);
nsTableColFrame* colFrame = mTableFrame.GetColFrame(aColIndex);
nsIFrame* colGroupFrame;
colFrame->GetParent(&colGroupFrame);
colGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));

View File

@ -71,10 +71,9 @@ nsTableCellFrame::Init(nsIPresContext* aPresContext,
if (aPrevInFlow) {
// Set the column index
nsTableCellFrame* cellFrame = (nsTableCellFrame*)aPrevInFlow;
PRInt32 baseColIndex;
cellFrame->GetColIndex(baseColIndex);
InitCellFrame(baseColIndex);
PRInt32 colIndex;
cellFrame->GetColIndex(colIndex);
InitCellFrame(colIndex);
}
return rv;
@ -139,29 +138,24 @@ nsTableCellFrame::RemoveFrame(nsIPresContext* aPresContext,
void nsTableCellFrame::InitCellFrame(PRInt32 aColIndex)
{
NS_PRECONDITION(0<=aColIndex, "bad col index arg");
SetColIndex(aColIndex); // this also sets the contents col index
nsTableFrame* tableFrame=nsnull; // I should be checking my own style context, but border-collapse isn't inheriting correctly
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
{
if (NS_STYLE_BORDER_COLLAPSE == tableFrame->GetBorderCollapseStyle())
{
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame)) {
SetColIndex(aColIndex);
if (NS_STYLE_BORDER_COLLAPSE == tableFrame->GetBorderCollapseStyle()) {
mBorderEdges = new nsBorderEdges;
mBorderEdges->mOutsideEdge=PR_FALSE;
PRInt32 rowspan = GetRowSpan();
PRInt32 i;
for (i=0; i<rowspan; i++)
{
for (i=0; i<rowspan; i++) {
nsBorderEdge *borderToAdd = new nsBorderEdge();
mBorderEdges->mEdges[NS_SIDE_LEFT].AppendElement(borderToAdd);
borderToAdd = new nsBorderEdge();
mBorderEdges->mEdges[NS_SIDE_RIGHT].AppendElement(borderToAdd);
}
PRInt32 colspan = GetColSpan();
for (i=0; i<colspan; i++)
{
for (i=0; i<colspan; i++) {
nsBorderEdge *borderToAdd = new nsBorderEdge();
mBorderEdges->mEdges[NS_SIDE_TOP].AppendElement(borderToAdd);
borderToAdd = new nsBorderEdge();

View File

@ -19,6 +19,7 @@
*
* Contributor(s):
*/
#include "nsCOMPtr.h"
#include "nsTableColFrame.h"
#include "nsContainerFrame.h"
#include "nsIReflowCommand.h"
@ -30,6 +31,11 @@
#include "nsCSSRendering.h"
#include "nsLayoutAtoms.h"
#define COL_TYPE_CONTENT 0x0
#define COL_TYPE_ANONYMOUS_COL 0x1
#define COL_TYPE_ANONYMOUS_COLGROUP 0x2
#define COL_TYPE_ANONYMOUS_CELL 0x3
nsTableColFrame::nsTableColFrame()
: nsFrame(),
mProportion(WIDTH_NOT_SET),
@ -38,12 +44,55 @@ nsTableColFrame::nsTableColFrame()
{
// note that all fields are initialized to 0 by nsFrame::operator new
ResetSizingInfo();
SetType(eColContent);
}
nsTableColFrame::~nsTableColFrame()
{
}
nsTableColType nsTableColFrame::GetType() const {
switch(mBits.mType) {
case COL_TYPE_ANONYMOUS_COL:
return eColAnonymousCol;
case COL_TYPE_ANONYMOUS_COLGROUP:
return eColAnonymousColGroup;
case COL_TYPE_ANONYMOUS_CELL:
return eColAnonymousCell;
default:
return eColContent;
}
}
void nsTableColFrame::SetType(nsTableColType aType) {
mBits.mType = aType - eColContent;
}
// XXX what about other style besides width
nsStyleCoord nsTableColFrame::GetStyleWidth() const
{
nsStylePosition* position = nsnull;
position = (nsStylePosition*)mStyleContext->GetStyleData(eStyleStruct_Position);
nsStyleCoord styleWidth = position->mWidth;
// the following should not be necessary since html.css defines table-col and
// :table-col to inherit. However, :table-col is not inheriting properly
if (eStyleUnit_Auto == styleWidth.GetUnit()) {
nsIFrame* parent;
GetParent(&parent);
nsCOMPtr<nsIStyleContext> styleContext;
parent->GetStyleContext(getter_AddRefs(styleContext));
if (styleContext) {
position = (nsStylePosition*)styleContext->GetStyleData(eStyleStruct_Position);
styleWidth = position->mWidth;
}
}
nsStyleCoord returnWidth;
returnWidth.mUnit = styleWidth.mUnit;
returnWidth.mValue = styleWidth.mValue;
return returnWidth;
}
void nsTableColFrame::ResetSizingInfo()
{
nsCRT::memset(mWidths, WIDTH_NOT_SET, NUM_WIDTHS * sizeof(PRInt32));

View File

@ -55,6 +55,13 @@ enum nsColConstraint {
e0ProportionConstraint = 4 // 0*, means to force to min width
};
enum nsTableColType {
eColContent = 0, // there is real col content associated
eColAnonymousCol = 1, // the result of a span on a col
eColAnonymousColGroup = 2, // the result of a span on a col group
eColAnonymousCell = 3, // the result of a cell alone
};
class nsTableColFrame : public nsFrame {
public:
@ -63,7 +70,8 @@ public:
eWIDTH_SOURCE_CELL_WITH_SPAN=2 // a cell implicitly specified a width via colspan
};
void InitColFrame(PRInt32 aColIndex);
nsTableColType GetType() const;
void nsTableColFrame::SetType(nsTableColType aType);
/** instantiate a new instance of nsTableColFrame.
* @param aResult the new object is returned in this out-param
@ -75,6 +83,12 @@ public:
friend nsresult
NS_NewTableColFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
nsStyleCoord GetStyleWidth() const;
PRInt32 GetColIndex() const;
void SetColIndex (PRInt32 aColIndex);
NS_IMETHOD Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
@ -97,15 +111,9 @@ public:
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
#endif
/** return the index of the column the col represents. always >= 0 */
virtual PRInt32 GetColumnIndex ();
/** return the number of the columns the col represents. always >= 0 */
virtual PRInt32 GetSpan ();
/** set the index of the column this content object represents. must be >= 0 */
virtual void SetColumnIndex (int aColIndex);
/** convenience method, calls into cellmap */
nsVoidArray * GetCells();
@ -138,6 +146,11 @@ public:
protected:
struct ColBits {
unsigned int mType:4;
unsigned int mUnused:28;
} mBits;
nsTableColFrame();
~nsTableColFrame();
@ -153,18 +166,11 @@ protected:
PRPackedBool mNonPercentSpansPercent;
};
inline void nsTableColFrame::InitColFrame(PRInt32 aColIndex)
{
NS_ASSERTION(0<=aColIndex, "bad col index param");
mColIndex = aColIndex;
}
inline PRInt32 nsTableColFrame::GetColumnIndex()
inline PRInt32 nsTableColFrame::GetColIndex() const
{ return mColIndex; }
inline void nsTableColFrame::SetColumnIndex (int aColIndex)
{ mColIndex = aColIndex;}
inline void nsTableColFrame::SetColIndex (PRInt32 aColIndex)
{ mColIndex = aColIndex; }
inline nsColConstraint nsTableColFrame::GetConstraint() const
{ return mConstraint; }

View File

@ -23,6 +23,7 @@
#include "nsTableColFrame.h"
#include "nsTableFrame.h"
#include "nsIHTMLTableColElement.h"
#include "nsIDOMHTMLTableColElement.h"
#include "nsIReflowCommand.h"
#include "nsIStyleContext.h"
#include "nsStyleConsts.h"
@ -40,101 +41,230 @@
NS_DEF_PTR(nsIContent);
static NS_DEFINE_IID(kIHTMLTableColElementIID, NS_IHTMLTABLECOLELEMENT_IID);
static NS_DEFINE_IID(kIDOMHTMLTableColElementIID, NS_IDOMHTMLTABLECOLELEMENT_IID);
#define COLGROUP_TYPE_CONTENT 0x0
#define COLGROUP_TYPE_ANONYMOUS_COL 0x1
#define COLGROUP_TYPE_ANONYMOUS_CELL 0x2
nsTableColGroupType nsTableColGroupFrame::GetType() const {
switch(mBits.mType) {
case COLGROUP_TYPE_ANONYMOUS_COL:
return eColGroupAnonymousCol;
case COLGROUP_TYPE_ANONYMOUS_CELL:
return eColGroupAnonymousCell;
default:
return eColGroupContent;
}
}
void nsTableColGroupFrame::SetType(nsTableColGroupType aType) {
mBits.mType = aType - eColGroupContent;
}
void nsTableColGroupFrame::ResetColIndices(nsIFrame* aFirstColGroup,
PRInt32 aFirstColIndex,
nsIFrame* aStartColFrame)
{
nsTableColGroupFrame* colGroupFrame = (nsTableColGroupFrame*)aFirstColGroup;
PRInt32 colIndex = aFirstColIndex;
while (colGroupFrame) {
nsIAtom* cgType;
colGroupFrame->GetFrameType(&cgType);
if (nsLayoutAtoms::tableColGroupFrame == cgType) {
colGroupFrame->SetStartColumnIndex(colIndex);
nsIFrame* colFrame = aStartColFrame;
if (!colFrame || (colIndex != aFirstColIndex)) {
colGroupFrame->FirstChild(nsnull, &colFrame);
}
while (colFrame) {
nsIAtom* colType;
colFrame->GetFrameType(&colType);
if (nsLayoutAtoms::tableColFrame == colType) {
((nsTableColFrame*)colFrame)->SetColIndex(colIndex);
colIndex++;
}
NS_IF_RELEASE(colType);
colFrame->GetNextSibling(&colFrame);
}
}
NS_IF_RELEASE(cgType);
colGroupFrame->GetNextSibling((nsIFrame**)&colGroupFrame);
}
}
NS_IMETHODIMP
nsTableColGroupFrame::InitNewFrames(nsIPresContext* aPresContext, nsIFrame* aChildList)
nsTableColGroupFrame::AddColsToTable(nsIPresContext& aPresContext,
PRInt32 aFirstColIndex,
PRBool aResetSubsequentColIndices,
nsIFrame* aFirstFrame,
nsIFrame* aLastFrame)
{
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
nsresult rv=NS_OK;
nsTableFrame* tableFrame=nsnull;
nsresult rv = NS_OK;
nsTableFrame* tableFrame = nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame)) {
// Process the newly added column frames
for (nsIFrame* kidFrame = aChildList; nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame)) {
const nsStyleDisplay* display;
kidFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)display);
if (NS_STYLE_DISPLAY_TABLE_COLUMN == display->mDisplay) {
// Set the preliminary values for the column frame
PRInt32 colIndex = mStartColIndex + mColCount;
((nsTableColFrame *)(kidFrame))->InitColFrame (colIndex);
PRInt32 repeat = ((nsTableColFrame *)(kidFrame))->GetSpan();
mColCount += repeat;
for (PRInt32 i=0; i<repeat; i++) {
tableFrame->AddColumnFrame((nsTableColFrame *)kidFrame);
}
}
}
// colgroup's span attribute is how many columns the group represents
// in the absence of any COL children
// Note that this is the correct, though perhaps unexpected, behavior for the span attribute.
// The spec says that if there are any COL children, the colgroup's span is ignored.
if (0==mColCount)
{
nsIFrame *firstImplicitColFrame=nsnull;
nsIFrame *prevColFrame=nsnull;
nsAutoString colTag;
nsHTMLAtoms::col->ToString(colTag);
mColCount = GetSpan();
for (PRInt32 colIndex=0; colIndex<mColCount; colIndex++)
{
nsIHTMLContent *col=nsnull;
// create an implicit col
rv = NS_CreateHTMLElement(&col, colTag); // ADDREF: col++
//XXX mark the col implicit
mContent->AppendChildTo((nsIContent*)col, PR_FALSE);
// Create a new col frame
nsIFrame* colFrame;
NS_NewTableColFrame(shell, &colFrame);
// Set its style context
nsCOMPtr<nsIStyleContext> colStyleContext;
aPresContext->ResolveStyleContextFor(col, mStyleContext,
PR_TRUE,
getter_AddRefs(colStyleContext));
colFrame->Init(aPresContext, col, this, colStyleContext, nsnull);
colFrame->SetInitialChildList(aPresContext, nsnull, nsnull);
// Set nsColFrame-specific information
PRInt32 absColIndex = mStartColIndex + colIndex;
((nsTableColFrame *)(colFrame))->InitColFrame (absColIndex);
((nsTableColFrame *)colFrame)->SetColumnIndex(absColIndex);
tableFrame->AddColumnFrame((nsTableColFrame *)colFrame);
//hook into list of children
if (nsnull==firstImplicitColFrame)
firstImplicitColFrame = colFrame;
else
prevColFrame->SetNextSibling(colFrame);
prevColFrame = colFrame;
}
// hook new columns into col group child list
mFrames.AppendFrames(nsnull, firstImplicitColFrame);
}
SetStyleContextForFirstPass(aPresContext);
if (!(NS_SUCCEEDED(rv) && tableFrame && aFirstFrame)) {
return rv;
}
// set the col indices of the col frames and and add col info to the table
PRInt32 colIndex = aFirstColIndex;
nsIFrame* kidFrame = aFirstFrame;
PRBool foundLastFrame = PR_FALSE;
while (kidFrame) {
nsIAtom* kidType;
kidFrame->GetFrameType(&kidType);
if (nsLayoutAtoms::tableColFrame == kidType) {
((nsTableColFrame*)kidFrame)->SetColIndex(colIndex);
if (!foundLastFrame) {
tableFrame->InsertCol(aPresContext, (nsTableColFrame &)*kidFrame, colIndex);
mColCount++;
}
colIndex++;
}
NS_IF_RELEASE(kidType);
if (kidFrame == aLastFrame) {
foundLastFrame = PR_TRUE;
}
kidFrame->GetNextSibling(&kidFrame);
}
if (aResetSubsequentColIndices) {
nsIFrame* nextSibling;
GetNextSibling(&nextSibling);
if (nextSibling) {
ResetColIndices(nextSibling, colIndex);
}
}
return rv;
}
NS_IMETHODIMP
nsTableColGroupFrame::AppendNewFrames(nsIPresContext* aPresContext, nsIFrame* aChildList)
// this is called when a col frame doesn't have an explicit col group parent.
nsTableColGroupFrame*
nsTableColGroupFrame::FindParentForAppendedCol(nsTableFrame* aTableFrame,
nsTableColType aColType)
{
if (nsnull!=aChildList)
mFrames.AppendFrames(nsnull, aChildList);
return NS_OK;
nsVoidArray& cols = aTableFrame->GetColCache();
PRInt32 numCols = cols.Count();
nsIFrame* lastColGroup;
nsIFrame* lastCol = (nsIFrame*)cols.ElementAt(numCols - 1);
if (!lastCol) return nsnull; // no columns so no colgroups
lastCol->GetParent(&lastColGroup);
if (!lastColGroup) return nsnull; // shouldn't happen
nsTableColGroupFrame* relevantColGroup = (nsTableColGroupFrame *)lastColGroup;
nsTableColGroupType relevantColGroupType = relevantColGroup->GetType();
if (eColGroupAnonymousCell == relevantColGroupType) {
if (eColAnonymousCell == aColType) {
return relevantColGroup;
}
else {
// find the next to last col group
for (PRInt32 colX = numCols - 2; colX >= 0; colX--) {
nsTableColFrame* colFrame = (nsTableColFrame*)cols.ElementAt(colX);
nsTableColGroupFrame* colGroupFrame;
colFrame->GetParent((nsIFrame**)&colGroupFrame);
nsTableColGroupType cgType = colGroupFrame->GetType();
if (cgType != relevantColGroupType) {
relevantColGroup = colGroupFrame;
relevantColGroupType = cgType;
break;
}
else if (0 == colX) {
return nsnull;
}
}
}
}
if (eColGroupAnonymousCol == relevantColGroupType) {
if ((eColContent == aColType) || (eColAnonymousCol == aColType)) {
return relevantColGroup;
}
}
return nsnull;
}
PRBool
nsTableColGroupFrame::GetLastRealColGroup(nsTableFrame* aTableFrame,
nsIFrame** aLastColGroup)
{
*aLastColGroup = nsnull;
nsFrameList colGroups = aTableFrame->GetColGroups();
nsIFrame* nextToLastColGroup = nsnull;
nsIFrame* lastColGroup = colGroups.FirstChild();
while(lastColGroup) {
nsIFrame* next;
lastColGroup->GetNextSibling(&next);
if (next) {
nextToLastColGroup = lastColGroup;
lastColGroup = next;
}
else {
break;
}
}
if (!lastColGroup) return PR_TRUE; // there are no col group frames
nsTableColGroupType lastColGroupType = ((nsTableColGroupFrame *)lastColGroup)->GetType();
if (eColGroupAnonymousCell == lastColGroupType) {
*aLastColGroup = nextToLastColGroup;
return PR_FALSE;
}
else {
*aLastColGroup = lastColGroup;
return PR_TRUE;
}
}
// don't set mColCount here, it is done in AddColsToTable
NS_IMETHODIMP
nsTableColGroupFrame::SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
nsresult result = AppendNewFrames(aPresContext, aChildList);
if (NS_OK==result)
result = InitNewFrames(aPresContext, aChildList);
return result;
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
if (!aChildList) {
nsIFrame* firstChild;
tableFrame->CreateAnonymousColFrames(*aPresContext, *this, GetSpan(), eColAnonymousColGroup,
PR_FALSE, nsnull, &firstChild);
if (firstChild) {
SetInitialChildList(aPresContext, aListName, firstChild);
}
return NS_OK;
}
nsIFrame* kidFrame = aChildList;
while (kidFrame) {
nsIAtom* kidType;
kidFrame->GetFrameType(&kidType);
if (nsLayoutAtoms::tableColFrame == kidType) {
// Set the preliminary values for the column frame
PRInt32 span = ((nsTableColFrame*)kidFrame)->GetSpan();
if (span > 1) {
nsTableColFrame* firstSpannedCol;
tableFrame->CreateAnonymousColFrames(*aPresContext, *this, span - 1, eColAnonymousCol,
PR_FALSE, (nsTableColFrame*)kidFrame, (nsIFrame **)&firstSpannedCol);
nsIFrame* spanner = kidFrame;
kidFrame->GetNextSibling(&kidFrame); // need to do this before we insert the new frames
nsFrameList newChildren(aChildList); // used as a convience to hook up siblings
newChildren.InsertFrames(this, (nsTableColFrame*)spanner, (nsIFrame *)firstSpannedCol);
NS_RELEASE(kidType);
continue;
}
}
NS_IF_RELEASE(kidType);
kidFrame->GetNextSibling(&kidFrame);
}
mFrames.AppendFrames(this, aChildList);
return NS_OK;
}
// Helper function. It marks the table frame as dirty and generates
@ -173,35 +303,8 @@ nsTableColGroupFrame::AppendFrames(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aFrameList)
{
// Append the new frames to our child list
mFrames.AppendFrames(nsnull, aFrameList);
// Reset the starting column index of the col groups that follow
PRInt32 startingColIndex = mStartColIndex;
startingColIndex += GetColumnCount(); // has the side effect of resetting all column indexes
nsIFrame *nextColGroupFrame=nsnull;
GetNextSibling(&nextColGroupFrame);
while (nextColGroupFrame)
{
const nsStyleDisplay *display;
nextColGroupFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)display);
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
{
startingColIndex += ((nsTableColGroupFrame *)nextColGroupFrame)->SetStartColumnIndex(startingColIndex);
}
nextColGroupFrame->GetNextSibling(&nextColGroupFrame);
}
// Today we need to rebuild the whole column cache.
// If the table frame is ever recoded to build the column cache incrementally,
// we could take advantage of that here
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
tableFrame->InvalidateColumnCache();
// Generate a reflow command so we reflow the table
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
mFrames.AppendFrames(this, aFrameList);
InsertColsReflow(*aPresContext, aPresShell, mColCount, aFrameList);
return NS_OK;
}
@ -209,76 +312,121 @@ NS_IMETHODIMP
nsTableColGroupFrame::InsertFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aPrevFrameIn,
nsIFrame* aFrameList)
{
// Insert the new frames into our child list
mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
nsFrameList frames(aFrameList); // convience for getting last frame
nsIFrame* lastFrame = frames.LastChild();
// Reset the starting column index of the col groups that follow
PRInt32 startingColIndex=mStartColIndex;
startingColIndex += GetColumnCount(); // has the side effect of resetting all column indexes
mFrames.InsertFrames(this, aPrevFrameIn, aFrameList);
nsIFrame* prevFrame = nsTableFrame::GetFrameAtOrBefore(this, aPrevFrameIn,
nsLayoutAtoms::tableColFrame);
nsIFrame *nextColGroupFrame=nsnull;
GetNextSibling(&nextColGroupFrame);
while (nextColGroupFrame)
{
const nsStyleDisplay *display;
nextColGroupFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)display);
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
{
startingColIndex += ((nsTableColGroupFrame *)nextColGroupFrame)->SetStartColumnIndex(startingColIndex);
}
nextColGroupFrame->GetNextSibling(&nextColGroupFrame);
}
PRInt32 colIndex = (prevFrame) ? ((nsTableColFrame*)prevFrame)->GetColIndex() + 1 : 0;
InsertColsReflow(*aPresContext, aPresShell, colIndex, aFrameList, lastFrame);
// Today we need to rebuild the whole column cache.
// If the table frame is ever recoded to build the column cache incrementally,
// we could take advantage of that here.
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
tableFrame->InvalidateColumnCache();
// Generate a reflow command so we reflow the table
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
return NS_OK;
}
void
nsTableColGroupFrame::InsertColsReflow(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
PRInt32 aColIndex,
nsIFrame* aFirstFrame,
nsIFrame* aLastFrame)
{
AddColsToTable(aPresContext, aColIndex, PR_TRUE, aFirstFrame, aLastFrame);
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
tableFrame->InvalidateColumnWidths();
// Generate a reflow command so we reflow the table
AddTableDirtyReflowCommand(&aPresContext, aPresShell, tableFrame);
}
void
nsTableColGroupFrame::RemoveChild(nsIPresContext& aPresContext,
nsTableColFrame& aChild,
PRBool aResetColIndices)
{
PRInt32 colIndex = 0;
nsIFrame* nextChild = nsnull;
if (aResetColIndices) {
colIndex = aChild.GetColIndex();
aChild.GetNextSibling(&nextChild);
}
if (mFrames.DestroyFrame(&aPresContext, (nsIFrame*)&aChild)) {
mColCount--;
if (aResetColIndices) {
ResetColIndices(this, colIndex, nextChild);
}
}
}
// this removes children form the last col group (eColGroupAnonymousCell) in the
// table only,so there is no need to reset col indices for subsequent col groups.
void
nsTableColGroupFrame::RemoveChildrenAtEnd(nsIPresContext& aPresContext,
PRInt32 aNumChildrenToRemove)
{
PRInt32 numToRemove = aNumChildrenToRemove;
if (numToRemove > mColCount) {
NS_ASSERTION(PR_FALSE, "invalid arg to RemoveChildrenAtEnd");
numToRemove = mColCount;
}
PRInt32 offsetOfFirstRemoval = mColCount - numToRemove;
PRInt32 offsetX = 0;
nsIFrame* kidFrame = mFrames.FirstChild();
while(kidFrame) {
nsIAtom* kidType;
kidFrame->GetFrameType(&kidType);
if (nsLayoutAtoms::tableColFrame == kidType) {
offsetX++;
if (offsetX > offsetOfFirstRemoval) {
nsIFrame* byebye = kidFrame;
kidFrame->GetNextSibling(&kidFrame);
mFrames.DestroyFrame(&aPresContext, byebye);
NS_RELEASE(kidType);
continue;
}
}
NS_IF_RELEASE(kidType);
kidFrame->GetNextSibling(&kidFrame);
}
}
NS_IMETHODIMP
nsTableColGroupFrame::RemoveFrame(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame)
{
// Remove the frame from our child list
mFrames.DestroyFrame(aPresContext, aOldFrame);
if (!aOldFrame) return NS_OK;
// Reset the starting column index of the col groups that follow
PRInt32 startingColIndex=mStartColIndex;
startingColIndex += GetColumnCount(); // has the side effect of resetting all column indexes
nsIFrame *nextColGroupFrame=nsnull;
GetNextSibling(&nextColGroupFrame);
while (nextColGroupFrame)
{
const nsStyleDisplay *display;
nextColGroupFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)display);
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
{
startingColIndex += ((nsTableColGroupFrame *)nextColGroupFrame)->SetStartColumnIndex(startingColIndex);
nsIAtom* frameType = nsnull;
aOldFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableColFrame == frameType) {
nsTableColFrame* colFrame = (nsTableColFrame*)aOldFrame;
PRInt32 colIndex = colFrame->GetColIndex();
RemoveChild(*aPresContext, *colFrame, PR_TRUE);
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
if (tableFrame) {
tableFrame->RemoveCol(*aPresContext, this, colIndex, PR_TRUE, PR_TRUE);
}
nextColGroupFrame->GetNextSibling(&nextColGroupFrame);
tableFrame->InvalidateColumnWidths();
// Generate a reflow command so we reflow the table
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
}
else {
mFrames.DestroyFrame(aPresContext, aOldFrame);
}
NS_IF_RELEASE(frameType);
// Today we need to rebuild the whole column cache.
// If the table frame is ever recoded to build the column cache incrementally,
// we could take advantage of that here
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
tableFrame->InvalidateColumnCache();
// Generate a reflow command so we reflow the table
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
return NS_OK;
}
@ -429,11 +577,10 @@ NS_METHOD nsTableColGroupFrame::IR_StyleChanged(nsIPresContext* aPresCo
nsresult rv = NS_OK;
// we presume that all the easy optimizations were done in the nsHTMLStyleSheet before we were called here
// XXX: we can optimize this when we know which style attribute changed
nsTableFrame* tableFrame=nsnull;
nsTableFrame* tableFrame = nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
{
tableFrame->InvalidateColumnCache();
if ((NS_SUCCEEDED(rv)) && tableFrame) {
tableFrame->InvalidateColumnWidths();
tableFrame->InvalidateFirstPassCache();
}
return rv;
@ -448,7 +595,7 @@ NS_METHOD nsTableColGroupFrame::IR_TargetIsChild(nsIPresContext* aPresC
nsresult rv;
// Remember the old col count
const PRInt32 oldColCount = GetColumnCount();
const PRInt32 oldColCount = GetColCount();
// Pass along the reflow command
nsHTMLReflowMetrics desiredSize(nsnull);
@ -462,136 +609,16 @@ NS_METHOD nsTableColGroupFrame::IR_TargetIsChild(nsIPresContext* aPresC
nsTableFrame *tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
{
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame)) {
// compare the new col count to the old col count.
// If they are the same, we just need to rebalance column widths
// If they differ, we need to fix up other column groups and the column cache
const PRInt32 newColCount = GetColumnCount(); // this will set the new column indexes if necessary
if (oldColCount==newColCount)
tableFrame->InvalidateColumnWidths();
else
tableFrame->InvalidateColumnCache();
const PRInt32 newColCount = GetColCount();
tableFrame->InvalidateColumnWidths();
}
return rv;
}
// Subclass hook for style post processing
NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext* aPresContext)
{
// get the table frame
nsTableFrame* tableFrame=nsnull;
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
{
// get the style for the table frame
const nsStyleTable *tableStyle;
tableFrame->GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
// if COLS is set, then map it into the COL frames
if (NS_STYLE_TABLE_COLS_NONE != tableStyle->mCols)
{
// set numCols to the number of columns effected by the COLS attribute
PRInt32 numCols=0;
if (NS_STYLE_TABLE_COLS_ALL == tableStyle->mCols)
numCols = mFrames.GetLength();
else
numCols = tableStyle->mCols;
// for every column effected, set its width style
PRInt32 colIndex=0;
nsIFrame *colFrame=mFrames.FirstChild();
while (nsnull!=colFrame)
{
const nsStyleDisplay * colDisplay=nsnull;
colFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)colDisplay));
if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
{
nsCOMPtr<nsIStyleContext> colStyleContext;
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleContext(getter_AddRefs(colStyleContext));
colPosition = (nsStylePosition*)colStyleContext->GetMutableStyleData(eStyleStruct_Position);
if (colIndex<numCols)
{
nsStyleCoord width (1, eStyleUnit_Proportional);
colPosition->mWidth = width;
}
else
{
colPosition->mWidth.SetCoordValue(0);
}
colStyleContext->RecalcAutomaticData(aPresContext);
colIndex++;
}
colFrame->GetNextSibling(&colFrame);
}
}
else
{
// propagate the colgroup width attribute down to the columns if they have no width of their own
nsStylePosition* position = (nsStylePosition*)mStyleContext->GetStyleData(eStyleStruct_Position);
if (eStyleUnit_Null!=position->mWidth.GetUnit())
{
// now for every column that doesn't have it's own width, set the width style
nsIFrame *colFrame=mFrames.FirstChild();
while (nsnull!=colFrame)
{
const nsStyleDisplay * colDisplay=nsnull;
colFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)colDisplay));
if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
{
nsCOMPtr<nsIStyleContext> colStyleContext;
const nsStylePosition * colPosition=nsnull;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)colPosition); // get a read-only version of the style context
//XXX: how do I know this is auto because it's defaulted, vs. set explicitly to "auto"?
if (eStyleUnit_Auto==colPosition->mWidth.GetUnit())
{
// notice how we defer getting a mutable style context until we're sure we really need one
colFrame->GetStyleContext(getter_AddRefs(colStyleContext));
nsStylePosition * mutableColPosition = (nsStylePosition*)colStyleContext->GetMutableStyleData(eStyleStruct_Position);
mutableColPosition->mWidth = position->mWidth;
colStyleContext->RecalcAutomaticData(aPresContext);
}
}
colFrame->GetNextSibling(&colFrame);
}
}
}
//mStyleContext->RecalcAutomaticData(aPresContext);
}
return rv;
}
/** returns the number of columns represented by this group.
* if there are col children, count them (taking into account the span of each)
* else, check my own span attribute.
*/
int nsTableColGroupFrame::GetColumnCount ()
{
mColCount=0;
nsIFrame *childFrame = mFrames.FirstChild();
while (nsnull!=childFrame)
{
const nsStyleDisplay *childDisplay;
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay)
{
nsTableColFrame *col = (nsTableColFrame *)childFrame;
col->SetColumnIndex (mStartColIndex + mColCount);
mColCount += col->GetSpan();
}
childFrame->GetNextSibling(&childFrame);
}
if (0==mColCount)
{ // there were no children of this colgroup that were columns. So use my span attribute
const nsStyleTable *tableStyle;
GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
mColCount = tableStyle->mSpan;
}
return mColCount;
}
nsTableColFrame * nsTableColGroupFrame::GetFirstColumn()
{
return GetNextColumn(nsnull);
@ -642,28 +669,26 @@ nsTableColFrame * nsTableColGroupFrame::GetColumnAt (PRInt32 aColIndex)
PRInt32 nsTableColGroupFrame::GetSpan()
{
PRInt32 span=1;
const nsStyleTable* tableStyle=nsnull;
GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
if (nsnull!=tableStyle)
{
span = tableStyle->mSpan;
PRInt32 span = 1;
nsCOMPtr<nsIContent> iContent;
nsresult rv = GetContent(getter_AddRefs(iContent));
if (NS_FAILED(rv) || !iContent) return rv;
// col group element derives from col element
nsIDOMHTMLTableColElement* cgContent = nsnull;
rv = iContent->QueryInterface(kIDOMHTMLTableColElementIID,
(void **)&cgContent);
if (cgContent && NS_SUCCEEDED(rv)) {
cgContent->GetSpan(&span);
// XXX why does this work!!
if (span == -1) {
span = 1;
}
NS_RELEASE(cgContent);
}
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.
@ -671,15 +696,41 @@ PRBool nsTableColGroupFrame::IsManufactured()
PRInt32 nsTableColGroupFrame::SetStartColumnIndex (int aIndex)
{
PRInt32 result = mColCount;
if (aIndex != mStartColIndex)
{
if (aIndex != mStartColIndex) {
mStartColIndex = aIndex;
mColCount=0;
result = GetColumnCount(); // has the side effect of setting each column index based on new start index
result = GetColCount();
}
return result;
}
// this could be optimized by using col group frame starting indicies,
// but typically there aren't enough very large col groups for the added complexity.
nsTableColGroupFrame*
nsTableColGroupFrame::GetColGroupFrameContaining(nsFrameList& aColGroupList,
nsTableColFrame& aColFrame)
{
nsIFrame* childFrame = aColGroupList.FirstChild();
while (childFrame) {
nsIAtom* frameType = nsnull;
childFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableColGroupFrame == frameType) {
nsTableColFrame* colFrame = nsnull;
childFrame->FirstChild(nsnull, (nsIFrame **)&colFrame);
while (colFrame) {
if (colFrame = &aColFrame) {
NS_RELEASE(frameType);
return (nsTableColGroupFrame *)childFrame;
}
colFrame->GetNextSibling((nsIFrame **)&colFrame);
}
}
NS_IF_RELEASE(frameType);
childFrame->GetNextSibling(&childFrame);
}
return nsnull;
}
void nsTableColGroupFrame::DeleteColFrame(nsIPresContext* aPresContext, nsTableColFrame* aColFrame)
{
mFrames.DestroyFrame(aPresContext, aColFrame);

View File

@ -26,7 +26,14 @@
#include "nsHTMLContainerFrame.h"
class nsTableColFrame;
class nsTableFrame;
enum nsTableColType;
enum nsTableColGroupType {
eColGroupContent = 0, // there is real col group content associated
eColGroupAnonymousCol = 1, // the result of a col
eColGroupAnonymousCell = 2, // the result of a cell alone
};
/**
* nsTableColGroupFrame
@ -52,6 +59,16 @@ public:
nsIAtom* aListName,
nsIFrame* aChildList);
nsTableColGroupType GetType() const;
void SetType(nsTableColGroupType aType);
static PRBool GetLastRealColGroup(nsTableFrame* aTableFrame,
nsIFrame** aLastColGroup);
static nsTableColGroupFrame* FindParentForAppendedCol(nsTableFrame* aTableFrame,
nsTableColType aColType);
NS_IMETHOD AppendFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
@ -66,6 +83,13 @@ public:
nsIAtom* aListName,
nsIFrame* aOldFrame);
void RemoveChild(nsIPresContext& aPresContext,
nsTableColFrame& aLastChild,
PRBool aResetColIndices);
void RemoveChildrenAtEnd(nsIPresContext& aPresContext,
PRInt32 aNumChildrenToRemove);
NS_IMETHOD Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
@ -89,6 +113,12 @@ public:
*/
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
NS_IMETHOD AddColsToTable(nsIPresContext& aPresContext,
PRInt32 aFirstColIndex,
PRBool aResetSubsequentColIndices,
nsIFrame* aFirstFrame,
nsIFrame* aLastFrame = nsnull);
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsString& aResult) const;
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
@ -98,7 +128,7 @@ 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 GetColCount() const;
virtual nsTableColFrame * GetFirstColumn();
@ -124,23 +154,25 @@ public:
void DeleteColFrame(nsIPresContext* aPresContext, nsTableColFrame* aColFrame);
protected:
static nsTableColGroupFrame* GetColGroupFrameContaining(nsFrameList& aColGroupList,
nsTableColFrame& aColFrame);
nsFrameList& GetChildList();
static void ResetColIndices(nsIFrame* aFirstColGroup,
PRInt32 aFirstColIndex,
nsIFrame* aStartColFrame = nsnull);
protected:
nsTableColGroupFrame();
void InsertColsReflow(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
PRInt32 aColIndex,
nsIFrame* aFirstFrame,
nsIFrame* aLastFrame = nsnull);
/** implement abstract method on nsHTMLContainerFrame */
virtual PRIntn GetSkipSides() const;
/** Hook for style post processing.
* Since we need to know the full column structure before the COLS attribute
* can be interpreted, we can't just use DidSetStyleContext
*/
NS_IMETHOD SetStyleContextForFirstPass(nsIPresContext* aPresContext);
NS_IMETHOD InitNewFrames(nsIPresContext* aPresContext, nsIFrame* aChildList);
NS_IMETHOD AppendNewFrames(nsIPresContext* aPresContext, nsIFrame* aChildList);
NS_IMETHOD IncrementalReflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
@ -174,13 +206,33 @@ protected:
/** the starting column index this col group represents. Must be >= 0. */
PRInt32 mStartColIndex;
struct ColGroupBits {
unsigned int mType:4;
unsigned int mUnused:28;
} mBits;
};
inline nsTableColGroupFrame::nsTableColGroupFrame()
: mColCount(0), mStartColIndex(0)
{}
{
mBits.mType = 0;
}
inline int nsTableColGroupFrame::GetStartColumnIndex ()
{ return mStartColIndex;}
inline PRInt32 nsTableColGroupFrame::GetStartColumnIndex()
{
return mStartColIndex;
}
inline PRInt32 nsTableColGroupFrame::GetColCount() const
{
return mColCount;
}
inline nsFrameList& nsTableColGroupFrame::GetChildList()
{
return mFrames;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,8 @@ class nsHTMLValue;
struct InnerTableReflowState;
struct nsStylePosition;
struct nsStyleSpacing;
enum nsTableColType;
enum nsTableColGroupType;
/**
* Child list name indices
@ -124,8 +126,14 @@ public:
/** helper method to find the table parent of any table frame object */
// TODO: today, this depends on display types. This should be changed to rely
// on stronger criteria, like an inner table frame atom
static NS_METHOD GetTableFrame(nsIFrame *aSourceFrame, nsTableFrame *& aTableFrame);
static NS_METHOD GetTableFrame(nsIFrame* aSourceFrame,
nsTableFrame*& aTableFrame);
// Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
// of type aChildType.
static nsIFrame* nsTableFrame::GetFrameAtOrBefore(nsIFrame* aParentFrame,
nsIFrame* aPriorChildFrame,
nsIAtom* aChildType);
/**
* @param aReflowState the context within which we're to determine the table width info
* @param aSpecifiedTableWidth [OUT] if the table is not auto-width,
@ -143,10 +151,6 @@ public:
PRBool IsRowGroup(PRInt32 aDisplayType) const;
/** Initialize the table frame with a set of children.
* Calls DidAppendRowGroup which calls nsTableRowFrame::InitChildren
* which finally calls back into this table frame to build the cell map.
* Also ensures we have the right number of column frames for the child list.
*
* @see nsIFrame::SetInitialChildList
*/
NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext,
@ -162,16 +166,6 @@ public:
NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex,
nsIAtom** aListName) const;
/** complete the append of aRowGroupFrame to the table
* this builds the cell map by calling nsTableRowFrame::InitChildren
* which calls back into this table frame to build the cell map.
* @param aRowGroupFrame the row group that was appended.
* note that this method is optimized for content appended, and doesn't
* work for random insertion of row groups. Random insertion must go
* through incremental reflow notifications.
*/
NS_IMETHOD DidAppendRowGroup(nsTableRowGroupFrame *aRowGroupFrame);
/** @see nsIFrame::Paint */
NS_IMETHOD Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -221,6 +215,8 @@ public:
*/
NS_METHOD GetColumnFrame(PRInt32 aColIndex, nsTableColFrame *&aColFrame);
nsFrameList& GetColGroups();
/** return PR_TRUE if the column width information has been set */
PRBool IsColumnWidthsSet();
@ -308,14 +304,84 @@ public:
*/
PRInt32 GetNextAvailRowIndex() const;
/** build as much of the CellMap as possible from the info we have so far
*/
virtual PRInt32 AddCellToTable (nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
virtual void RemoveCellFromTable (nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
/** return the column frame associated with aColIndex */
nsTableColFrame* GetColFrame(PRInt32 aColIndex) const;
virtual void AddColumnFrame (nsTableColFrame *aColFrame);
void InsertCol(nsIPresContext& aPresContext,
nsTableColFrame& aColFrame,
PRInt32 aColIndex);
nsTableColGroupFrame* CreateAnonymousColGroupFrame(nsIPresContext& aPresContext,
nsTableColGroupType aType);
PRInt32 DestroyAnonymousColFrames(nsIPresContext& aPresContext,
PRInt32 aNumFrames);
void CreateAnonymousColFrames(nsIPresContext& aPresContext,
PRInt32 aNumColsToAdd,
nsTableColType aColType,
PRBool aDoAppend,
nsIFrame* aPrevCol = nsnull);
void CreateAnonymousColFrames(nsIPresContext& aPresContext,
nsTableColGroupFrame& aColGroupFrame,
PRInt32 aNumColsToAdd,
nsTableColType aColType,
PRBool aAddToColGroupAndTable,
nsIFrame* aPrevCol,
nsIFrame** aFirstNewFrame);
/** empty the column frame cache */
void ClearColCache();
virtual PRInt32 AppendCell(nsIPresContext& aPresContext,
nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex);
virtual void InsertCells(nsIPresContext& aPresContext,
nsVoidArray& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndexBefore);
virtual void RemoveCell(nsIPresContext& aPresContext,
nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
void AppendRows(nsIPresContext& aPresContext,
nsVoidArray& aRowFrames);
PRInt32 InsertRow(nsIPresContext& aPresContext,
nsIFrame& aFrame,
PRInt32 aRowIndex,
PRBool aConsiderSpans);
PRInt32 InsertRows(nsIPresContext& aPresContext,
nsVoidArray& aFrames,
PRInt32 aRowIndex,
PRBool aConsiderSpans);
virtual void RemoveRows(nsIPresContext& aPresContext,
PRInt32 aFirstRowFrame,
PRInt32 aNumRowsToRemove,
PRBool aConsiderSpans);
void AppendRowGroups(nsIPresContext& aPresContext,
nsIFrame* aFirstRowGroupFrame);
void InsertRowGroups(nsIPresContext& aPresContext,
nsIFrame* aFirstRowGroupFrame,
PRInt32 aRowIndex);
void InsertColGroups(nsIPresContext& aPresContext,
PRInt32 aColIndex,
nsIFrame* aFirstFrame,
nsIFrame* aLastFrame = nsnull);
virtual void RemoveCol(nsIPresContext& aPresContext,
nsTableColGroupFrame* aColGroupFrame,
PRInt32 aColIndex,
PRBool aRemoveFromCache,
PRBool aRemoveFromCellMap);
static PRBool IsFinalPass(const nsHTMLReflowState& aReflowState);
@ -323,7 +389,7 @@ public:
PRInt32 aColX,
PRBool* aOriginates = nsnull,
PRInt32* aColSpan = nsnull);
PRInt32 GetNumCellsOriginatingInRow(PRInt32 aRowIndex) const;
PRInt32 GetNumCellsOriginatingInCol(PRInt32 aColIndex) const;
NS_METHOD GetBorderPlusMarginPadding(nsMargin& aResult);
@ -554,9 +620,6 @@ 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;
/** returns PR_TRUE if the cached column info is still valid */
virtual PRBool IsColumnWidthsValid() const;
@ -612,8 +675,6 @@ public:
virtual void InvalidateFirstPassCache();
virtual void InvalidateColumnCache();
virtual void InvalidateColumnWidths();
protected:
@ -623,38 +684,18 @@ protected:
void MapHTMLBorderStyle(nsStyleSpacing& aSpacingStyle, nscoord aBorderWidth);
PRBool ConvertToPixelValue(nsHTMLValue& aValue, PRInt32 aDefault, PRInt32& aResult);
/** returns PR_TRUE if the cached pass 1 data is still valid */
virtual PRBool IsCellMapValid() const;
public:
/** Get the cell map for this table frame. It is not always mCellMap.
* Only the firstInFlow has a legit cell map
*/
virtual nsCellMap *GetCellMap() const;
/** ResetCellMap is called when the cell structure of the table is changed.
* Call with caution, only when changing the structure of the table such as
* inserting or removing rows, changing the rowspan or colspan attribute of a cell, etc.
*/
virtual void InvalidateCellMap();
/** sum the columns represented by all nsTableColGroup objects.
* if the cell map says there are more columns than this,
* add extra implicit columns to the content tree.
*
* returns whether any implicit column frames were created
*/
virtual void EnsureColumns (nsIPresContext* aPresContext,
PRBool& aCreatedColFrames);
// These methods are used to incrementally insert and remove rows
// from the cell map without having to invalidate the entire map.
NS_IMETHOD InsertRowIntoMap(nsTableRowFrame* aRow, PRInt32 aRowIndex);
NS_IMETHOD RemoveRowFromMap(nsTableRowFrame* aRow, PRInt32 aRowIndex);
void AdjustRowIndices(PRInt32 aRowIndex,
PRInt32 aAdjustment);
NS_IMETHOD AdjustRowIndices(nsIFrame* aRowGroup,
PRInt32 aRowIndex,
PRInt32 anAdjustment);
PRInt32 aRowIndex,
PRInt32 anAdjustment);
// Return PR_TRUE if rules=groups is set for the table content
PRBool HasGroupRules() const;
@ -662,9 +703,9 @@ public:
// Remove cell borders which aren't bordering row and/or col groups
void ProcessGroupRules(nsIPresContext* aPresContext);
nsVoidArray& GetColCache();
protected:
/** iterates all child frames and creates a new cell map */
NS_IMETHOD ReBuildCellMap();
void SetColumnDimensions(nsIPresContext* aPresContext, nscoord aHeight);
@ -685,7 +726,14 @@ protected:
/**
* Return aFrame's child if aFrame is an nsScrollFrame, otherwise return aFrame
*/
nsTableRowGroupFrame* GetRowGroupFrameFor(nsIFrame* aFrame, const nsStyleDisplay* aDisplay);
nsTableRowGroupFrame* GetRowGroupFrameFor(nsIFrame* aFrame,
const nsStyleDisplay* aDisplay);
nsTableRowGroupFrame* GetRowGroupFrame(nsIFrame* aFrame,
nsIAtom* aFrameTypeIn = nsnull);
void CollectRows(nsIFrame* aFrame,
nsVoidArray& aCollection);
public: /* ----- Cell Map public methods ----- */
@ -752,14 +800,16 @@ public: /* ----- Cell Map public methods ----- */
/*------------end of nsITableLayout methods -----------------------*/
virtual void CacheColFrames(nsIPresContext* aPresContext,
PRBool aReset = PR_FALSE);
public:
static nsIAtom* gColGroupAtom;
void Dump(PRBool aDumpCols, PRBool aDumpCellMap);
void Dump(PRBool aDumpRows,
PRBool aDumpCols,
PRBool aDumpCellMap);
nsVoidArray mColFrames; // XXX temporarily public
protected:
void DumpRowGroup(nsIFrame* aChildFrame);
void DebugPrintCount() const; // Debugging routine
// data members
@ -770,15 +820,11 @@ protected:
unsigned mColumnWidthsSet:1; // PR_TRUE if column widths have been set at least once
unsigned mColumnWidthsValid:1; // PR_TRUE if column width data is still legit, PR_FALSE if it needs to be recalculated
unsigned mFirstPassValid:1; // PR_TRUE if first pass data is still legit, PR_FALSE if it needs to be recalculated
unsigned mColumnCacheValid:1; // PR_TRUE if column cache info is still legit, PR_FALSE if it needs to be recalculated
unsigned mCellMapValid:1; // PR_TRUE if cell map data is still legit, PR_FALSE if it needs to be recalculated
unsigned mIsInvariantWidth:1; // PR_TRUE if table width cannot change
unsigned mHasScrollableRowGroup:1; // PR_TRUE if any section has overflow == "auto" or "scroll"
unsigned mNonPercentSpansPercent:1;
int : 24; // unused
int : 26; // unused
} mBits;
PRInt32 mColCount; // the number of columns in this table
nsCellMap* mCellMap; // maintains the relationships between rows, cols, and cells
nsITableLayoutStrategy * mTableLayoutStrategy; // the layout strategy for this frame
nsFrameList mColGroups; // the list of colgroup frames
@ -811,6 +857,16 @@ inline void nsTableFrame::SetHasNonPercentSpanningPercent(PRBool aValue)
mBits.mNonPercentSpansPercent = (unsigned)aValue;
}
inline nsFrameList& nsTableFrame::GetColGroups()
{
return mColGroups;
}
inline nsVoidArray& nsTableFrame::GetColCache()
{
return mColFrames;
}
enum nsTableIteration {
eTableLTR = 0,
eTableRTL = 1,

View File

@ -56,6 +56,7 @@ nsTableRowFrame::nsTableRowFrame()
mAllBits(0)
{
mBits.mMinRowSpan = 1;
mBits.mRowIndex = 0;
}
NS_IMETHODIMP
@ -129,23 +130,11 @@ nsTableRowFrame::AppendFrames(nsIPresContext* aPresContext,
if (NS_STYLE_DISPLAY_TABLE_CELL == display->mDisplay) {
// Add the cell to the cell map
PRInt32 colIndex = tableFrame->AddCellToTable((nsTableCellFrame*)childFrame,
GetRowIndex());
// Initialize the cell frame and give it its column index
((nsTableCellFrame*)childFrame)->InitCellFrame(colIndex);
tableFrame->AppendCell(*aPresContext, (nsTableCellFrame&)*childFrame, GetRowIndex());
}
}
// See if any implicit column frames need to be created as a result of
// adding the new rows
PRBool createdColFrames;
tableFrame->EnsureColumns(aPresContext, createdColFrames);
if (createdColFrames) {
// We need to rebuild the column cache
// XXX It would be nice if this could be done incrementally
tableFrame->InvalidateColumnCache();
}
tableFrame->InvalidateColumnWidths();
// Reflow the new frames. They're already marked dirty, so generate a reflow
// command that tells us to reflow our dirty child frames
@ -160,6 +149,7 @@ nsTableRowFrame::AppendFrames(nsIPresContext* aPresContext,
return NS_OK;
}
NS_IMETHODIMP
nsTableRowFrame::InsertFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
@ -171,26 +161,39 @@ nsTableRowFrame::InsertFrames(nsIPresContext* aPresContext,
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
// Insert the frames
// gather the new frames (only those which are cells) into an array
nsTableCellFrame* prevCellFrame = (nsTableCellFrame *)nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame, nsLayoutAtoms::tableCellFrame);
nsVoidArray cellChildren;
for (nsIFrame* childFrame = aFrameList; childFrame; childFrame->GetNextSibling(&childFrame)) {
nsIAtom* frameType;
childFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableCellFrame == frameType) {
cellChildren.AppendElement(childFrame);
}
NS_IF_RELEASE(frameType);
}
// insert the cells into the cell map
PRInt32 colIndex = -1;
if (prevCellFrame) {
prevCellFrame->GetColIndex(colIndex);
}
tableFrame->InsertCells(*aPresContext, cellChildren, GetRowIndex(), colIndex);
// Insert the frames in the frame list
mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
// We need to rebuild the cell map, because currently we can't insert
// new frames except at the end (append)
tableFrame->InvalidateCellMap();
// Because the number of columns may have changed invalidate the column widths
tableFrame->InvalidateColumnWidths();
// We should try and avoid doing a pass1 reflow on all the cells and just
// do it for the newly added frames, but we need to add these frames to the
// cell map before we reflow them
tableFrame->InvalidateFirstPassCache();
// Reflow the new frames. They're already marked dirty, so generate a reflow
// command that tells us to reflow our dirty child frames
nsIReflowCommand* reflowCmd;
// Because the number of columns may have changed invalidate the column
// cache. Note that this has the side effect of recomputing the column
// widths, so we don't need to call InvalidateColumnWidths()
tableFrame->InvalidateColumnCache();
// Generate a reflow command so we reflow the table itself. This will
// do a pass-1 reflow of all the rows including any rows we just added
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
if (NS_SUCCEEDED(NS_NewHTMLReflowCommand(&reflowCmd, this,
nsIReflowCommand::ReflowDirty))) {
aPresShell.AppendReflowCommand(reflowCmd);
NS_RELEASE(reflowCmd);
}
return NS_OK;
}
@ -203,91 +206,28 @@ nsTableRowFrame::RemoveFrame(nsIPresContext* aPresContext,
// Get the table frame
nsTableFrame* tableFrame=nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
if (tableFrame) {
nsIAtom* frameType;
aOldFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableCellFrame == frameType) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)aOldFrame;
PRInt32 colIndex;
cellFrame->GetColIndex(colIndex);
tableFrame->RemoveCell(*aPresContext, cellFrame, GetRowIndex());
#if 0
// XXX Currently we can't incrementally remove cells from the cell map
PRInt32 colIndex;
aDeletedFrame->GetColIndex(colIndex);
tableFrame->RemoveCellFromTable(aOldFrame, GetRowIndex());
// Remove the frame and destroy it
mFrames.DestroyFrame(aPresContext, aOldFrame);
// Remove the frame and destroy it
mFrames.DestroyFrame(aPresContext, (nsIFrame*)aOldFrame);
// cells have possibly shifted into different columns.
tableFrame->InvalidateColumnWidths();
// XXX Reflow the row
#else
// Remove the frame and destroy it
mFrames.DestroyFrame(aPresContext, aOldFrame);
// We need to rebuild the cell map, because currently we can't incrementally
// remove rows
tableFrame->InvalidateCellMap();
// Because the number of columns may have changed invalidate the column
// cache. Note that this has the side effect of recomputing the column
// widths, so we don't need to call InvalidateColumnWidths()
tableFrame->InvalidateColumnCache();
// Because we haven't added any new frames we don't need to do a pass1
// reflow. Just generate a reflow command so we reflow the table itself
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
#endif
return NS_OK;
}
NS_IMETHODIMP
nsTableRowFrame::InitChildrenWithIndex(PRInt32 aRowIndex)
{
nsTableFrame* table = nsnull;
nsresult result=NS_OK;
// each child cell can only be added to the table one time.
// for now, we remember globally whether we've added all or none
if (0 == (mState & NS_TABLE_ROW_FRAME_INITIALIZED_CHILDREN))
{
result = nsTableFrame::GetTableFrame(this, table);
if ((NS_OK==result) && (table != nsnull))
{
mState |= NS_TABLE_ROW_FRAME_INITIALIZED_CHILDREN;
SetRowIndex(aRowIndex);
for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame))
{
const nsStyleDisplay *kidDisplay;
kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)kidDisplay));
if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay)
{
// add the cell frame to the table's cell map and get its col index
PRInt32 colIndex;
colIndex = table->AddCellToTable((nsTableCellFrame *)kidFrame, aRowIndex);
// what column does this cell belong to?
// this sets the frame's notion of its column index
((nsTableCellFrame *)kidFrame)->InitCellFrame(colIndex);
}
}
// Because we haven't added any new frames we don't need to do a pass1
// reflow. Just generate a reflow command so we reflow the table itself
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
}
NS_IF_RELEASE(frameType);
}
return NS_OK;
}
NS_IMETHODIMP
nsTableRowFrame::InitChildren()
{
nsTableFrame* table = nsnull;
nsresult result=NS_OK;
// each child cell can only be added to the table one time.
// for now, we remember globally whether we've added all or none
if (0 == (mState & NS_TABLE_ROW_FRAME_INITIALIZED_CHILDREN))
{
result = nsTableFrame::GetTableFrame(this, table);
if ((NS_OK==result) && (table != nsnull))
{
PRInt32 rowIndex = table->GetNextAvailRowIndex();
InitChildrenWithIndex(rowIndex);
}
}
return NS_OK;
}

View File

@ -62,9 +62,6 @@ struct RowReflowState {
/**
* Additional frame-state bits
*/
#define NS_TABLE_ROW_FRAME_INITIALIZED_CHILDREN 0x80000000 // set if child cells have been
// added to the table
#define NS_TABLE_MAX_ROW_INDEX (1<<19)
/**
@ -100,12 +97,6 @@ public:
nsIAtom* aListName,
nsIFrame* aOldFrame);
/** Initialization of data */
NS_IMETHOD InitChildren();
NS_IMETHOD InitChildrenWithIndex(PRInt32 aRowIndex);
void ResetInitChildren();
/** instantiate a new instance of nsTableRowFrame.
* @param aResult the new object is returned in this out-param
* @param aContent the table object to map
@ -322,11 +313,6 @@ inline void nsTableRowFrame::SetRowIndex (int aRowIndex)
mBits.mRowIndex = aRowIndex;
}
inline void nsTableRowFrame::ResetInitChildren()
{
mState &= ~NS_TABLE_ROW_FRAME_INITIALIZED_CHILDREN;
}
inline void nsTableRowFrame::GetMaxElementSize(nsSize& aMaxElementSize) const
{
aMaxElementSize.width = mMaxElementSize.width;

View File

@ -565,6 +565,7 @@ NS_METHOD nsTableRowGroupFrame::PullUpAllRowFrames(nsIPresContext* aPresContext)
void nsTableRowGroupFrame::GetNextRowSibling(nsIFrame** aRowFrame)
{
if (!*aRowFrame) return;
GetNextFrame(*aRowFrame, aRowFrame);
while(*aRowFrame) {
const nsStyleDisplay *display;
@ -596,7 +597,9 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
PRBool hasRowSpanningCell = PR_FALSE;
PRInt32 numRows;
GetRowCount(numRows, PR_FALSE);
if (numRows <= 0) return;
nscoord *rowHeights = new nscoord[numRows];
if (!rowHeights) return;
nsCRT::memset (rowHeights, 0, numRows*sizeof(nscoord));
/* Step 1: get the height of the tallest cell in the row and save it for
@ -747,10 +750,11 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
// If this is pass 2 then resize the row to its final size and move the
// row's position if the previous rows have caused a shift
if (1 == counter) {
nsRect rowBounds;
rowFrame->GetRect(rowBounds);
PRBool movedFrame = (deltaY != 0);
nsRect rowBounds;
// Move the row to the correct position
rowFrame->GetRect(rowBounds); // added
rowBounds.y += deltaY;
// Adjust our running delta
@ -759,6 +763,17 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
// Resize the row to its final size and position
rowBounds.height = rowHeights[rowIndex];
rowFrame->SetRect(aPresContext, rowBounds);
if (movedFrame) {
// Make sure any views are positioned properly
nsIView* view;
rowFrame->GetView(aPresContext, &view);
if (view) {
nsContainerFrame::PositionFrameView(aPresContext, rowFrame, view);
} else {
nsContainerFrame::PositionChildViews(aPresContext, rowFrame);
}
}
}
rowIndex++;
@ -1155,45 +1170,47 @@ nsTableRowGroupFrame::AddTableDirtyReflowCommand(nsIPresContext* aPresContext,
return rv;
}
#if 0
// Reflow the new frames. They're already marked dirty, so generate a reflow
// command that tells us to reflow our dirty child frames
nsIReflowCommand* reflowCmd;
if (NS_SUCCEEDED(NS_NewHTMLReflowCommand(&reflowCmd, this,
nsIReflowCommand::ReflowDirty))) {
aPresShell.AppendReflowCommand(reflowCmd);
NS_RELEASE(reflowCmd);
}
#endif
// this does not get called for trees
NS_IMETHODIMP
nsTableRowGroupFrame::AppendFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList)
{
// Get the table frame
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
// collect the new row frames in an array
nsVoidArray rows;
for (nsIFrame* rowFrame = aFrameList; rowFrame; rowFrame->GetNextSibling(&rowFrame)) {
nsIAtom* frameType;
rowFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableRowFrame == frameType) {
rows.AppendElement(rowFrame);
}
NS_IF_RELEASE(frameType);
}
// Append the frames
// Append the frames to the sibling chain
mFrames.AppendFrames(nsnull, aFrameList);
const nsStyleDisplay *display;
aFrameList->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
// See if the newly appended rows are the last rows in the table.
// XXX is this the correct code path for nested row groups, considering that whitespace frames may exist currently
if ((NS_STYLE_DISPLAY_TABLE_ROW_GROUP != display->mDisplay) && NoRowsFollow()) {
// The rows we appended are the last rows in the table so incrementally
// add them to the cell map
PRBool haveRows = PR_FALSE;
for (nsIFrame* rowFrame = aFrameList; rowFrame; rowFrame->GetNextSibling(&rowFrame)) {
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
if (NS_STYLE_DISPLAY_TABLE_ROW == display->mDisplay) {
DidAppendRow((nsTableRowFrame*)rowFrame);
haveRows = PR_TRUE;
}
}
if (rows.Count() > 0) {
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
if (tableFrame) {
tableFrame->AppendRows(*aPresContext, rows);
if (haveRows) {
// See if any implicit column frames need to be created as a result of
// adding the new rows
PRBool createdColFrames;
tableFrame->EnsureColumns(aPresContext, createdColFrames);
if (createdColFrames) {
// We need to rebuild the column cache
// XXX It would be nice if this could be done incrementally
tableFrame->InvalidateColumnCache();
}
// Because the number of columns may have changed invalidate the column widths
tableFrame->InvalidateColumnWidths();
// Reflow the new frames. They're already marked dirty, so generate a reflow
// command that tells us to reflow our dirty child frames
@ -1205,29 +1222,12 @@ nsTableRowGroupFrame::AppendFrames(nsIPresContext* aPresContext,
NS_RELEASE(reflowCmd);
}
}
} else {
// We need to rebuild the cell map, because currently we can't insert
// new frames except at the end (append)
tableFrame->InvalidateCellMap();
// We should try and avoid doing a pass1 reflow on all the cells and just
// do it for the newly added frames, but we need to add these frames to the
// cell map before we reflow them
tableFrame->InvalidateFirstPassCache();
// Because the number of columns may have changed invalidate the column
// cache. Note that this has the side effect of recomputing the column
// widths, so we don't need to call InvalidateColumnWidths()
tableFrame->InvalidateColumnCache();
// Generate a reflow command so we reflow the table itself. This will
// do a pass-1 reflow of all the rows including any rows we just added
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
}
return NS_OK;
}
// this does not get called for trees
NS_IMETHODIMP
nsTableRowGroupFrame::InsertFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
@ -1235,65 +1235,76 @@ nsTableRowGroupFrame::InsertFrames(nsIPresContext* aPresContext,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList)
{
// Get the table frame
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
// collect the new row frames in an array
nsVoidArray rows;
for (nsIFrame* rowFrame = aFrameList; rowFrame; rowFrame->GetNextSibling(&rowFrame)) {
nsIAtom* frameType;
rowFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableRowFrame == frameType) {
rows.AppendElement(rowFrame);
}
NS_IF_RELEASE(frameType);
}
// Insert the frames
// Insert the frames in the sibling chain
mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
// We need to rebuild the cell map, because currently we can't insert
// new frames except at the end (append)
tableFrame->InvalidateCellMap();
if (rows.Count() > 0) {
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
if (tableFrame) {
nsTableRowFrame* prevRow = (nsTableRowFrame *)nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame, nsLayoutAtoms::tableRowFrame);
PRInt32 rowIndex = (prevRow) ? prevRow->GetRowIndex() : 0;
tableFrame->InsertRows(*aPresContext, rows, rowIndex, PR_TRUE);
// We should try and avoid doing a pass1 reflow on all the cells and just
// do it for the newly added frames, but we need to add these frames to the
// cell map before we reflow them
tableFrame->InvalidateFirstPassCache();
// Reflow the new frames. They're already marked dirty, so generate a reflow
// command that tells us to reflow our dirty child frames
nsIReflowCommand* reflowCmd;
// Because the number of columns may have changed invalidate the column
// cache. Note that this has the side effect of recomputing the column
// widths, so we don't need to call InvalidateColumnWidths()
tableFrame->InvalidateColumnCache();
if (NS_SUCCEEDED(NS_NewHTMLReflowCommand(&reflowCmd, this,
nsIReflowCommand::ReflowDirty))) {
aPresShell.AppendReflowCommand(reflowCmd);
NS_RELEASE(reflowCmd);
}
// Because the number of columns may have changed invalidate the column widths
tableFrame->InvalidateColumnWidths();
// Generate a reflow command so we reflow the table itself. This will
// do a pass-1 reflow of all the rows including any rows we just added
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
}
}
// Generate a reflow command so we reflow the table itself. This will
// do a pass-1 reflow of all the rows including any rows we just added
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
return NS_OK;
}
// this does not get called for trees
NS_IMETHODIMP
nsTableRowGroupFrame::RemoveFrame(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame)
{
const nsStyleDisplay *display;
aOldFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
PRBool validChild = (NS_STYLE_DISPLAY_TABLE_ROW == display->mDisplay) ||
(NS_STYLE_DISPLAY_TABLE_ROW_GROUP == display->mDisplay);
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
if (tableFrame) {
nsIAtom* frameType;
aOldFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableRowFrame == frameType) {
PRInt32 firstRowIndex = ((nsTableRowFrame *)aOldFrame)->GetRowIndex();
// Remove the frame and destroy it
if (mFrames.DestroyFrame(aPresContext, aOldFrame)) {
if (validChild) {
// Get the table frame
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
// We need to rebuild the cell map, because currently we can't incrementally
// remove rows
tableFrame->InvalidateCellMap();
// Because the number of columns may have changed invalidate the column
// cache. Note that this has the side effect of recomputing the column
// widths, so we don't need to call InvalidateColumnWidths()
tableFrame->InvalidateColumnCache();
tableFrame->RemoveRows(*aPresContext, firstRowIndex, 1, PR_TRUE);
// Because the number of columns may have changed invalidate the column widths
tableFrame->InvalidateColumnWidths();
// Because we haven't added any new frames we don't need to do a pass1
// reflow. Just generate a reflow command so we reflow the table itself
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
}
NS_IF_RELEASE(frameType);
}
mFrames.DestroyFrame(aPresContext, aOldFrame);
return NS_OK;
}
@ -1350,54 +1361,6 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext* aPresContext,
return rv;
}
NS_METHOD nsTableRowGroupFrame::DidAppendRow(nsTableRowFrame *aRowFrame)
{
nsresult rv=NS_OK;
/* need to make space in the cell map. Remeber that row spans can't cross row groups
once the space is made, tell the row to initizalize its children.
it will automatically find the row to initialize into.
but this is tough because a cell in aInsertedFrame could have a rowspan
which must be respected if a subsequent row is appended.
*/
rv = aRowFrame->InitChildren();
return rv;
}
// support method that tells us if there are any rows in the table after our rows
// returns PR_TRUE if there are no rows after ours
PRBool nsTableRowGroupFrame::NoRowsFollow()
{
// XXX This method doesn't play well with the tree widget.
PRBool result = PR_TRUE;
nsIFrame *nextSib=nsnull;
GetNextSibling(&nextSib);
while (nsnull!=nextSib)
{
const nsStyleDisplay *sibDisplay;
nextSib->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)sibDisplay));
if ((NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == sibDisplay->mDisplay) ||
(NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == sibDisplay->mDisplay) ||
(NS_STYLE_DISPLAY_TABLE_ROW_GROUP == sibDisplay->mDisplay))
{
nsIFrame *childFrame=nsnull;
nextSib->FirstChild(nsnull, &childFrame);
while (nsnull!=childFrame)
{
const nsStyleDisplay *childDisplay;
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{ // found a row
result = PR_FALSE;
break;
}
childFrame->GetNextSibling(&childFrame);
}
}
nextSib->GetNextSibling(&nextSib);
}
return result;
}
NS_METHOD nsTableRowGroupFrame::GetHeightOfRows(nscoord& aResult)
{
// the rows in rowGroupFrame need to be expanded by rowHeightDelta[i]

View File

@ -244,10 +244,6 @@ protected:
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD DidAppendRow(nsTableRowFrame *aRowFrame);
PRBool NoRowsFollow();
nsresult AdjustSiblingsAfterReflow(nsIPresContext* aPresContext,
RowGroupReflowState& aReflowState,
nsIFrame* aKidFrame,

View File

@ -59,17 +59,6 @@ PRBool CanAllocate(PRInt32 aTypeToAllocate,
/* ---------- BasicTableLayoutStrategy ---------- */
/* return true if the style indicates that the width is fixed
* for the purposes of column width determination
*/
inline
PRBool BasicTableLayoutStrategy::IsFixedWidth(const nsStylePosition* aStylePosition,
const nsStyleTable* aStyleTable)
{
return PRBool ((eStyleUnit_Coord==aStylePosition->mWidth.GetUnit()) ||
(eStyleUnit_Coord==aStyleTable->mSpanWidth.GetUnit()));
}
MOZ_DECL_CTOR_COUNTER(BasicTableLayoutStrategy);
@ -90,8 +79,7 @@ BasicTableLayoutStrategy::~BasicTableLayoutStrategy()
MOZ_COUNT_DTOR(BasicTableLayoutStrategy);
}
PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize,
PRInt32 aNumCols,
PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize,
nscoord aMaxWidth)
{
ContinuingFrameCheck();
@ -99,12 +87,10 @@ PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize,
PRBool result = PR_TRUE;
// re-init instance variables
mNumCols = aNumCols;
mMinTableContentWidth = 0;
mMaxTableContentWidth = 0;
mCellSpacingTotal = 0;
mCols = mTableFrame->GetEffectiveCOLSAttribute();
// assign the width of all fixed-width columns
AssignPreliminaryColumnWidths(aMaxWidth);
@ -157,7 +143,7 @@ PRBool BCW_Wrapup(BasicTableLayoutStrategy* aStrategy,
{
if (aAllocTypes)
delete [] aAllocTypes;
if (gsDebugBalance) {printf("BalanceColumnWidths ex \n"); aTableFrame->Dump(PR_TRUE, PR_FALSE);}
if (gsDebugBalance) {printf("BalanceColumnWidths ex \n"); aTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE);}
return PR_TRUE;
}
@ -176,7 +162,7 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
const nsHTMLReflowState& aReflowState,
nscoord aMaxWidthIn)
{
if (gsDebugBalance) {printf("BalanceColumnWidths en max=%d\n", aMaxWidthIn); mTableFrame->Dump(PR_TRUE, PR_FALSE);}
if (gsDebugBalance) {printf("BalanceColumnWidths en max=%d\n", aMaxWidthIn); mTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE);}
ContinuingFrameCheck();
if (!aTableStyle) {
@ -184,6 +170,8 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
return PR_FALSE;
}
PRInt32 numCols = mTableFrame->GetColCount();
// determine if the table is auto/fixed and get the fixed width if available
nscoord maxWidth = aMaxWidthIn;
nscoord specifiedTableWidth = 0;
@ -204,7 +192,7 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
}
// initialize the col percent and cell percent values to 0.
PRInt32 colX;
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
colFrame->SetWidth(PCT, WIDTH_NOT_SET);
colFrame->SetWidth(PCT_ADJ, WIDTH_NOT_SET);
@ -220,7 +208,7 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
PRBool recomputedAdjMin = RecomputeAdjMinIfNecessary();
// set the table's columns to the min width
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord colMinWidth = colFrame->GetMinWidth();
mTableFrame->SetColumnWidth(colX, colMinWidth);
@ -257,10 +245,10 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
nscoord totalAllocated = totalWidths[MIN_CON] + cellSpacingTotal;
// allocate and initialize arrays indicating what col gets set
PRInt32* allocTypes = new PRInt32[mNumCols];
PRInt32* allocTypes = new PRInt32[numCols];
if (!allocTypes) return PR_FALSE;
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
allocTypes[colX] = -1;
}
@ -330,9 +318,9 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
PRBool skip0Proportional = totalCounts[DES_CON] > num0Proportional;
if ( (tableIsAutoWidth && (perAdjTableWidth - totalAllocated > 0)) ||
(!tableIsAutoWidth && (totalAllocated < maxWidth)) ) {
if (totalCounts[PCT] != mNumCols) {
if (totalCounts[PCT] != numCols) {
//PRBool onlyAuto = (totalCounts[DES_CON] > 0) && !mIsNavQuirksMode;
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
if (PCT == allocTypes[colX]) {
allocTypes[colX] = -1;
}
@ -350,7 +338,7 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aTableSty
}
// give the proportional cols the rest up to the max width in quirks mode
else if (tableIsAutoWidth && mIsNavQuirksMode && (totalCounts[MIN_PRO] > 0)) {
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
if (DES_CON != allocTypes[colX]) {
allocTypes[colX] = -1;
}
@ -369,7 +357,8 @@ void BasicTableLayoutStrategy::AllocateFully(nscoord& aTotalAllocated,
PRInt32 aWidthType,
PRBool aMarkAllocated)
{
for (PRInt32 colX = 0; colX < mNumCols; colX++) {
PRInt32 numCols = mTableFrame->GetColCount();
for (PRInt32 colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord oldWidth = mTableFrame->GetColumnWidth(colX);
nscoord newWidth = colFrame->GetWidth(aWidthType);
@ -408,13 +397,14 @@ void BasicTableLayoutStrategy::AllocateUnconstrained(PRInt32 aAllocAmount,
PRInt32 numColsAllocated = 0;
PRInt32 totalAllocated = 0;
PRInt32 colX;
for (colX = 0; colX < mNumCols; colX++) {
PRInt32 numCols = mTableFrame->GetColCount();
for (colX = 0; colX < numCols; colX++) {
if (-1 != aAllocTypes[colX]) {
divisor += mTableFrame->GetColumnWidth(colX);
numColsAllocated++;
}
}
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
if (-1 != aAllocTypes[colX]) {
if (aSkip0Proportional) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
@ -703,9 +693,10 @@ BasicTableLayoutStrategy::ComputeColspanWidths(PRInt32 aWidthIndex,
// and calculate min/max table width
PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth)
{
if (gsDebugAssign) {printf("AssignPrelimColWidths en max=%d\n", aMaxWidth); mTableFrame->Dump(PR_TRUE, PR_FALSE);}
if (gsDebugAssign) {printf("AssignPrelimColWidths en max=%d\n", aMaxWidth); mTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE);}
PRBool rv = PR_FALSE;
PRInt32 numRows = mTableFrame->GetRowCount();
PRInt32 numCols = mTableFrame->GetColCount();
nscoord spacingX = mTableFrame->GetCellSpacingX();
PRInt32 colX, rowX;
mCellSpacingTotal = 0;
@ -713,12 +704,12 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
PRInt32 propTotal = 0; // total of numbers of the type 1*, 2*, etc
PRInt32 numColsForColsAttr = 0; // Nav Quirks cols attribute for equal width cols
if (NS_STYLE_TABLE_COLS_NONE != mCols) {
numColsForColsAttr = (NS_STYLE_TABLE_COLS_ALL == mCols) ? mNumCols : mCols;
numColsForColsAttr = (NS_STYLE_TABLE_COLS_ALL == mCols) ? numCols : mCols;
}
// For every column, determine it's min and desired width based on cell style
// base on cells which do not span cols. Also, determine mCellSpacingTotal
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nscoord minWidth = 0;
nscoord desWidth = 0;
nscoord fixWidth = WIDTH_NOT_SET;
@ -794,6 +785,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
// proportional width on a col or Nav Quirks cols attr
if (fixWidth <= 0) {
nscoord proportion = WIDTH_NOT_SET;
#ifdef foobar
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)colPosition);
if (eStyleUnit_Proportional == colPosition->mWidth.GetUnit()) {
@ -806,6 +798,19 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
proportion = WIDTH_NOT_SET;
}
}
#else
nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
if (eStyleUnit_Proportional == colStyleWidth.GetUnit()) {
proportion = colStyleWidth.GetIntValue();
}
else if (colX < numColsForColsAttr) {
proportion = 1;
if ((eStyleUnit_Percent == colStyleWidth.GetUnit()) &&
(colStyleWidth.GetPercentValue() > 0.0f)) {
proportion = WIDTH_NOT_SET;
}
}
#endif
if (proportion >= 0) {
colFrame->SetWidth(MIN_PRO, proportion);
if (proportion > 0) {
@ -831,7 +836,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
nscoord minPropTotal = 0;
nscoord desPropTotal = 0;
// figure the totals of all proportional cols which support every min and desired width
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord colProp = colFrame->GetWidth(MIN_PRO);
if (colProp > 0) {
@ -846,7 +851,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
mMinToDesProportionRatio = ((float)desPropTotal) / ((float)minPropTotal);
}
// figure the cols proportional min width based on the new totals
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord colProp = colFrame->GetWidth(MIN_PRO);
if (colProp > 0) {
@ -861,7 +866,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
// Adjust the cols that each cell spans if necessary. Iterate backwards
// so that nested and/or overlaping col spans handle the inner ones first,
// ensuring more accurated calculations.
for (colX = mNumCols - 1; colX >= 0; colX--) {
for (colX = numCols - 1; colX >= 0; colX--) {
for (rowX = 0; rowX < numRows; rowX++) {
PRBool originates;
PRInt32 colSpan;
@ -878,11 +883,12 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
// Set the col's fixed width if present
// Set the table col width for each col to the content min.
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord fixColWidth = colFrame->GetWidth(FIX);
// use the style width of a col only if the col hasn't gotten a fixed width from any cell
if (fixColWidth <= 0) {
#ifdef foobar
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)colPosition);
if (eStyleUnit_Coord == colPosition->mWidth.GetUnit()) {
@ -891,13 +897,22 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth
colFrame->SetWidth(FIX, fixColWidth);
}
}
#else
nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
if (eStyleUnit_Coord == colStyleWidth.GetUnit()) {
fixColWidth = colStyleWidth.GetCoordValue();
if (fixColWidth > 0) {
colFrame->SetWidth(FIX, fixColWidth);
}
}
#endif
}
nscoord minWidth = colFrame->GetMinWidth();
mTableFrame->SetColumnWidth(colX, minWidth);
}
SetMinAndMaxTableContentWidths();
if (gsDebugAssign) {printf("AssignPrelimColWidths ex\n"); mTableFrame->Dump(PR_TRUE, PR_FALSE);}
if (gsDebugAssign) {printf("AssignPrelimColWidths ex\n"); mTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE);}
return rv;
}
@ -906,6 +921,7 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
PRBool aTableIsAutoWidth)
{
PRInt32 numRows = mTableFrame->GetRowCount();
PRInt32 numCols = mTableFrame->GetColCount();
nscoord spacingX = mTableFrame->GetCellSpacingX();
PRInt32 colX, rowX;
nscoord basis = aBasisIn;
@ -918,7 +934,7 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
PRInt32 numPerCols = 0; // number of colums that have percentage constraints
nscoord prefWidthTotal = 0;// total of des/fix widths of cols that don't have percentage constraints
basis = 0; // basis to use for percentages, computed considering percentage values
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord colBasis = -1;
// Scan the cells in the col
@ -950,6 +966,7 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
}
if (-1 == colBasis) {
// see if the col has a style percent width specified
#ifdef foobar
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)colPosition);
if (eStyleUnit_Percent == colPosition->mWidth.GetUnit()) {
@ -960,6 +977,17 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
colBasis = NSToCoordRound((float)desWidth / percent);
}
}
#else
nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
if (eStyleUnit_Percent == colStyleWidth.GetUnit()) {
float percent = colStyleWidth.GetPercentValue();
colBasis = 0;
if (percent > 0.0f) {
nscoord desWidth = colFrame->GetDesWidth();
colBasis = NSToCoordRound((float)desWidth / percent);
}
}
#endif
}
basis = PR_MAX(basis, colBasis);
nscoord fixWidth = colFrame->GetFixWidth();
@ -976,7 +1004,7 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
return 0;
}
// If there is only one col and it is % based, it won't affect anything
if ((1 == mNumCols) && (mNumCols == numPerCols)) {
if ((1 == numCols) && (numCols == numPerCols)) {
return 0;
}
// compute a basis considering total percentages and the desired width of everything else
@ -995,12 +1023,12 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
}
nscoord colPctTotal = 0;
nscoord* colPcts = new nscoord[mNumCols];
nscoord* colPcts = new nscoord[numCols];
if (!colPcts) return 0;
// Determine the percentage contribution for cols and for cells with colspan = 1
// Iterate backwards, similarly to the reasoning in AssignPreliminaryColumnWidths
for (colX = mNumCols - 1; colX >= 0; colX--) {
for (colX = numCols - 1; colX >= 0; colX--) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord maxColPctWidth = WIDTH_NOT_SET;
float maxColPct = 0.0f;
@ -1039,12 +1067,20 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
}
if (WIDTH_NOT_SET == maxColPctWidth) {
// see if the col has a style percent width specified
#ifdef foobar
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)colPosition);
if (eStyleUnit_Percent == colPosition->mWidth.GetUnit()) {
maxColPct = colPosition->mWidth.GetPercentValue();
maxColPctWidth = NSToCoordRound( ((float)basis) * maxColPct );
}
#else
nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
if (eStyleUnit_Percent == colStyleWidth.GetUnit()) {
maxColPct = colStyleWidth.GetPercentValue();
maxColPctWidth = NSToCoordRound( ((float)basis) * maxColPct );
}
#endif
}
// conflicting pct/fixed widths are recorded. Nav 4.x may be changing the
// fixed width value if it exceeds the pct value and not recording the pct
@ -1066,7 +1102,7 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
// For each col, consider the cells originating in it with colspans > 1.
// Adjust the cols that each cell spans if necessary.
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
for (rowX = 0; rowX < numRows; rowX++) {
PRBool originates;
PRInt32 colSpan;
@ -1162,7 +1198,7 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
// if the percent total went over 100%, adjustments need to be made to right most cols
if (colPctTotal > 100) {
for (colX = mNumCols - 1; colX >= 0; colX--) {
for (colX = numCols - 1; colX >= 0; colX--) {
if (colPcts[colX] > 0) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nscoord newPct = colPcts[colX] - (colPctTotal - 100);
@ -1197,10 +1233,11 @@ nscoord BasicTableLayoutStrategy::AssignPercentageColumnWidths(nscoord aBasisIn,
PRBool BasicTableLayoutStrategy::RecomputeAdjMinIfNecessary()
{
PRInt32 numRows = mTableFrame->GetRowCount();
PRInt32 numCols = mTableFrame->GetColCount();
PRInt32 colX, rowX, spanX;
PRBool spansPercent = PR_FALSE;
for (colX = mNumCols - 1; colX >= 0; colX--) {
for (colX = numCols - 1; colX >= 0; colX--) {
for (rowX = 0; rowX < numRows; rowX++) {
PRBool originates;
PRInt32 colSpan;
@ -1233,7 +1270,7 @@ PRBool BasicTableLayoutStrategy::RecomputeAdjMinIfNecessary()
nscoord spacingX = mTableFrame->GetCellSpacingX();
for (colX = mNumCols - 1; colX >= 0; colX--) {
for (colX = numCols - 1; colX >= 0; colX--) {
for (rowX = 0; rowX < numRows; rowX++) {
PRBool originates;
PRInt32 colSpan;
@ -1267,7 +1304,8 @@ void BasicTableLayoutStrategy::SetMinAndMaxTableContentWidths()
mMaxTableContentWidth = 0;
nscoord spacingX = mTableFrame->GetCellSpacingX();
for (PRInt32 colX = 0; colX < mNumCols; colX++) {
PRInt32 numCols = mTableFrame->GetColCount();
for (PRInt32 colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
mMinTableContentWidth += colFrame->GetMinWidth();
mMaxTableContentWidth += PR_MAX(colFrame->GetDesWidth(), colFrame->GetFixWidth());
@ -1302,7 +1340,8 @@ void BasicTableLayoutStrategy::CalculateTotals(PRInt32& aCellSpacing,
a0ProportionalCount = 0;
nscoord spacingX = mTableFrame->GetCellSpacingX();
for (PRInt32 colX = 0; colX < mNumCols; colX++) {
PRInt32 numCols = mTableFrame->GetColCount();
for (PRInt32 colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
if (mTableFrame->GetNumCellsOriginatingInCol(colX) > 0) {
aCellSpacing += spacingX;
@ -1387,7 +1426,7 @@ void BasicTableLayoutStrategy::CalculateTotals(PRInt32& aCellSpacing,
aMinWidths[DES_CON] += minCol;
}
// if it is not a degenerate table, add the last spacing on the right
if (mNumCols > 0) {
if (numCols > 0) {
aCellSpacing += spacingX;
}
}
@ -1508,11 +1547,12 @@ void BasicTableLayoutStrategy::AllocateConstrained(PRInt32 aAvailWidth,
return;
}
PRInt32 numCols = mTableFrame->GetColCount();
PRInt32 numConstrainedCols = 0;
nscoord sumMaxConstraints = 0;
PRBool useAdj = PR_TRUE;
PRInt32 colX;
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame, useAdj)) {
if (-1 != aAllocTypes[colX]) {
@ -1539,7 +1579,7 @@ void BasicTableLayoutStrategy::AllocateConstrained(PRInt32 aAvailWidth,
PRInt32 maxMinDiff = 0;
PRInt32 constrColX = 0;
// set the col info entries for each constrained col
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame, useAdj)) {
if (-1 != aAllocTypes[colX]) {
@ -1810,11 +1850,16 @@ PRBool BasicTableLayoutStrategy::ColIsSpecifiedAsMinimumWidth(PRInt32 aColIndex)
PRBool result = PR_FALSE;
nsTableColFrame* colFrame;
mTableFrame->GetColumnFrame(aColIndex, colFrame);
#ifdef foobar
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)colPosition);
switch (colPosition->mWidth.GetUnit()) {
#else
nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
switch (colStyleWidth.GetUnit()) {
#endif
case eStyleUnit_Coord:
if (0 == colPosition->mWidth.GetCoordValue()) {
if (0 == colStyleWidth.GetCoordValue()) {
result = PR_TRUE;
}
break;
@ -1823,14 +1868,14 @@ PRBool BasicTableLayoutStrategy::ColIsSpecifiedAsMinimumWidth(PRInt32 aColIndex)
// total hack for now for 0% and 1% specifications
// should compare percent to available parent width and see that it is below minimum
// for this column
float percent = colPosition->mWidth.GetPercentValue();
float percent = colStyleWidth.GetPercentValue();
if (0.0f == percent || 0.01f == percent) {
result = PR_TRUE;
}
break;
}
case eStyleUnit_Proportional:
if (0 == colPosition->mWidth.GetIntValue()) {
if (0 == colStyleWidth.GetIntValue()) {
result = PR_TRUE;
}
@ -1849,8 +1894,8 @@ void BasicTableLayoutStrategy::Dump(PRInt32 aIndent)
}
indent[aIndent] = 0;
printf("%s**START BASIC STRATEGY DUMP** table=%p cols=%X numCols=%d",
indent, mTableFrame, mCols, mNumCols);
printf("%s**START BASIC STRATEGY DUMP** table=%p cols=%X",
indent, mTableFrame, mCols);
printf("\n%s minConWidth=%d maxConWidth=%d cellSpacing=%d propRatio=%.2f navQuirks=%d",
indent, mMinTableContentWidth, mMaxTableContentWidth, mCellSpacingTotal, mMinToDesProportionRatio, mIsNavQuirksMode);
printf(" **END BASIC STRATEGY DUMP** \n");

View File

@ -57,11 +57,9 @@ public:
/** call every time any table thing changes that might effect the width of any column
* in the table (content, structure, or style)
* @param aMaxElementSize [OUT] if not null, the max element size is computed and returned in this param
* @param aNumCols the total number of columns in the table
*/
virtual PRBool Initialize(nsSize* aMaxElementSize,
PRInt32 aNumCols,
nscoord aMaxSize);
virtual PRBool Initialize(nsSize* aMaxElementSize,
nscoord aMaxSize);
/** compute the max element size of the table.
* assumes that Initialize has been called
@ -83,7 +81,6 @@ public:
nscoord GetTableMinContentWidth() const;
nscoord GetTableMaxContentWidth() const;
nscoord GetCOLSAttribute() const;
nscoord GetNumCols() const;
void Dump(PRInt32 aIndent);
protected:
@ -159,13 +156,6 @@ protected:
PRInt32* aAllocTypes,
PRBool aSkip0Proportional);
/** return true if the style indicates that the width is a specific width
* for the purposes of column width determination.
* return false if the width changes based on content, parent size, etc.
*/
static PRBool IsFixedWidth(const nsStylePosition* aStylePosition,
const nsStyleTable* aStyleTable);
/** return true if the colIndex is in the list of colIndexes */
virtual PRBool IsColumnInList(const PRInt32 colIndex,
PRInt32 *colIndexes,
@ -214,7 +204,6 @@ protected:
protected:
nsTableFrame * mTableFrame;
PRInt32 mCols;
PRInt32 mNumCols;
// cached data
nscoord mMinTableContentWidth; // the smallest size for the table (excluding border and padding)
nscoord mMaxTableContentWidth; // the "natural" size for the table, if unconstrained (excluding border and padding)
@ -233,9 +222,6 @@ inline nscoord BasicTableLayoutStrategy::GetTableMaxContentWidth() const
inline nscoord BasicTableLayoutStrategy::GetCOLSAttribute() const
{ return mCols; };
inline nscoord BasicTableLayoutStrategy::GetNumCols() const
{ return mNumCols; };
#endif

View File

@ -59,7 +59,6 @@ PRBool FixedTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext* aT
PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputedWidth)
{
// NS_ASSERTION(aComputedWidth != NS_UNCONSTRAINEDSIZE, "bad computed width");
const nsStylePosition* tablePosition;
mTableFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)tablePosition);
PRBool tableIsFixedWidth = eStyleUnit_Coord == tablePosition->mWidth.GetUnit() ||
@ -70,24 +69,25 @@ PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputed
nsMargin borderPadding;
tableSpacing->CalcBorderPaddingFor(mTableFrame, borderPadding);
PRInt32 numCols = mTableFrame->GetColCount();
PRInt32 colX;
// availWidth is used as the basis for percentage width columns. It is aComputedWidth
// minus table border, padding, & cellspacing
nscoord availWidth = aComputedWidth - borderPadding.left - borderPadding.right -
((mNumCols + 1) * mTableFrame->GetCellSpacingX());
((numCols + 1) * mTableFrame->GetCellSpacingX());
PRInt32 specifiedCols = 0; // the number of columns whose width is given
nscoord totalColWidth = 0; // the sum of the widths of the columns
nscoord* colWidths = new PRBool[mNumCols];
nsCRT::memset(colWidths, WIDTH_NOT_SET, mNumCols*sizeof(nscoord));
nscoord* colWidths = new PRBool[numCols];
nsCRT::memset(colWidths, WIDTH_NOT_SET, numCols*sizeof(nscoord));
nscoord* propInfo = new PRBool[mNumCols];
nsCRT::memset(propInfo, 0, mNumCols*sizeof(nscoord));
nscoord* propInfo = new PRBool[numCols];
nsCRT::memset(propInfo, 0, numCols*sizeof(nscoord));
nscoord propTotal = 0;
// for every column, determine its specified width
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
// Get column information
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
if (!colFrame) {
@ -115,6 +115,7 @@ PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputed
propTotal += propInfo[colX];
}
else { // get width from the cell
nsTableCellFrame* cellFrame = mTableFrame->GetCellFrameAt(0, colX);
if (nsnull != cellFrame) {
// Get the cell's style
@ -148,7 +149,7 @@ PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputed
if (0 < remainingWidth) {
if (propTotal > 0) {
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
if (propInfo[colX] > 0) {
// We're proportional
float percent = ((float)propInfo[colX])/((float)propTotal);
@ -159,10 +160,10 @@ PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputed
}
}
else if (tableIsFixedWidth) {
if (mNumCols > specifiedCols) {
if (numCols > specifiedCols) {
// allocate the extra space to the columns which have no width specified
nscoord colAlloc = NSToCoordRound( ((float)remainingWidth) / (((float)mNumCols) - ((float)specifiedCols)));
for (colX = 0; colX < mNumCols; colX++) {
nscoord colAlloc = NSToCoordRound( ((float)remainingWidth) / (((float)numCols) - ((float)specifiedCols)));
for (colX = 0; colX < numCols; colX++) {
if (-1 == colWidths[colX]) {
colWidths[colX] = colAlloc;
totalColWidth += colAlloc;
@ -172,7 +173,7 @@ PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputed
}
else { // allocate the extra space to the columns which have width specified
float divisor = (float)totalColWidth;
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
if (colWidths[colX] > 0) {
nscoord colAlloc = NSToCoordRound(remainingWidth * colWidths[colX] / divisor);
colWidths[colX] += colAlloc;
@ -187,7 +188,7 @@ PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputed
nscoord overAllocation = (availWidth >= 0)
? totalColWidth - availWidth : 0;
// set the column widths
for (colX = 0; colX < mNumCols; colX++) {
for (colX = 0; colX < numCols; colX++) {
if (colWidths[colX] < 0)
colWidths[colX] = 0;
// if there was too much allocated due to rounding, remove it from the last col

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,22 @@
#include "nsVoidArray.h"
class nsTableColFrame;
class nsTableCellFrame;
class nsIPresContext;
// XXX the collapsing row and col data structures need to be moved
// into nsTableFrame. Collapsing cols are broken due to the recent
// incremental cell map methods which don't attempt to update
// collapsing col info here.
struct nsColInfo
{
PRInt32 mNumCellsOrig; // number of cells originating in the col
PRInt32 mNumCellsSpan; // number of cells spanning into the col via colspans (not rowspans)
nsColInfo();
nsColInfo(PRInt32 aNumCellsOrig,
PRInt32 aNumCellsSpan);
};
/** nsCellMap is a support class for nsTablePart.
* It maintains an Rows x Columns grid onto which the cells of the table are mapped.
@ -60,23 +76,29 @@ public:
CellData* GetCellAt(PRInt32 aRowIndex,
PRInt32 aColIndex) const;
/** insert a new row into the map
makes a blank row and adjusts spans
*/
void InsertRowIntoMap(PRInt32 aRowIndex);
/** removes a row from the map and adjusts spans
*/
void RemoveRowFromMap(PRInt32 aRowIndex);
void AppendCol();
/** append the cellFrame at the end of the row at aRowIndex and return the col index
*/
PRInt32 AppendCell(nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
PRInt32 aRowIndex,
PRBool aRebuildIfNecessary);
void InsertCells(nsVoidArray& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndexBefore);
void RemoveCell(nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
void InsertRows(nsVoidArray& aRows,
PRInt32 aFirstRowIndex,
PRBool aConsiderSpans);
void RemoveRows(PRInt32 aFirstRowIndex,
PRInt32 aNumRowsToRemove,
PRBool aConsiderSpans);
PRInt32 GetNextAvailRowIndex();
PRInt32 GetEffectiveColSpan(nsTableCellFrame* aCell) const;
@ -102,17 +124,6 @@ public:
/** return the actual number of rows in the table represented by this CellMap */
PRInt32 GetRowCount() const;
/** return the column frame associated with aColIndex */
nsTableColFrame* GetColumnFrame(PRInt32 aColIndex) const;
/** add a column frame to the list of column frames
* column frames must be added in order
*/
void AppendColumnFrame(nsTableColFrame *aColFrame);
/** empty the column frame cache */
void ClearColumnCache();
// temporary until nsTableFrame::GetCellData uses GetCellFrameAt
nsTableCellFrame* GetCellFrameOriginatingAt(PRInt32 aRowX,
PRInt32 aColX) const;
@ -123,6 +134,7 @@ public:
PRInt32* aColSpan = nsnull) const;
void AddColsAtEnd(PRUint32 aNumCols);
PRInt32 RemoveUnusedCols(PRInt32 aMaxNumToRemove);
PRBool RowIsSpannedInto(PRInt32 aRowIndex) const;
PRBool RowHasSpanningCells(PRInt32 aRowIndex) const;
@ -156,23 +168,48 @@ protected:
CellData* GetMapCellAt(PRInt32 aMapRowIndex,
PRInt32 aColIndex) const;
PRInt32 GetNumCellsIn(PRInt32 aColIndex,
PRBool aOriginating) const;
PRInt32 GetNumCellsIn(PRInt32 aColIndex) const;
void ExpandWithRows(nsVoidArray& aRowFrames,
PRInt32 aStartRowIndex);
void ExpandWithCells(nsVoidArray& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRInt32 aRowSpan);
void ShrinkWithoutRows(PRInt32 aFirstRowIndex,
PRInt32 aNumRowsToRemove);
void ShrinkWithoutCell(nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex,
PRInt32 aColIndex);
void RebuildConsideringRows(PRInt32 aStartRowIndex,
nsVoidArray* aRowsToInsert,
PRInt32 aNumRowsToRemove = 0);
void RebuildConsideringCells(nsVoidArray* aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool aInsert);
PRBool CellsSpanOut(nsVoidArray& aNewRows);
PRBool CellsSpanInOrOut(PRInt32 aStartRowIndex,
PRInt32 aEndRowIndex,
PRInt32 aStartColIndex,
PRInt32 aEndColIndex);
PRBool CreateEmptyRow(PRInt32 aRowIndex,
PRInt32 aNumCols);
/** an array containing col array. It can be larger than mRowCount due to
* row spans extending beyond the table */
nsVoidArray mRows;
/** an array of col frames. It is as large as mRowCount */
nsVoidArray mColFrames;
/** an array of PRInt32 indexed by row and giving the number of cells originating
* in each row. */
nsVoidArray mNumCellsOrigInRow;
/** an array of PRInt32 indexed by col and giving the number of cells originating
* in each col. */
nsVoidArray mNumCellsOrigInCol;
/** an array of nsColInfo indexed by col and giving the number of
* cells originating and spanning each col. */
nsVoidArray mCols;
// an array of booleans where the ith element indicates if the ith row is collapsed
PRPackedBool* mIsCollapsedRows;
@ -196,7 +233,7 @@ inline CellData* nsCellMap::GetCellAt(PRInt32 aRowIndex,
PRInt32 aColIndex) const
{
if ((0 > aRowIndex) || (aRowIndex >= mRowCount) ||
(0 > aColIndex) || (aColIndex >= mNumCellsOrigInCol.Count())) {
(0 > aColIndex) || (aColIndex >= mCols.Count())) {
//bug 9024 tickled this
//printf("%s \n", "nsCellMap::GetCellAt called with invalid row or col index"); // XXX look at this when bug 10911 get fixed
return nsnull;
@ -213,7 +250,7 @@ inline CellData* nsCellMap::GetMapCellAt(PRInt32 aMapRowIndex,
PRInt32 aColIndex) const
{
if ((0 > aMapRowIndex) || (aMapRowIndex >= mRows.Count()) ||
(0 > aColIndex) || (aColIndex >= mNumCellsOrigInCol.Count())) {
(0 > aColIndex) || (aColIndex >= mCols.Count())) {
//see bug 9024 comments above
//printf("%s \n", "nsCellMap::GetMapCellAt called with invalid row or col index"); // XXX look at this when bug 10911 get fixed
return nsnull;
@ -228,7 +265,7 @@ inline CellData* nsCellMap::GetMapCellAt(PRInt32 aMapRowIndex,
inline PRInt32 nsCellMap::GetColCount() const
{
return mNumCellsOrigInCol.Count();
return mCols.Count();
}
inline PRInt32 nsCellMap::GetRowCount() const
@ -236,15 +273,16 @@ inline PRInt32 nsCellMap::GetRowCount() const
return mRowCount;
}
inline void nsCellMap::AppendColumnFrame(nsTableColFrame *aColFrame)
{
mColFrames.AppendElement(aColFrame);
}
// nsColInfo
inline void nsCellMap::ClearColumnCache()
{
mColFrames.Clear();
}
inline nsColInfo::nsColInfo()
:mNumCellsOrig(0), mNumCellsSpan(0)
{}
inline nsColInfo::nsColInfo(PRInt32 aNumCellsOrig,
PRInt32 aNumCellsSpan)
:mNumCellsOrig(aNumCellsOrig), mNumCellsSpan(aNumCellsSpan)
{}
#endif

View File

@ -38,11 +38,9 @@ public:
/** call once every time any table thing changes (content, structure, or style)
* @param aMaxElementSize [OUT] if not null, the max element size is computed and returned in this param
* @param aNumCols the total number of columns in the table
* @param aComputedWidth the computed size of the table
*/
virtual PRBool Initialize(nsSize* aMaxElementSize,
PRInt32 aNumCols,
nscoord aComputedWidth)=0;
/** compute the max-element-size for the table
@ -80,9 +78,6 @@ public:
/** return the value of the COLS attribute, used for balancing column widths */
virtual nscoord GetCOLSAttribute() const = 0;
/** return the total number of columns in the table */
virtual nscoord GetNumCols() const = 0;
// see nsTableFrame::ColumnsCanBeInvalidatedBy
virtual PRBool ColumnsCanBeInvalidatedBy(nsStyleCoord* aPrevStyleWidth,
const nsTableCellFrame& aCellFrame) const = 0;

View File

@ -71,10 +71,9 @@ nsTableCellFrame::Init(nsIPresContext* aPresContext,
if (aPrevInFlow) {
// Set the column index
nsTableCellFrame* cellFrame = (nsTableCellFrame*)aPrevInFlow;
PRInt32 baseColIndex;
cellFrame->GetColIndex(baseColIndex);
InitCellFrame(baseColIndex);
PRInt32 colIndex;
cellFrame->GetColIndex(colIndex);
InitCellFrame(colIndex);
}
return rv;
@ -139,29 +138,24 @@ nsTableCellFrame::RemoveFrame(nsIPresContext* aPresContext,
void nsTableCellFrame::InitCellFrame(PRInt32 aColIndex)
{
NS_PRECONDITION(0<=aColIndex, "bad col index arg");
SetColIndex(aColIndex); // this also sets the contents col index
nsTableFrame* tableFrame=nsnull; // I should be checking my own style context, but border-collapse isn't inheriting correctly
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
{
if (NS_STYLE_BORDER_COLLAPSE == tableFrame->GetBorderCollapseStyle())
{
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame)) {
SetColIndex(aColIndex);
if (NS_STYLE_BORDER_COLLAPSE == tableFrame->GetBorderCollapseStyle()) {
mBorderEdges = new nsBorderEdges;
mBorderEdges->mOutsideEdge=PR_FALSE;
PRInt32 rowspan = GetRowSpan();
PRInt32 i;
for (i=0; i<rowspan; i++)
{
for (i=0; i<rowspan; i++) {
nsBorderEdge *borderToAdd = new nsBorderEdge();
mBorderEdges->mEdges[NS_SIDE_LEFT].AppendElement(borderToAdd);
borderToAdd = new nsBorderEdge();
mBorderEdges->mEdges[NS_SIDE_RIGHT].AppendElement(borderToAdd);
}
PRInt32 colspan = GetColSpan();
for (i=0; i<colspan; i++)
{
for (i=0; i<colspan; i++) {
nsBorderEdge *borderToAdd = new nsBorderEdge();
mBorderEdges->mEdges[NS_SIDE_TOP].AppendElement(borderToAdd);
borderToAdd = new nsBorderEdge();

View File

@ -19,6 +19,7 @@
*
* Contributor(s):
*/
#include "nsCOMPtr.h"
#include "nsTableColFrame.h"
#include "nsContainerFrame.h"
#include "nsIReflowCommand.h"
@ -30,6 +31,11 @@
#include "nsCSSRendering.h"
#include "nsLayoutAtoms.h"
#define COL_TYPE_CONTENT 0x0
#define COL_TYPE_ANONYMOUS_COL 0x1
#define COL_TYPE_ANONYMOUS_COLGROUP 0x2
#define COL_TYPE_ANONYMOUS_CELL 0x3
nsTableColFrame::nsTableColFrame()
: nsFrame(),
mProportion(WIDTH_NOT_SET),
@ -38,12 +44,55 @@ nsTableColFrame::nsTableColFrame()
{
// note that all fields are initialized to 0 by nsFrame::operator new
ResetSizingInfo();
SetType(eColContent);
}
nsTableColFrame::~nsTableColFrame()
{
}
nsTableColType nsTableColFrame::GetType() const {
switch(mBits.mType) {
case COL_TYPE_ANONYMOUS_COL:
return eColAnonymousCol;
case COL_TYPE_ANONYMOUS_COLGROUP:
return eColAnonymousColGroup;
case COL_TYPE_ANONYMOUS_CELL:
return eColAnonymousCell;
default:
return eColContent;
}
}
void nsTableColFrame::SetType(nsTableColType aType) {
mBits.mType = aType - eColContent;
}
// XXX what about other style besides width
nsStyleCoord nsTableColFrame::GetStyleWidth() const
{
nsStylePosition* position = nsnull;
position = (nsStylePosition*)mStyleContext->GetStyleData(eStyleStruct_Position);
nsStyleCoord styleWidth = position->mWidth;
// the following should not be necessary since html.css defines table-col and
// :table-col to inherit. However, :table-col is not inheriting properly
if (eStyleUnit_Auto == styleWidth.GetUnit()) {
nsIFrame* parent;
GetParent(&parent);
nsCOMPtr<nsIStyleContext> styleContext;
parent->GetStyleContext(getter_AddRefs(styleContext));
if (styleContext) {
position = (nsStylePosition*)styleContext->GetStyleData(eStyleStruct_Position);
styleWidth = position->mWidth;
}
}
nsStyleCoord returnWidth;
returnWidth.mUnit = styleWidth.mUnit;
returnWidth.mValue = styleWidth.mValue;
return returnWidth;
}
void nsTableColFrame::ResetSizingInfo()
{
nsCRT::memset(mWidths, WIDTH_NOT_SET, NUM_WIDTHS * sizeof(PRInt32));

View File

@ -55,6 +55,13 @@ enum nsColConstraint {
e0ProportionConstraint = 4 // 0*, means to force to min width
};
enum nsTableColType {
eColContent = 0, // there is real col content associated
eColAnonymousCol = 1, // the result of a span on a col
eColAnonymousColGroup = 2, // the result of a span on a col group
eColAnonymousCell = 3, // the result of a cell alone
};
class nsTableColFrame : public nsFrame {
public:
@ -63,7 +70,8 @@ public:
eWIDTH_SOURCE_CELL_WITH_SPAN=2 // a cell implicitly specified a width via colspan
};
void InitColFrame(PRInt32 aColIndex);
nsTableColType GetType() const;
void nsTableColFrame::SetType(nsTableColType aType);
/** instantiate a new instance of nsTableColFrame.
* @param aResult the new object is returned in this out-param
@ -75,6 +83,12 @@ public:
friend nsresult
NS_NewTableColFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
nsStyleCoord GetStyleWidth() const;
PRInt32 GetColIndex() const;
void SetColIndex (PRInt32 aColIndex);
NS_IMETHOD Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
@ -97,15 +111,9 @@ public:
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
#endif
/** return the index of the column the col represents. always >= 0 */
virtual PRInt32 GetColumnIndex ();
/** return the number of the columns the col represents. always >= 0 */
virtual PRInt32 GetSpan ();
/** set the index of the column this content object represents. must be >= 0 */
virtual void SetColumnIndex (int aColIndex);
/** convenience method, calls into cellmap */
nsVoidArray * GetCells();
@ -138,6 +146,11 @@ public:
protected:
struct ColBits {
unsigned int mType:4;
unsigned int mUnused:28;
} mBits;
nsTableColFrame();
~nsTableColFrame();
@ -153,18 +166,11 @@ protected:
PRPackedBool mNonPercentSpansPercent;
};
inline void nsTableColFrame::InitColFrame(PRInt32 aColIndex)
{
NS_ASSERTION(0<=aColIndex, "bad col index param");
mColIndex = aColIndex;
}
inline PRInt32 nsTableColFrame::GetColumnIndex()
inline PRInt32 nsTableColFrame::GetColIndex() const
{ return mColIndex; }
inline void nsTableColFrame::SetColumnIndex (int aColIndex)
{ mColIndex = aColIndex;}
inline void nsTableColFrame::SetColIndex (PRInt32 aColIndex)
{ mColIndex = aColIndex; }
inline nsColConstraint nsTableColFrame::GetConstraint() const
{ return mConstraint; }

View File

@ -23,6 +23,7 @@
#include "nsTableColFrame.h"
#include "nsTableFrame.h"
#include "nsIHTMLTableColElement.h"
#include "nsIDOMHTMLTableColElement.h"
#include "nsIReflowCommand.h"
#include "nsIStyleContext.h"
#include "nsStyleConsts.h"
@ -40,101 +41,230 @@
NS_DEF_PTR(nsIContent);
static NS_DEFINE_IID(kIHTMLTableColElementIID, NS_IHTMLTABLECOLELEMENT_IID);
static NS_DEFINE_IID(kIDOMHTMLTableColElementIID, NS_IDOMHTMLTABLECOLELEMENT_IID);
#define COLGROUP_TYPE_CONTENT 0x0
#define COLGROUP_TYPE_ANONYMOUS_COL 0x1
#define COLGROUP_TYPE_ANONYMOUS_CELL 0x2
nsTableColGroupType nsTableColGroupFrame::GetType() const {
switch(mBits.mType) {
case COLGROUP_TYPE_ANONYMOUS_COL:
return eColGroupAnonymousCol;
case COLGROUP_TYPE_ANONYMOUS_CELL:
return eColGroupAnonymousCell;
default:
return eColGroupContent;
}
}
void nsTableColGroupFrame::SetType(nsTableColGroupType aType) {
mBits.mType = aType - eColGroupContent;
}
void nsTableColGroupFrame::ResetColIndices(nsIFrame* aFirstColGroup,
PRInt32 aFirstColIndex,
nsIFrame* aStartColFrame)
{
nsTableColGroupFrame* colGroupFrame = (nsTableColGroupFrame*)aFirstColGroup;
PRInt32 colIndex = aFirstColIndex;
while (colGroupFrame) {
nsIAtom* cgType;
colGroupFrame->GetFrameType(&cgType);
if (nsLayoutAtoms::tableColGroupFrame == cgType) {
colGroupFrame->SetStartColumnIndex(colIndex);
nsIFrame* colFrame = aStartColFrame;
if (!colFrame || (colIndex != aFirstColIndex)) {
colGroupFrame->FirstChild(nsnull, &colFrame);
}
while (colFrame) {
nsIAtom* colType;
colFrame->GetFrameType(&colType);
if (nsLayoutAtoms::tableColFrame == colType) {
((nsTableColFrame*)colFrame)->SetColIndex(colIndex);
colIndex++;
}
NS_IF_RELEASE(colType);
colFrame->GetNextSibling(&colFrame);
}
}
NS_IF_RELEASE(cgType);
colGroupFrame->GetNextSibling((nsIFrame**)&colGroupFrame);
}
}
NS_IMETHODIMP
nsTableColGroupFrame::InitNewFrames(nsIPresContext* aPresContext, nsIFrame* aChildList)
nsTableColGroupFrame::AddColsToTable(nsIPresContext& aPresContext,
PRInt32 aFirstColIndex,
PRBool aResetSubsequentColIndices,
nsIFrame* aFirstFrame,
nsIFrame* aLastFrame)
{
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
nsresult rv=NS_OK;
nsTableFrame* tableFrame=nsnull;
nsresult rv = NS_OK;
nsTableFrame* tableFrame = nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame)) {
// Process the newly added column frames
for (nsIFrame* kidFrame = aChildList; nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame)) {
const nsStyleDisplay* display;
kidFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)display);
if (NS_STYLE_DISPLAY_TABLE_COLUMN == display->mDisplay) {
// Set the preliminary values for the column frame
PRInt32 colIndex = mStartColIndex + mColCount;
((nsTableColFrame *)(kidFrame))->InitColFrame (colIndex);
PRInt32 repeat = ((nsTableColFrame *)(kidFrame))->GetSpan();
mColCount += repeat;
for (PRInt32 i=0; i<repeat; i++) {
tableFrame->AddColumnFrame((nsTableColFrame *)kidFrame);
}
}
}
// colgroup's span attribute is how many columns the group represents
// in the absence of any COL children
// Note that this is the correct, though perhaps unexpected, behavior for the span attribute.
// The spec says that if there are any COL children, the colgroup's span is ignored.
if (0==mColCount)
{
nsIFrame *firstImplicitColFrame=nsnull;
nsIFrame *prevColFrame=nsnull;
nsAutoString colTag;
nsHTMLAtoms::col->ToString(colTag);
mColCount = GetSpan();
for (PRInt32 colIndex=0; colIndex<mColCount; colIndex++)
{
nsIHTMLContent *col=nsnull;
// create an implicit col
rv = NS_CreateHTMLElement(&col, colTag); // ADDREF: col++
//XXX mark the col implicit
mContent->AppendChildTo((nsIContent*)col, PR_FALSE);
// Create a new col frame
nsIFrame* colFrame;
NS_NewTableColFrame(shell, &colFrame);
// Set its style context
nsCOMPtr<nsIStyleContext> colStyleContext;
aPresContext->ResolveStyleContextFor(col, mStyleContext,
PR_TRUE,
getter_AddRefs(colStyleContext));
colFrame->Init(aPresContext, col, this, colStyleContext, nsnull);
colFrame->SetInitialChildList(aPresContext, nsnull, nsnull);
// Set nsColFrame-specific information
PRInt32 absColIndex = mStartColIndex + colIndex;
((nsTableColFrame *)(colFrame))->InitColFrame (absColIndex);
((nsTableColFrame *)colFrame)->SetColumnIndex(absColIndex);
tableFrame->AddColumnFrame((nsTableColFrame *)colFrame);
//hook into list of children
if (nsnull==firstImplicitColFrame)
firstImplicitColFrame = colFrame;
else
prevColFrame->SetNextSibling(colFrame);
prevColFrame = colFrame;
}
// hook new columns into col group child list
mFrames.AppendFrames(nsnull, firstImplicitColFrame);
}
SetStyleContextForFirstPass(aPresContext);
if (!(NS_SUCCEEDED(rv) && tableFrame && aFirstFrame)) {
return rv;
}
// set the col indices of the col frames and and add col info to the table
PRInt32 colIndex = aFirstColIndex;
nsIFrame* kidFrame = aFirstFrame;
PRBool foundLastFrame = PR_FALSE;
while (kidFrame) {
nsIAtom* kidType;
kidFrame->GetFrameType(&kidType);
if (nsLayoutAtoms::tableColFrame == kidType) {
((nsTableColFrame*)kidFrame)->SetColIndex(colIndex);
if (!foundLastFrame) {
tableFrame->InsertCol(aPresContext, (nsTableColFrame &)*kidFrame, colIndex);
mColCount++;
}
colIndex++;
}
NS_IF_RELEASE(kidType);
if (kidFrame == aLastFrame) {
foundLastFrame = PR_TRUE;
}
kidFrame->GetNextSibling(&kidFrame);
}
if (aResetSubsequentColIndices) {
nsIFrame* nextSibling;
GetNextSibling(&nextSibling);
if (nextSibling) {
ResetColIndices(nextSibling, colIndex);
}
}
return rv;
}
NS_IMETHODIMP
nsTableColGroupFrame::AppendNewFrames(nsIPresContext* aPresContext, nsIFrame* aChildList)
// this is called when a col frame doesn't have an explicit col group parent.
nsTableColGroupFrame*
nsTableColGroupFrame::FindParentForAppendedCol(nsTableFrame* aTableFrame,
nsTableColType aColType)
{
if (nsnull!=aChildList)
mFrames.AppendFrames(nsnull, aChildList);
return NS_OK;
nsVoidArray& cols = aTableFrame->GetColCache();
PRInt32 numCols = cols.Count();
nsIFrame* lastColGroup;
nsIFrame* lastCol = (nsIFrame*)cols.ElementAt(numCols - 1);
if (!lastCol) return nsnull; // no columns so no colgroups
lastCol->GetParent(&lastColGroup);
if (!lastColGroup) return nsnull; // shouldn't happen
nsTableColGroupFrame* relevantColGroup = (nsTableColGroupFrame *)lastColGroup;
nsTableColGroupType relevantColGroupType = relevantColGroup->GetType();
if (eColGroupAnonymousCell == relevantColGroupType) {
if (eColAnonymousCell == aColType) {
return relevantColGroup;
}
else {
// find the next to last col group
for (PRInt32 colX = numCols - 2; colX >= 0; colX--) {
nsTableColFrame* colFrame = (nsTableColFrame*)cols.ElementAt(colX);
nsTableColGroupFrame* colGroupFrame;
colFrame->GetParent((nsIFrame**)&colGroupFrame);
nsTableColGroupType cgType = colGroupFrame->GetType();
if (cgType != relevantColGroupType) {
relevantColGroup = colGroupFrame;
relevantColGroupType = cgType;
break;
}
else if (0 == colX) {
return nsnull;
}
}
}
}
if (eColGroupAnonymousCol == relevantColGroupType) {
if ((eColContent == aColType) || (eColAnonymousCol == aColType)) {
return relevantColGroup;
}
}
return nsnull;
}
PRBool
nsTableColGroupFrame::GetLastRealColGroup(nsTableFrame* aTableFrame,
nsIFrame** aLastColGroup)
{
*aLastColGroup = nsnull;
nsFrameList colGroups = aTableFrame->GetColGroups();
nsIFrame* nextToLastColGroup = nsnull;
nsIFrame* lastColGroup = colGroups.FirstChild();
while(lastColGroup) {
nsIFrame* next;
lastColGroup->GetNextSibling(&next);
if (next) {
nextToLastColGroup = lastColGroup;
lastColGroup = next;
}
else {
break;
}
}
if (!lastColGroup) return PR_TRUE; // there are no col group frames
nsTableColGroupType lastColGroupType = ((nsTableColGroupFrame *)lastColGroup)->GetType();
if (eColGroupAnonymousCell == lastColGroupType) {
*aLastColGroup = nextToLastColGroup;
return PR_FALSE;
}
else {
*aLastColGroup = lastColGroup;
return PR_TRUE;
}
}
// don't set mColCount here, it is done in AddColsToTable
NS_IMETHODIMP
nsTableColGroupFrame::SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
nsresult result = AppendNewFrames(aPresContext, aChildList);
if (NS_OK==result)
result = InitNewFrames(aPresContext, aChildList);
return result;
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
if (!aChildList) {
nsIFrame* firstChild;
tableFrame->CreateAnonymousColFrames(*aPresContext, *this, GetSpan(), eColAnonymousColGroup,
PR_FALSE, nsnull, &firstChild);
if (firstChild) {
SetInitialChildList(aPresContext, aListName, firstChild);
}
return NS_OK;
}
nsIFrame* kidFrame = aChildList;
while (kidFrame) {
nsIAtom* kidType;
kidFrame->GetFrameType(&kidType);
if (nsLayoutAtoms::tableColFrame == kidType) {
// Set the preliminary values for the column frame
PRInt32 span = ((nsTableColFrame*)kidFrame)->GetSpan();
if (span > 1) {
nsTableColFrame* firstSpannedCol;
tableFrame->CreateAnonymousColFrames(*aPresContext, *this, span - 1, eColAnonymousCol,
PR_FALSE, (nsTableColFrame*)kidFrame, (nsIFrame **)&firstSpannedCol);
nsIFrame* spanner = kidFrame;
kidFrame->GetNextSibling(&kidFrame); // need to do this before we insert the new frames
nsFrameList newChildren(aChildList); // used as a convience to hook up siblings
newChildren.InsertFrames(this, (nsTableColFrame*)spanner, (nsIFrame *)firstSpannedCol);
NS_RELEASE(kidType);
continue;
}
}
NS_IF_RELEASE(kidType);
kidFrame->GetNextSibling(&kidFrame);
}
mFrames.AppendFrames(this, aChildList);
return NS_OK;
}
// Helper function. It marks the table frame as dirty and generates
@ -173,35 +303,8 @@ nsTableColGroupFrame::AppendFrames(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aFrameList)
{
// Append the new frames to our child list
mFrames.AppendFrames(nsnull, aFrameList);
// Reset the starting column index of the col groups that follow
PRInt32 startingColIndex = mStartColIndex;
startingColIndex += GetColumnCount(); // has the side effect of resetting all column indexes
nsIFrame *nextColGroupFrame=nsnull;
GetNextSibling(&nextColGroupFrame);
while (nextColGroupFrame)
{
const nsStyleDisplay *display;
nextColGroupFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)display);
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
{
startingColIndex += ((nsTableColGroupFrame *)nextColGroupFrame)->SetStartColumnIndex(startingColIndex);
}
nextColGroupFrame->GetNextSibling(&nextColGroupFrame);
}
// Today we need to rebuild the whole column cache.
// If the table frame is ever recoded to build the column cache incrementally,
// we could take advantage of that here
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
tableFrame->InvalidateColumnCache();
// Generate a reflow command so we reflow the table
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
mFrames.AppendFrames(this, aFrameList);
InsertColsReflow(*aPresContext, aPresShell, mColCount, aFrameList);
return NS_OK;
}
@ -209,76 +312,121 @@ NS_IMETHODIMP
nsTableColGroupFrame::InsertFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aPrevFrameIn,
nsIFrame* aFrameList)
{
// Insert the new frames into our child list
mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
nsFrameList frames(aFrameList); // convience for getting last frame
nsIFrame* lastFrame = frames.LastChild();
// Reset the starting column index of the col groups that follow
PRInt32 startingColIndex=mStartColIndex;
startingColIndex += GetColumnCount(); // has the side effect of resetting all column indexes
mFrames.InsertFrames(this, aPrevFrameIn, aFrameList);
nsIFrame* prevFrame = nsTableFrame::GetFrameAtOrBefore(this, aPrevFrameIn,
nsLayoutAtoms::tableColFrame);
nsIFrame *nextColGroupFrame=nsnull;
GetNextSibling(&nextColGroupFrame);
while (nextColGroupFrame)
{
const nsStyleDisplay *display;
nextColGroupFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)display);
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
{
startingColIndex += ((nsTableColGroupFrame *)nextColGroupFrame)->SetStartColumnIndex(startingColIndex);
}
nextColGroupFrame->GetNextSibling(&nextColGroupFrame);
}
PRInt32 colIndex = (prevFrame) ? ((nsTableColFrame*)prevFrame)->GetColIndex() + 1 : 0;
InsertColsReflow(*aPresContext, aPresShell, colIndex, aFrameList, lastFrame);
// Today we need to rebuild the whole column cache.
// If the table frame is ever recoded to build the column cache incrementally,
// we could take advantage of that here.
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
tableFrame->InvalidateColumnCache();
// Generate a reflow command so we reflow the table
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
return NS_OK;
}
void
nsTableColGroupFrame::InsertColsReflow(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
PRInt32 aColIndex,
nsIFrame* aFirstFrame,
nsIFrame* aLastFrame)
{
AddColsToTable(aPresContext, aColIndex, PR_TRUE, aFirstFrame, aLastFrame);
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
tableFrame->InvalidateColumnWidths();
// Generate a reflow command so we reflow the table
AddTableDirtyReflowCommand(&aPresContext, aPresShell, tableFrame);
}
void
nsTableColGroupFrame::RemoveChild(nsIPresContext& aPresContext,
nsTableColFrame& aChild,
PRBool aResetColIndices)
{
PRInt32 colIndex = 0;
nsIFrame* nextChild = nsnull;
if (aResetColIndices) {
colIndex = aChild.GetColIndex();
aChild.GetNextSibling(&nextChild);
}
if (mFrames.DestroyFrame(&aPresContext, (nsIFrame*)&aChild)) {
mColCount--;
if (aResetColIndices) {
ResetColIndices(this, colIndex, nextChild);
}
}
}
// this removes children form the last col group (eColGroupAnonymousCell) in the
// table only,so there is no need to reset col indices for subsequent col groups.
void
nsTableColGroupFrame::RemoveChildrenAtEnd(nsIPresContext& aPresContext,
PRInt32 aNumChildrenToRemove)
{
PRInt32 numToRemove = aNumChildrenToRemove;
if (numToRemove > mColCount) {
NS_ASSERTION(PR_FALSE, "invalid arg to RemoveChildrenAtEnd");
numToRemove = mColCount;
}
PRInt32 offsetOfFirstRemoval = mColCount - numToRemove;
PRInt32 offsetX = 0;
nsIFrame* kidFrame = mFrames.FirstChild();
while(kidFrame) {
nsIAtom* kidType;
kidFrame->GetFrameType(&kidType);
if (nsLayoutAtoms::tableColFrame == kidType) {
offsetX++;
if (offsetX > offsetOfFirstRemoval) {
nsIFrame* byebye = kidFrame;
kidFrame->GetNextSibling(&kidFrame);
mFrames.DestroyFrame(&aPresContext, byebye);
NS_RELEASE(kidType);
continue;
}
}
NS_IF_RELEASE(kidType);
kidFrame->GetNextSibling(&kidFrame);
}
}
NS_IMETHODIMP
nsTableColGroupFrame::RemoveFrame(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame)
{
// Remove the frame from our child list
mFrames.DestroyFrame(aPresContext, aOldFrame);
if (!aOldFrame) return NS_OK;
// Reset the starting column index of the col groups that follow
PRInt32 startingColIndex=mStartColIndex;
startingColIndex += GetColumnCount(); // has the side effect of resetting all column indexes
nsIFrame *nextColGroupFrame=nsnull;
GetNextSibling(&nextColGroupFrame);
while (nextColGroupFrame)
{
const nsStyleDisplay *display;
nextColGroupFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)display);
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
{
startingColIndex += ((nsTableColGroupFrame *)nextColGroupFrame)->SetStartColumnIndex(startingColIndex);
nsIAtom* frameType = nsnull;
aOldFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableColFrame == frameType) {
nsTableColFrame* colFrame = (nsTableColFrame*)aOldFrame;
PRInt32 colIndex = colFrame->GetColIndex();
RemoveChild(*aPresContext, *colFrame, PR_TRUE);
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
if (tableFrame) {
tableFrame->RemoveCol(*aPresContext, this, colIndex, PR_TRUE, PR_TRUE);
}
nextColGroupFrame->GetNextSibling(&nextColGroupFrame);
tableFrame->InvalidateColumnWidths();
// Generate a reflow command so we reflow the table
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
}
else {
mFrames.DestroyFrame(aPresContext, aOldFrame);
}
NS_IF_RELEASE(frameType);
// Today we need to rebuild the whole column cache.
// If the table frame is ever recoded to build the column cache incrementally,
// we could take advantage of that here
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
tableFrame->InvalidateColumnCache();
// Generate a reflow command so we reflow the table
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
return NS_OK;
}
@ -429,11 +577,10 @@ NS_METHOD nsTableColGroupFrame::IR_StyleChanged(nsIPresContext* aPresCo
nsresult rv = NS_OK;
// we presume that all the easy optimizations were done in the nsHTMLStyleSheet before we were called here
// XXX: we can optimize this when we know which style attribute changed
nsTableFrame* tableFrame=nsnull;
nsTableFrame* tableFrame = nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
{
tableFrame->InvalidateColumnCache();
if ((NS_SUCCEEDED(rv)) && tableFrame) {
tableFrame->InvalidateColumnWidths();
tableFrame->InvalidateFirstPassCache();
}
return rv;
@ -448,7 +595,7 @@ NS_METHOD nsTableColGroupFrame::IR_TargetIsChild(nsIPresContext* aPresC
nsresult rv;
// Remember the old col count
const PRInt32 oldColCount = GetColumnCount();
const PRInt32 oldColCount = GetColCount();
// Pass along the reflow command
nsHTMLReflowMetrics desiredSize(nsnull);
@ -462,136 +609,16 @@ NS_METHOD nsTableColGroupFrame::IR_TargetIsChild(nsIPresContext* aPresC
nsTableFrame *tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
{
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame)) {
// compare the new col count to the old col count.
// If they are the same, we just need to rebalance column widths
// If they differ, we need to fix up other column groups and the column cache
const PRInt32 newColCount = GetColumnCount(); // this will set the new column indexes if necessary
if (oldColCount==newColCount)
tableFrame->InvalidateColumnWidths();
else
tableFrame->InvalidateColumnCache();
const PRInt32 newColCount = GetColCount();
tableFrame->InvalidateColumnWidths();
}
return rv;
}
// Subclass hook for style post processing
NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext* aPresContext)
{
// get the table frame
nsTableFrame* tableFrame=nsnull;
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
{
// get the style for the table frame
const nsStyleTable *tableStyle;
tableFrame->GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
// if COLS is set, then map it into the COL frames
if (NS_STYLE_TABLE_COLS_NONE != tableStyle->mCols)
{
// set numCols to the number of columns effected by the COLS attribute
PRInt32 numCols=0;
if (NS_STYLE_TABLE_COLS_ALL == tableStyle->mCols)
numCols = mFrames.GetLength();
else
numCols = tableStyle->mCols;
// for every column effected, set its width style
PRInt32 colIndex=0;
nsIFrame *colFrame=mFrames.FirstChild();
while (nsnull!=colFrame)
{
const nsStyleDisplay * colDisplay=nsnull;
colFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)colDisplay));
if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
{
nsCOMPtr<nsIStyleContext> colStyleContext;
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleContext(getter_AddRefs(colStyleContext));
colPosition = (nsStylePosition*)colStyleContext->GetMutableStyleData(eStyleStruct_Position);
if (colIndex<numCols)
{
nsStyleCoord width (1, eStyleUnit_Proportional);
colPosition->mWidth = width;
}
else
{
colPosition->mWidth.SetCoordValue(0);
}
colStyleContext->RecalcAutomaticData(aPresContext);
colIndex++;
}
colFrame->GetNextSibling(&colFrame);
}
}
else
{
// propagate the colgroup width attribute down to the columns if they have no width of their own
nsStylePosition* position = (nsStylePosition*)mStyleContext->GetStyleData(eStyleStruct_Position);
if (eStyleUnit_Null!=position->mWidth.GetUnit())
{
// now for every column that doesn't have it's own width, set the width style
nsIFrame *colFrame=mFrames.FirstChild();
while (nsnull!=colFrame)
{
const nsStyleDisplay * colDisplay=nsnull;
colFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)colDisplay));
if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
{
nsCOMPtr<nsIStyleContext> colStyleContext;
const nsStylePosition * colPosition=nsnull;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)colPosition); // get a read-only version of the style context
//XXX: how do I know this is auto because it's defaulted, vs. set explicitly to "auto"?
if (eStyleUnit_Auto==colPosition->mWidth.GetUnit())
{
// notice how we defer getting a mutable style context until we're sure we really need one
colFrame->GetStyleContext(getter_AddRefs(colStyleContext));
nsStylePosition * mutableColPosition = (nsStylePosition*)colStyleContext->GetMutableStyleData(eStyleStruct_Position);
mutableColPosition->mWidth = position->mWidth;
colStyleContext->RecalcAutomaticData(aPresContext);
}
}
colFrame->GetNextSibling(&colFrame);
}
}
}
//mStyleContext->RecalcAutomaticData(aPresContext);
}
return rv;
}
/** returns the number of columns represented by this group.
* if there are col children, count them (taking into account the span of each)
* else, check my own span attribute.
*/
int nsTableColGroupFrame::GetColumnCount ()
{
mColCount=0;
nsIFrame *childFrame = mFrames.FirstChild();
while (nsnull!=childFrame)
{
const nsStyleDisplay *childDisplay;
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay)
{
nsTableColFrame *col = (nsTableColFrame *)childFrame;
col->SetColumnIndex (mStartColIndex + mColCount);
mColCount += col->GetSpan();
}
childFrame->GetNextSibling(&childFrame);
}
if (0==mColCount)
{ // there were no children of this colgroup that were columns. So use my span attribute
const nsStyleTable *tableStyle;
GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
mColCount = tableStyle->mSpan;
}
return mColCount;
}
nsTableColFrame * nsTableColGroupFrame::GetFirstColumn()
{
return GetNextColumn(nsnull);
@ -642,28 +669,26 @@ nsTableColFrame * nsTableColGroupFrame::GetColumnAt (PRInt32 aColIndex)
PRInt32 nsTableColGroupFrame::GetSpan()
{
PRInt32 span=1;
const nsStyleTable* tableStyle=nsnull;
GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
if (nsnull!=tableStyle)
{
span = tableStyle->mSpan;
PRInt32 span = 1;
nsCOMPtr<nsIContent> iContent;
nsresult rv = GetContent(getter_AddRefs(iContent));
if (NS_FAILED(rv) || !iContent) return rv;
// col group element derives from col element
nsIDOMHTMLTableColElement* cgContent = nsnull;
rv = iContent->QueryInterface(kIDOMHTMLTableColElementIID,
(void **)&cgContent);
if (cgContent && NS_SUCCEEDED(rv)) {
cgContent->GetSpan(&span);
// XXX why does this work!!
if (span == -1) {
span = 1;
}
NS_RELEASE(cgContent);
}
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.
@ -671,15 +696,41 @@ PRBool nsTableColGroupFrame::IsManufactured()
PRInt32 nsTableColGroupFrame::SetStartColumnIndex (int aIndex)
{
PRInt32 result = mColCount;
if (aIndex != mStartColIndex)
{
if (aIndex != mStartColIndex) {
mStartColIndex = aIndex;
mColCount=0;
result = GetColumnCount(); // has the side effect of setting each column index based on new start index
result = GetColCount();
}
return result;
}
// this could be optimized by using col group frame starting indicies,
// but typically there aren't enough very large col groups for the added complexity.
nsTableColGroupFrame*
nsTableColGroupFrame::GetColGroupFrameContaining(nsFrameList& aColGroupList,
nsTableColFrame& aColFrame)
{
nsIFrame* childFrame = aColGroupList.FirstChild();
while (childFrame) {
nsIAtom* frameType = nsnull;
childFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableColGroupFrame == frameType) {
nsTableColFrame* colFrame = nsnull;
childFrame->FirstChild(nsnull, (nsIFrame **)&colFrame);
while (colFrame) {
if (colFrame = &aColFrame) {
NS_RELEASE(frameType);
return (nsTableColGroupFrame *)childFrame;
}
colFrame->GetNextSibling((nsIFrame **)&colFrame);
}
}
NS_IF_RELEASE(frameType);
childFrame->GetNextSibling(&childFrame);
}
return nsnull;
}
void nsTableColGroupFrame::DeleteColFrame(nsIPresContext* aPresContext, nsTableColFrame* aColFrame)
{
mFrames.DestroyFrame(aPresContext, aColFrame);

View File

@ -26,7 +26,14 @@
#include "nsHTMLContainerFrame.h"
class nsTableColFrame;
class nsTableFrame;
enum nsTableColType;
enum nsTableColGroupType {
eColGroupContent = 0, // there is real col group content associated
eColGroupAnonymousCol = 1, // the result of a col
eColGroupAnonymousCell = 2, // the result of a cell alone
};
/**
* nsTableColGroupFrame
@ -52,6 +59,16 @@ public:
nsIAtom* aListName,
nsIFrame* aChildList);
nsTableColGroupType GetType() const;
void SetType(nsTableColGroupType aType);
static PRBool GetLastRealColGroup(nsTableFrame* aTableFrame,
nsIFrame** aLastColGroup);
static nsTableColGroupFrame* FindParentForAppendedCol(nsTableFrame* aTableFrame,
nsTableColType aColType);
NS_IMETHOD AppendFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
@ -66,6 +83,13 @@ public:
nsIAtom* aListName,
nsIFrame* aOldFrame);
void RemoveChild(nsIPresContext& aPresContext,
nsTableColFrame& aLastChild,
PRBool aResetColIndices);
void RemoveChildrenAtEnd(nsIPresContext& aPresContext,
PRInt32 aNumChildrenToRemove);
NS_IMETHOD Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
@ -89,6 +113,12 @@ public:
*/
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
NS_IMETHOD AddColsToTable(nsIPresContext& aPresContext,
PRInt32 aFirstColIndex,
PRBool aResetSubsequentColIndices,
nsIFrame* aFirstFrame,
nsIFrame* aLastFrame = nsnull);
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsString& aResult) const;
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
@ -98,7 +128,7 @@ 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 GetColCount() const;
virtual nsTableColFrame * GetFirstColumn();
@ -124,23 +154,25 @@ public:
void DeleteColFrame(nsIPresContext* aPresContext, nsTableColFrame* aColFrame);
protected:
static nsTableColGroupFrame* GetColGroupFrameContaining(nsFrameList& aColGroupList,
nsTableColFrame& aColFrame);
nsFrameList& GetChildList();
static void ResetColIndices(nsIFrame* aFirstColGroup,
PRInt32 aFirstColIndex,
nsIFrame* aStartColFrame = nsnull);
protected:
nsTableColGroupFrame();
void InsertColsReflow(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
PRInt32 aColIndex,
nsIFrame* aFirstFrame,
nsIFrame* aLastFrame = nsnull);
/** implement abstract method on nsHTMLContainerFrame */
virtual PRIntn GetSkipSides() const;
/** Hook for style post processing.
* Since we need to know the full column structure before the COLS attribute
* can be interpreted, we can't just use DidSetStyleContext
*/
NS_IMETHOD SetStyleContextForFirstPass(nsIPresContext* aPresContext);
NS_IMETHOD InitNewFrames(nsIPresContext* aPresContext, nsIFrame* aChildList);
NS_IMETHOD AppendNewFrames(nsIPresContext* aPresContext, nsIFrame* aChildList);
NS_IMETHOD IncrementalReflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
@ -174,13 +206,33 @@ protected:
/** the starting column index this col group represents. Must be >= 0. */
PRInt32 mStartColIndex;
struct ColGroupBits {
unsigned int mType:4;
unsigned int mUnused:28;
} mBits;
};
inline nsTableColGroupFrame::nsTableColGroupFrame()
: mColCount(0), mStartColIndex(0)
{}
{
mBits.mType = 0;
}
inline int nsTableColGroupFrame::GetStartColumnIndex ()
{ return mStartColIndex;}
inline PRInt32 nsTableColGroupFrame::GetStartColumnIndex()
{
return mStartColIndex;
}
inline PRInt32 nsTableColGroupFrame::GetColCount() const
{
return mColCount;
}
inline nsFrameList& nsTableColGroupFrame::GetChildList()
{
return mFrames;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,8 @@ class nsHTMLValue;
struct InnerTableReflowState;
struct nsStylePosition;
struct nsStyleSpacing;
enum nsTableColType;
enum nsTableColGroupType;
/**
* Child list name indices
@ -124,8 +126,14 @@ public:
/** helper method to find the table parent of any table frame object */
// TODO: today, this depends on display types. This should be changed to rely
// on stronger criteria, like an inner table frame atom
static NS_METHOD GetTableFrame(nsIFrame *aSourceFrame, nsTableFrame *& aTableFrame);
static NS_METHOD GetTableFrame(nsIFrame* aSourceFrame,
nsTableFrame*& aTableFrame);
// Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
// of type aChildType.
static nsIFrame* nsTableFrame::GetFrameAtOrBefore(nsIFrame* aParentFrame,
nsIFrame* aPriorChildFrame,
nsIAtom* aChildType);
/**
* @param aReflowState the context within which we're to determine the table width info
* @param aSpecifiedTableWidth [OUT] if the table is not auto-width,
@ -143,10 +151,6 @@ public:
PRBool IsRowGroup(PRInt32 aDisplayType) const;
/** Initialize the table frame with a set of children.
* Calls DidAppendRowGroup which calls nsTableRowFrame::InitChildren
* which finally calls back into this table frame to build the cell map.
* Also ensures we have the right number of column frames for the child list.
*
* @see nsIFrame::SetInitialChildList
*/
NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext,
@ -162,16 +166,6 @@ public:
NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex,
nsIAtom** aListName) const;
/** complete the append of aRowGroupFrame to the table
* this builds the cell map by calling nsTableRowFrame::InitChildren
* which calls back into this table frame to build the cell map.
* @param aRowGroupFrame the row group that was appended.
* note that this method is optimized for content appended, and doesn't
* work for random insertion of row groups. Random insertion must go
* through incremental reflow notifications.
*/
NS_IMETHOD DidAppendRowGroup(nsTableRowGroupFrame *aRowGroupFrame);
/** @see nsIFrame::Paint */
NS_IMETHOD Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -221,6 +215,8 @@ public:
*/
NS_METHOD GetColumnFrame(PRInt32 aColIndex, nsTableColFrame *&aColFrame);
nsFrameList& GetColGroups();
/** return PR_TRUE if the column width information has been set */
PRBool IsColumnWidthsSet();
@ -308,14 +304,84 @@ public:
*/
PRInt32 GetNextAvailRowIndex() const;
/** build as much of the CellMap as possible from the info we have so far
*/
virtual PRInt32 AddCellToTable (nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
virtual void RemoveCellFromTable (nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
/** return the column frame associated with aColIndex */
nsTableColFrame* GetColFrame(PRInt32 aColIndex) const;
virtual void AddColumnFrame (nsTableColFrame *aColFrame);
void InsertCol(nsIPresContext& aPresContext,
nsTableColFrame& aColFrame,
PRInt32 aColIndex);
nsTableColGroupFrame* CreateAnonymousColGroupFrame(nsIPresContext& aPresContext,
nsTableColGroupType aType);
PRInt32 DestroyAnonymousColFrames(nsIPresContext& aPresContext,
PRInt32 aNumFrames);
void CreateAnonymousColFrames(nsIPresContext& aPresContext,
PRInt32 aNumColsToAdd,
nsTableColType aColType,
PRBool aDoAppend,
nsIFrame* aPrevCol = nsnull);
void CreateAnonymousColFrames(nsIPresContext& aPresContext,
nsTableColGroupFrame& aColGroupFrame,
PRInt32 aNumColsToAdd,
nsTableColType aColType,
PRBool aAddToColGroupAndTable,
nsIFrame* aPrevCol,
nsIFrame** aFirstNewFrame);
/** empty the column frame cache */
void ClearColCache();
virtual PRInt32 AppendCell(nsIPresContext& aPresContext,
nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex);
virtual void InsertCells(nsIPresContext& aPresContext,
nsVoidArray& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndexBefore);
virtual void RemoveCell(nsIPresContext& aPresContext,
nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
void AppendRows(nsIPresContext& aPresContext,
nsVoidArray& aRowFrames);
PRInt32 InsertRow(nsIPresContext& aPresContext,
nsIFrame& aFrame,
PRInt32 aRowIndex,
PRBool aConsiderSpans);
PRInt32 InsertRows(nsIPresContext& aPresContext,
nsVoidArray& aFrames,
PRInt32 aRowIndex,
PRBool aConsiderSpans);
virtual void RemoveRows(nsIPresContext& aPresContext,
PRInt32 aFirstRowFrame,
PRInt32 aNumRowsToRemove,
PRBool aConsiderSpans);
void AppendRowGroups(nsIPresContext& aPresContext,
nsIFrame* aFirstRowGroupFrame);
void InsertRowGroups(nsIPresContext& aPresContext,
nsIFrame* aFirstRowGroupFrame,
PRInt32 aRowIndex);
void InsertColGroups(nsIPresContext& aPresContext,
PRInt32 aColIndex,
nsIFrame* aFirstFrame,
nsIFrame* aLastFrame = nsnull);
virtual void RemoveCol(nsIPresContext& aPresContext,
nsTableColGroupFrame* aColGroupFrame,
PRInt32 aColIndex,
PRBool aRemoveFromCache,
PRBool aRemoveFromCellMap);
static PRBool IsFinalPass(const nsHTMLReflowState& aReflowState);
@ -323,7 +389,7 @@ public:
PRInt32 aColX,
PRBool* aOriginates = nsnull,
PRInt32* aColSpan = nsnull);
PRInt32 GetNumCellsOriginatingInRow(PRInt32 aRowIndex) const;
PRInt32 GetNumCellsOriginatingInCol(PRInt32 aColIndex) const;
NS_METHOD GetBorderPlusMarginPadding(nsMargin& aResult);
@ -554,9 +620,6 @@ 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;
/** returns PR_TRUE if the cached column info is still valid */
virtual PRBool IsColumnWidthsValid() const;
@ -612,8 +675,6 @@ public:
virtual void InvalidateFirstPassCache();
virtual void InvalidateColumnCache();
virtual void InvalidateColumnWidths();
protected:
@ -623,38 +684,18 @@ protected:
void MapHTMLBorderStyle(nsStyleSpacing& aSpacingStyle, nscoord aBorderWidth);
PRBool ConvertToPixelValue(nsHTMLValue& aValue, PRInt32 aDefault, PRInt32& aResult);
/** returns PR_TRUE if the cached pass 1 data is still valid */
virtual PRBool IsCellMapValid() const;
public:
/** Get the cell map for this table frame. It is not always mCellMap.
* Only the firstInFlow has a legit cell map
*/
virtual nsCellMap *GetCellMap() const;
/** ResetCellMap is called when the cell structure of the table is changed.
* Call with caution, only when changing the structure of the table such as
* inserting or removing rows, changing the rowspan or colspan attribute of a cell, etc.
*/
virtual void InvalidateCellMap();
/** sum the columns represented by all nsTableColGroup objects.
* if the cell map says there are more columns than this,
* add extra implicit columns to the content tree.
*
* returns whether any implicit column frames were created
*/
virtual void EnsureColumns (nsIPresContext* aPresContext,
PRBool& aCreatedColFrames);
// These methods are used to incrementally insert and remove rows
// from the cell map without having to invalidate the entire map.
NS_IMETHOD InsertRowIntoMap(nsTableRowFrame* aRow, PRInt32 aRowIndex);
NS_IMETHOD RemoveRowFromMap(nsTableRowFrame* aRow, PRInt32 aRowIndex);
void AdjustRowIndices(PRInt32 aRowIndex,
PRInt32 aAdjustment);
NS_IMETHOD AdjustRowIndices(nsIFrame* aRowGroup,
PRInt32 aRowIndex,
PRInt32 anAdjustment);
PRInt32 aRowIndex,
PRInt32 anAdjustment);
// Return PR_TRUE if rules=groups is set for the table content
PRBool HasGroupRules() const;
@ -662,9 +703,9 @@ public:
// Remove cell borders which aren't bordering row and/or col groups
void ProcessGroupRules(nsIPresContext* aPresContext);
nsVoidArray& GetColCache();
protected:
/** iterates all child frames and creates a new cell map */
NS_IMETHOD ReBuildCellMap();
void SetColumnDimensions(nsIPresContext* aPresContext, nscoord aHeight);
@ -685,7 +726,14 @@ protected:
/**
* Return aFrame's child if aFrame is an nsScrollFrame, otherwise return aFrame
*/
nsTableRowGroupFrame* GetRowGroupFrameFor(nsIFrame* aFrame, const nsStyleDisplay* aDisplay);
nsTableRowGroupFrame* GetRowGroupFrameFor(nsIFrame* aFrame,
const nsStyleDisplay* aDisplay);
nsTableRowGroupFrame* GetRowGroupFrame(nsIFrame* aFrame,
nsIAtom* aFrameTypeIn = nsnull);
void CollectRows(nsIFrame* aFrame,
nsVoidArray& aCollection);
public: /* ----- Cell Map public methods ----- */
@ -752,14 +800,16 @@ public: /* ----- Cell Map public methods ----- */
/*------------end of nsITableLayout methods -----------------------*/
virtual void CacheColFrames(nsIPresContext* aPresContext,
PRBool aReset = PR_FALSE);
public:
static nsIAtom* gColGroupAtom;
void Dump(PRBool aDumpCols, PRBool aDumpCellMap);
void Dump(PRBool aDumpRows,
PRBool aDumpCols,
PRBool aDumpCellMap);
nsVoidArray mColFrames; // XXX temporarily public
protected:
void DumpRowGroup(nsIFrame* aChildFrame);
void DebugPrintCount() const; // Debugging routine
// data members
@ -770,15 +820,11 @@ protected:
unsigned mColumnWidthsSet:1; // PR_TRUE if column widths have been set at least once
unsigned mColumnWidthsValid:1; // PR_TRUE if column width data is still legit, PR_FALSE if it needs to be recalculated
unsigned mFirstPassValid:1; // PR_TRUE if first pass data is still legit, PR_FALSE if it needs to be recalculated
unsigned mColumnCacheValid:1; // PR_TRUE if column cache info is still legit, PR_FALSE if it needs to be recalculated
unsigned mCellMapValid:1; // PR_TRUE if cell map data is still legit, PR_FALSE if it needs to be recalculated
unsigned mIsInvariantWidth:1; // PR_TRUE if table width cannot change
unsigned mHasScrollableRowGroup:1; // PR_TRUE if any section has overflow == "auto" or "scroll"
unsigned mNonPercentSpansPercent:1;
int : 24; // unused
int : 26; // unused
} mBits;
PRInt32 mColCount; // the number of columns in this table
nsCellMap* mCellMap; // maintains the relationships between rows, cols, and cells
nsITableLayoutStrategy * mTableLayoutStrategy; // the layout strategy for this frame
nsFrameList mColGroups; // the list of colgroup frames
@ -811,6 +857,16 @@ inline void nsTableFrame::SetHasNonPercentSpanningPercent(PRBool aValue)
mBits.mNonPercentSpansPercent = (unsigned)aValue;
}
inline nsFrameList& nsTableFrame::GetColGroups()
{
return mColGroups;
}
inline nsVoidArray& nsTableFrame::GetColCache()
{
return mColFrames;
}
enum nsTableIteration {
eTableLTR = 0,
eTableRTL = 1,

View File

@ -56,6 +56,7 @@ nsTableRowFrame::nsTableRowFrame()
mAllBits(0)
{
mBits.mMinRowSpan = 1;
mBits.mRowIndex = 0;
}
NS_IMETHODIMP
@ -129,23 +130,11 @@ nsTableRowFrame::AppendFrames(nsIPresContext* aPresContext,
if (NS_STYLE_DISPLAY_TABLE_CELL == display->mDisplay) {
// Add the cell to the cell map
PRInt32 colIndex = tableFrame->AddCellToTable((nsTableCellFrame*)childFrame,
GetRowIndex());
// Initialize the cell frame and give it its column index
((nsTableCellFrame*)childFrame)->InitCellFrame(colIndex);
tableFrame->AppendCell(*aPresContext, (nsTableCellFrame&)*childFrame, GetRowIndex());
}
}
// See if any implicit column frames need to be created as a result of
// adding the new rows
PRBool createdColFrames;
tableFrame->EnsureColumns(aPresContext, createdColFrames);
if (createdColFrames) {
// We need to rebuild the column cache
// XXX It would be nice if this could be done incrementally
tableFrame->InvalidateColumnCache();
}
tableFrame->InvalidateColumnWidths();
// Reflow the new frames. They're already marked dirty, so generate a reflow
// command that tells us to reflow our dirty child frames
@ -160,6 +149,7 @@ nsTableRowFrame::AppendFrames(nsIPresContext* aPresContext,
return NS_OK;
}
NS_IMETHODIMP
nsTableRowFrame::InsertFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
@ -171,26 +161,39 @@ nsTableRowFrame::InsertFrames(nsIPresContext* aPresContext,
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
// Insert the frames
// gather the new frames (only those which are cells) into an array
nsTableCellFrame* prevCellFrame = (nsTableCellFrame *)nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame, nsLayoutAtoms::tableCellFrame);
nsVoidArray cellChildren;
for (nsIFrame* childFrame = aFrameList; childFrame; childFrame->GetNextSibling(&childFrame)) {
nsIAtom* frameType;
childFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableCellFrame == frameType) {
cellChildren.AppendElement(childFrame);
}
NS_IF_RELEASE(frameType);
}
// insert the cells into the cell map
PRInt32 colIndex = -1;
if (prevCellFrame) {
prevCellFrame->GetColIndex(colIndex);
}
tableFrame->InsertCells(*aPresContext, cellChildren, GetRowIndex(), colIndex);
// Insert the frames in the frame list
mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
// We need to rebuild the cell map, because currently we can't insert
// new frames except at the end (append)
tableFrame->InvalidateCellMap();
// Because the number of columns may have changed invalidate the column widths
tableFrame->InvalidateColumnWidths();
// We should try and avoid doing a pass1 reflow on all the cells and just
// do it for the newly added frames, but we need to add these frames to the
// cell map before we reflow them
tableFrame->InvalidateFirstPassCache();
// Reflow the new frames. They're already marked dirty, so generate a reflow
// command that tells us to reflow our dirty child frames
nsIReflowCommand* reflowCmd;
// Because the number of columns may have changed invalidate the column
// cache. Note that this has the side effect of recomputing the column
// widths, so we don't need to call InvalidateColumnWidths()
tableFrame->InvalidateColumnCache();
// Generate a reflow command so we reflow the table itself. This will
// do a pass-1 reflow of all the rows including any rows we just added
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
if (NS_SUCCEEDED(NS_NewHTMLReflowCommand(&reflowCmd, this,
nsIReflowCommand::ReflowDirty))) {
aPresShell.AppendReflowCommand(reflowCmd);
NS_RELEASE(reflowCmd);
}
return NS_OK;
}
@ -203,91 +206,28 @@ nsTableRowFrame::RemoveFrame(nsIPresContext* aPresContext,
// Get the table frame
nsTableFrame* tableFrame=nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
if (tableFrame) {
nsIAtom* frameType;
aOldFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableCellFrame == frameType) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)aOldFrame;
PRInt32 colIndex;
cellFrame->GetColIndex(colIndex);
tableFrame->RemoveCell(*aPresContext, cellFrame, GetRowIndex());
#if 0
// XXX Currently we can't incrementally remove cells from the cell map
PRInt32 colIndex;
aDeletedFrame->GetColIndex(colIndex);
tableFrame->RemoveCellFromTable(aOldFrame, GetRowIndex());
// Remove the frame and destroy it
mFrames.DestroyFrame(aPresContext, aOldFrame);
// Remove the frame and destroy it
mFrames.DestroyFrame(aPresContext, (nsIFrame*)aOldFrame);
// cells have possibly shifted into different columns.
tableFrame->InvalidateColumnWidths();
// XXX Reflow the row
#else
// Remove the frame and destroy it
mFrames.DestroyFrame(aPresContext, aOldFrame);
// We need to rebuild the cell map, because currently we can't incrementally
// remove rows
tableFrame->InvalidateCellMap();
// Because the number of columns may have changed invalidate the column
// cache. Note that this has the side effect of recomputing the column
// widths, so we don't need to call InvalidateColumnWidths()
tableFrame->InvalidateColumnCache();
// Because we haven't added any new frames we don't need to do a pass1
// reflow. Just generate a reflow command so we reflow the table itself
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
#endif
return NS_OK;
}
NS_IMETHODIMP
nsTableRowFrame::InitChildrenWithIndex(PRInt32 aRowIndex)
{
nsTableFrame* table = nsnull;
nsresult result=NS_OK;
// each child cell can only be added to the table one time.
// for now, we remember globally whether we've added all or none
if (0 == (mState & NS_TABLE_ROW_FRAME_INITIALIZED_CHILDREN))
{
result = nsTableFrame::GetTableFrame(this, table);
if ((NS_OK==result) && (table != nsnull))
{
mState |= NS_TABLE_ROW_FRAME_INITIALIZED_CHILDREN;
SetRowIndex(aRowIndex);
for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame))
{
const nsStyleDisplay *kidDisplay;
kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)kidDisplay));
if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay)
{
// add the cell frame to the table's cell map and get its col index
PRInt32 colIndex;
colIndex = table->AddCellToTable((nsTableCellFrame *)kidFrame, aRowIndex);
// what column does this cell belong to?
// this sets the frame's notion of its column index
((nsTableCellFrame *)kidFrame)->InitCellFrame(colIndex);
}
}
// Because we haven't added any new frames we don't need to do a pass1
// reflow. Just generate a reflow command so we reflow the table itself
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
}
NS_IF_RELEASE(frameType);
}
return NS_OK;
}
NS_IMETHODIMP
nsTableRowFrame::InitChildren()
{
nsTableFrame* table = nsnull;
nsresult result=NS_OK;
// each child cell can only be added to the table one time.
// for now, we remember globally whether we've added all or none
if (0 == (mState & NS_TABLE_ROW_FRAME_INITIALIZED_CHILDREN))
{
result = nsTableFrame::GetTableFrame(this, table);
if ((NS_OK==result) && (table != nsnull))
{
PRInt32 rowIndex = table->GetNextAvailRowIndex();
InitChildrenWithIndex(rowIndex);
}
}
return NS_OK;
}

View File

@ -62,9 +62,6 @@ struct RowReflowState {
/**
* Additional frame-state bits
*/
#define NS_TABLE_ROW_FRAME_INITIALIZED_CHILDREN 0x80000000 // set if child cells have been
// added to the table
#define NS_TABLE_MAX_ROW_INDEX (1<<19)
/**
@ -100,12 +97,6 @@ public:
nsIAtom* aListName,
nsIFrame* aOldFrame);
/** Initialization of data */
NS_IMETHOD InitChildren();
NS_IMETHOD InitChildrenWithIndex(PRInt32 aRowIndex);
void ResetInitChildren();
/** instantiate a new instance of nsTableRowFrame.
* @param aResult the new object is returned in this out-param
* @param aContent the table object to map
@ -322,11 +313,6 @@ inline void nsTableRowFrame::SetRowIndex (int aRowIndex)
mBits.mRowIndex = aRowIndex;
}
inline void nsTableRowFrame::ResetInitChildren()
{
mState &= ~NS_TABLE_ROW_FRAME_INITIALIZED_CHILDREN;
}
inline void nsTableRowFrame::GetMaxElementSize(nsSize& aMaxElementSize) const
{
aMaxElementSize.width = mMaxElementSize.width;

View File

@ -565,6 +565,7 @@ NS_METHOD nsTableRowGroupFrame::PullUpAllRowFrames(nsIPresContext* aPresContext)
void nsTableRowGroupFrame::GetNextRowSibling(nsIFrame** aRowFrame)
{
if (!*aRowFrame) return;
GetNextFrame(*aRowFrame, aRowFrame);
while(*aRowFrame) {
const nsStyleDisplay *display;
@ -596,7 +597,9 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
PRBool hasRowSpanningCell = PR_FALSE;
PRInt32 numRows;
GetRowCount(numRows, PR_FALSE);
if (numRows <= 0) return;
nscoord *rowHeights = new nscoord[numRows];
if (!rowHeights) return;
nsCRT::memset (rowHeights, 0, numRows*sizeof(nscoord));
/* Step 1: get the height of the tallest cell in the row and save it for
@ -747,10 +750,11 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
// If this is pass 2 then resize the row to its final size and move the
// row's position if the previous rows have caused a shift
if (1 == counter) {
nsRect rowBounds;
rowFrame->GetRect(rowBounds);
PRBool movedFrame = (deltaY != 0);
nsRect rowBounds;
// Move the row to the correct position
rowFrame->GetRect(rowBounds); // added
rowBounds.y += deltaY;
// Adjust our running delta
@ -759,6 +763,17 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
// Resize the row to its final size and position
rowBounds.height = rowHeights[rowIndex];
rowFrame->SetRect(aPresContext, rowBounds);
if (movedFrame) {
// Make sure any views are positioned properly
nsIView* view;
rowFrame->GetView(aPresContext, &view);
if (view) {
nsContainerFrame::PositionFrameView(aPresContext, rowFrame, view);
} else {
nsContainerFrame::PositionChildViews(aPresContext, rowFrame);
}
}
}
rowIndex++;
@ -1155,45 +1170,47 @@ nsTableRowGroupFrame::AddTableDirtyReflowCommand(nsIPresContext* aPresContext,
return rv;
}
#if 0
// Reflow the new frames. They're already marked dirty, so generate a reflow
// command that tells us to reflow our dirty child frames
nsIReflowCommand* reflowCmd;
if (NS_SUCCEEDED(NS_NewHTMLReflowCommand(&reflowCmd, this,
nsIReflowCommand::ReflowDirty))) {
aPresShell.AppendReflowCommand(reflowCmd);
NS_RELEASE(reflowCmd);
}
#endif
// this does not get called for trees
NS_IMETHODIMP
nsTableRowGroupFrame::AppendFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList)
{
// Get the table frame
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
// collect the new row frames in an array
nsVoidArray rows;
for (nsIFrame* rowFrame = aFrameList; rowFrame; rowFrame->GetNextSibling(&rowFrame)) {
nsIAtom* frameType;
rowFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableRowFrame == frameType) {
rows.AppendElement(rowFrame);
}
NS_IF_RELEASE(frameType);
}
// Append the frames
// Append the frames to the sibling chain
mFrames.AppendFrames(nsnull, aFrameList);
const nsStyleDisplay *display;
aFrameList->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
// See if the newly appended rows are the last rows in the table.
// XXX is this the correct code path for nested row groups, considering that whitespace frames may exist currently
if ((NS_STYLE_DISPLAY_TABLE_ROW_GROUP != display->mDisplay) && NoRowsFollow()) {
// The rows we appended are the last rows in the table so incrementally
// add them to the cell map
PRBool haveRows = PR_FALSE;
for (nsIFrame* rowFrame = aFrameList; rowFrame; rowFrame->GetNextSibling(&rowFrame)) {
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
if (NS_STYLE_DISPLAY_TABLE_ROW == display->mDisplay) {
DidAppendRow((nsTableRowFrame*)rowFrame);
haveRows = PR_TRUE;
}
}
if (rows.Count() > 0) {
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
if (tableFrame) {
tableFrame->AppendRows(*aPresContext, rows);
if (haveRows) {
// See if any implicit column frames need to be created as a result of
// adding the new rows
PRBool createdColFrames;
tableFrame->EnsureColumns(aPresContext, createdColFrames);
if (createdColFrames) {
// We need to rebuild the column cache
// XXX It would be nice if this could be done incrementally
tableFrame->InvalidateColumnCache();
}
// Because the number of columns may have changed invalidate the column widths
tableFrame->InvalidateColumnWidths();
// Reflow the new frames. They're already marked dirty, so generate a reflow
// command that tells us to reflow our dirty child frames
@ -1205,29 +1222,12 @@ nsTableRowGroupFrame::AppendFrames(nsIPresContext* aPresContext,
NS_RELEASE(reflowCmd);
}
}
} else {
// We need to rebuild the cell map, because currently we can't insert
// new frames except at the end (append)
tableFrame->InvalidateCellMap();
// We should try and avoid doing a pass1 reflow on all the cells and just
// do it for the newly added frames, but we need to add these frames to the
// cell map before we reflow them
tableFrame->InvalidateFirstPassCache();
// Because the number of columns may have changed invalidate the column
// cache. Note that this has the side effect of recomputing the column
// widths, so we don't need to call InvalidateColumnWidths()
tableFrame->InvalidateColumnCache();
// Generate a reflow command so we reflow the table itself. This will
// do a pass-1 reflow of all the rows including any rows we just added
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
}
return NS_OK;
}
// this does not get called for trees
NS_IMETHODIMP
nsTableRowGroupFrame::InsertFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
@ -1235,65 +1235,76 @@ nsTableRowGroupFrame::InsertFrames(nsIPresContext* aPresContext,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList)
{
// Get the table frame
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
// collect the new row frames in an array
nsVoidArray rows;
for (nsIFrame* rowFrame = aFrameList; rowFrame; rowFrame->GetNextSibling(&rowFrame)) {
nsIAtom* frameType;
rowFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableRowFrame == frameType) {
rows.AppendElement(rowFrame);
}
NS_IF_RELEASE(frameType);
}
// Insert the frames
// Insert the frames in the sibling chain
mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
// We need to rebuild the cell map, because currently we can't insert
// new frames except at the end (append)
tableFrame->InvalidateCellMap();
if (rows.Count() > 0) {
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
if (tableFrame) {
nsTableRowFrame* prevRow = (nsTableRowFrame *)nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame, nsLayoutAtoms::tableRowFrame);
PRInt32 rowIndex = (prevRow) ? prevRow->GetRowIndex() : 0;
tableFrame->InsertRows(*aPresContext, rows, rowIndex, PR_TRUE);
// We should try and avoid doing a pass1 reflow on all the cells and just
// do it for the newly added frames, but we need to add these frames to the
// cell map before we reflow them
tableFrame->InvalidateFirstPassCache();
// Reflow the new frames. They're already marked dirty, so generate a reflow
// command that tells us to reflow our dirty child frames
nsIReflowCommand* reflowCmd;
// Because the number of columns may have changed invalidate the column
// cache. Note that this has the side effect of recomputing the column
// widths, so we don't need to call InvalidateColumnWidths()
tableFrame->InvalidateColumnCache();
if (NS_SUCCEEDED(NS_NewHTMLReflowCommand(&reflowCmd, this,
nsIReflowCommand::ReflowDirty))) {
aPresShell.AppendReflowCommand(reflowCmd);
NS_RELEASE(reflowCmd);
}
// Because the number of columns may have changed invalidate the column widths
tableFrame->InvalidateColumnWidths();
// Generate a reflow command so we reflow the table itself. This will
// do a pass-1 reflow of all the rows including any rows we just added
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
}
}
// Generate a reflow command so we reflow the table itself. This will
// do a pass-1 reflow of all the rows including any rows we just added
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
return NS_OK;
}
// this does not get called for trees
NS_IMETHODIMP
nsTableRowGroupFrame::RemoveFrame(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame)
{
const nsStyleDisplay *display;
aOldFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
PRBool validChild = (NS_STYLE_DISPLAY_TABLE_ROW == display->mDisplay) ||
(NS_STYLE_DISPLAY_TABLE_ROW_GROUP == display->mDisplay);
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
if (tableFrame) {
nsIAtom* frameType;
aOldFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableRowFrame == frameType) {
PRInt32 firstRowIndex = ((nsTableRowFrame *)aOldFrame)->GetRowIndex();
// Remove the frame and destroy it
if (mFrames.DestroyFrame(aPresContext, aOldFrame)) {
if (validChild) {
// Get the table frame
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
// We need to rebuild the cell map, because currently we can't incrementally
// remove rows
tableFrame->InvalidateCellMap();
// Because the number of columns may have changed invalidate the column
// cache. Note that this has the side effect of recomputing the column
// widths, so we don't need to call InvalidateColumnWidths()
tableFrame->InvalidateColumnCache();
tableFrame->RemoveRows(*aPresContext, firstRowIndex, 1, PR_TRUE);
// Because the number of columns may have changed invalidate the column widths
tableFrame->InvalidateColumnWidths();
// Because we haven't added any new frames we don't need to do a pass1
// reflow. Just generate a reflow command so we reflow the table itself
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
}
NS_IF_RELEASE(frameType);
}
mFrames.DestroyFrame(aPresContext, aOldFrame);
return NS_OK;
}
@ -1350,54 +1361,6 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext* aPresContext,
return rv;
}
NS_METHOD nsTableRowGroupFrame::DidAppendRow(nsTableRowFrame *aRowFrame)
{
nsresult rv=NS_OK;
/* need to make space in the cell map. Remeber that row spans can't cross row groups
once the space is made, tell the row to initizalize its children.
it will automatically find the row to initialize into.
but this is tough because a cell in aInsertedFrame could have a rowspan
which must be respected if a subsequent row is appended.
*/
rv = aRowFrame->InitChildren();
return rv;
}
// support method that tells us if there are any rows in the table after our rows
// returns PR_TRUE if there are no rows after ours
PRBool nsTableRowGroupFrame::NoRowsFollow()
{
// XXX This method doesn't play well with the tree widget.
PRBool result = PR_TRUE;
nsIFrame *nextSib=nsnull;
GetNextSibling(&nextSib);
while (nsnull!=nextSib)
{
const nsStyleDisplay *sibDisplay;
nextSib->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)sibDisplay));
if ((NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == sibDisplay->mDisplay) ||
(NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == sibDisplay->mDisplay) ||
(NS_STYLE_DISPLAY_TABLE_ROW_GROUP == sibDisplay->mDisplay))
{
nsIFrame *childFrame=nsnull;
nextSib->FirstChild(nsnull, &childFrame);
while (nsnull!=childFrame)
{
const nsStyleDisplay *childDisplay;
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{ // found a row
result = PR_FALSE;
break;
}
childFrame->GetNextSibling(&childFrame);
}
}
nextSib->GetNextSibling(&nextSib);
}
return result;
}
NS_METHOD nsTableRowGroupFrame::GetHeightOfRows(nscoord& aResult)
{
// the rows in rowGroupFrame need to be expanded by rowHeightDelta[i]

View File

@ -244,10 +244,6 @@ protected:
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD DidAppendRow(nsTableRowFrame *aRowFrame);
PRBool NoRowsFollow();
nsresult AdjustSiblingsAfterReflow(nsIPresContext* aPresContext,
RowGroupReflowState& aReflowState,
nsIFrame* aKidFrame,

View File

@ -498,8 +498,6 @@ NS_IMETHODIMP
nsTreeFrame::MarkForDirtyReflow(nsIPresContext* aPresContext)
{
mSuppressReflow = PR_FALSE;
InvalidateCellMap();
InvalidateColumnCache();
InvalidateFirstPassCache();
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));

View File

@ -91,7 +91,7 @@ NS_METHOD nsTreeRowFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
tableFrame->InvalidateCellMap();
tableFrame->InvalidateColumnWidths();
}
}
return rv;

View File

@ -45,6 +45,28 @@
#include "nsIDOMEventReceiver.h"
#include "nsIDOMDragListener.h"
#include "nsTreeItemDragCapturer.h"
#include "nsLayoutAtoms.h"
// I added the following function to improve keeping the frame
// chains in synch with the table. repackage as appropriate - karnaze
void GetRowStartAndCount(nsIFrame* aFrame,
PRInt32& aStartRowIndex,
PRInt32& aNumRows)
{
aStartRowIndex = -1;
aNumRows = 0;
nsIAtom* fType;
aFrame->GetFrameType(&fType);
if (nsLayoutAtoms::tableRowFrame == fType) {
aStartRowIndex = ((nsTableRowFrame*)aFrame)->GetRowIndex();
aNumRows = 0;
}
else if (nsLayoutAtoms::tableRowGroupFrame == fType) {
aStartRowIndex = ((nsTableRowGroupFrame*)aFrame)->GetStartRowIndex();
((nsTableRowGroupFrame*)aFrame)->GetRowCount(aNumRows);
}
NS_IF_RELEASE(fType);
}
static nsILayoutHistoryState*
GetStateStorageObject(nsTreeRowGroupFrame* aTreeRowGroupFrame,
@ -179,6 +201,7 @@ void nsTreeRowGroupFrame::DestroyRows(nsTableFrame* aTableFrame, nsIPresContext*
// reduced. A reflow will then pick up and create the new frames.
nsIFrame* childFrame = GetFirstFrame();
while (childFrame && rowsToLose > 0) {
PRBool rowIndex = -1;
if (IsTableRowGroupFrame(childFrame))
{
PRInt32 rowGroupCount;
@ -196,16 +219,18 @@ void nsTreeRowGroupFrame::DestroyRows(nsTableFrame* aTableFrame, nsIPresContext*
{
// Lost a row.
rowsToLose--;
// Remove this row from our cell map.
nsTableRowFrame* rowFrame = (nsTableRowFrame*)childFrame;
aTableFrame->RemoveRowFromMap(rowFrame, rowFrame->GetRowIndex());
rowIndex = ((nsTableRowFrame*)childFrame)->GetRowIndex();
}
nsIFrame* nextFrame;
GetNextFrame(childFrame, &nextFrame);
mFrameConstructor->RemoveMappingsForFrameSubtree(aPresContext, childFrame, GetStateStorageObject(this, aTableFrame));
mFrames.DestroyFrame(aPresContext, childFrame);
// remove the row from the table after it is removed from the sibling chain
if (rowIndex >= 0) {
aTableFrame->RemoveRows(*aPresContext, rowIndex, 1, PR_FALSE);
aTableFrame->InvalidateColumnWidths();
}
mTopFrame = childFrame = nextFrame;
}
}
@ -216,6 +241,7 @@ void nsTreeRowGroupFrame::ReverseDestroyRows(nsTableFrame* aTableFrame, nsIPresC
// reduced. A reflow will then pick up and create the new frames.
nsIFrame* childFrame = GetLastFrame();
while (childFrame && rowsToLose > 0) {
PRInt32 rowIndex = -1;
if (IsTableRowGroupFrame(childFrame))
{
PRInt32 rowGroupCount;
@ -233,15 +259,18 @@ void nsTreeRowGroupFrame::ReverseDestroyRows(nsTableFrame* aTableFrame, nsIPresC
{
// Lost a row.
rowsToLose--;
// Remove this row from our cell map.
nsTableRowFrame* rowFrame = (nsTableRowFrame*)childFrame;
aTableFrame->RemoveRowFromMap(rowFrame, rowFrame->GetRowIndex());
rowIndex = ((nsTableRowFrame*)childFrame)->GetRowIndex();
}
nsIFrame* prevFrame;
prevFrame = mFrames.GetPrevSiblingFor(childFrame);
mFrameConstructor->RemoveMappingsForFrameSubtree(aPresContext, childFrame, GetStateStorageObject(this, aTableFrame));
mFrames.DestroyFrame(aPresContext, childFrame);
// remove the row from the table after it is removed from the sibling chain
if (rowIndex >= 0) {
aTableFrame->RemoveRows(*aPresContext, rowIndex, 1, PR_FALSE);
aTableFrame->InvalidateColumnWidths();
}
mBottomFrame = childFrame = prevFrame;
}
}
@ -714,9 +743,19 @@ nsTreeRowGroupFrame::PositionChanged(nsIPresContext* aPresContext, PRInt32 aOldI
// Just blow away all our frames, but keep a content chain
// as a hint to figure out how to build the frames.
// Remove the scrollbar first.
// get the starting row index and row count
PRInt32 startRowIndex, numRows;
GetRowStartAndCount(this, startRowIndex, numRows);
mFrameConstructor->RemoveMappingsForFrameSubtree(aPresContext, this, GetStateStorageObject(this, tableFrame));
mFrames.DestroyFrames(aPresContext);
tableFrame->InvalidateCellMap();
// remove the rows from the table after removing from the sibling chain
if ((startRowIndex >= 0) && (numRows > 0)) {
tableFrame->RemoveRows(*aPresContext, startRowIndex, rowCount, PR_FALSE);
tableFrame->InvalidateColumnWidths();
}
nsCOMPtr<nsIContent> topRowContent;
FindRowContentAtIndex(aNewIndex, mContent, getter_AddRefs(topRowContent));
@ -1189,9 +1228,11 @@ nsTreeRowGroupFrame::GetFirstFrameForReflow(nsIPresContext* aPresContext)
FindPreviousRowContent(delta, rowContent, nsnull, getter_AddRefs(topRowContent));
AddRowToMap(tableFrame, aPresContext, topRowContent, mTopFrame);
PostAppendRow(mTopFrame, aPresContext);
PRInt32 numColsAdded = AddRowToMap(tableFrame, *aPresContext, topRowContent, mTopFrame);
if (numColsAdded > 0) {
MarkTreeAsDirty(aPresContext, (nsTreeFrame*) tableFrame);
}
//PostAppendRow(mTopFrame, aPresContext, aTableFrame->GetColCount());
}
else if (IsTableRowGroupFrame(mTopFrame) && mContentChain) {
// We have just instantiated a row group, and we have a content chain. This
@ -1268,8 +1309,11 @@ nsTreeRowGroupFrame::GetNextFrameForReflow(nsIPresContext* aPresContext, nsIFram
nsCOMPtr<nsIContent> topRowContent;
PRInt32 delta = 1;
FindPreviousRowContent(delta, nextContent, nsnull, getter_AddRefs(topRowContent));
AddRowToMap(tableFrame, aPresContext, topRowContent, (*aResult));
PostAppendRow(*aResult, aPresContext);
PRInt32 numColsAdded = AddRowToMap(tableFrame, *aPresContext, topRowContent, (*aResult));
if (numColsAdded > 0) {
MarkTreeAsDirty(aPresContext, (nsTreeFrame*) tableFrame);
}
//PostAppendRow(*aResult, aPresContext, tableFrame->GetColCount());
}
}
}
@ -1296,7 +1340,6 @@ nsTreeRowGroupFrame::TreeAppendFrames(nsIFrame* aFrameList)
return NS_OK;
}
PRBool nsTreeRowGroupFrame::ContinueReflow(nsIPresContext* aPresContext, nscoord y, nscoord height)
{
//printf("Y is: %d\n", y);
@ -1316,10 +1359,23 @@ PRBool nsTreeRowGroupFrame::ContinueReflow(nsIPresContext* aPresContext, nscoord
nsIFrame* currFrame;
startingPoint->GetNextSibling(&currFrame);
while (currFrame) {
// get the starting row index and row count
PRInt32 startRowIndex, numRows;
GetRowStartAndCount(currFrame, startRowIndex, numRows);
nsIFrame* nextFrame;
currFrame->GetNextSibling(&nextFrame);
mFrameConstructor->RemoveMappingsForFrameSubtree(aPresContext, currFrame, nsnull);
mFrames.DestroyFrame(aPresContext, currFrame);
// remove the rows from the table after removing from the sibling chain
if ((startRowIndex >= 0) && (numRows > 0)) {
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
tableFrame->RemoveRows(*aPresContext, startRowIndex, numRows, PR_FALSE);
tableFrame->InvalidateColumnWidths();
}
currFrame = nextFrame;
//printf("Nuked one off the end.\n");
}
@ -1368,9 +1424,21 @@ void nsTreeRowGroupFrame::OnContentInserted(nsIPresContext* aPresContext, nsIFra
currFrame->GetNextSibling(&nextFrame);
mFrameConstructor->RemoveMappingsForFrameSubtree(aPresContext, currFrame,
GetStateStorageObject(this, NULL));
// get the starting row index and row count
PRInt32 startRowIndex, numRows;
GetRowStartAndCount(currFrame, startRowIndex, numRows);
mFrames.DestroyFrame(aPresContext, currFrame);
currFrame = nextFrame;
//printf("Nuked one off the end.\n");
// remove the rows from the table after removing from the sibling chain
if ((startRowIndex >= 0) && (numRows > 0)) {
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
tableFrame->RemoveRows(*aPresContext, startRowIndex, numRows, PR_FALSE);
tableFrame->InvalidateColumnWidths();
}
}
OnContentAdded(aPresContext);
@ -1439,10 +1507,18 @@ void nsTreeRowGroupFrame::OnContentRemoved(nsIPresContext* aPresContext,
// Go ahead and delete the frame.
if (aChildFrame) {
// get the starting row index and row count
PRInt32 startRowIndex, numRows;
GetRowStartAndCount(aChildFrame, startRowIndex, numRows);
mFrameConstructor->RemoveMappingsForFrameSubtree(aPresContext, aChildFrame, nsnull);
mFrames.DestroyFrame(aPresContext, aChildFrame);
treeFrame->InvalidateCellMap();
treeFrame->InvalidateColumnCache();
// remove the rows from the table after removing from the sibling chain
if ((startRowIndex >= 0) && (numRows > 0)) {
treeFrame->RemoveRows(*aPresContext, startRowIndex, numRows, PR_FALSE);
treeFrame->InvalidateColumnWidths();
}
}
MarkTreeAsDirty(aPresContext, treeFrame);
@ -1647,28 +1723,6 @@ nsTreeRowGroupFrame::GetCellFrameAtIndex(PRInt32 aRowIndex, PRInt32 aColIndex,
#endif
}
void nsTreeRowGroupFrame::PostAppendRow(nsIFrame* aRowFrame, nsIPresContext* aPresContext)
{
// shouldn't need this anymore
// DidAppendRow((nsTableRowFrame*)aRowFrame);
// Get the table frame.
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
// See if any implicit column frames need to be created as a result of
// adding the new rows
PRBool createdColFrames;
tableFrame->EnsureColumns(aPresContext, createdColFrames);
if (createdColFrames) {
// We need to rebuild the column cache
// XXX It would be nice if this could be done incrementally
tableFrame->InvalidateColumnCache();
MarkTreeAsDirty(aPresContext, (nsTreeFrame*) tableFrame);
}
}
void nsTreeRowGroupFrame::ScrollByLines(nsIPresContext* aPresContext,
PRInt32 lines)
{
@ -1726,18 +1780,23 @@ nsTreeRowGroupFrame::MarkTreeAsDirty(nsIPresContext* aPresContext, nsTreeFrame*
// given a content node, insert a row into the cellmap
// for wherever it belows in the map
void
nsTreeRowGroupFrame::AddRowToMap(nsTableFrame *aTableFrame,
nsIPresContext* aPresContext,
nsIContent *aContent,
nsIFrame* aCurrentFrame)
// for wherever it belows in the map. Return the number of new colums that were added
PRInt32
nsTreeRowGroupFrame::AddRowToMap(nsTableFrame* aTableFrame,
nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aCurrentFrame)
{
PRInt32 insertionIndex =
GetInsertionIndexForContent(aTableFrame, aPresContext, aContent);
aTableFrame->InsertRowIntoMap((nsTableRowFrame*)aCurrentFrame,
insertionIndex);
GetInsertionIndexForContent(aTableFrame, &aPresContext, aContent);
PRInt32 numNewCols = 0;
if (aCurrentFrame) {
numNewCols = aTableFrame->InsertRow(aPresContext, *aCurrentFrame,
insertionIndex, PR_FALSE);
}
return numNewCols;
}

View File

@ -150,10 +150,6 @@ protected:
void ComputeTotalRowCount(PRInt32& rowCount, nsIContent* aParent);
void PostAppendRow(nsIFrame* aRowFrame, nsIPresContext* aPresContext);
void GetFirstRow(nsTableRowFrame **aRowFrame);
public:
// Helpers that allow access to info. The tree is the primary consumer of this
// info.
@ -190,9 +186,11 @@ public:
nsIPresContext* aPresContext,
nsIContent *aContent);
void AddRowToMap(nsTableFrame *aTableFrame,
nsIPresContext* aPresContext,
nsIContent *aContent, nsIFrame *aCurrentFrame);
// Also returns the number of new columns that were added
PRInt32 AddRowToMap(nsTableFrame* aTableFrame,
nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aCurrentFrame);
static PRBool IsTableRowGroupFrame(nsIFrame*);
static PRBool IsTableRowFrame(nsIFrame*);