* reworked the way colspan and rowspans are handled in table layout strategy. We do less work, and we look better.

* fixed more margin code.  we're inching towards correctness.
* the width contributed by a colspanning cell is now proportionately distributed to the columns based on the columns "effective width"
* added logic for handling illegal COLS attribute on a table (like COLS=4 in a 3-column table).  See nsTableFrame::GetEffectiveCOLSAttribute()
* added logic for handling illegal COLSPAN attribute on a cell (like COLSPAN=4 in a 3-column table).  See nsTableFrame::GetEffectiveColSpan().  This is wrong, and will get reworked soon.
* added the ability for cell width attributes to effect column width like Nav4.
This commit is contained in:
buster%netscape.com 1998-07-22 03:53:43 +00:00
Родитель 190657d936
Коммит a064b4803b
14 изменённых файлов: 1224 добавлений и 342 удалений

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

@ -112,13 +112,7 @@ BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame, PRInt32
mFixedTableWidth=0;
//cache the value of the cols attribute
nsIFrame * tableFrame = mTableFrame;
// begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! XXX
tableFrame->GetGeometricParent(tableFrame);
// end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! XXX
nsStyleTable *tableStyle;
tableFrame->GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
mCols = tableStyle->mCols;
mCols = mTableFrame->GetEffectiveCOLSAttribute();
}
BasicTableLayoutStrategy::~BasicTableLayoutStrategy()
@ -254,34 +248,9 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
/* Scan the column, simulatneously assigning column widths
* and computing the min/max column widths
*/
// first, deal with any cells that span into this column from a pervious column
if (nsnull!=spanList)
{
PRInt32 spanCount = spanList->Count();
// go through the list backwards so we can delete easily
for (PRInt32 spanIndex=spanCount-1; 0<=spanIndex; spanIndex--)
{
SpanInfo *spanInfo = (SpanInfo *)(spanList->ElementAt(spanIndex));
nscoord cellMinWidth = (spanInfo->cellMinWidth)/(spanInfo->initialColSpan);
if (minColWidth < cellMinWidth)
minColWidth = cellMinWidth;
nscoord cellDesiredWidth = (spanInfo->cellDesiredWidth)/(spanInfo->initialColSpan);
if (maxColWidth < cellDesiredWidth)
maxColWidth = cellDesiredWidth;
spanInfo->span--;
if (gsDebug==PR_TRUE)
printf (" for spanning cell %d with remaining span=%d, min = %d and des = %d\n",
spanIndex, spanInfo->span, cellMinWidth, cellDesiredWidth);
if (0==spanInfo->span)
{
spanList->RemoveElementAt(spanIndex);
delete spanInfo;
}
}
}
PRInt32 firstRowIndex = -1;
PRInt32 maxColSpan = 1;
PRBool cellGrantingWidth=PR_TRUE;
for (PRInt32 rowIndex = 0; rowIndex<numRows; rowIndex++)
{
nsTableCellFrame * cellFrame = mTableFrame->GetCellAt(rowIndex, colIndex);
@ -307,21 +276,23 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
nsSize cellDesiredSize = cellFrame->GetPass1DesiredSize();
nscoord cellDesiredWidth = cellDesiredSize.width/colSpan;
nscoord cellDesiredWidth = cellDesiredSize.width;
if (gsDebug==PR_TRUE)
printf (" for cell %d with colspan=%d, min = %d,%d and des = %d,%d\n",
rowIndex, colSpan, cellMinSize.width, cellMinSize.height,
cellDesiredSize.width, cellDesiredSize.height);
if (PR_TRUE==haveColWidth)
if (PR_TRUE==haveColWidth && PR_TRUE==cellGrantingWidth)
{
// This col has a specified fixed width so set the minand max width to the larger of
// This col has a specified fixed width so set the min and max width to the larger of
// (specified width, largest max_element_size of the cells in the column)
// factoring in the min width of the prior cells (stored in minColWidth)
nscoord widthForThisCell = PR_MAX(cellMinSize.width, colPosition->mWidth.GetCoordValue());
widthForThisCell = PR_MAX(widthForThisCell, minColWidth);
widthForThisCell = widthForThisCell/colSpan;
mTableFrame->SetColumnWidth(colIndex, widthForThisCell);
maxColWidth = widthForThisCell;
minColWidth = widthForThisCell;
//minColWidth = (cellMinSize.width)/colSpan;
if ((1==colSpan) && (effectiveMaxColumnWidth < widthForThisCell))
effectiveMaxColumnWidth = widthForThisCell;
if (gsDebug)
@ -335,8 +306,18 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
effectiveMaxColumnWidth = cellDesiredWidth;
}
//bookkeeping: is this the cell that gave the column it's fixed width attribute?
// must be done after "haveColWidth && cellGrantingWidth" used above
if (PR_TRUE==cellGrantingWidth && 1==colSpan)
{
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)cellPosition);
if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit())
cellGrantingWidth=PR_FALSE; //I've found the cell that gave the col it's width
}
// cellMinWidth can override fixed width, so factor it in here
nscoord cellMinWidth = cellMinSize.width/colSpan;
nscoord cellMinWidth = cellMinSize.width;
if (minColWidth < cellMinWidth)
minColWidth = cellMinWidth;
// effectiveMinColumnWidth is the min width as if no cells with colspans existed
@ -344,14 +325,36 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
effectiveMinColumnWidth = cellMinWidth;
if (1<colSpan)
{
// add the column to our list of post-process columns
ColSpanStruct *colSpanInfo = new ColSpanStruct(colSpan, colIndex, cellDesiredSize.width);
if (nsnull==colSpanList)
colSpanList = new nsVoidArray();
colSpanList->AppendElement(colSpanInfo);
// add the column to our list of post-process columns, if all of the intersected columns are auto
PRBool okToAdd = PR_TRUE;
if (numRows==1 || (PR_FALSE==IsFixedWidth(colPosition)))
okToAdd = PR_FALSE;
else
{
for (PRInt32 i=1; i<colSpan; i++)
{
nsTableColFrame *cf;
mTableFrame->GetColumnFrame(i+colIndex, cf);
const nsStylePosition* colPos;
cf->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPos);
if (colPos->mWidth.GetUnit() != eStyleUnit_Auto)
{
okToAdd = PR_FALSE;
break;
}
}
}
if (PR_TRUE==okToAdd)
{
ColSpanStruct *colSpanInfo = new ColSpanStruct(colSpan, colIndex, cellDesiredSize.width);
if (nsnull==colSpanList)
colSpanList = new nsVoidArray();
colSpanList->AppendElement(colSpanInfo);
}
// add the cell to our list of spanning cells
SpanInfo *spanInfo = new SpanInfo(colSpan-1, cellMinWidth, cellDesiredWidth);
SpanInfo *spanInfo = new SpanInfo(colIndex, colSpan, cellMinWidth, cellDesiredWidth);
if (nsnull==spanList)
spanList = new nsVoidArray();
spanList->AppendElement(spanInfo);
@ -366,26 +369,30 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
nscoord colInset = mTableFrame->GetCellSpacing();
// keep a running total of the amount of space taken up by all fixed-width columns
if (PR_TRUE==haveColWidth)
mFixedTableWidth += specifiedFixedColWidth + (colInset*maxColSpan);
{
mFixedTableWidth += maxColWidth + colInset;
if (0==colIndex)
mFixedTableWidth += colInset;
}
if (gsDebug) {
printf (" after col %d, mFixedTableWidth = %d\n", colIndex, mFixedTableWidth);
}
// cache the computed column info
colFrame->SetMinColWidth(minColWidth);
colFrame->SetMaxColWidth(maxColWidth);
colFrame->SetMinColWidth(effectiveMinColumnWidth);
colFrame->SetMaxColWidth(effectiveMaxColumnWidth);
colFrame->SetEffectiveMinColWidth(effectiveMinColumnWidth);
colFrame->SetEffectiveMaxColWidth(effectiveMaxColumnWidth);
mTableFrame->SetColumnWidth(colIndex, maxColWidth);
mTableFrame->SetColumnWidth(colIndex, effectiveMaxColumnWidth);
// add col[i] metrics to the running totals for the table min/max width
if (NS_UNCONSTRAINEDSIZE!=mMinTableWidth)
mMinTableWidth += minColWidth + colInset;
if (mMinTableWidth<=0)
mMinTableWidth += effectiveMinColumnWidth + colInset;
if (mMinTableWidth<0)
mMinTableWidth = NS_UNCONSTRAINEDSIZE; // handle overflow
if (NS_UNCONSTRAINEDSIZE!=mMaxTableWidth)
mMaxTableWidth += maxColWidth + colInset;
if (mMaxTableWidth<=0)
mMaxTableWidth += effectiveMaxColumnWidth + colInset;
if (mMaxTableWidth<0)
mMaxTableWidth = NS_UNCONSTRAINEDSIZE; // handle overflow
if (PR_TRUE==hasColsAttribute)
{
@ -398,6 +405,110 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
}
// now, post-process the computed values based on the table attributes
// first, factor in min/max values of spanning cells proportionately.
// We can't do this above in the first loop, because we don't have enough information
// to determine the proportion each column gets from spanners.
if (nsnull!=spanList)
{
for (PRInt32 colIndex=0; colIndex<mNumCols; colIndex++)
{
PRInt32 spanCount = spanList->Count();
// go through the list backwards so we can delete easily
for (PRInt32 spanIndex=spanCount-1; 0<=spanIndex; spanIndex--)
{
SpanInfo *spanInfo = (SpanInfo *)(spanList->ElementAt(spanIndex));
// if the spanInfo is about a column before the current column, it effects
// the current column (otherwise it would have already been deleted.)
if (spanInfo->initialColIndex <= colIndex)
{
if (0==spanInfo->effectiveMaxWidthOfSpannedCols)
{
for (PRInt32 span=0; span<spanInfo->initialColSpan; span++)
{
nsTableColFrame *nextColFrame = mTableFrame->GetColFrame(colIndex+span);
if (nsnull==nextColFrame)
break;
spanInfo->effectiveMaxWidthOfSpannedCols += nextColFrame->GetEffectiveMaxColWidth();
spanInfo->effectiveMinWidthOfSpannedCols += nextColFrame->GetEffectiveMinColWidth();
}
}
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
// compute the spanning cell's contribution to the column min width
nscoord colMinWidth = colFrame->GetMinColWidth();
nscoord spanCellMinWidth;
if (0!=spanInfo->effectiveMinWidthOfSpannedCols)
{
spanCellMinWidth = (spanInfo->cellMinWidth * colFrame->GetEffectiveMinColWidth()) /
(spanInfo->effectiveMinWidthOfSpannedCols);
if (gsDebug==PR_TRUE)
printf (" spanlist min: %d of %d\n", spanCellMinWidth, spanInfo->effectiveMaxWidthOfSpannedCols);
if (colMinWidth < spanCellMinWidth)
{
colFrame->SetMinColWidth(spanCellMinWidth); // set the new min width for the col
mMinTableWidth += spanCellMinWidth-colMinWidth; // add in the col min width delta
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
old min = %d, new min = %d\n",
colIndex, spanInfo->span, colMinWidth, spanCellMinWidth);
}
}
else
{
spanCellMinWidth = spanInfo->cellMinWidth/spanInfo->initialColSpan;
colFrame->SetMinColWidth(spanCellMinWidth);
//QQQ is mMinTableWidth already taken care of at this point?
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
old min = %d, new min = %d\n",
colIndex, spanInfo->span, colMinWidth, spanCellMinWidth);
}
// compute the spanning cell's contribution to the column max width
nscoord colMaxWidth = colFrame->GetMaxColWidth();
nscoord spanCellMaxWidth;
if (0!=spanInfo->effectiveMaxWidthOfSpannedCols)
{
spanCellMaxWidth = (spanInfo->cellDesiredWidth * colFrame->GetEffectiveMinColWidth()) /
(spanInfo->effectiveMaxWidthOfSpannedCols);
if (gsDebug==PR_TRUE)
printf (" spanlist max: %d of %d\n", spanCellMaxWidth, spanInfo->effectiveMaxWidthOfSpannedCols);
if (colMaxWidth < spanCellMaxWidth)
{
colFrame->SetMaxColWidth(spanCellMaxWidth); // set the new max width for the col
mMaxTableWidth += spanCellMaxWidth-colMaxWidth; // add in the col max width delta
mTableFrame->SetColumnWidth(colIndex, spanCellMaxWidth); // set the column to the new desired max width
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
old max = %d, new max = %d\n",
colIndex, spanInfo->span, colMaxWidth, spanCellMaxWidth);
}
}
else
{
spanCellMaxWidth = spanInfo->cellDesiredWidth/spanInfo->initialColSpan;
colFrame->SetMaxColWidth(spanCellMaxWidth);
mTableFrame->SetColumnWidth(colIndex, spanCellMaxWidth);
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
old max = %d, new max = %d\n",
colIndex, spanInfo->span, colMaxWidth, spanCellMaxWidth);
}
spanInfo->span--;
if (0==spanInfo->span)
{
spanList->RemoveElementAt(spanIndex);
delete spanInfo;
}
}
}
}
}
// second, handle the COLS attribute (equal column widths)
// if there is a COLS attribute, fix up mMinTableWidth and mMaxTableWidth
if (PR_TRUE==hasColsAttribute)
{
@ -639,11 +750,11 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(const nsReflowState& aR
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
{
if (gsDebug==PR_TRUE) printf ("for col %d\n", colIndex);
PRInt32 minColWidth = 0;
PRInt32 maxColWidth = 0;
// Get column information
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
PRInt32 minColWidth = colFrame->GetMinColWidth();
PRInt32 maxColWidth = 0;
PRInt32 rowIndex;
PRInt32 firstRowIndex = -1;
nscoord colInset = mTableFrame->GetCellSpacing();
@ -652,6 +763,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(const nsReflowState& aR
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
// first, deal with any cells that span into this column from a pervious column
// go through the list backwards so we can delete easily
if (nsnull!=spanList)
{
PRInt32 spanCount = spanList->Count();
@ -661,15 +773,65 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(const nsReflowState& aR
SpanInfo *spanInfo = (SpanInfo *)(spanList->ElementAt(spanIndex));
if (PR_FALSE==IsFixedWidth(colPosition))
{
if (minColWidth < spanInfo->cellMinWidth)
minColWidth = spanInfo->cellMinWidth;
if (maxColWidth < spanInfo->cellDesiredWidth)
maxColWidth = spanInfo->cellDesiredWidth;
// compute the spanning cell's contribution to the column min width
nscoord spanCellMinWidth;
if (0!=spanInfo->effectiveMinWidthOfSpannedCols)
{
spanCellMinWidth = (spanInfo->cellMinWidth * colFrame->GetEffectiveMinColWidth()) /
(spanInfo->effectiveMinWidthOfSpannedCols);
if (gsDebug==PR_TRUE)
printf (" spanlist min: %d of %d\n", spanCellMinWidth, spanInfo->effectiveMaxWidthOfSpannedCols);
if (minColWidth < spanCellMinWidth)
{
minColWidth = spanCellMinWidth; // set the new min width for the col
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new min = %d\n",
colIndex, spanInfo->span, minColWidth);
}
}
else
{
spanCellMinWidth = spanInfo->cellMinWidth/spanInfo->initialColSpan;
minColWidth = spanCellMinWidth;
//QQQ is mMinTableWidth already taken care of at this point?
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new min = %d\n",
colIndex, spanInfo->span, minColWidth);
}
// compute the spanning cell's contribution to the column max width
nscoord spanCellMaxWidth;
if (0!=spanInfo->effectiveMaxWidthOfSpannedCols)
{
spanCellMaxWidth = (spanInfo->cellDesiredWidth * colFrame->GetEffectiveMinColWidth()) /
(spanInfo->effectiveMaxWidthOfSpannedCols);
if (gsDebug==PR_TRUE)
printf (" spanlist max: %d of %d\n", spanCellMaxWidth, spanInfo->effectiveMaxWidthOfSpannedCols);
if (maxColWidth < spanCellMaxWidth)
{
maxColWidth = spanCellMaxWidth; // set the new max width for the col
mTableFrame->SetColumnWidth(colIndex, spanCellMaxWidth); // set the column to the new desired max width
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new max = %d\n",
colIndex, spanInfo->span, maxColWidth);
}
}
else
{
spanCellMaxWidth = spanInfo->cellDesiredWidth/spanInfo->initialColSpan;
maxColWidth = spanCellMaxWidth;
mTableFrame->SetColumnWidth(colIndex, spanCellMaxWidth);
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new max = %d\n",
colIndex, spanInfo->span, maxColWidth);
}
}
spanInfo->span--;
if (gsDebug==PR_TRUE)
printf (" for spanning cell %d with remaining span=%d, min = %d and des = %d\n",
spanIndex, spanInfo->span, spanInfo->cellMinWidth, spanInfo->cellDesiredWidth);
if (0==spanInfo->span)
{
spanList->RemoveElementAt(spanIndex);
@ -702,53 +864,93 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(const nsReflowState& aR
}
PRInt32 colSpan = mTableFrame->GetEffectiveColSpan(colIndex, cellFrame);
// distribute a portion of the spanning cell's min and max width to this column
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
nsSize cellDesiredSize = cellFrame->GetPass1DesiredSize();
nscoord cellMinWidth = cellMinSize.width/colSpan;
// first get the desired size info from reflow pass 1
nscoord cellDesiredWidth = cellDesiredSize.width/colSpan;
nscoord cellMinWidth=colFrame->GetMinColWidth();
nscoord cellDesiredWidth=colFrame->GetMaxColWidth();
// then get the desired size info factoring in the cell style attributes
nscoord specifiedCellWidth=-1;
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
if (eStyleUnit_Percent==cellPosition->mWidth.GetUnit())
{ //QQQ what if table is auto width?
float percent = cellPosition->mWidth.GetPercentValue();
specifiedCellWidth = (PRInt32)(aTableSpecifiedWidth*percent);
if (gsDebug) printf("specified percent width %f of %d = %d\n",
percent, aTableSpecifiedWidth, specifiedCellWidth);
}
if (-1!=specifiedCellWidth)
if (1==colSpan)
{
if (specifiedCellWidth/colSpan>cellMinWidth)
cellMinWidth = cellMinSize.width;
cellDesiredWidth = cellDesiredSize.width;
nscoord specifiedCellWidth=-1;
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
if (eStyleUnit_Percent==cellPosition->mWidth.GetUnit())
{ //QQQ what if table is auto width?
float percent = cellPosition->mWidth.GetPercentValue();
specifiedCellWidth = (PRInt32)(aTableSpecifiedWidth*percent);
if (gsDebug) printf("specified percent width %f of %d = %d\n",
percent, aTableSpecifiedWidth, specifiedCellWidth);
}
if (-1!=specifiedCellWidth)
{
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
cellDesiredWidth, specifiedCellWidth/colSpan);
cellDesiredWidth = specifiedCellWidth/colSpan;
//QQQ should be proportionately distributed as a post-process
if (specifiedCellWidth>cellMinWidth)
{
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
cellDesiredWidth, specifiedCellWidth);
cellDesiredWidth = specifiedCellWidth;
}
}
}
else
{ // colSpan>1, get the proportion for this column
// then get the desired size info factoring in the cell style attributes
nscoord effectiveMaxWidthOfSpannedCols = colFrame->GetEffectiveMaxColWidth();
nscoord effectiveMinWidthOfSpannedCols = colFrame->GetEffectiveMinColWidth();
for (PRInt32 span=1; span<colSpan; span++)
{
nsTableColFrame *nextColFrame = mTableFrame->GetColFrame(colIndex+span);
if (nsnull==nextColFrame)
break;
effectiveMaxWidthOfSpannedCols += nextColFrame->GetEffectiveMaxColWidth();
effectiveMinWidthOfSpannedCols += nextColFrame->GetEffectiveMinColWidth();
}
nscoord specifiedCellWidth=-1;
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
if (eStyleUnit_Percent==cellPosition->mWidth.GetUnit())
{ //QQQ what if table is auto width?
float percent = cellPosition->mWidth.GetPercentValue();
specifiedCellWidth = (PRInt32)(aTableSpecifiedWidth*percent);
if (gsDebug) printf("specified percent width %f of %d = %d\n",
percent, aTableSpecifiedWidth, specifiedCellWidth);
}
if (-1!=specifiedCellWidth)
{
float percentForThisCol = (float)(cellDesiredSize.width * colFrame->GetEffectiveMaxColWidth()) /
(float)effectiveMaxWidthOfSpannedCols;
nscoord cellWidthForThisCol = (nscoord)(specifiedCellWidth * percentForThisCol);
if (cellWidthForThisCol>cellMinWidth)
{
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
cellDesiredWidth, cellWidthForThisCol);
cellDesiredWidth = cellWidthForThisCol;
}
}
// otherwise it's already been factored in.
// now, if this column holds the cell, create a spanInfo struct for the cell
// so subsequent columns can take a proportion of this cell's space into account
if (cellFrame->GetColIndex()==colIndex)
{ // add this cell to span list iff we are currently processing the column the cell starts in
SpanInfo *spanInfo = new SpanInfo(colIndex, colSpan-1, cellMinSize.width, cellDesiredSize.width);
spanInfo->effectiveMaxWidthOfSpannedCols = effectiveMaxWidthOfSpannedCols;
spanInfo->effectiveMinWidthOfSpannedCols = effectiveMinWidthOfSpannedCols;
if (nsnull==spanList)
spanList = new nsVoidArray();
spanList->AppendElement(spanInfo);
}
}
if (PR_TRUE==gsDebug)
printf("factoring in cell %d with colSpan=%d\n factoring in min=%d and desired=%d\n",
rowIndex, colSpan, cellMinWidth, cellDesiredWidth);
if (minColWidth < cellMinWidth)
minColWidth = cellMinWidth;
if (maxColWidth < cellDesiredWidth)
maxColWidth = cellDesiredWidth;
if (gsDebug==PR_TRUE)
printf (" after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d\n",
rowIndex, minColWidth, maxColWidth,
colIndex, colFrame->GetEffectiveMaxColWidth());
if ((1<colSpan) && (cellFrame->GetColIndex()==colIndex))
{ // add this cell to span list iff we are currently processing the column the cell starts in
SpanInfo *spanInfo = new SpanInfo(colSpan-1, cellMinWidth, cellDesiredWidth);
if (nsnull==spanList)
spanList = new nsVoidArray();
spanList->AppendElement(spanInfo);
}
} // end looping through cells in the column
if (gsDebug==PR_TRUE)
@ -1032,8 +1234,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
PRBool result = PR_TRUE;
PRInt32 maxOfAllMinColWidths = 0; // for the case where we have equal column widths, this is the smallest a column can be
nscoord tableWidth; // the width of the table as a result of setting column widths
tableWidth = aMaxWidth-aAvailWidth; // the starting table width is the sum of fixed-width columns
nscoord tableWidth=0; // the width of the table as a result of setting column widths
PRInt32 totalSlices=0; // the total number of slices the proportional-width columns request
nsVoidArray *proportionalColumnsList=nsnull; // a list of the columns that are proportional-width
PRBool equalWidthColumns = PR_TRUE; // remember if we're in the special case where all
@ -1041,6 +1242,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
PRBool atLeastOneAutoWidthColumn = PR_FALSE; // true if at least one column is auto-width, requiring us to post-process
nsVoidArray *spanList=nsnull; // a list of the cells that span columns
PRInt32 numRows = mTableFrame->GetRowCount();
nscoord colInset = mTableFrame->GetCellSpacing();
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
{
@ -1054,11 +1256,11 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
// Get the columns's style and margins
PRInt32 rowIndex;
PRInt32 firstRowIndex = -1;
nscoord colInset = mTableFrame->GetCellSpacing();
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
// first, deal with any cells that span into this column from a pervious column
// go through the list backwards so we can delete easily
if (nsnull!=spanList)
{
PRInt32 spanCount = spanList->Count();
@ -1068,15 +1270,65 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
SpanInfo *spanInfo = (SpanInfo *)(spanList->ElementAt(spanIndex));
if (PR_FALSE==IsFixedWidth(colPosition))
{
if (minColWidth < spanInfo->cellMinWidth)
minColWidth = spanInfo->cellMinWidth;
if (maxColWidth < spanInfo->cellDesiredWidth)
maxColWidth = spanInfo->cellDesiredWidth;
// compute the spanning cell's contribution to the column min width
nscoord spanCellMinWidth;
if (0!=spanInfo->effectiveMinWidthOfSpannedCols)
{
spanCellMinWidth = (spanInfo->cellMinWidth * colFrame->GetEffectiveMinColWidth()) /
(spanInfo->effectiveMinWidthOfSpannedCols);
if (gsDebug==PR_TRUE)
printf (" spanlist min: %d of %d\n", spanCellMinWidth, spanInfo->effectiveMaxWidthOfSpannedCols);
if (minColWidth < spanCellMinWidth)
{
minColWidth = spanCellMinWidth; // set the new min width for the col
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new min = %d\n",
colIndex, spanInfo->span, minColWidth);
}
}
else
{
spanCellMinWidth = spanInfo->cellMinWidth/spanInfo->initialColSpan;
minColWidth = spanCellMinWidth;
//QQQ is mMinTableWidth already taken care of at this point?
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new min = %d\n",
colIndex, spanInfo->span, minColWidth);
}
// compute the spanning cell's contribution to the column max width
nscoord spanCellMaxWidth;
if (0!=spanInfo->effectiveMaxWidthOfSpannedCols)
{
spanCellMaxWidth = (spanInfo->cellDesiredWidth * colFrame->GetEffectiveMinColWidth()) /
(spanInfo->effectiveMaxWidthOfSpannedCols);
if (gsDebug==PR_TRUE)
printf (" spanlist max: %d of %d\n", spanCellMaxWidth, spanInfo->effectiveMaxWidthOfSpannedCols);
if (maxColWidth < spanCellMaxWidth)
{
maxColWidth = spanCellMaxWidth; // set the new max width for the col
mTableFrame->SetColumnWidth(colIndex, spanCellMaxWidth); // set the column to the new desired max width
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new max = %d\n",
colIndex, spanInfo->span, maxColWidth);
}
}
else
{
spanCellMaxWidth = spanInfo->cellDesiredWidth/spanInfo->initialColSpan;
maxColWidth = spanCellMaxWidth;
mTableFrame->SetColumnWidth(colIndex, spanCellMaxWidth);
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new max = %d\n",
colIndex, spanInfo->span, maxColWidth);
}
}
spanInfo->span--;
if (gsDebug==PR_TRUE)
printf (" for spanning cell %d with remaining span=%d, min = %d and des = %d\n",
spanIndex, spanInfo->span, spanInfo->cellMinWidth, spanInfo->cellDesiredWidth);
if (0==spanInfo->span)
{
spanList->RemoveElementAt(spanIndex);
@ -1085,6 +1337,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
}
}
// second, process non-fixed-width columns
if (PR_FALSE==IsFixedWidth(colPosition))
{
for (rowIndex = 0; rowIndex<numRows; rowIndex++)
@ -1109,31 +1362,78 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
nsSize cellDesiredSize = cellFrame->GetPass1DesiredSize();
PRInt32 cellMinWidth = cellMinSize.width/colSpan;
// first get the desired size info from reflow pass 1
PRInt32 cellDesiredWidth = cellDesiredSize.width/colSpan;
// then get the desired size info factoring in the cell style attributes
nscoord specifiedCellWidth=-1;
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)cellPosition);
switch (cellPosition->mWidth.GetUnit()) {
case eStyleUnit_Percent:
nscoord cellMinWidth=colFrame->GetMinColWidth();
nscoord cellDesiredWidth=colFrame->GetMaxColWidth();
if (1==colSpan)
{
cellMinWidth = cellMinSize.width;
cellDesiredWidth = cellDesiredSize.width;
nscoord specifiedCellWidth=-1;
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
if (eStyleUnit_Percent==cellPosition->mWidth.GetUnit())
{
nscoord knownTableWidth=0;
float percent = cellPosition->mWidth.GetPercentValue();
specifiedCellWidth = (PRInt32)(aMaxWidth*percent);
if (gsDebug) printf("specified percent width %f of %d = %d\n",
percent, aMaxWidth, specifiedCellWidth);
break;
}
if (-1!=specifiedCellWidth)
{
if (specifiedCellWidth>cellMinWidth)
{
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
cellDesiredWidth, specifiedCellWidth);
cellDesiredWidth = specifiedCellWidth;
}
}
}
if (-1!=specifiedCellWidth)
{
if (specifiedCellWidth>cellMinWidth)
else
{ // colSpan>1, get the proportion for this column
// then get the desired size info factoring in the cell style attributes
nscoord effectiveMaxWidthOfSpannedCols = colFrame->GetEffectiveMaxColWidth();
nscoord effectiveMinWidthOfSpannedCols = colFrame->GetEffectiveMinColWidth();
for (PRInt32 span=1; span<colSpan; span++)
{
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
cellDesiredWidth, specifiedCellWidth);
cellDesiredWidth = specifiedCellWidth; // TODO: some math needed here for colspans
nsTableColFrame *nextColFrame = mTableFrame->GetColFrame(colIndex+span);
if (nsnull==nextColFrame)
break;
effectiveMaxWidthOfSpannedCols += nextColFrame->GetEffectiveMaxColWidth();
effectiveMinWidthOfSpannedCols += nextColFrame->GetEffectiveMinColWidth();
}
nscoord specifiedCellWidth=-1;
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
if (eStyleUnit_Percent==cellPosition->mWidth.GetUnit())
{ //QQQ what if table is auto width?
float percent = cellPosition->mWidth.GetPercentValue();
specifiedCellWidth = (PRInt32)(aMaxWidth*percent);
if (gsDebug) printf("specified percent width %f of %d = %d\n",
percent, aMaxWidth, specifiedCellWidth);
}
if (-1!=specifiedCellWidth)
{
float percentForThisCol = (float)(cellDesiredSize.width * colFrame->GetEffectiveMaxColWidth()) /
(float)effectiveMaxWidthOfSpannedCols;
nscoord cellWidthForThisCol = (nscoord)(specifiedCellWidth * percentForThisCol);
if (cellWidthForThisCol>cellMinWidth)
{
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
cellDesiredWidth, cellWidthForThisCol);
cellDesiredWidth = cellWidthForThisCol;
}
}
// otherwise it's already been factored in.
// now, if this column holds the cell, create a spanInfo struct for the cell
// so subsequent columns can take a proportion of this cell's space into account
if (cellFrame->GetColIndex()==colIndex)
{ // add this cell to span list iff we are currently processing the column the cell starts in
SpanInfo *spanInfo = new SpanInfo(colIndex, colSpan-1, cellMinSize.width, cellDesiredSize.width);
spanInfo->effectiveMaxWidthOfSpannedCols = effectiveMaxWidthOfSpannedCols;
spanInfo->effectiveMinWidthOfSpannedCols = effectiveMinWidthOfSpannedCols;
if (nsnull==spanList)
spanList = new nsVoidArray();
spanList->AppendElement(spanInfo);
}
}
@ -1153,14 +1453,6 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
printf (" after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d,%d\n",
rowIndex, minColWidth, maxColWidth,
colIndex, colFrame->GetEffectiveMinColWidth(), colFrame->GetEffectiveMaxColWidth());
if ((1<colSpan) && (cellFrame->GetColIndex()==colIndex))
{ // if this cell spans columns and we are processing the column that owns the cell
// add the cell to our list of spanners
SpanInfo *spanInfo = new SpanInfo(colSpan-1, cellMinWidth, cellDesiredWidth);
if (nsnull==spanList)
spanList = new nsVoidArray();
spanList->AppendElement(spanInfo);
}
}
if (gsDebug==PR_TRUE)
@ -1178,7 +1470,6 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
// Get column width if it has one
nscoord specifiedProportionColumnWidth = -1;
float specifiedPercentageColWidth = -1.0f;
nscoord specifiedFixedColumnWidth = -1;
PRBool isAutoWidth = PR_FALSE;
switch (colPosition->mWidth.GetUnit()) {
case eStyleUnit_Percent:
@ -1279,23 +1570,23 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
}
}
}
tableWidth += mTableFrame->GetColumnWidth(colIndex);
}
tableWidth += mTableFrame->GetColumnWidth(colIndex) + colInset;
}
/* --- post-process if necessary --- */
// first, assign autoWidth columns a width
if (PR_TRUE==atLeastOneAutoWidthColumn)
{ // proportionately distribute the remaining space to autowidth columns
DistributeRemainingSpace(aAvailWidth, tableWidth);
DistributeRemainingSpace(aMaxWidth, tableWidth);
}
// second, fix up tables where column width attributes give us a table that is too wide or too narrow
nscoord computedWidth=0;
for (PRInt32 i=0; i<mNumCols; i++) {
computedWidth += mTableFrame->GetColumnWidth(i);
computedWidth += mTableFrame->GetColumnWidth(i) + colInset;
}
if (computedWidth<tableWidth) {
AdjustTableThatIsTooNarrow(computedWidth, tableWidth);
if (computedWidth<aMaxWidth) {
AdjustTableThatIsTooNarrow(computedWidth, aMaxWidth);
}
else if (computedWidth>aMaxWidth) {
AdjustTableThatIsTooWide(computedWidth, aMaxWidth);
@ -1343,7 +1634,6 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
return result;
}
//XXX: make sure aTFW takes into account fixed width cells already assigned
// take the remaining space in the table and distribute it proportionately
// to the auto-width cells in the table (based on desired width)
void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecifiedWidth,
@ -1404,31 +1694,46 @@ void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecified
if (PR_TRUE==gsDebug)
{
nscoord tableWidth=0;
for (PRInt32 i=0; i<mNumCols; i++)
printf("before EnsureCellMinWidth: ");
for (PRInt32 i=0; i<mNumCols; i++)
{
tableWidth += mTableFrame->GetColumnWidth(i);
printf ("before EnsureCellMinWidth, computed table width is %d\n",tableWidth);
printf(" %d ", mTableFrame->GetColumnWidth(i));
}
printf ("\n computed table width is %d\n",tableWidth);
}
EnsureCellMinWidths();
EnsureCellMinWidths(PR_FALSE);
}
if (PR_TRUE==gsDebug)
{
nscoord tableWidth=0;
for (PRInt32 i=0; i<mNumCols; i++)
printf("after EnsureCellMinWidth: ");
for (PRInt32 i=0; i<mNumCols; i++)
{
tableWidth += mTableFrame->GetColumnWidth(i);
printf ("after EnsureCellMinWidth, computed table width is %d\n",tableWidth);
printf(" %d ", mTableFrame->GetColumnWidth(i));
}
printf ("\n computed table width is %d\n",tableWidth);
}
}
void BasicTableLayoutStrategy::EnsureCellMinWidths()
void BasicTableLayoutStrategy::EnsureCellMinWidths(PRBool aShrinkFixedWidthCells)
{
PRBool atLeastOne = PR_TRUE;
/* XXX we'll use this if it turns out that fixed-width cells
XXX should NOT be shrunk to accomodate table width
PRInt32 numFixedColumns;
PRInt32 *fixedColumns=nsnull;
mTableFrame->GetColumnsByType(eStyleUnit_Coord, numFixedColumns, fixedColumns);
*/
PRBool *colsToRemoveFrom = new PRBool[mNumCols];
for (PRInt32 i=0; i<mNumCols; i++)
colsToRemoveFrom[i] = PR_TRUE;
if (PR_FALSE==aShrinkFixedWidthCells)
{
PRInt32 numFixedColumns=0;
PRInt32 *fixedColumns=nsnull;
mTableFrame->GetColumnsByType(eStyleUnit_Coord, numFixedColumns, fixedColumns);
for (PRInt32 i=0; i<numFixedColumns; i++)
colsToRemoveFrom[fixedColumns[i]]=PR_FALSE;
}
while (PR_TRUE==atLeastOne)
{
atLeastOne=PR_FALSE;
@ -1449,6 +1754,7 @@ void BasicTableLayoutStrategy::EnsureCellMinWidths()
}
// second, remove the added space from cells that can afford to slim down
//QQQ boy is this slow! there has to be a faster way that is still guaranteed to be accurate...
while ((addedWidth>0))
{ // while we still have some extra space, and last time we were able to take some off...
PRInt32 startingAddedWidth = addedWidth;
@ -1457,7 +1763,7 @@ void BasicTableLayoutStrategy::EnsureCellMinWidths()
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
nscoord minEffectiveColWidth = colFrame->GetEffectiveMinColWidth();
nscoord colWidth = mTableFrame->GetColumnWidth(colIndex);
if (colWidth>minEffectiveColWidth)
if ((colWidth>minEffectiveColWidth) && (PR_TRUE==colsToRemoveFrom[colIndex]))
{
mTableFrame->SetColumnWidth(colIndex, colWidth-1);
addedWidth--;
@ -1469,7 +1775,17 @@ void BasicTableLayoutStrategy::EnsureCellMinWidths()
}
if (startingAddedWidth==addedWidth)
{ // we we unable to find any columns to remove space from
break; // while ((addedWidth>0))
PRBool okToContinue=PR_FALSE;
for (PRInt32 i=0; i<mNumCols; i++)
{
if (PR_FALSE==colsToRemoveFrom[i])
{
colsToRemoveFrom[i] = PR_TRUE;
okToContinue=PR_TRUE;
}
}
if (PR_FALSE==okToContinue)
break; // while ((addedWidth>0))
}
}
if (0<addedWidth)
@ -1477,6 +1793,7 @@ void BasicTableLayoutStrategy::EnsureCellMinWidths()
break; // while (PR_TRUE==atLeastOne)
}
}
delete [] colsToRemoveFrom;
}
// for now, extra space just falls on the floor (that is, it stays in the table)
@ -1485,6 +1802,18 @@ void BasicTableLayoutStrategy::EnsureCellMinWidths()
void BasicTableLayoutStrategy::AdjustTableThatIsTooWide(nscoord aComputedWidth,
nscoord aTableWidth)
{
if (PR_TRUE==gsDebug)
{
nscoord tableWidth=0;
printf("before AdjustTableThatIsTooWide: ");
for (PRInt32 i=0; i<mNumCols; i++)
{
tableWidth += mTableFrame->GetColumnWidth(i);
printf(" %d ", mTableFrame->GetColumnWidth(i));
}
printf ("\n computed table width is %d\n",tableWidth);
}
PRInt32 numFixedColumns=0;
PRInt32 *fixedColumns=nsnull;
//XXX todo: exclude fixed width columns
@ -1508,11 +1837,34 @@ void BasicTableLayoutStrategy::AdjustTableThatIsTooWide(nscoord aComputedWidth,
}
}
}
if (PR_TRUE==gsDebug)
{
nscoord tableWidth=0;
printf("after AdjustTableThatIsTooWide: ");
for (PRInt32 i=0; i<mNumCols; i++)
{
tableWidth += mTableFrame->GetColumnWidth(i);
printf(" %d ", mTableFrame->GetColumnWidth(i));
}
printf ("\n computed table width is %d\n",tableWidth);
}
}
void BasicTableLayoutStrategy::AdjustTableThatIsTooNarrow(nscoord aComputedWidth,
nscoord aTableWidth)
{
if (PR_TRUE==gsDebug)
{
nscoord tableWidth=0;
printf("before AdjustTableThatIsTooNarrow: ");
for (PRInt32 i=0; i<mNumCols; i++)
{
tableWidth += mTableFrame->GetColumnWidth(i);
printf(" %d ", mTableFrame->GetColumnWidth(i));
}
printf ("\n computed table width is %d\n",tableWidth);
}
PRInt32 numFixedColumns=0;
PRInt32 *fixedColumns=nsnull;
//XXX todo: exclude fixed width columns
@ -1536,6 +1888,17 @@ void BasicTableLayoutStrategy::AdjustTableThatIsTooNarrow(nscoord aComputedWidth
}
}
}
if (PR_TRUE==gsDebug)
{
nscoord tableWidth=0;
printf("after AdjustTableThatIsTooNarrow: ");
for (PRInt32 i=0; i<mNumCols; i++)
{
tableWidth += mTableFrame->GetColumnWidth(i);
printf(" %d ", mTableFrame->GetColumnWidth(i));
}
printf ("\n computed table width is %d\n",tableWidth);
}
}
//PRBool BasicTableLayoutStrategy::IsFixedWidthColumn(PRInt32 colIndex, PRInt32 *colIndexes)

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

