improved colspan handling.

cells with colspans and specified widths divide their width provisionally between the columns they span. This provisional division is ammended by any cell in any of the effected columns that:
1) has a colspan=1, and
2) has a width specified
the widths of all other columns must be adjusted for cells like these.  Further complicating matters is that it seems <faith> that if multiple colspanning cells intersect a column and each has a width
specified such that the column would have a different width depending on which is used, only the first such cell is used </faith>.  I can neither confirm nor deny this reading the mozilla code.

I also taught the cell map how to deal with this situation:

 colspan=1 | colspan=2 | colspan=1
 colspan=1 | colspan=2 | colspan=1

This table "really" has 4 columns, but the middle cells are treated as if they have no colspan.
Trust me, it matters.  The original colspan attributes can't simply be thrown away because Mr. DOM
could come along at any time and add/remove a cell that would make them important.


git-svn-id: svn://10.0.0.236/trunk@8185 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
buster%netscape.com
1998-08-19 15:43:51 +00:00
parent 78a287cde8
commit ad76084cb9
8 changed files with 284 additions and 106 deletions

View File

@@ -253,6 +253,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
if (gsDebug==PR_TRUE) printf ("** %p: AssignPreliminaryColumnWidths **\n", mTableFrame);
nsVoidArray *spanList=nsnull;
nsVoidArray *colSpanList=nsnull;
PRInt32 numProvisionalFixedColumns = 0; // used for assigning width from cell with colspan to columns that are spanned
PRBool hasColsAttribute = (PRBool)(NS_STYLE_TABLE_COLS_NONE!=mCols);
@@ -291,6 +292,8 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
{
haveColWidth = PR_TRUE;
specifiedFixedColWidth = colPosition->mWidth.GetCoordValue();
if (nsTableColFrame::eWIDTH_SOURCE_CELL_WITH_SPAN==colFrame->GetWidthSource())
numProvisionalFixedColumns++;
}
/* Scan the column, simulatneously assigning column widths
@@ -341,7 +344,8 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
rowIndex, colSpan, cellMinSize.width, cellMinSize.height,
cellDesiredSize.width, cellDesiredSize.height);
if (PR_TRUE==haveColWidth)// && PR_TRUE==cellGrantingWidth)
if ((PR_TRUE==haveColWidth) &&
(nsTableColFrame::eWIDTH_SOURCE_CELL_WITH_SPAN!=colFrame->GetWidthSource()))
{
// 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)
@@ -380,16 +384,6 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
effectiveMinColumnWidth = cellMinWidth;
}
//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
}
if (1<colSpan)
{
// add the column to our list of post-process columns, if all of the intersected columns are auto
@@ -404,7 +398,8 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
mTableFrame->GetColumnFrame(i+colIndex, cf);
const nsStylePosition* colPos;
cf->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPos);
if (colPos->mWidth.GetUnit() != eStyleUnit_Auto)
if (colPos->mWidth.GetUnit() != eStyleUnit_Auto &&
(nsTableColFrame::eWIDTH_SOURCE_CELL_WITH_SPAN!=cf->GetWidthSource()))
{
okToAdd = PR_FALSE;
break;
@@ -412,20 +407,39 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
}
}
nscoord width = cellDesiredSize.width; // used below as the cell's "natural" width
if (PR_TRUE == haveColWidth)
width = colSpan*specifiedFixedColWidth;
if (PR_TRUE==okToAdd)
{
ColSpanStruct *colSpanInfo = new ColSpanStruct(colSpan, colIndex, cellDesiredSize.width);
ColSpanStruct *colSpanInfo = new ColSpanStruct(colSpan, colIndex, width);
if (nsnull==colSpanList)
colSpanList = new nsVoidArray();
colSpanList->AppendElement(colSpanInfo);
}
// add the cell to our list of spanning cells
SpanInfo *spanInfo = new SpanInfo(colIndex, colSpan, cellMinWidth, cellDesiredWidth);
if (nsnull==spanList)
spanList = new nsVoidArray();
spanList->AppendElement(spanInfo);
if (PR_TRUE==cellGrantingWidth)
{
// add the cell to our list of spanning cells
SpanInfo *spanInfo = new SpanInfo(colIndex, colSpan, cellMinWidth, width);
if (nsnull==spanList)
spanList = new nsVoidArray();
spanList->AppendElement(spanInfo);
}
}
//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)
{
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
}
// book 'em, Danno
if (gsDebug) {
printf (" after cell %d, minColWidth = %d and maxColWidth = %d\n",
rowIndex, minColWidth, maxColWidth);
@@ -454,7 +468,8 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
colFrame->SetEffectiveMaxColWidth(effectiveMaxColumnWidth);
// this is the default, the real adjustment happens below where we deal with colspans
colFrame->SetAdjustedMinColWidth(effectiveMinColumnWidth);
if (PR_TRUE==haveColWidth)
if ((PR_TRUE==haveColWidth) &&
(nsTableColFrame::eWIDTH_SOURCE_CELL_WITH_SPAN!=colFrame->GetWidthSource()))
mTableFrame->SetColumnWidth(colIndex, specifiedFixedColWidth);
else
mTableFrame->SetColumnWidth(colIndex, effectiveMaxColumnWidth);
@@ -467,8 +482,8 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
maxColWidthArray[colIndex] = maxColWidth;
}
if (gsDebug==PR_TRUE)
printf ("after col %d, minColWidth=%d effectiveMinColumnWidth=%d\n\tminTableWidth = %d and maxTableWidth = %d\n",
colIndex, minColWidth, effectiveMinColumnWidth, mMinTableWidth, mMaxTableWidth);
printf ("after col %d, minColWidth=%d effectiveMinColumnWidth=%d\n\teffectiveMaxColumnWidth = %d\n",
colIndex, minColWidth, effectiveMinColumnWidth, effectiveMaxColumnWidth);
}
// now, post-process the computed values based on the table attributes
@@ -479,10 +494,11 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
if (nsnull!=spanList)
{
// we only want to do this if there are auto-cells involved
// or if we have columns that are provisionally fixed-width with colspans
PRInt32 numAutoColumns=0;
PRInt32 *autoColumns=nsnull;
mTableFrame->GetColumnsByType(eStyleUnit_Auto, numAutoColumns, autoColumns);
if (0==numAutoColumns)
if (0==numAutoColumns && 0==numProvisionalFixedColumns)
{ //table fully specified, so no need to do any extra work here
PRInt32 spanCount = spanList->Count();
// go through the list backwards so we can delete easily
@@ -494,21 +510,21 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
}
}
else
{
{ // for every column, handle spanning cells that impact that column
for (PRInt32 colIndex=0; colIndex<mNumCols; colIndex++)
{
if (gsDebug) printf("handling span for %d\n", colIndex);
PRInt32 spanCount = spanList->Count();
// go through the list backwards so we can delete easily
for (PRInt32 spanIndex=spanCount-1; 0<=spanIndex; spanIndex--)
{
{ // get each spanInfo struct and see if it impacts this column
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)
{
{ // if we have not yet computed effectiveMaxWidthOfSpannedCols, do it now
for (PRInt32 span=0; span<spanInfo->initialColSpan; span++)
{
nsTableColFrame *nextColFrame = mTableFrame->GetColFrame(colIndex+span);
@@ -550,10 +566,13 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
nscoord spanCellMaxWidth;
if (0!=spanInfo->effectiveMaxWidthOfSpannedCols)
{
spanCellMaxWidth = (spanInfo->cellDesiredWidth * colFrame->GetEffectiveMaxColWidth()) /
(spanInfo->effectiveMaxWidthOfSpannedCols);
float percent = ((float)(colFrame->GetEffectiveMaxColWidth())) /
((float)(spanInfo->effectiveMaxWidthOfSpannedCols));
spanCellMaxWidth = (nscoord)(((float)(spanInfo->cellDesiredWidth)) * percent);
if (gsDebug==PR_TRUE)
printf ("spanCellMaxWidth portion = %d\n", spanCellMaxWidth);
printf ("spanCellMaxWidth portion = %d with percent = %f from effMaxColW=%d and sum=%d\n",
spanCellMaxWidth, percent, colFrame->GetEffectiveMaxColWidth(),
spanInfo->effectiveMaxWidthOfSpannedCols);
if (colMaxWidth < spanCellMaxWidth)
{
// make sure we're at least as big as our min
@@ -1561,7 +1580,7 @@ void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aAvailWidth,
nscoord excessForThisColumn = (nscoord)(excess*percent);
nscoord colWidth = excessForThisColumn+oldColWidth;
if (gsDebug==PR_TRUE)
printf(" distribute excess to all columns: column %d was %d, now set to %d from % = %f\n",
printf(" distribute excess: column %d was %d, now %d from %=%f\n",
colIndex, oldColWidth, colWidth, percent);
mTableFrame->SetColumnWidth(colIndex, colWidth);
}