@ -33,19 +33,26 @@ struct SpanInfo
{
PRInt32 span;
const PRInt32 initialColSpan;
const PRInt32 initialColIndex;
nscoord cellMinWidth;
nscoord cellDesiredWidth;
nscoord effectiveMinWidthOfSpannedCols;
nscoord effectiveMaxWidthOfSpannedCols;
SpanInfo(PRInt32 aSpan, nscoord aMinWidth, nscoord aDesiredWidth);
SpanInfo(PRInt32 aColIndex, PRInt32 aSpan, nscoord aMinWidth, nscoord aDesiredWidth);
~SpanInfo() {};
};
inline SpanInfo::SpanInfo(PRInt32 aSpan, nscoord aMinWidth, nscoord aDesiredWidth)
: initialColSpan(aSpan)
inline SpanInfo::SpanInfo(PRInt32 aColIndex, PRInt32 aSpan,
nscoord aMinWidth, nscoord aDesiredWidth)
: initialColIndex(aColIndex),
initialColSpan(aSpan)
{
span = aSpan;
cellMinWidth = aMinWidth;
cellDesiredWidth = aDesiredWidth;
effectiveMinWidthOfSpannedCols=0;
effectiveMaxWidthOfSpannedCols=0;
}
@ -189,7 +196,7 @@ public:
/** force all cells to be at least their minimum width, removing any excess space
* created in the process from fat cells that can afford to lose a little tonnage.
*/
virtual void EnsureCellMinWidths();
virtual void EnsureCellMinWidths(PRBool aShrinkFixedWidthCells);
virtual void AdjustTableThatIsTooWide(nscoord aComputedWidth,
nscoord aTableWidth);

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

@ -42,6 +42,7 @@ nsTableColFrame::nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame)
mMinColWidth = 0;
mMaxEffectiveColWidth = 0;
mMinEffectiveColWidth = 0;
mWidthSource = eWIDTH_SOURCE_NONE;
}

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

@ -24,6 +24,11 @@
class nsTableColFrame : public nsFrame {
public:
enum {eWIDTH_SOURCE_NONE =0, // no cell has contributed to the width style
eWIDTH_SOURCE_CELL =1, // a cell specified a width
eWIDTH_SOURCE_CELL_WITH_SPAN=2 // a cell implicitly specified a width via colspan
};
void Init(PRInt32 aColIndex, PRInt32 aRepeat);
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
@ -63,6 +68,9 @@ public:
nscoord GetEffectiveMinColWidth();
void SetEffectiveMinColWidth(nscoord aMinColWidth);
PRInt32 GetWidthSource();
void SetWidthSource(PRInt32 aMinColWidth);
/** convenience method, calls into cellmap */
PRInt32 Count() const;
@ -84,6 +92,8 @@ protected:
nscoord mMaxEffectiveColWidth;
nscoord mMinEffectiveColWidth;
PRInt32 mWidthSource;
};
@ -129,5 +139,10 @@ inline nscoord nsTableColFrame::GetEffectiveMinColWidth()
inline void nsTableColFrame::SetEffectiveMinColWidth(nscoord aMinColWidth)
{ mMinEffectiveColWidth = aMinColWidth; }
inline PRInt32 nsTableColFrame::GetWidthSource()
{ return mWidthSource; }
inline void nsTableColFrame::SetWidthSource(PRInt32 aWidthSource)
{ mWidthSource = aWidthSource; }
#endif

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

@ -364,6 +364,26 @@ PRInt32 nsTableFrame::GetRowCount ()
return rowCount;
}
PRInt32 nsTableFrame::GetColCount ()
{
PRInt32 colCount = 0;
if (nsnull != mCellMap)
return mCellMap->GetColCount();
nsIFrame *child=mFirstChild;
while (nsnull!=child)
{
const nsStyleDisplay *childDisplay;
child->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
colCount += ((nsTableColGroupFrame *)child)->GetColumnCount ();
child->GetNextSibling(child);
}
return colCount;
}
nsTableColFrame * nsTableFrame::GetColFrame(PRInt32 aColIndex)
{
nsTableColFrame *result = nsnull;
@ -405,8 +425,8 @@ PRInt32 nsTableFrame::GetEffectiveRowSpan (PRInt32 aRowIndex, nsTableCellFrame *
NS_PRECONDITION (nsnull!=aCell, "bad cell arg");
NS_PRECONDITION (0<=aRowIndex && aRowIndex<GetRowCount(), "bad row index arg");
int rowSpan = aCell->GetRowSpan();
int rowCount = GetRowCount();
PRInt32 rowSpan = aCell->GetRowSpan();
PRInt32 rowCount = GetRowCount();
if (rowCount < (aRowIndex + rowSpan))
return (rowCount - aRowIndex);
return rowSpan;
@ -423,13 +443,33 @@ PRInt32 nsTableFrame::GetEffectiveColSpan (PRInt32 aColIndex, nsTableCellFrame *
NS_PRECONDITION (nsnull!=mCellMap, "bad call, mCellMap not yet allocated.");
NS_PRECONDITION (0<=aColIndex && aColIndex<mCellMap->GetColCount(), "bad col index arg");
int colSpan = aCell->GetColSpan();
int colCount = mCellMap->GetColCount();
if (mCellMap->GetRowCount()==1)
return 1;
PRInt32 colSpan = aCell->GetColSpan();
PRInt32 colCount = mCellMap->GetColCount();
if (colCount < (aColIndex + colSpan))
return (colCount - aColIndex);
return colSpan;
}
PRInt32 nsTableFrame::GetEffectiveCOLSAttribute()
{
NS_PRECONDITION (nsnull!=mCellMap, "bad call, mCellMap not yet allocated.");
PRInt32 result;
nsIFrame *tableFrame = this;
// begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! XXX
tableFrame->GetGeometricParent(tableFrame);
// end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! XXX
nsStyleTable *tableStyle;
tableFrame->GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
result = tableStyle->mCols;
PRInt32 numCols = GetColCount();
if (result>numCols)
result = numCols;
return result;
}
/* call when the cell structure has changed. mCellMap will be rebuilt on demand. */
void nsTableFrame::ResetCellMap ()
{
@ -2385,20 +2425,20 @@ nsTableFrame::SetColumnStyleFromCell(nsIPresContext * aPresContext,
// also acts as the width attribute for the entire column
if ((nsnull!=aPresContext) && (nsnull!=aCellFrame) && (nsnull!=aRowFrame))
{
if (0==aRowFrame->GetRowIndex())
{
// get the cell style info
const nsStylePosition* cellPosition;
aCellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)cellPosition);
if ((eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) ||
(eStyleUnit_Percent==cellPosition->mWidth.GetUnit())) {
// compute the width per column spanned
PRInt32 colSpan = aCellFrame->GetColSpan();
for (PRInt32 i=0; i<colSpan; i++)
// get the cell style info
const nsStylePosition* cellPosition;
aCellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)cellPosition);
if ((eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) ||
(eStyleUnit_Percent==cellPosition->mWidth.GetUnit())) {
// compute the width per column spanned
PRInt32 colSpan = aCellFrame->GetColSpan();
for (PRInt32 i=0; i<colSpan; i++)
{
// get the appropriate column frame
nsTableColFrame *colFrame;
GetColumnFrame(i+aCellFrame->GetColIndex(), colFrame);
if (nsTableColFrame::eWIDTH_SOURCE_CELL != colFrame->GetWidthSource())
{
// get the appropriate column frame
nsTableColFrame *colFrame;
GetColumnFrame(i+aCellFrame->GetColIndex(), colFrame);
// get the column style and set the width attribute
nsIStyleContext* colSC;
colFrame->GetStyleContext(aPresContext, colSC);
@ -2414,6 +2454,11 @@ nsTableFrame::SetColumnStyleFromCell(nsIPresContext * aPresContext,
float width = cellPosition->mWidth.GetPercentValue();
colPosition->mWidth.SetPercentValue(width/colSpan);
}
// set the column width-set-type
if (1==colSpan)
colFrame->SetWidthSource(nsTableColFrame::eWIDTH_SOURCE_CELL);
else
colFrame->SetWidthSource(nsTableColFrame::eWIDTH_SOURCE_CELL_WITH_SPAN);
}
}
}
@ -2505,7 +2550,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext* aPresContext,
{ // if it's a row group, get the cells and set the column style if appropriate
nsIFrame *rowFrame;
childFrame->FirstChild(rowFrame);
if (nsnull!=rowFrame)
while (nsnull!=rowFrame)
{
nsIFrame *cellFrame;
rowFrame->FirstChild(cellFrame);
@ -2518,6 +2563,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext* aPresContext,
SetColumnStyleFromCell(aPresContext, (nsTableCellFrame *)cellFrame, (nsTableRowFrame *)rowFrame);
cellFrame->GetNextSibling(cellFrame);
}
rowFrame->GetNextSibling(rowFrame);
}
}
childFrame->GetNextSibling(childFrame);

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

@ -190,6 +190,12 @@ public:
*/
virtual PRInt32 GetEffectiveColSpan(PRInt32 aColIndex, nsTableCellFrame *aCell);
/** return the value of the COLS attribute, adjusted for the
* actual number of columns in the table
*/
PRInt32 GetEffectiveCOLSAttribute();
// For DEBUGGING Purposes Only
NS_IMETHOD MoveTo(nscoord aX, nscoord aY);
NS_IMETHOD SizeTo(nscoord aWidth, nscoord aHeight);
@ -406,6 +412,8 @@ public: /* ----- Cell Map public methods ----- */
*/
virtual PRInt32 GetRowCount();
virtual PRInt32 GetColCount();
nsTableColFrame * GetColFrame(PRInt32 aColIndex);
nsTableCellFrame * GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex);

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

@ -464,7 +464,7 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext& aPresContext,
// begin special Nav4 compatibility code
if (0==cellWidth)
{
cellWidth = aState.tableFrame->GetColumnWidth(cellColIndex);
cellWidth = availWidth;
}
// end special Nav4 compatibility code
@ -537,6 +537,7 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext,
nsSize kidAvailSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
// See if there's a width constraint for the cell
/*
const nsStylePosition* cellPosition = (const nsStylePosition*)
kidSC->GetStyleData(eStyleStruct_Position);
if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit())
@ -544,7 +545,7 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext,
kidAvailSize.width = cellPosition->mWidth.GetCoordValue();
}
NS_RELEASE(kidSC);
*/
// Get the child's margins
nsMargin margin;
nscoord topMargin = 0;

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

@ -112,13 +112,7 @@ BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame, PRInt32
mFixedTableWidth=0;
//cache the value of the cols attribute
nsIFrame * tableFrame = mTableFrame;
// begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! XXX
tableFrame->GetGeometricParent(tableFrame);
// end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! XXX
nsStyleTable *tableStyle;
tableFrame->GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
mCols = tableStyle->mCols;
mCols = mTableFrame->GetEffectiveCOLSAttribute();
}
BasicTableLayoutStrategy::~BasicTableLayoutStrategy()
@ -254,34 +248,9 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
/* Scan the column, simulatneously assigning column widths
* and computing the min/max column widths
*/
// first, deal with any cells that span into this column from a pervious column
if (nsnull!=spanList)
{
PRInt32 spanCount = spanList->Count();
// go through the list backwards so we can delete easily
for (PRInt32 spanIndex=spanCount-1; 0<=spanIndex; spanIndex--)
{
SpanInfo *spanInfo = (SpanInfo *)(spanList->ElementAt(spanIndex));
nscoord cellMinWidth = (spanInfo->cellMinWidth)/(spanInfo->initialColSpan);
if (minColWidth < cellMinWidth)
minColWidth = cellMinWidth;
nscoord cellDesiredWidth = (spanInfo->cellDesiredWidth)/(spanInfo->initialColSpan);
if (maxColWidth < cellDesiredWidth)
maxColWidth = cellDesiredWidth;
spanInfo->span--;
if (gsDebug==PR_TRUE)
printf (" for spanning cell %d with remaining span=%d, min = %d and des = %d\n",
spanIndex, spanInfo->span, cellMinWidth, cellDesiredWidth);
if (0==spanInfo->span)
{
spanList->RemoveElementAt(spanIndex);
delete spanInfo;
}
}
}
PRInt32 firstRowIndex = -1;
PRInt32 maxColSpan = 1;
PRBool cellGrantingWidth=PR_TRUE;
for (PRInt32 rowIndex = 0; rowIndex<numRows; rowIndex++)
{
nsTableCellFrame * cellFrame = mTableFrame->GetCellAt(rowIndex, colIndex);
@ -307,21 +276,23 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
nsSize cellDesiredSize = cellFrame->GetPass1DesiredSize();
nscoord cellDesiredWidth = cellDesiredSize.width/colSpan;
nscoord cellDesiredWidth = cellDesiredSize.width;
if (gsDebug==PR_TRUE)
printf (" for cell %d with colspan=%d, min = %d,%d and des = %d,%d\n",
rowIndex, colSpan, cellMinSize.width, cellMinSize.height,
cellDesiredSize.width, cellDesiredSize.height);
if (PR_TRUE==haveColWidth)
if (PR_TRUE==haveColWidth && PR_TRUE==cellGrantingWidth)
{
// This col has a specified fixed width so set the minand max width to the larger of
// This col has a specified fixed width so set the min and max width to the larger of
// (specified width, largest max_element_size of the cells in the column)
// factoring in the min width of the prior cells (stored in minColWidth)
nscoord widthForThisCell = PR_MAX(cellMinSize.width, colPosition->mWidth.GetCoordValue());
widthForThisCell = PR_MAX(widthForThisCell, minColWidth);
widthForThisCell = widthForThisCell/colSpan;
mTableFrame->SetColumnWidth(colIndex, widthForThisCell);
maxColWidth = widthForThisCell;
minColWidth = widthForThisCell;
//minColWidth = (cellMinSize.width)/colSpan;
if ((1==colSpan) && (effectiveMaxColumnWidth < widthForThisCell))
effectiveMaxColumnWidth = widthForThisCell;
if (gsDebug)
@ -335,8 +306,18 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
effectiveMaxColumnWidth = cellDesiredWidth;
}
//bookkeeping: is this the cell that gave the column it's fixed width attribute?
// must be done after "haveColWidth && cellGrantingWidth" used above
if (PR_TRUE==cellGrantingWidth && 1==colSpan)
{
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)cellPosition);
if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit())
cellGrantingWidth=PR_FALSE; //I've found the cell that gave the col it's width
}
// cellMinWidth can override fixed width, so factor it in here
nscoord cellMinWidth = cellMinSize.width/colSpan;
nscoord cellMinWidth = cellMinSize.width;
if (minColWidth < cellMinWidth)
minColWidth = cellMinWidth;
// effectiveMinColumnWidth is the min width as if no cells with colspans existed
@ -344,14 +325,36 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
effectiveMinColumnWidth = cellMinWidth;
if (1<colSpan)
{
// add the column to our list of post-process columns
ColSpanStruct *colSpanInfo = new ColSpanStruct(colSpan, colIndex, cellDesiredSize.width);
if (nsnull==colSpanList)
colSpanList = new nsVoidArray();
colSpanList->AppendElement(colSpanInfo);
// add the column to our list of post-process columns, if all of the intersected columns are auto
PRBool okToAdd = PR_TRUE;
if (numRows==1 || (PR_FALSE==IsFixedWidth(colPosition)))
okToAdd = PR_FALSE;
else
{
for (PRInt32 i=1; i<colSpan; i++)
{
nsTableColFrame *cf;
mTableFrame->GetColumnFrame(i+colIndex, cf);
const nsStylePosition* colPos;
cf->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPos);
if (colPos->mWidth.GetUnit() != eStyleUnit_Auto)
{
okToAdd = PR_FALSE;
break;
}
}
}
if (PR_TRUE==okToAdd)
{
ColSpanStruct *colSpanInfo = new ColSpanStruct(colSpan, colIndex, cellDesiredSize.width);
if (nsnull==colSpanList)
colSpanList = new nsVoidArray();
colSpanList->AppendElement(colSpanInfo);
}
// add the cell to our list of spanning cells
SpanInfo *spanInfo = new SpanInfo(colSpan-1, cellMinWidth, cellDesiredWidth);
SpanInfo *spanInfo = new SpanInfo(colIndex, colSpan, cellMinWidth, cellDesiredWidth);
if (nsnull==spanList)
spanList = new nsVoidArray();
spanList->AppendElement(spanInfo);
@ -366,26 +369,30 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
nscoord colInset = mTableFrame->GetCellSpacing();
// keep a running total of the amount of space taken up by all fixed-width columns
if (PR_TRUE==haveColWidth)
mFixedTableWidth += specifiedFixedColWidth + (colInset*maxColSpan);
{
mFixedTableWidth += maxColWidth + colInset;
if (0==colIndex)
mFixedTableWidth += colInset;
}
if (gsDebug) {
printf (" after col %d, mFixedTableWidth = %d\n", colIndex, mFixedTableWidth);
}
// cache the computed column info
colFrame->SetMinColWidth(minColWidth);
colFrame->SetMaxColWidth(maxColWidth);
colFrame->SetMinColWidth(effectiveMinColumnWidth);
colFrame->SetMaxColWidth(effectiveMaxColumnWidth);
colFrame->SetEffectiveMinColWidth(effectiveMinColumnWidth);
colFrame->SetEffectiveMaxColWidth(effectiveMaxColumnWidth);
mTableFrame->SetColumnWidth(colIndex, maxColWidth);
mTableFrame->SetColumnWidth(colIndex, effectiveMaxColumnWidth);
// add col[i] metrics to the running totals for the table min/max width
if (NS_UNCONSTRAINEDSIZE!=mMinTableWidth)
mMinTableWidth += minColWidth + colInset;
if (mMinTableWidth<=0)
mMinTableWidth += effectiveMinColumnWidth + colInset;
if (mMinTableWidth<0)
mMinTableWidth = NS_UNCONSTRAINEDSIZE; // handle overflow
if (NS_UNCONSTRAINEDSIZE!=mMaxTableWidth)
mMaxTableWidth += maxColWidth + colInset;
if (mMaxTableWidth<=0)
mMaxTableWidth += effectiveMaxColumnWidth + colInset;
if (mMaxTableWidth<0)
mMaxTableWidth = NS_UNCONSTRAINEDSIZE; // handle overflow
if (PR_TRUE==hasColsAttribute)
{
@ -398,6 +405,110 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
}
// now, post-process the computed values based on the table attributes
// first, factor in min/max values of spanning cells proportionately.
// We can't do this above in the first loop, because we don't have enough information
// to determine the proportion each column gets from spanners.
if (nsnull!=spanList)
{
for (PRInt32 colIndex=0; colIndex<mNumCols; colIndex++)
{
PRInt32 spanCount = spanList->Count();
// go through the list backwards so we can delete easily
for (PRInt32 spanIndex=spanCount-1; 0<=spanIndex; spanIndex--)
{
SpanInfo *spanInfo = (SpanInfo *)(spanList->ElementAt(spanIndex));
// if the spanInfo is about a column before the current column, it effects
// the current column (otherwise it would have already been deleted.)
if (spanInfo->initialColIndex <= colIndex)
{
if (0==spanInfo->effectiveMaxWidthOfSpannedCols)
{
for (PRInt32 span=0; span<spanInfo->initialColSpan; span++)
{
nsTableColFrame *nextColFrame = mTableFrame->GetColFrame(colIndex+span);
if (nsnull==nextColFrame)
break;
spanInfo->effectiveMaxWidthOfSpannedCols += nextColFrame->GetEffectiveMaxColWidth();
spanInfo->effectiveMinWidthOfSpannedCols += nextColFrame->GetEffectiveMinColWidth();
}
}
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
// compute the spanning cell's contribution to the column min width
nscoord colMinWidth = colFrame->GetMinColWidth();
nscoord spanCellMinWidth;
if (0!=spanInfo->effectiveMinWidthOfSpannedCols)
{
spanCellMinWidth = (spanInfo->cellMinWidth * colFrame->GetEffectiveMinColWidth()) /
(spanInfo->effectiveMinWidthOfSpannedCols);
if (gsDebug==PR_TRUE)
printf (" spanlist min: %d of %d\n", spanCellMinWidth, spanInfo->effectiveMaxWidthOfSpannedCols);
if (colMinWidth < spanCellMinWidth)
{
colFrame->SetMinColWidth(spanCellMinWidth); // set the new min width for the col
mMinTableWidth += spanCellMinWidth-colMinWidth; // add in the col min width delta
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
old min = %d, new min = %d\n",
colIndex, spanInfo->span, colMinWidth, spanCellMinWidth);
}
}
else
{
spanCellMinWidth = spanInfo->cellMinWidth/spanInfo->initialColSpan;
colFrame->SetMinColWidth(spanCellMinWidth);
//QQQ is mMinTableWidth already taken care of at this point?
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
old min = %d, new min = %d\n",
colIndex, spanInfo->span, colMinWidth, spanCellMinWidth);
}
// compute the spanning cell's contribution to the column max width
nscoord colMaxWidth = colFrame->GetMaxColWidth();
nscoord spanCellMaxWidth;
if (0!=spanInfo->effectiveMaxWidthOfSpannedCols)
{
spanCellMaxWidth = (spanInfo->cellDesiredWidth * colFrame->GetEffectiveMinColWidth()) /
(spanInfo->effectiveMaxWidthOfSpannedCols);
if (gsDebug==PR_TRUE)
printf (" spanlist max: %d of %d\n", spanCellMaxWidth, spanInfo->effectiveMaxWidthOfSpannedCols);
if (colMaxWidth < spanCellMaxWidth)
{
colFrame->SetMaxColWidth(spanCellMaxWidth); // set the new max width for the col
mMaxTableWidth += spanCellMaxWidth-colMaxWidth; // add in the col max width delta
mTableFrame->SetColumnWidth(colIndex, spanCellMaxWidth); // set the column to the new desired max width
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
old max = %d, new max = %d\n",
colIndex, spanInfo->span, colMaxWidth, spanCellMaxWidth);
}
}
else
{
spanCellMaxWidth = spanInfo->cellDesiredWidth/spanInfo->initialColSpan;
colFrame->SetMaxColWidth(spanCellMaxWidth);
mTableFrame->SetColumnWidth(colIndex, spanCellMaxWidth);
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
old max = %d, new max = %d\n",
colIndex, spanInfo->span, colMaxWidth, spanCellMaxWidth);
}
spanInfo->span--;
if (0==spanInfo->span)
{
spanList->RemoveElementAt(spanIndex);
delete spanInfo;
}
}
}
}
}
// second, handle the COLS attribute (equal column widths)
// if there is a COLS attribute, fix up mMinTableWidth and mMaxTableWidth
if (PR_TRUE==hasColsAttribute)
{
@ -639,11 +750,11 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(const nsReflowState& aR
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
{
if (gsDebug==PR_TRUE) printf ("for col %d\n", colIndex);
PRInt32 minColWidth = 0;
PRInt32 maxColWidth = 0;
// Get column information
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
PRInt32 minColWidth = colFrame->GetMinColWidth();
PRInt32 maxColWidth = 0;
PRInt32 rowIndex;
PRInt32 firstRowIndex = -1;
nscoord colInset = mTableFrame->GetCellSpacing();
@ -652,6 +763,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(const nsReflowState& aR
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
// first, deal with any cells that span into this column from a pervious column
// go through the list backwards so we can delete easily
if (nsnull!=spanList)
{
PRInt32 spanCount = spanList->Count();
@ -661,15 +773,65 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(const nsReflowState& aR
SpanInfo *spanInfo = (SpanInfo *)(spanList->ElementAt(spanIndex));
if (PR_FALSE==IsFixedWidth(colPosition))
{
if (minColWidth < spanInfo->cellMinWidth)
minColWidth = spanInfo->cellMinWidth;
if (maxColWidth < spanInfo->cellDesiredWidth)
maxColWidth = spanInfo->cellDesiredWidth;
// compute the spanning cell's contribution to the column min width
nscoord spanCellMinWidth;
if (0!=spanInfo->effectiveMinWidthOfSpannedCols)
{
spanCellMinWidth = (spanInfo->cellMinWidth * colFrame->GetEffectiveMinColWidth()) /
(spanInfo->effectiveMinWidthOfSpannedCols);
if (gsDebug==PR_TRUE)
printf (" spanlist min: %d of %d\n", spanCellMinWidth, spanInfo->effectiveMaxWidthOfSpannedCols);
if (minColWidth < spanCellMinWidth)
{
minColWidth = spanCellMinWidth; // set the new min width for the col
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new min = %d\n",
colIndex, spanInfo->span, minColWidth);
}
}
else
{
spanCellMinWidth = spanInfo->cellMinWidth/spanInfo->initialColSpan;
minColWidth = spanCellMinWidth;
//QQQ is mMinTableWidth already taken care of at this point?
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new min = %d\n",
colIndex, spanInfo->span, minColWidth);
}
// compute the spanning cell's contribution to the column max width
nscoord spanCellMaxWidth;
if (0!=spanInfo->effectiveMaxWidthOfSpannedCols)
{
spanCellMaxWidth = (spanInfo->cellDesiredWidth * colFrame->GetEffectiveMinColWidth()) /
(spanInfo->effectiveMaxWidthOfSpannedCols);
if (gsDebug==PR_TRUE)
printf (" spanlist max: %d of %d\n", spanCellMaxWidth, spanInfo->effectiveMaxWidthOfSpannedCols);
if (maxColWidth < spanCellMaxWidth)
{
maxColWidth = spanCellMaxWidth; // set the new max width for the col
mTableFrame->SetColumnWidth(colIndex, spanCellMaxWidth); // set the column to the new desired max width
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new max = %d\n",
colIndex, spanInfo->span, maxColWidth);
}
}
else
{
spanCellMaxWidth = spanInfo->cellDesiredWidth/spanInfo->initialColSpan;
maxColWidth = spanCellMaxWidth;
mTableFrame->SetColumnWidth(colIndex, spanCellMaxWidth);
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new max = %d\n",
colIndex, spanInfo->span, maxColWidth);
}
}
spanInfo->span--;
if (gsDebug==PR_TRUE)
printf (" for spanning cell %d with remaining span=%d, min = %d and des = %d\n",
spanIndex, spanInfo->span, spanInfo->cellMinWidth, spanInfo->cellDesiredWidth);
if (0==spanInfo->span)
{
spanList->RemoveElementAt(spanIndex);
@ -702,53 +864,93 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(const nsReflowState& aR
}
PRInt32 colSpan = mTableFrame->GetEffectiveColSpan(colIndex, cellFrame);
// distribute a portion of the spanning cell's min and max width to this column
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
nsSize cellDesiredSize = cellFrame->GetPass1DesiredSize();
nscoord cellMinWidth = cellMinSize.width/colSpan;
// first get the desired size info from reflow pass 1
nscoord cellDesiredWidth = cellDesiredSize.width/colSpan;
nscoord cellMinWidth=colFrame->GetMinColWidth();
nscoord cellDesiredWidth=colFrame->GetMaxColWidth();
// then get the desired size info factoring in the cell style attributes
nscoord specifiedCellWidth=-1;
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
if (eStyleUnit_Percent==cellPosition->mWidth.GetUnit())
{ //QQQ what if table is auto width?
float percent = cellPosition->mWidth.GetPercentValue();
specifiedCellWidth = (PRInt32)(aTableSpecifiedWidth*percent);
if (gsDebug) printf("specified percent width %f of %d = %d\n",
percent, aTableSpecifiedWidth, specifiedCellWidth);
}
if (-1!=specifiedCellWidth)
if (1==colSpan)
{
if (specifiedCellWidth/colSpan>cellMinWidth)
cellMinWidth = cellMinSize.width;
cellDesiredWidth = cellDesiredSize.width;
nscoord specifiedCellWidth=-1;
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
if (eStyleUnit_Percent==cellPosition->mWidth.GetUnit())
{ //QQQ what if table is auto width?
float percent = cellPosition->mWidth.GetPercentValue();
specifiedCellWidth = (PRInt32)(aTableSpecifiedWidth*percent);
if (gsDebug) printf("specified percent width %f of %d = %d\n",
percent, aTableSpecifiedWidth, specifiedCellWidth);
}
if (-1!=specifiedCellWidth)
{
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
cellDesiredWidth, specifiedCellWidth/colSpan);
cellDesiredWidth = specifiedCellWidth/colSpan;
//QQQ should be proportionately distributed as a post-process
if (specifiedCellWidth>cellMinWidth)
{
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
cellDesiredWidth, specifiedCellWidth);
cellDesiredWidth = specifiedCellWidth;
}
}
}
else
{ // colSpan>1, get the proportion for this column
// then get the desired size info factoring in the cell style attributes
nscoord effectiveMaxWidthOfSpannedCols = colFrame->GetEffectiveMaxColWidth();
nscoord effectiveMinWidthOfSpannedCols = colFrame->GetEffectiveMinColWidth();
for (PRInt32 span=1; span<colSpan; span++)
{
nsTableColFrame *nextColFrame = mTableFrame->GetColFrame(colIndex+span);
if (nsnull==nextColFrame)
break;
effectiveMaxWidthOfSpannedCols += nextColFrame->GetEffectiveMaxColWidth();
effectiveMinWidthOfSpannedCols += nextColFrame->GetEffectiveMinColWidth();
}
nscoord specifiedCellWidth=-1;
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
if (eStyleUnit_Percent==cellPosition->mWidth.GetUnit())
{ //QQQ what if table is auto width?
float percent = cellPosition->mWidth.GetPercentValue();
specifiedCellWidth = (PRInt32)(aTableSpecifiedWidth*percent);
if (gsDebug) printf("specified percent width %f of %d = %d\n",
percent, aTableSpecifiedWidth, specifiedCellWidth);
}
if (-1!=specifiedCellWidth)
{
float percentForThisCol = (float)(cellDesiredSize.width * colFrame->GetEffectiveMaxColWidth()) /
(float)effectiveMaxWidthOfSpannedCols;
nscoord cellWidthForThisCol = (nscoord)(specifiedCellWidth * percentForThisCol);
if (cellWidthForThisCol>cellMinWidth)
{
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
cellDesiredWidth, cellWidthForThisCol);
cellDesiredWidth = cellWidthForThisCol;
}
}
// otherwise it's already been factored in.
// now, if this column holds the cell, create a spanInfo struct for the cell
// so subsequent columns can take a proportion of this cell's space into account
if (cellFrame->GetColIndex()==colIndex)
{ // add this cell to span list iff we are currently processing the column the cell starts in
SpanInfo *spanInfo = new SpanInfo(colIndex, colSpan-1, cellMinSize.width, cellDesiredSize.width);
spanInfo->effectiveMaxWidthOfSpannedCols = effectiveMaxWidthOfSpannedCols;
spanInfo->effectiveMinWidthOfSpannedCols = effectiveMinWidthOfSpannedCols;
if (nsnull==spanList)
spanList = new nsVoidArray();
spanList->AppendElement(spanInfo);
}
}
if (PR_TRUE==gsDebug)
printf("factoring in cell %d with colSpan=%d\n factoring in min=%d and desired=%d\n",
rowIndex, colSpan, cellMinWidth, cellDesiredWidth);
if (minColWidth < cellMinWidth)
minColWidth = cellMinWidth;
if (maxColWidth < cellDesiredWidth)
maxColWidth = cellDesiredWidth;
if (gsDebug==PR_TRUE)
printf (" after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d\n",
rowIndex, minColWidth, maxColWidth,
colIndex, colFrame->GetEffectiveMaxColWidth());
if ((1<colSpan) && (cellFrame->GetColIndex()==colIndex))
{ // add this cell to span list iff we are currently processing the column the cell starts in
SpanInfo *spanInfo = new SpanInfo(colSpan-1, cellMinWidth, cellDesiredWidth);
if (nsnull==spanList)
spanList = new nsVoidArray();
spanList->AppendElement(spanInfo);
}
} // end looping through cells in the column
if (gsDebug==PR_TRUE)
@ -1032,8 +1234,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
PRBool result = PR_TRUE;
PRInt32 maxOfAllMinColWidths = 0; // for the case where we have equal column widths, this is the smallest a column can be
nscoord tableWidth; // the width of the table as a result of setting column widths
tableWidth = aMaxWidth-aAvailWidth; // the starting table width is the sum of fixed-width columns
nscoord tableWidth=0; // the width of the table as a result of setting column widths
PRInt32 totalSlices=0; // the total number of slices the proportional-width columns request
nsVoidArray *proportionalColumnsList=nsnull; // a list of the columns that are proportional-width
PRBool equalWidthColumns = PR_TRUE; // remember if we're in the special case where all
@ -1041,6 +1242,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
PRBool atLeastOneAutoWidthColumn = PR_FALSE; // true if at least one column is auto-width, requiring us to post-process
nsVoidArray *spanList=nsnull; // a list of the cells that span columns
PRInt32 numRows = mTableFrame->GetRowCount();
nscoord colInset = mTableFrame->GetCellSpacing();
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
{
@ -1054,11 +1256,11 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
// Get the columns's style and margins
PRInt32 rowIndex;
PRInt32 firstRowIndex = -1;
nscoord colInset = mTableFrame->GetCellSpacing();
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
// first, deal with any cells that span into this column from a pervious column
// go through the list backwards so we can delete easily
if (nsnull!=spanList)
{
PRInt32 spanCount = spanList->Count();
@ -1068,15 +1270,65 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
SpanInfo *spanInfo = (SpanInfo *)(spanList->ElementAt(spanIndex));
if (PR_FALSE==IsFixedWidth(colPosition))
{
if (minColWidth < spanInfo->cellMinWidth)
minColWidth = spanInfo->cellMinWidth;
if (maxColWidth < spanInfo->cellDesiredWidth)
maxColWidth = spanInfo->cellDesiredWidth;
// compute the spanning cell's contribution to the column min width
nscoord spanCellMinWidth;
if (0!=spanInfo->effectiveMinWidthOfSpannedCols)
{
spanCellMinWidth = (spanInfo->cellMinWidth * colFrame->GetEffectiveMinColWidth()) /
(spanInfo->effectiveMinWidthOfSpannedCols);
if (gsDebug==PR_TRUE)
printf (" spanlist min: %d of %d\n", spanCellMinWidth, spanInfo->effectiveMaxWidthOfSpannedCols);
if (minColWidth < spanCellMinWidth)
{
minColWidth = spanCellMinWidth; // set the new min width for the col
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new min = %d\n",
colIndex, spanInfo->span, minColWidth);
}
}
else
{
spanCellMinWidth = spanInfo->cellMinWidth/spanInfo->initialColSpan;
minColWidth = spanCellMinWidth;
//QQQ is mMinTableWidth already taken care of at this point?
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new min = %d\n",
colIndex, spanInfo->span, minColWidth);
}
// compute the spanning cell's contribution to the column max width
nscoord spanCellMaxWidth;
if (0!=spanInfo->effectiveMaxWidthOfSpannedCols)
{
spanCellMaxWidth = (spanInfo->cellDesiredWidth * colFrame->GetEffectiveMinColWidth()) /
(spanInfo->effectiveMaxWidthOfSpannedCols);
if (gsDebug==PR_TRUE)
printf (" spanlist max: %d of %d\n", spanCellMaxWidth, spanInfo->effectiveMaxWidthOfSpannedCols);
if (maxColWidth < spanCellMaxWidth)
{
maxColWidth = spanCellMaxWidth; // set the new max width for the col
mTableFrame->SetColumnWidth(colIndex, spanCellMaxWidth); // set the column to the new desired max width
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new max = %d\n",
colIndex, spanInfo->span, maxColWidth);
}
}
else
{
spanCellMaxWidth = spanInfo->cellDesiredWidth/spanInfo->initialColSpan;
maxColWidth = spanCellMaxWidth;
mTableFrame->SetColumnWidth(colIndex, spanCellMaxWidth);
if (gsDebug==PR_TRUE)
printf (" for spanning cell into col %d with remaining span=%d, \
new max = %d\n",
colIndex, spanInfo->span, maxColWidth);
}
}
spanInfo->span--;
if (gsDebug==PR_TRUE)
printf (" for spanning cell %d with remaining span=%d, min = %d and des = %d\n",
spanIndex, spanInfo->span, spanInfo->cellMinWidth, spanInfo->cellDesiredWidth);
if (0==spanInfo->span)
{
spanList->RemoveElementAt(spanIndex);
@ -1085,6 +1337,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
}
}
// second, process non-fixed-width columns
if (PR_FALSE==IsFixedWidth(colPosition))
{
for (rowIndex = 0; rowIndex<numRows; rowIndex++)
@ -1109,31 +1362,78 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
nsSize cellDesiredSize = cellFrame->GetPass1DesiredSize();
PRInt32 cellMinWidth = cellMinSize.width/colSpan;
// first get the desired size info from reflow pass 1
PRInt32 cellDesiredWidth = cellDesiredSize.width/colSpan;
// then get the desired size info factoring in the cell style attributes
nscoord specifiedCellWidth=-1;
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)cellPosition);
switch (cellPosition->mWidth.GetUnit()) {
case eStyleUnit_Percent:
nscoord cellMinWidth=colFrame->GetMinColWidth();
nscoord cellDesiredWidth=colFrame->GetMaxColWidth();
if (1==colSpan)
{
cellMinWidth = cellMinSize.width;
cellDesiredWidth = cellDesiredSize.width;
nscoord specifiedCellWidth=-1;
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
if (eStyleUnit_Percent==cellPosition->mWidth.GetUnit())
{
nscoord knownTableWidth=0;
float percent = cellPosition->mWidth.GetPercentValue();
specifiedCellWidth = (PRInt32)(aMaxWidth*percent);
if (gsDebug) printf("specified percent width %f of %d = %d\n",
percent, aMaxWidth, specifiedCellWidth);
break;
}
if (-1!=specifiedCellWidth)
{
if (specifiedCellWidth>cellMinWidth)
{
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
cellDesiredWidth, specifiedCellWidth);
cellDesiredWidth = specifiedCellWidth;
}
}
}
if (-1!=specifiedCellWidth)
{
if (specifiedCellWidth>cellMinWidth)
else
{ // colSpan>1, get the proportion for this column
// then get the desired size info factoring in the cell style attributes
nscoord effectiveMaxWidthOfSpannedCols = colFrame->GetEffectiveMaxColWidth();
nscoord effectiveMinWidthOfSpannedCols = colFrame->GetEffectiveMinColWidth();
for (PRInt32 span=1; span<colSpan; span++)
{
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
cellDesiredWidth, specifiedCellWidth);
cellDesiredWidth = specifiedCellWidth; // TODO: some math needed here for colspans
nsTableColFrame *nextColFrame = mTableFrame->GetColFrame(colIndex+span);
if (nsnull==nextColFrame)
break;
effectiveMaxWidthOfSpannedCols += nextColFrame->GetEffectiveMaxColWidth();
effectiveMinWidthOfSpannedCols += nextColFrame->GetEffectiveMinColWidth();
}
nscoord specifiedCellWidth=-1;
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
if (eStyleUnit_Percent==cellPosition->mWidth.GetUnit())
{ //QQQ what if table is auto width?
float percent = cellPosition->mWidth.GetPercentValue();
specifiedCellWidth = (PRInt32)(aMaxWidth*percent);
if (gsDebug) printf("specified percent width %f of %d = %d\n",
percent, aMaxWidth, specifiedCellWidth);
}
if (-1!=specifiedCellWidth)
{
float percentForThisCol = (float)(cellDesiredSize.width * colFrame->GetEffectiveMaxColWidth()) /
(float)effectiveMaxWidthOfSpannedCols;
nscoord cellWidthForThisCol = (nscoord)(specifiedCellWidth * percentForThisCol);
if (cellWidthForThisCol>cellMinWidth)
{
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
cellDesiredWidth, cellWidthForThisCol);
cellDesiredWidth = cellWidthForThisCol;
}
}
// otherwise it's already been factored in.
// now, if this column holds the cell, create a spanInfo struct for the cell
// so subsequent columns can take a proportion of this cell's space into account
if (cellFrame->GetColIndex()==colIndex)
{ // add this cell to span list iff we are currently processing the column the cell starts in
SpanInfo *spanInfo = new SpanInfo(colIndex, colSpan-1, cellMinSize.width, cellDesiredSize.width);
spanInfo->effectiveMaxWidthOfSpannedCols = effectiveMaxWidthOfSpannedCols;
spanInfo->effectiveMinWidthOfSpannedCols = effectiveMinWidthOfSpannedCols;
if (nsnull==spanList)
spanList = new nsVoidArray();
spanList->AppendElement(spanInfo);
}
}
@ -1153,14 +1453,6 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
printf (" after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d,%d\n",
rowIndex, minColWidth, maxColWidth,
colIndex, colFrame->GetEffectiveMinColWidth(), colFrame->GetEffectiveMaxColWidth());
if ((1<colSpan) && (cellFrame->GetColIndex()==colIndex))
{ // if this cell spans columns and we are processing the column that owns the cell
// add the cell to our list of spanners
SpanInfo *spanInfo = new SpanInfo(colSpan-1, cellMinWidth, cellDesiredWidth);
if (nsnull==spanList)
spanList = new nsVoidArray();
spanList->AppendElement(spanInfo);
}
}
if (gsDebug==PR_TRUE)
@ -1178,7 +1470,6 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
// Get column width if it has one
nscoord specifiedProportionColumnWidth = -1;
float specifiedPercentageColWidth = -1.0f;
nscoord specifiedFixedColumnWidth = -1;
PRBool isAutoWidth = PR_FALSE;
switch (colPosition->mWidth.GetUnit()) {
case eStyleUnit_Percent:
@ -1279,23 +1570,23 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
}
}
}
tableWidth += mTableFrame->GetColumnWidth(colIndex);
}
tableWidth += mTableFrame->GetColumnWidth(colIndex) + colInset;
}
/* --- post-process if necessary --- */
// first, assign autoWidth columns a width
if (PR_TRUE==atLeastOneAutoWidthColumn)
{ // proportionately distribute the remaining space to autowidth columns
DistributeRemainingSpace(aAvailWidth, tableWidth);
DistributeRemainingSpace(aMaxWidth, tableWidth);
}
// second, fix up tables where column width attributes give us a table that is too wide or too narrow
nscoord computedWidth=0;
for (PRInt32 i=0; i<mNumCols; i++) {
computedWidth += mTableFrame->GetColumnWidth(i);
computedWidth += mTableFrame->GetColumnWidth(i) + colInset;
}
if (computedWidth<tableWidth) {
AdjustTableThatIsTooNarrow(computedWidth, tableWidth);
if (computedWidth<aMaxWidth) {
AdjustTableThatIsTooNarrow(computedWidth, aMaxWidth);
}
else if (computedWidth>aMaxWidth) {
AdjustTableThatIsTooWide(computedWidth, aMaxWidth);
@ -1343,7 +1634,6 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState&
return result;
}
//XXX: make sure aTFW takes into account fixed width cells already assigned
// take the remaining space in the table and distribute it proportionately
// to the auto-width cells in the table (based on desired width)
void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecifiedWidth,
@ -1404,31 +1694,46 @@ void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableSpecified
if (PR_TRUE==gsDebug)
{
nscoord tableWidth=0;
for (PRInt32 i=0; i<mNumCols; i++)
printf("before EnsureCellMinWidth: ");
for (PRInt32 i=0; i<mNumCols; i++)
{
tableWidth += mTableFrame->GetColumnWidth(i);
printf ("before EnsureCellMinWidth, computed table width is %d\n",tableWidth);
printf(" %d ", mTableFrame->GetColumnWidth(i));
}
printf ("\n computed table width is %d\n",tableWidth);
}
EnsureCellMinWidths();
EnsureCellMinWidths(PR_FALSE);
}
if (PR_TRUE==gsDebug)
{
nscoord tableWidth=0;
for (PRInt32 i=0; i<mNumCols; i++)
printf("after EnsureCellMinWidth: ");
for (PRInt32 i=0; i<mNumCols; i++)
{
tableWidth += mTableFrame->GetColumnWidth(i);
printf ("after EnsureCellMinWidth, computed table width is %d\n",tableWidth);
printf(" %d ", mTableFrame->GetColumnWidth(i));
}
printf ("\n computed table width is %d\n",tableWidth);
}
}
void BasicTableLayoutStrategy::EnsureCellMinWidths()
void BasicTableLayoutStrategy::EnsureCellMinWidths(PRBool aShrinkFixedWidthCells)
{
PRBool atLeastOne = PR_TRUE;
/* XXX we'll use this if it turns out that fixed-width cells
XXX should NOT be shrunk to accomodate table width
PRInt32 numFixedColumns;
PRInt32 *fixedColumns=nsnull;
mTableFrame->GetColumnsByType(eStyleUnit_Coord, numFixedColumns, fixedColumns);
*/
PRBool *colsToRemoveFrom = new PRBool[mNumCols];
for (PRInt32 i=0; i<mNumCols; i++)
colsToRemoveFrom[i] = PR_TRUE;
if (PR_FALSE==aShrinkFixedWidthCells)
{
PRInt32 numFixedColumns=0;
PRInt32 *fixedColumns=nsnull;
mTableFrame->GetColumnsByType(eStyleUnit_Coord, numFixedColumns, fixedColumns);
for (PRInt32 i=0; i<numFixedColumns; i++)
colsToRemoveFrom[fixedColumns[i]]=PR_FALSE;
}
while (PR_TRUE==atLeastOne)
{
atLeastOne=PR_FALSE;
@ -1449,6 +1754,7 @@ void BasicTableLayoutStrategy::EnsureCellMinWidths()
}
// second, remove the added space from cells that can afford to slim down
//QQQ boy is this slow! there has to be a faster way that is still guaranteed to be accurate...
while ((addedWidth>0))
{ // while we still have some extra space, and last time we were able to take some off...
PRInt32 startingAddedWidth = addedWidth;
@ -1457,7 +1763,7 @@ void BasicTableLayoutStrategy::EnsureCellMinWidths()
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
nscoord minEffectiveColWidth = colFrame->GetEffectiveMinColWidth();
nscoord colWidth = mTableFrame->GetColumnWidth(colIndex);
if (colWidth>minEffectiveColWidth)
if ((colWidth>minEffectiveColWidth) && (PR_TRUE==colsToRemoveFrom[colIndex]))
{
mTableFrame->SetColumnWidth(colIndex, colWidth-1);
addedWidth--;
@ -1469,7 +1775,17 @@ void BasicTableLayoutStrategy::EnsureCellMinWidths()
}
if (startingAddedWidth==addedWidth)
{ // we we unable to find any columns to remove space from
break; // while ((addedWidth>0))
PRBool okToContinue=PR_FALSE;
for (PRInt32 i=0; i<mNumCols; i++)
{
if (PR_FALSE==colsToRemoveFrom[i])
{
colsToRemoveFrom[i] = PR_TRUE;
okToContinue=PR_TRUE;
}
}
if (PR_FALSE==okToContinue)
break; // while ((addedWidth>0))
}
}
if (0<addedWidth)
@ -1477,6 +1793,7 @@ void BasicTableLayoutStrategy::EnsureCellMinWidths()
break; // while (PR_TRUE==atLeastOne)
}
}
delete [] colsToRemoveFrom;
}
// for now, extra space just falls on the floor (that is, it stays in the table)
@ -1485,6 +1802,18 @@ void BasicTableLayoutStrategy::EnsureCellMinWidths()
void BasicTableLayoutStrategy::AdjustTableThatIsTooWide(nscoord aComputedWidth,
nscoord aTableWidth)
{
if (PR_TRUE==gsDebug)
{
nscoord tableWidth=0;
printf("before AdjustTableThatIsTooWide: ");
for (PRInt32 i=0; i<mNumCols; i++)
{
tableWidth += mTableFrame->GetColumnWidth(i);
printf(" %d ", mTableFrame->GetColumnWidth(i));
}
printf ("\n computed table width is %d\n",tableWidth);
}
PRInt32 numFixedColumns=0;
PRInt32 *fixedColumns=nsnull;
//XXX todo: exclude fixed width columns
@ -1508,11 +1837,34 @@ void BasicTableLayoutStrategy::AdjustTableThatIsTooWide(nscoord aComputedWidth,
}
}
}
if (PR_TRUE==gsDebug)
{
nscoord tableWidth=0;
printf("after AdjustTableThatIsTooWide: ");
for (PRInt32 i=0; i<mNumCols; i++)
{
tableWidth += mTableFrame->GetColumnWidth(i);
printf(" %d ", mTableFrame->GetColumnWidth(i));
}
printf ("\n computed table width is %d\n",tableWidth);
}
}
void BasicTableLayoutStrategy::AdjustTableThatIsTooNarrow(nscoord aComputedWidth,
nscoord aTableWidth)
{
if (PR_TRUE==gsDebug)
{
nscoord tableWidth=0;
printf("before AdjustTableThatIsTooNarrow: ");
for (PRInt32 i=0; i<mNumCols; i++)
{
tableWidth += mTableFrame->GetColumnWidth(i);
printf(" %d ", mTableFrame->GetColumnWidth(i));
}
printf ("\n computed table width is %d\n",tableWidth);
}
PRInt32 numFixedColumns=0;
PRInt32 *fixedColumns=nsnull;
//XXX todo: exclude fixed width columns
@ -1536,6 +1888,17 @@ void BasicTableLayoutStrategy::AdjustTableThatIsTooNarrow(nscoord aComputedWidth
}
}
}
if (PR_TRUE==gsDebug)
{
nscoord tableWidth=0;
printf("after AdjustTableThatIsTooNarrow: ");
for (PRInt32 i=0; i<mNumCols; i++)
{
tableWidth += mTableFrame->GetColumnWidth(i);
printf(" %d ", mTableFrame->GetColumnWidth(i));
}
printf ("\n computed table width is %d\n",tableWidth);
}
}
//PRBool BasicTableLayoutStrategy::IsFixedWidthColumn(PRInt32 colIndex, PRInt32 *colIndexes)

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

@ -33,19 +33,26 @@ struct SpanInfo
{
PRInt32 span;
const PRInt32 initialColSpan;
const PRInt32 initialColIndex;
nscoord cellMinWidth;
nscoord cellDesiredWidth;
nscoord effectiveMinWidthOfSpannedCols;
nscoord effectiveMaxWidthOfSpannedCols;
SpanInfo(PRInt32 aSpan, nscoord aMinWidth, nscoord aDesiredWidth);
SpanInfo(PRInt32 aColIndex, PRInt32 aSpan, nscoord aMinWidth, nscoord aDesiredWidth);
~SpanInfo() {};
};
inline SpanInfo::SpanInfo(PRInt32 aSpan, nscoord aMinWidth, nscoord aDesiredWidth)
: initialColSpan(aSpan)
inline SpanInfo::SpanInfo(PRInt32 aColIndex, PRInt32 aSpan,
nscoord aMinWidth, nscoord aDesiredWidth)
: initialColIndex(aColIndex),
initialColSpan(aSpan)
{
span = aSpan;
cellMinWidth = aMinWidth;
cellDesiredWidth = aDesiredWidth;
effectiveMinWidthOfSpannedCols=0;
effectiveMaxWidthOfSpannedCols=0;
}
@ -189,7 +196,7 @@ public:
/** force all cells to be at least their minimum width, removing any excess space
* created in the process from fat cells that can afford to lose a little tonnage.
*/
virtual void EnsureCellMinWidths();
virtual void EnsureCellMinWidths(PRBool aShrinkFixedWidthCells);
virtual void AdjustTableThatIsTooWide(nscoord aComputedWidth,
nscoord aTableWidth);

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

@ -42,6 +42,7 @@ nsTableColFrame::nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame)
mMinColWidth = 0;
mMaxEffectiveColWidth = 0;
mMinEffectiveColWidth = 0;
mWidthSource = eWIDTH_SOURCE_NONE;
}

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

@ -24,6 +24,11 @@
class nsTableColFrame : public nsFrame {
public:
enum {eWIDTH_SOURCE_NONE =0, // no cell has contributed to the width style
eWIDTH_SOURCE_CELL =1, // a cell specified a width
eWIDTH_SOURCE_CELL_WITH_SPAN=2 // a cell implicitly specified a width via colspan
};
void Init(PRInt32 aColIndex, PRInt32 aRepeat);
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
@ -63,6 +68,9 @@ public:
nscoord GetEffectiveMinColWidth();
void SetEffectiveMinColWidth(nscoord aMinColWidth);
PRInt32 GetWidthSource();
void SetWidthSource(PRInt32 aMinColWidth);
/** convenience method, calls into cellmap */
PRInt32 Count() const;
@ -84,6 +92,8 @@ protected:
nscoord mMaxEffectiveColWidth;
nscoord mMinEffectiveColWidth;
PRInt32 mWidthSource;
};
@ -129,5 +139,10 @@ inline nscoord nsTableColFrame::GetEffectiveMinColWidth()
inline void nsTableColFrame::SetEffectiveMinColWidth(nscoord aMinColWidth)
{ mMinEffectiveColWidth = aMinColWidth; }
inline PRInt32 nsTableColFrame::GetWidthSource()
{ return mWidthSource; }
inline void nsTableColFrame::SetWidthSource(PRInt32 aWidthSource)
{ mWidthSource = aWidthSource; }
#endif

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

@ -364,6 +364,26 @@ PRInt32 nsTableFrame::GetRowCount ()
return rowCount;
}
PRInt32 nsTableFrame::GetColCount ()
{
PRInt32 colCount = 0;
if (nsnull != mCellMap)
return mCellMap->GetColCount();
nsIFrame *child=mFirstChild;
while (nsnull!=child)
{
const nsStyleDisplay *childDisplay;
child->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
colCount += ((nsTableColGroupFrame *)child)->GetColumnCount ();
child->GetNextSibling(child);
}
return colCount;
}
nsTableColFrame * nsTableFrame::GetColFrame(PRInt32 aColIndex)
{
nsTableColFrame *result = nsnull;
@ -405,8 +425,8 @@ PRInt32 nsTableFrame::GetEffectiveRowSpan (PRInt32 aRowIndex, nsTableCellFrame *
NS_PRECONDITION (nsnull!=aCell, "bad cell arg");
NS_PRECONDITION (0<=aRowIndex && aRowIndex<GetRowCount(), "bad row index arg");
int rowSpan = aCell->GetRowSpan();
int rowCount = GetRowCount();
PRInt32 rowSpan = aCell->GetRowSpan();
PRInt32 rowCount = GetRowCount();
if (rowCount < (aRowIndex + rowSpan))
return (rowCount - aRowIndex);
return rowSpan;
@ -423,13 +443,33 @@ PRInt32 nsTableFrame::GetEffectiveColSpan (PRInt32 aColIndex, nsTableCellFrame *
NS_PRECONDITION (nsnull!=mCellMap, "bad call, mCellMap not yet allocated.");
NS_PRECONDITION (0<=aColIndex && aColIndex<mCellMap->GetColCount(), "bad col index arg");
int colSpan = aCell->GetColSpan();
int colCount = mCellMap->GetColCount();
if (mCellMap->GetRowCount()==1)
return 1;
PRInt32 colSpan = aCell->GetColSpan();
PRInt32 colCount = mCellMap->GetColCount();
if (colCount < (aColIndex + colSpan))
return (colCount - aColIndex);
return colSpan;
}
PRInt32 nsTableFrame::GetEffectiveCOLSAttribute()
{
NS_PRECONDITION (nsnull!=mCellMap, "bad call, mCellMap not yet allocated.");
PRInt32 result;
nsIFrame *tableFrame = this;
// begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! XXX
tableFrame->GetGeometricParent(tableFrame);
// end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! XXX
nsStyleTable *tableStyle;
tableFrame->GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
result = tableStyle->mCols;
PRInt32 numCols = GetColCount();
if (result>numCols)
result = numCols;
return result;
}
/* call when the cell structure has changed. mCellMap will be rebuilt on demand. */
void nsTableFrame::ResetCellMap ()
{
@ -2385,20 +2425,20 @@ nsTableFrame::SetColumnStyleFromCell(nsIPresContext * aPresContext,
// also acts as the width attribute for the entire column
if ((nsnull!=aPresContext) && (nsnull!=aCellFrame) && (nsnull!=aRowFrame))
{
if (0==aRowFrame->GetRowIndex())
{
// get the cell style info
const nsStylePosition* cellPosition;
aCellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)cellPosition);
if ((eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) ||
(eStyleUnit_Percent==cellPosition->mWidth.GetUnit())) {
// compute the width per column spanned
PRInt32 colSpan = aCellFrame->GetColSpan();
for (PRInt32 i=0; i<colSpan; i++)
// get the cell style info
const nsStylePosition* cellPosition;
aCellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)cellPosition);
if ((eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) ||
(eStyleUnit_Percent==cellPosition->mWidth.GetUnit())) {
// compute the width per column spanned
PRInt32 colSpan = aCellFrame->GetColSpan();
for (PRInt32 i=0; i<colSpan; i++)
{
// get the appropriate column frame
nsTableColFrame *colFrame;
GetColumnFrame(i+aCellFrame->GetColIndex(), colFrame);
if (nsTableColFrame::eWIDTH_SOURCE_CELL != colFrame->GetWidthSource())
{
// get the appropriate column frame
nsTableColFrame *colFrame;
GetColumnFrame(i+aCellFrame->GetColIndex(), colFrame);
// get the column style and set the width attribute
nsIStyleContext* colSC;
colFrame->GetStyleContext(aPresContext, colSC);
@ -2414,6 +2454,11 @@ nsTableFrame::SetColumnStyleFromCell(nsIPresContext * aPresContext,
float width = cellPosition->mWidth.GetPercentValue();
colPosition->mWidth.SetPercentValue(width/colSpan);
}
// set the column width-set-type
if (1==colSpan)
colFrame->SetWidthSource(nsTableColFrame::eWIDTH_SOURCE_CELL);
else
colFrame->SetWidthSource(nsTableColFrame::eWIDTH_SOURCE_CELL_WITH_SPAN);
}
}
}
@ -2505,7 +2550,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext* aPresContext,
{ // if it's a row group, get the cells and set the column style if appropriate
nsIFrame *rowFrame;
childFrame->FirstChild(rowFrame);
if (nsnull!=rowFrame)
while (nsnull!=rowFrame)
{
nsIFrame *cellFrame;
rowFrame->FirstChild(cellFrame);
@ -2518,6 +2563,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext* aPresContext,
SetColumnStyleFromCell(aPresContext, (nsTableCellFrame *)cellFrame, (nsTableRowFrame *)rowFrame);
cellFrame->GetNextSibling(cellFrame);
}
rowFrame->GetNextSibling(rowFrame);
}
}
childFrame->GetNextSibling(childFrame);

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

@ -190,6 +190,12 @@ public:
*/
virtual PRInt32 GetEffectiveColSpan(PRInt32 aColIndex, nsTableCellFrame *aCell);
/** return the value of the COLS attribute, adjusted for the
* actual number of columns in the table
*/
PRInt32 GetEffectiveCOLSAttribute();
// For DEBUGGING Purposes Only
NS_IMETHOD MoveTo(nscoord aX, nscoord aY);
NS_IMETHOD SizeTo(nscoord aWidth, nscoord aHeight);
@ -406,6 +412,8 @@ public: /* ----- Cell Map public methods ----- */
*/
virtual PRInt32 GetRowCount();
virtual PRInt32 GetColCount();
nsTableColFrame * GetColFrame(PRInt32 aColIndex);
nsTableCellFrame * GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex);

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

@ -464,7 +464,7 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext& aPresContext,
// begin special Nav4 compatibility code
if (0==cellWidth)
{
cellWidth = aState.tableFrame->GetColumnWidth(cellColIndex);
cellWidth = availWidth;
}
// end special Nav4 compatibility code
@ -537,6 +537,7 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext,
nsSize kidAvailSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
// See if there's a width constraint for the cell
/*
const nsStylePosition* cellPosition = (const nsStylePosition*)
kidSC->GetStyleData(eStyleStruct_Position);
if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit())
@ -544,7 +545,7 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext,
kidAvailSize.width = cellPosition->mWidth.GetCoordValue();
}
NS_RELEASE(kidSC);
*/
// Get the child's margins
nsMargin margin;
nscoord topMargin = 0;