some proportional column balancing now works

the <TABLE> COLS attribute is supported via proportional column balancing.
This commit is contained in:
buster 1998-05-29 22:08:19 +00:00
parent d1a5cf5769
commit a58280cec0
17 changed files with 769 additions and 634 deletions

View File

@ -19,6 +19,7 @@
#include <stdio.h>
#include "BasicTableLayoutStrategy.h"
#include "nsTableFrame.h"
#include "nsTableColFrame.h"
#include "nsColLayoutData.h"
#include "nsCellLayoutData.h"
#include "nsTableCol.h"
@ -42,12 +43,39 @@ static const PRBool gsDebugCLD = PR_FALSE;
static const PRBool gsTiming = PR_FALSE;
#endif
/* ---------- ProportionalColumnLayoutStruct ---------- */
// TODO: make public so other subclasses can use it
/** useful info about a column for layout */
struct ProportionalColumnLayoutStruct
{
ProportionalColumnLayoutStruct(PRInt32 aColIndex,
nscoord aMinColWidth,
nscoord aMaxColWidth,
PRInt32 aProportion)
{
mColIndex = aColIndex;
mMinColWidth = aMinColWidth;
mMaxColWidth = aMaxColWidth;
mProportion = aProportion;
};
PRInt32 mColIndex;
nscoord mMinColWidth;
nscoord mMaxColWidth;
PRInt32 mProportion;
};
/* ---------- BasicTableLayoutStrategy ---------- */
/* return true if the style indicates that the width is proportional
* for the purposes of column width determination
*/
PRBool BasicTableLayoutStrategy::IsProportionalWidth(nsStylePosition* aStylePosition)
PRBool BasicTableLayoutStrategy::IsFixedWidth(nsStylePosition* aStylePosition)
{
PRBool result = PR_FALSE; // assume that it is not
PRBool result = PR_FALSE; // assume that it is not fixed width
PRInt32 unitType;
if (nsnull == aStylePosition) {
unitType = eStyleUnit_Auto;
@ -58,12 +86,11 @@ PRBool BasicTableLayoutStrategy::IsProportionalWidth(nsStylePosition* aStylePosi
switch (unitType) {
case eStyleUnit_Coord:
break;
result = PR_TRUE;
case eStyleUnit_Auto:
case eStyleUnit_Proportional:
case eStyleUnit_Percent:
result = PR_TRUE;
break;
// TODO
@ -71,7 +98,7 @@ PRBool BasicTableLayoutStrategy::IsProportionalWidth(nsStylePosition* aStylePosi
break;
default:
NS_ASSERTION(PR_FALSE, "illegal style type in IsProportionalWidth");
NS_ASSERTION(PR_FALSE, "illegal style type in IsFixedWidth");
break;
}
return result;
@ -263,6 +290,8 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
NS_ASSERTION(nsnull != colData, "bad column data");
nsTableColFrame *colFrame = colData->GetColFrame();
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
nsTableColPtr col = colData->GetCol(); // col: ADDREF++
NS_ASSERTION(col.IsNotNull(), "bad col");
@ -273,35 +302,25 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
PRInt32 numCells = cells->Count();
if (gsDebug==PR_TRUE) printf (" for column %d numCells = %d\n", colIndex, numCells);
#if XXX_need_access_to_column_frame_help
// Get the columns's style
nsIStyleContextPtr colSC;
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
nsStylePosition* colPosition = (nsStylePosition*)
colSC->GetData(eStyleStruct_Position);
nsStylePosition* colPosition = (nsStylePosition*) colSC->GetData(eStyleStruct_Position);
// Get column width if it has one
PRBool haveColWidth = PR_FALSE;
nscoord colWidth;
nscoord specifiedFixedColWidth=0;
switch (colPosition->mWidth.GetUnit()) {
default:
case eStyleUnit_Auto:
case eStyleUnit_Inherit:
break;
case eStyleUnit_Coord:
haveColWidth = PR_TRUE;
specifiedFixedColWidth = colPosition->mWidth.GetCoordValue();
break;
case eStyleUnit_Coord:
haveColWidth = PR_TRUE;
colWidth = colPosition->mWidth.GetCoordValue;
break;
case eStyleUnit_Percent:
case eStyleUnit_Proportional:
//XXX haveColWidth = PR_TRUE;
//XXX colWidth = colPosition->mWidthPCT * something;
break;
default:
break;
}
#endif
// TODO - use specifiedFixedColWidth to influence the width when both col span and fixed col width are given
/* Scan the column, simulatneously assigning fixed column widths
* and computing the min/max column widths
*/
@ -388,34 +407,27 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
}
}
#if XXX_need_access_to_column_frame_help
// TODO - use cellWidth found above to influence the cell width here
switch (colPosition->mWidth.GetUnit()) {
default:
case eStyleUnit_Auto:
case eStyleUnit_Inherit:
break;
case eStyleUnit_Coord:
{
// This col has a fixed width, so set the cell's width to the
// larger of (specified width, largest max_element_size of the
// cells in the column)
PRInt32 widthForThisCell = max(cellMinSize->width, colPosition->mWidth.GetCoordValue());
if (mTableFrame->GetColumnWidth(colIndex) < widthForThisCell)
case eStyleUnit_Coord:
{
if (gsDebug) printf (" setting fixed width to %d\n",widthForThisCell);
mTableFrame->SetColumnWidth(colIndex, widthForThisCell);
maxColWidth = widthForThisCell;
// This col has a fixed width, so set the cell's width to the
// larger of (specified width, largest max_element_size of the
// cells in the column)
PRInt32 widthForThisCell = PR_MAX(cellMinSize->width, colPosition->mWidth.GetCoordValue());
if (mTableFrame->GetColumnWidth(colIndex) < widthForThisCell)
{
if (gsDebug) printf (" setting fixed width to %d\n",widthForThisCell);
mTableFrame->SetColumnWidth(colIndex, widthForThisCell);
maxColWidth = widthForThisCell;
}
}
}
break;
break;
default:
break;
case NS_STYLE_POSITION_VALUE_PCT:
case NS_STYLE_POSITION_VALUE_PROPORTIONAL:
// XXX write me when pct/proportional are supported
break;
}
#endif
// regardless of the width specification, keep track of the
// min/max column widths
@ -443,20 +455,18 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
}
}
#if 0
// if the col is fixed-width, expand the col to the specified
// fixed width if necessary
if (colStyle->fixedWidth > mTableFrame->GetColumnWidth(colIndex))
mTableFrame->SetColumnWidth(colIndex, colStyle->fixedWidth);
if (PR_TRUE==haveColWidth && specifiedFixedColWidth > mTableFrame->GetColumnWidth(colIndex))
mTableFrame->SetColumnWidth(colIndex, specifiedFixedColWidth);
// keep a running total of the amount of space taken up by all
// fixed-width columns
aTotalFixedWidth += mTableFrame->GetColumnWidths(colIndex);
aTotalFixedWidth += mTableFrame->GetColumnWidth(colIndex);
if (gsDebug) {
printf (" after col %d, aTotalFixedWidth = %d\n",
colIndex, aTotalFixedWidth);
}
#endif
// add col[i] metrics to the running totals for the table min/max width
if (NS_UNCONSTRAINEDSIZE!=aMinTableWidth)
@ -478,10 +488,10 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPresContext,
PRInt32 aAvailWidth,
PRInt32 aMaxWidth,
PRInt32 aMinTableWidth,
PRInt32 aMaxTableWidth,
nscoord aAvailWidth,
nscoord aMaxWidth,
nscoord aMinTableWidth,
nscoord aMaxTableWidth,
nscoord aTableFixedWidth)
{
PRBool result = PR_TRUE;
@ -491,7 +501,7 @@ PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPre
if (NS_UNCONSTRAINEDSIZE==aMaxWidth)
{ // the max width of the table fits comfortably in the available space
if (gsDebug) printf (" * table laying out in NS_UNCONSTRAINEDSIZE, calling BalanceColumnsTableFits\n");
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aTableFixedWidth);
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aMaxWidth, aTableFixedWidth);
}
else if (aMinTableWidth > aMaxWidth)
{ // the table doesn't fit in the available space
@ -501,7 +511,7 @@ PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPre
else if (aMaxTableWidth <= aMaxWidth)
{ // the max width of the table fits comfortably in the available space
if (gsDebug) printf (" * table desired size fits, calling BalanceColumnsTableFits\n");
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aTableFixedWidth);
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aMaxWidth, aTableFixedWidth);
}
else
{ // the table fits somewhere between its min and desired size
@ -511,9 +521,9 @@ PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPre
}
}
else
{
{ // tables with fixed-width have their own rules
if (aTableFixedWidth<aMinTableWidth)
{ // the table doesn't fit in the available space
{ // the table's specified width doesn't fit in the available space
if (gsDebug) printf (" * specified width table with width<minTableWidth, calling SetColumnsToMinWidth\n");
result = SetColumnsToMinWidth(aPresContext);
}
@ -526,7 +536,7 @@ PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPre
else
{ // the table's specified width is >= its max width, so give each column its max requested size
if (gsDebug) printf (" * specified width table > maxTableWidth, calling BalanceColumnsTableFits\n");
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aTableFixedWidth);
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aMaxWidth, aTableFixedWidth);
}
}
return result;
@ -550,7 +560,7 @@ PRBool BasicTableLayoutStrategy::SetColumnsToMinWidth(nsIPresContext* aPresConte
// XXX need column frame to ask this question
nsStylePosition* colPosition = nsnull;
if (PR_TRUE==IsProportionalWidth(colPosition))
if (PR_FALSE==IsFixedWidth(colPosition))
{
for (PRInt32 cellIndex = 0; cellIndex<numCells; cellIndex++)
{ // this col has proportional width, so determine its width requirements
@ -574,7 +584,7 @@ PRBool BasicTableLayoutStrategy::SetColumnsToMinWidth(nsIPresContext* aPresConte
if (gsDebug==PR_TRUE)
{
printf (" for determining width of col %d %s:\n",
colIndex, IsProportionalWidth(colPosition)? "(P)":"(A)");
colIndex, !IsFixedWidth(colPosition)? "(P)":"(A)");
printf (" minColWidth = %d and maxColWidth = %d\n", minColWidth, maxColWidth);
}
@ -587,7 +597,8 @@ PRBool BasicTableLayoutStrategy::SetColumnsToMinWidth(nsIPresContext* aPresConte
}
PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresContext,
PRInt32 aAvailWidth,
nscoord aAvailWidth,
nscoord aMaxWidth,
nscoord aTableFixedWidth)
{
#ifdef DEBUG
@ -597,25 +608,32 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
#endif
PRBool result = PR_TRUE;
nscoord tableWidth=0;
nscoord numProportionalColumns = 0;
nsVoidArray *spanList=nsnull;
nscoord tableWidth=0; // the width of the table as a result of setting column widths
nscoord numProportionalColumns = 0; // the total number of proportional-width columns
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
nsVoidArray *spanList=nsnull; // a list of the cells that span columns
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
PRInt32 numCols = columnLayoutData->Count();
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
{
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
PRInt32 minColWidth = 0;
PRInt32 maxColWidth = 0;
// Get column information
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
nsTableColPtr col = colData->GetCol(); // col: ADDREF++
nsVoidArray *cells = colData->GetCells();
PRInt32 minColWidth = 0;
PRInt32 maxColWidth = 0;
PRInt32 numCells = cells->Count();
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
// XXX Need columnFrame to ask the style question
nsStylePosition* colPosition = nsnull;
// Get the columns's style
nsTableColFrame *colFrame = colData->GetColFrame();
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
nsIStyleContextPtr colSC;
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
nsStylePosition* colPosition = (nsStylePosition*) colSC->GetData(eStyleStruct_Position);
if (PR_TRUE==IsProportionalWidth(colPosition))
if (PR_FALSE==IsFixedWidth(colPosition))
{
numProportionalColumns++;
// first, deal with any cells that span into this column from a pervious column
@ -683,60 +701,115 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
if (gsDebug==PR_TRUE)
{
printf (" for determining width of col %d %s:\n",
colIndex, IsProportionalWidth(colPosition)? "(P)":"(A)");
colIndex, !IsFixedWidth(colPosition)? "(P)":"(A)");
printf (" minColWidth = %d and maxColWidth = %d\n", minColWidth, maxColWidth);
printf (" aAvailWidth = %d\n", aAvailWidth);
}
// Get column width if it has one
nscoord specifiedProportion = -1;
float specifiedPercentageColWidth = -1.0f;
PRBool isAutoWidth = PR_FALSE;
switch (colPosition->mWidth.GetUnit()) {
case eStyleUnit_Percent:
specifiedPercentageColWidth = colPosition->mWidth.GetPercentValue();
break;
case eStyleUnit_Proportional:
specifiedProportion = colPosition->mWidth.GetIntValue();
break;
case eStyleUnit_Auto:
isAutoWidth = PR_TRUE;
break;
default:
break;
}
#if XXX_bug_kipp_about_this
if (0==colStyle->proportionalWidth)
/* set the column width, knowing that the table fits in the available space */
if (0==specifiedProportion || 0.0==specifiedPercentageColWidth)
{ // col width is specified to be the minimum
mTableFrame->SetColumnWidth(colIndex, minColWidth);
if (gsDebug==PR_TRUE)
printf (" 3 (0): col %d set to min width = %d because style set proportionalWidth=0\n",
colIndex, mTableFrame->GetColumnWidth(colIndex));
}
else // BUG? else? other code below has the else
#endif
if (PR_TRUE==IsAutoWidth(colPosition))
{ // give each remaining column it's desired width
else if (PR_TRUE==isAutoWidth)
{ // col width is determined by the cells' content,
// so give each remaining column it's desired width (because we know we fit.)
// if there is width left over, we'll factor that in after this loop is complete
mTableFrame->SetColumnWidth(colIndex, maxColWidth);
if (gsDebug==PR_TRUE)
printf (" 3a: col %d with availWidth %d, set to width = %d\n",
colIndex, aAvailWidth, mTableFrame->GetColumnWidth(colIndex));
}
else if (0!=specifiedProportion)
{ // we need to save these and do them after all other columns have been calculated
/* the calculation will be:
sum up n, the total number of slices for the columns with proportional width
compute the table "required" width, fixed-width + percentage-width +
the sum of the proportional column's max widths (especially because in this routine I know the table fits)
compute the remaining width: the required width - the used width (fixed + percentage)
compute the width per slice
set the width of each proportional-width column to it's number of slices * width per slice
*/
mTableFrame->SetColumnWidth(colIndex, 0); // set the column width to 0, since it isn't computed yet
if (nsnull==proportionalColumnsList)
proportionalColumnsList = new nsVoidArray();
ProportionalColumnLayoutStruct * info =
new ProportionalColumnLayoutStruct(colIndex, minColWidth, maxColWidth, specifiedProportion);
proportionalColumnsList->AppendElement(info);
totalSlices += specifiedProportion;
}
else
{ // give each remaining column an equal percentage of the remaining space
{ // give each remaining column a percentage of the remaining space
PRInt32 percentage = -1;
if (NS_UNCONSTRAINEDSIZE==aAvailWidth)
{
{ // since the "remaining space" is infinite, give the column it's max requested size
mTableFrame->SetColumnWidth(colIndex, maxColWidth);
}
else
{
#if XXX_bug_kipp_about_this
percentage = colStyle->proportionalWidth;
if (-1.0f != specifiedPercentageColWidth)
percentage = (PRInt32)(specifiedPercentageColWidth*100.0f); // TODO: rounding errors?
if (-1==percentage)
#endif
percentage = 100/numCols;
mTableFrame->SetColumnWidth(colIndex, (percentage*aAvailWidth)/100);
// base the % on the total max width
mTableFrame->SetColumnWidth(colIndex, (percentage*aMaxWidth)/100);
// if the column was computed to be too small, enlarge the column
if (mTableFrame->GetColumnWidth(colIndex) <= minColWidth)
mTableFrame->SetColumnWidth(colIndex, minColWidth);
}
if (gsDebug==PR_TRUE)
printf (" 3b: col %d given %d percent of availWidth %d, set to width = %d\n",
colIndex, percentage, aAvailWidth, mTableFrame->GetColumnWidth(colIndex));
printf (" 3b: col %d given %d percent of aMaxWidth %d, set to width = %d\n",
colIndex, percentage, aMaxWidth, mTableFrame->GetColumnWidth(colIndex));
}
}
tableWidth += mTableFrame->GetColumnWidth(colIndex);
}
// post-process if necessary
/* --- post-process if necessary --- */
// first, assign a width to proportional-width columns
if (nsnull!=proportionalColumnsList)
{
// first, figure out the amount of space per slice
nscoord widthRemaining = aMaxWidth - tableWidth;
nscoord widthPerSlice = widthRemaining/totalSlices;
PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count();
for (PRInt32 i=0; i<numSpecifiedProportionalColumns; i++)
{
ProportionalColumnLayoutStruct * info =
(ProportionalColumnLayoutStruct *)(proportionalColumnsList->ElementAt(i));
nscoord computedColWidth = info->mProportion*widthPerSlice;
mTableFrame->SetColumnWidth(info->mColIndex, computedColWidth);
if (gsDebug==PR_TRUE)
printf (" 3c: col %d given %d proportion of remaining space %d, set to width = %d\n",
info->mColIndex, info->mProportion, widthRemaining, computedColWidth);
tableWidth += computedColWidth;
delete info;
}
delete proportionalColumnsList;
}
// if the specified width of the table is greater than the table's computed width, expand the
// next, if the specified width of the table is greater than the table's computed width, expand the
// table's computed width to match the specified width, giving the extra space to proportionately-sized
// columns if possible.
if (aTableFixedWidth > tableWidth)
@ -750,7 +823,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
{
// need the column style here!
if (PR_TRUE==IsProportionalWidth(nsnull))
if (PR_FALSE==IsFixedWidth(nsnull))
{
nscoord colWidth = excessPerColumn+mTableFrame->GetColumnWidth(colIndex);
mTableFrame->SetColumnWidth(colIndex, colWidth);
@ -788,31 +861,33 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
#endif
PRBool result = PR_TRUE;
PRBool equalWidthColumns=PR_FALSE; // TODO: compute this via style system
PRInt32 maxOfAllMinColWidths = 0;
nsVoidArray *spanList=nsnull;
PRInt32 maxOfAllMinColWidths = 0; // for the case where we have equal column widths, this is the smallest a column can be
nscoord tableWidth=0; // the width of the table as a result of setting column widths
nscoord numProportionalColumns = 0; // the total number of proportional-width columns
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
nsVoidArray *spanList=nsnull; // a list of the cells that span columns
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
PRInt32 numCols = columnLayoutData->Count();
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
{
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
nsTableColPtr col = colData->GetCol(); // col: ADDREF++
#if XXX_bug_kipp_about_this
// XXX BUG: mStyleContext is for the table frame not for the column.
nsStyleMolecule* colStyle =
(nsStyleMolecule*)mStyleContext->GetData(eStyleStruct_Molecule);
#else
nsStylePosition* colPosition = nsnull;
#endif
nsVoidArray *cells = colData->GetCells();
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
PRInt32 minColWidth = 0;
PRInt32 maxColWidth = 0;
// Get column information
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
nsTableColPtr col = colData->GetCol(); // col: ADDREF++
nsVoidArray *cells = colData->GetCells();
PRInt32 numCells = cells->Count();
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
if (PR_TRUE==IsProportionalWidth(colPosition))
// Get the columns's style
nsTableColFrame *colFrame = colData->GetColFrame();
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
nsIStyleContextPtr colSC;
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
nsStylePosition* colPosition = (nsStylePosition*) colSC->GetData(eStyleStruct_Position);
if (PR_FALSE==IsFixedWidth(colPosition))
{
// first, deal with any cells that span into this column from a pervious column
if (nsnull!=spanList)
@ -873,31 +948,45 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
if (gsDebug==PR_TRUE)
{
printf (" for determining width of col %d %s:\n",
colIndex, IsProportionalWidth(colPosition)? "(P)":"(A)");
colIndex, !IsFixedWidth(colPosition)? "(P)":"(A)");
printf (" minTableWidth = %d and maxTableWidth = %d\n", aMinTableWidth, aMaxTableWidth);
printf (" minColWidth = %d and maxColWidth = %d\n", minColWidth, maxColWidth);
printf (" aAvailWidth = %d\n", aAvailWidth);
}
// this col has proportional width, so set its width based on the table width
// Get column width if it has one
nscoord specifiedProportion = -1;
float specifiedPercentageColWidth = -1.0f;
PRBool isAutoWidth = PR_FALSE;
switch (colPosition->mWidth.GetUnit()) {
case eStyleUnit_Percent:
specifiedPercentageColWidth = colPosition->mWidth.GetPercentValue();
break;
case eStyleUnit_Proportional:
specifiedProportion = colPosition->mWidth.GetIntValue();
break;
case eStyleUnit_Auto:
isAutoWidth = PR_TRUE;
break;
default:
break;
}
// the table fits in the space somewhere between its min and max size
// so dole out the available space appropriately
#if XXX_bug_kipp_about_this
if (0==colStyle->proportionalWidth)
if (0==specifiedProportion || 0.0==specifiedPercentageColWidth)
{ // col width is specified to be the minimum
mTableFrame->SetColumnWidth(colIndex, minColWidth);
if (gsDebug==PR_TRUE)
printf (" 4 (0): col %d set to min width = %d because style set proportionalWidth=0\n",
colIndex, mTableFrame->GetColumnWidth(colIndex));
}
else
#endif
if (1==numCols)
else if (1==numCols)
{ // there is only one column, so it should be as wide as the available space allows it to be
if (gsDebug==PR_TRUE) printf (" 4 one-column: col %d set to width = %d\n", colIndex, aAvailWidth);
mTableFrame->SetColumnWidth(colIndex, aAvailWidth);
}
else if (IsAutoWidth(colPosition))
else if (PR_TRUE==isAutoWidth)
{ // column's width is determined by its content
PRUint32 W = aMaxWidth - aMinTableWidth;
PRUint32 D = aMaxTableWidth - aMinTableWidth;
@ -910,34 +999,81 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
printf (" 4 auto-width: col %d W=%d D=%d d=%d, set to width = %d\n",
colIndex, W, D, d, mTableFrame->GetColumnWidth(colIndex));
}
else if (0!=specifiedProportion)
{ // we need to save these and do them after all other columns have been calculated
/* the calculation will be:
sum up n, the total number of slices for the columns with proportional width
compute the table "required" width, fixed-width + percentage-width +
the sum of the proportional column's max widths (especially because in this routine I know the table fits)
compute the remaining width: the required width - the used width (fixed + percentage)
compute the width per slice
set the width of each proportional-width column to it's number of slices * width per slice
*/
mTableFrame->SetColumnWidth(colIndex, 0); // set the column width to 0, since it isn't computed yet
if (nsnull==proportionalColumnsList)
proportionalColumnsList = new nsVoidArray();
ProportionalColumnLayoutStruct * info =
new ProportionalColumnLayoutStruct(colIndex, minColWidth, maxColWidth, specifiedProportion);
proportionalColumnsList->AppendElement(info);
totalSlices += specifiedProportion;
}
else
{ // give each remaining column an equal percentage of the remaining space
#if XXX_bug_kipp_about_this
PRInt32 percentage = colStyle->proportionalWidth;
if (-1==percentage)
#endif
PRInt32 percentage = 100/numCols;
mTableFrame->SetColumnWidth(colIndex, (percentage*aAvailWidth)/100);
// if the column was computed to be too small, enlarge the column
if (mTableFrame->GetColumnWidth(colIndex) <= minColWidth)
{ // give each remaining column a percentage of the remaining space
PRInt32 percentage = -1;
if (NS_UNCONSTRAINEDSIZE==aAvailWidth)
{ // since the "remaining space" is infinite, give the column it's max requested size
mTableFrame->SetColumnWidth(colIndex, maxColWidth);
}
else
{
mTableFrame->SetColumnWidth(colIndex, minColWidth);
if (maxOfAllMinColWidths < minColWidth)
maxOfAllMinColWidths = minColWidth;
if (-1.0f != specifiedPercentageColWidth)
percentage = (PRInt32)(specifiedPercentageColWidth*100.0f); // TODO: rounding errors?
if (-1==percentage)
percentage = 100/numCols;
// base the % on the total max width
mTableFrame->SetColumnWidth(colIndex, (percentage*aMaxWidth)/100);
// if the column was computed to be too small, enlarge the column
if (mTableFrame->GetColumnWidth(colIndex) <= minColWidth)
{
mTableFrame->SetColumnWidth(colIndex, minColWidth);
if (maxOfAllMinColWidths < minColWidth)
maxOfAllMinColWidths = minColWidth;
}
}
if (gsDebug==PR_TRUE)
{
printf (" 4 equal width: col %d given %d percent of availWidth %d, set to width = %d\n",
colIndex, percentage, aAvailWidth, mTableFrame->GetColumnWidth(colIndex));
printf (" 4b: col %d given %d percent of maxWidth %d, set to width = %d\n",
colIndex, percentage, aMaxWidth, mTableFrame->GetColumnWidth(colIndex));
if (0!=maxOfAllMinColWidths)
printf(" and setting maxOfAllMins to %d\n", maxOfAllMinColWidths);
}
}
}
}
/* --- post-process if necessary --- */
// first, assign a width to proportional-width columns
if (nsnull!=proportionalColumnsList)
{
// first, figure out the amount of space per slice
nscoord widthRemaining = aMaxWidth - tableWidth;
nscoord widthPerSlice = widthRemaining/totalSlices;
PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count();
for (PRInt32 i=0; i<numSpecifiedProportionalColumns; i++)
{
ProportionalColumnLayoutStruct * info =
(ProportionalColumnLayoutStruct *)(proportionalColumnsList->ElementAt(i));
nscoord computedColWidth = info->mProportion*widthPerSlice;
mTableFrame->SetColumnWidth(info->mColIndex, computedColWidth);
if (gsDebug==PR_TRUE)
printf (" 3c: col %d given %d proportion of remaining space %d, set to width = %d\n",
info->mColIndex, info->mProportion, widthRemaining, computedColWidth);
tableWidth += computedColWidth;
delete info;
}
delete proportionalColumnsList;
}
// post-process if necessary
/*
// if columns have equal width, and some column's content couldn't squeeze into the computed size,
// then expand every column to the min size of the column with the largest min size
if (equalWidthColumns && 0!=maxOfAllMinColWidths)
@ -946,6 +1082,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
mTableFrame->SetColumnWidth(colIndex, maxOfAllMinColWidths);
}
*/
if (nsnull!=spanList)
delete spanList;

View File

@ -124,13 +124,15 @@ public:
*
* @param aPresContext the presentation context
* @param aAvailWidth the remaining amount of horizontal space available
* @param aMaxWidth the total amount of horizontal space available
* @param aTableFixedWidth the specified width of the table. If there is none,
* this param is 0
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*/
virtual PRBool BalanceColumnsTableFits(nsIPresContext* aPresContext,
PRInt32 aAvailWidth,
nscoord aAvailWidth,
nscoord aMaxWidth,
nscoord aTableFixedWidth);
/** assign widths for each column that has proportional width inside a table that
@ -155,10 +157,11 @@ public:
PRInt32 aMinTableWidth,
PRInt32 aMaxTableWidth);
/** return true if the style indicates that the width is proportional
* for the purposes of column width determination
/** return true if the style indicates that the width is a specific width
* for the purposes of column width determination.
* return false if the width changes based on content, parent size, etc.
*/
virtual PRBool IsProportionalWidth(nsStylePosition* aStylePosition);
virtual PRBool IsFixedWidth(nsStylePosition* aStylePosition);
virtual PRBool IsAutoWidth(nsStylePosition* aStylePosition);

View File

@ -24,6 +24,7 @@ nsColLayoutData::nsColLayoutData(nsTableCol *aCol)
{
mCol = aCol;
mCells = new nsVoidArray();
mColFrame = nsnull;
}
nsColLayoutData::~nsColLayoutData()
@ -55,7 +56,17 @@ void nsColLayoutData::SetCol(nsTableCol * aCol)
NS_IF_RELEASE(mCol);
mCol = aCol;
}
};
}
nsTableColFrame * nsColLayoutData::GetColFrame()
{
return mColFrame;
}
void nsColLayoutData::SetColFrame(nsTableColFrame *aColFrame)
{
mColFrame = aColFrame;
}
nsCellLayoutData* nsColLayoutData::ElementAt(PRInt32 aIndex) const

View File

@ -26,6 +26,7 @@
class nsVoidArray;
class nsCellLayoutData;
class nsTableFrame;
class nsTableColFrame;
/** Simple data class that represents in-process reflow information about a column.
@ -42,6 +43,10 @@ public:
void SetCol(nsTableCol * aCol);
nsTableColFrame *GetColFrame();
void SetColFrame(nsTableColFrame *aColFrame);
nsVoidArray * GetCells();
PRInt32 Count() const;
@ -67,6 +72,7 @@ public:
private:
nsTableCol *mCol;
nsTableColFrame *mColFrame;
nsVoidArray *mCells;
};

View File

@ -44,99 +44,6 @@ public:
PRInt32 &aMinTableWidth,
PRInt32 &aMaxTableWidth,
nsSize* aMaxElementSize)=0;
/** assign widths for each column that has fixed width.
* Computes the minimum and maximum table widths.
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
* @param aMaxWidth the maximum width of the table
* @param aNumCols the total number of columns in the table
* @param aTableStyle the resolved style for the table
* @param aTotalFixedWidth out param, the sum of the fixed width columns
* @param aMinTableWidth out param, the min possible table width
* @param aMaxTableWidth out param, the max table width
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*
* TODO: should be renamed to "AssignKnownWidthInformation
*/
virtual PRBool AssignFixedColumnWidths(nsIPresContext* aPresContext,
PRInt32 aMaxWidth,
PRInt32 aNumCols,
PRInt32 & aTotalFixedWidth,
PRInt32 & aMinTableWidth,
PRInt32 & aMaxTableWidth)=0;
/** assign widths for each column that has proportional width inside a table that
* has auto width (width set by the content and available space.)
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
* @param aTableStyle the resolved style for the table
* @param aAvailWidth the remaining amount of horizontal space available
* @param aMaxWidth the total amount of horizontal space available
* @param aMinTableWidth the min possible table width
* @param aMaxTableWidth the max table width
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*/
virtual PRBool BalanceProportionalColumns(nsIPresContext* aPresContext,
PRInt32 aAvailWidth,
PRInt32 aMaxWidth,
PRInt32 aMinTableWidth,
PRInt32 aMaxTableWidth,
nscoord aTableFixedWidth)=0;
/** assign the minimum allowed width for each column that has proportional width.
* Typically called when the min table width doesn't fit in the available space.
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*/
virtual PRBool SetColumnsToMinWidth(nsIPresContext* aPresContext)=0;
/** assign the maximum allowed width for each column that has proportional width.
* Typically called when the desired max table width fits in the available space.
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
* @param aTableStyle the resolved style for the table
* @param aAvailWidth the remaining amount of horizontal space available
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*/
virtual PRBool BalanceColumnsTableFits(nsIPresContext* aPresContext,
PRInt32 aAvailWidth,
nscoord aTableFixedWidth)=0;
/** assign widths for each column that has proportional width inside a table that
* has auto width (width set by the content and available space) according to the
* HTML 4 specification.
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
* @param aTableStyle the resolved style for the table
* @param aAvailWidth the remaining amount of horizontal space available
* @param aMaxWidth the total amount of horizontal space available
* @param aMinTableWidth the min possible table width
* @param aMaxTableWidth the max table width
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*
* TODO: rename this method to reflect that it is a Nav4 compatibility method
*/
virtual PRBool BalanceColumnsConstrained(nsIPresContext* aPresContext,
PRInt32 aAvailWidth,
PRInt32 aMaxWidth,
PRInt32 aMinTableWidth,
PRInt32 aMaxTableWidth)=0;
};
#endif

View File

@ -16,6 +16,7 @@
* Reserved.
*/
#include "nsTableCol.h"
#include "nsTableColFrame.h"
#include "nsTableColGroup.h"
#include "nsTablePart.h"
#include "nsHTMLParts.h"
@ -35,29 +36,6 @@ static const PRBool gsDebug = PR_FALSE;
static const PRBool gsNoisyRefs = PR_FALSE;
#endif
class nsTableColFrame : public nsFrame {
public:
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
nsIContent* aContent,
nsIFrame* aParent);
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
NS_IMETHOD Reflow(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState,
nsReflowStatus& aStatus);
protected:
nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame);
~nsTableColFrame();
};
nsTableColFrame::nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame)

View File

@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsTableColFrame_h__
#define nsTableColFrame_h__
#include "nscore.h"
#include "nsContainerFrame.h"
class nsTableColFrame : public nsFrame {
public:
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
nsIContent* aContent,
nsIFrame* aParent);
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
NS_IMETHOD Reflow(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState,
nsReflowStatus& aStatus);
protected:
nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame);
~nsTableColFrame();
};
#endif

View File

@ -135,48 +135,52 @@ NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext* aPre
result = table->GetAttribute(nsHTMLAtoms::cols, value);
// if COLS is set, then map it into the COL frames
// chicken and egg problem here. I don't have any children yet, so I
// don't know how many columns there are, so I can't do this!
// I need to just set some state, and let the individual columns query up into me
// in their own hooks
PRInt32 numCols;
if (result == eContentAttr_NoValue)
ChildCount(numCols);
else if (result == eContentAttr_HasValue)
if (eContentAttr_NotThere != result)
{
nsHTMLUnit unit = value.GetUnit();
if (eHTMLUnit_Empty==unit)
PRInt32 numCols=0;
if (eContentAttr_NoValue == result)
ChildCount(numCols);
else
numCols = value.GetIntValue();
}
else if (eContentAttr_HasValue == result)
{
nsHTMLUnit unit = value.GetUnit();
if (eHTMLUnit_Empty==unit)
ChildCount(numCols);
else
numCols = value.GetIntValue();
}
PRInt32 colIndex=0;
nsIFrame *colFrame;
FirstChild(colFrame);
for (; colIndex<numCols; colIndex++)
{
if (nsnull==colFrame)
break; // the attribute value specified was greater than the actual number of columns
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
nsStyleCoord width (1, eStyleUnit_Proportional);
colPosition->mWidth = width;
colFrame->GetNextSibling(colFrame);
}
// if there are more columns, there width is set to "minimum"
PRInt32 numChildFrames;
ChildCount(numChildFrames);
for (; colIndex<numChildFrames; colIndex++)
{
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
nsStyleCoord width (0, eStyleUnit_Integer);
colPosition->mWidth = width;
colFrame->GetNextSibling(colFrame);
}
PRInt32 colIndex=0;
nsIFrame *colFrame=nsnull;
nsIStyleContext *colStyleContext;
for (; colIndex<numCols; colIndex++)
{
ChildAt(colIndex, colFrame);
if (nsnull==colFrame)
break; // the attribute value specified was greater than the actual number of columns
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
nsStyleCoord width (1, eStyleUnit_Proportional);
colPosition->mWidth = width;
colFrame->GetStyleContext(aPresContext, colStyleContext);
colStyleContext->RecalcAutomaticData(aPresContext);
}
// if there are more columns, there width is set to "minimum"
PRInt32 numChildFrames;
ChildCount(numChildFrames);
for (; colIndex<numChildFrames; colIndex++)
{
ChildAt(colIndex, colFrame);
NS_ASSERTION(nsnull!=colFrame, "bad first column frame");
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
nsStyleCoord width (0, eStyleUnit_Integer);
colPosition->mWidth = width;
colFrame->GetStyleContext(aPresContext, colStyleContext);
colStyleContext->RecalcAutomaticData(aPresContext);
}
mStyleContext->RecalcAutomaticData(aPresContext);
mStyleContext->RecalcAutomaticData(aPresContext);
}
return NS_OK;
}

View File

@ -630,40 +630,6 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext,
mLastContentIsComplete = PR_TRUE;
const PRInt32 contentType = ((nsTableContent *)(nsIContent*)kid)->GetType();
/*
if (contentType==nsITableContent::kTableColGroupType)
{
// Resolve style
nsIStyleContextPtr kidStyleContext =
aPresContext->ResolveStyleContextFor(kid, this);
NS_ASSERTION(kidStyleContext.IsNotNull(), "null style context for kid");
// SEC: TODO: when content is appended or deleted, be sure to clear out the frame hierarchy!!!!
// get next frame, creating one if needed
nsIFrame* kidFrame=nsnull;
if (nsnull!=prevKidFrame)
prevKidFrame->GetNextSibling(kidFrame); // no need to check for an error, just see if it returned null...
else
ChildAt(0, kidFrame);
// if this is the first time, allocate the frame
if (nsnull==kidFrame)
{
nsIContentDelegate* kidDel;
kidDel = kid->GetDelegate(aPresContext);
nsresult rv = kidDel->CreateFrame(aPresContext, kid,
this, kidStyleContext, kidFrame);
NS_RELEASE(kidDel);
}
// reflow the column group
nsReflowState kidReflowState(eReflowReason_Resize, availSize);
result = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState);
kidFrame->SetRect(0,0,0,0);
}
else */
//if (contentType==nsITableContent::kTableRowGroupType)
if (contentType!=nsITableContent::kTableCaptionType)
{
// Resolve style
@ -1983,6 +1949,7 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
nsTablePart * tablePart = (nsTablePart *)mContent;
PRInt32 cols = tablePart->GetMaxColumns();
PRInt32 tableKidCount = tablePart->ChildCount();
nsIFrame * colGroupFrame = mFirstChild;
for (PRInt32 i=0; i<tableKidCount; i++)
{
nsTableContentPtr tableKid = (nsTableContent *)tablePart->ChildAt(i);
@ -1996,6 +1963,9 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
nsTableColPtr col = (nsTableCol *)tableKid->ChildAt(j);
NS_ASSERTION(col.IsNotNull(), "bad content");
nsColLayoutData *colData = new nsColLayoutData(col);
nsTableColFrame *colFrame=nsnull;
colGroupFrame->ChildAt(j, (nsIFrame *&)colFrame);
colData->SetColFrame(colFrame);
mColumnLayoutData->AppendElement((void *)colData);
}
}
@ -2004,6 +1974,7 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
{
break;
}
ChildAt(i, colGroupFrame); // can't use colGroupFrame->GetNextSibling because it hasn't been set yet
}
}

View File

@ -129,15 +129,14 @@ public:
* DEBUG METHOD
*
*/
void ListColumnLayoutData(FILE* out = stdout, PRInt32 aIndent = 0) const;
virtual void ListColumnLayoutData(FILE* out = stdout, PRInt32 aIndent = 0) const;
/** return the width of the column at aColIndex */
PRInt32 GetColumnWidth(PRInt32 aColIndex);
virtual PRInt32 GetColumnWidth(PRInt32 aColIndex);
/** set the width of the column at aColIndex to aWidth */
void SetColumnWidth(PRInt32 aColIndex, PRInt32 aWidth);
virtual void SetColumnWidth(PRInt32 aColIndex, PRInt32 aWidth);
/**
* Calculate Layout Information

View File

@ -19,6 +19,7 @@
#include <stdio.h>
#include "BasicTableLayoutStrategy.h"
#include "nsTableFrame.h"
#include "nsTableColFrame.h"
#include "nsColLayoutData.h"
#include "nsCellLayoutData.h"
#include "nsTableCol.h"
@ -42,12 +43,39 @@ static const PRBool gsDebugCLD = PR_FALSE;
static const PRBool gsTiming = PR_FALSE;
#endif
/* ---------- ProportionalColumnLayoutStruct ---------- */
// TODO: make public so other subclasses can use it
/** useful info about a column for layout */
struct ProportionalColumnLayoutStruct
{
ProportionalColumnLayoutStruct(PRInt32 aColIndex,
nscoord aMinColWidth,
nscoord aMaxColWidth,
PRInt32 aProportion)
{
mColIndex = aColIndex;
mMinColWidth = aMinColWidth;
mMaxColWidth = aMaxColWidth;
mProportion = aProportion;
};
PRInt32 mColIndex;
nscoord mMinColWidth;
nscoord mMaxColWidth;
PRInt32 mProportion;
};
/* ---------- BasicTableLayoutStrategy ---------- */
/* return true if the style indicates that the width is proportional
* for the purposes of column width determination
*/
PRBool BasicTableLayoutStrategy::IsProportionalWidth(nsStylePosition* aStylePosition)
PRBool BasicTableLayoutStrategy::IsFixedWidth(nsStylePosition* aStylePosition)
{
PRBool result = PR_FALSE; // assume that it is not
PRBool result = PR_FALSE; // assume that it is not fixed width
PRInt32 unitType;
if (nsnull == aStylePosition) {
unitType = eStyleUnit_Auto;
@ -58,12 +86,11 @@ PRBool BasicTableLayoutStrategy::IsProportionalWidth(nsStylePosition* aStylePosi
switch (unitType) {
case eStyleUnit_Coord:
break;
result = PR_TRUE;
case eStyleUnit_Auto:
case eStyleUnit_Proportional:
case eStyleUnit_Percent:
result = PR_TRUE;
break;
// TODO
@ -71,7 +98,7 @@ PRBool BasicTableLayoutStrategy::IsProportionalWidth(nsStylePosition* aStylePosi
break;
default:
NS_ASSERTION(PR_FALSE, "illegal style type in IsProportionalWidth");
NS_ASSERTION(PR_FALSE, "illegal style type in IsFixedWidth");
break;
}
return result;
@ -263,6 +290,8 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
NS_ASSERTION(nsnull != colData, "bad column data");
nsTableColFrame *colFrame = colData->GetColFrame();
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
nsTableColPtr col = colData->GetCol(); // col: ADDREF++
NS_ASSERTION(col.IsNotNull(), "bad col");
@ -273,35 +302,25 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
PRInt32 numCells = cells->Count();
if (gsDebug==PR_TRUE) printf (" for column %d numCells = %d\n", colIndex, numCells);
#if XXX_need_access_to_column_frame_help
// Get the columns's style
nsIStyleContextPtr colSC;
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
nsStylePosition* colPosition = (nsStylePosition*)
colSC->GetData(eStyleStruct_Position);
nsStylePosition* colPosition = (nsStylePosition*) colSC->GetData(eStyleStruct_Position);
// Get column width if it has one
PRBool haveColWidth = PR_FALSE;
nscoord colWidth;
nscoord specifiedFixedColWidth=0;
switch (colPosition->mWidth.GetUnit()) {
default:
case eStyleUnit_Auto:
case eStyleUnit_Inherit:
break;
case eStyleUnit_Coord:
haveColWidth = PR_TRUE;
specifiedFixedColWidth = colPosition->mWidth.GetCoordValue();
break;
case eStyleUnit_Coord:
haveColWidth = PR_TRUE;
colWidth = colPosition->mWidth.GetCoordValue;
break;
case eStyleUnit_Percent:
case eStyleUnit_Proportional:
//XXX haveColWidth = PR_TRUE;
//XXX colWidth = colPosition->mWidthPCT * something;
break;
default:
break;
}
#endif
// TODO - use specifiedFixedColWidth to influence the width when both col span and fixed col width are given
/* Scan the column, simulatneously assigning fixed column widths
* and computing the min/max column widths
*/
@ -388,34 +407,27 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
}
}
#if XXX_need_access_to_column_frame_help
// TODO - use cellWidth found above to influence the cell width here
switch (colPosition->mWidth.GetUnit()) {
default:
case eStyleUnit_Auto:
case eStyleUnit_Inherit:
break;
case eStyleUnit_Coord:
{
// This col has a fixed width, so set the cell's width to the
// larger of (specified width, largest max_element_size of the
// cells in the column)
PRInt32 widthForThisCell = max(cellMinSize->width, colPosition->mWidth.GetCoordValue());
if (mTableFrame->GetColumnWidth(colIndex) < widthForThisCell)
case eStyleUnit_Coord:
{
if (gsDebug) printf (" setting fixed width to %d\n",widthForThisCell);
mTableFrame->SetColumnWidth(colIndex, widthForThisCell);
maxColWidth = widthForThisCell;
// This col has a fixed width, so set the cell's width to the
// larger of (specified width, largest max_element_size of the
// cells in the column)
PRInt32 widthForThisCell = PR_MAX(cellMinSize->width, colPosition->mWidth.GetCoordValue());
if (mTableFrame->GetColumnWidth(colIndex) < widthForThisCell)
{
if (gsDebug) printf (" setting fixed width to %d\n",widthForThisCell);
mTableFrame->SetColumnWidth(colIndex, widthForThisCell);
maxColWidth = widthForThisCell;
}
}
}
break;
break;
default:
break;
case NS_STYLE_POSITION_VALUE_PCT:
case NS_STYLE_POSITION_VALUE_PROPORTIONAL:
// XXX write me when pct/proportional are supported
break;
}
#endif
// regardless of the width specification, keep track of the
// min/max column widths
@ -443,20 +455,18 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
}
}
#if 0
// if the col is fixed-width, expand the col to the specified
// fixed width if necessary
if (colStyle->fixedWidth > mTableFrame->GetColumnWidth(colIndex))
mTableFrame->SetColumnWidth(colIndex, colStyle->fixedWidth);
if (PR_TRUE==haveColWidth && specifiedFixedColWidth > mTableFrame->GetColumnWidth(colIndex))
mTableFrame->SetColumnWidth(colIndex, specifiedFixedColWidth);
// keep a running total of the amount of space taken up by all
// fixed-width columns
aTotalFixedWidth += mTableFrame->GetColumnWidths(colIndex);
aTotalFixedWidth += mTableFrame->GetColumnWidth(colIndex);
if (gsDebug) {
printf (" after col %d, aTotalFixedWidth = %d\n",
colIndex, aTotalFixedWidth);
}
#endif
// add col[i] metrics to the running totals for the table min/max width
if (NS_UNCONSTRAINEDSIZE!=aMinTableWidth)
@ -478,10 +488,10 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPresContext,
PRInt32 aAvailWidth,
PRInt32 aMaxWidth,
PRInt32 aMinTableWidth,
PRInt32 aMaxTableWidth,
nscoord aAvailWidth,
nscoord aMaxWidth,
nscoord aMinTableWidth,
nscoord aMaxTableWidth,
nscoord aTableFixedWidth)
{
PRBool result = PR_TRUE;
@ -491,7 +501,7 @@ PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPre
if (NS_UNCONSTRAINEDSIZE==aMaxWidth)
{ // the max width of the table fits comfortably in the available space
if (gsDebug) printf (" * table laying out in NS_UNCONSTRAINEDSIZE, calling BalanceColumnsTableFits\n");
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aTableFixedWidth);
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aMaxWidth, aTableFixedWidth);
}
else if (aMinTableWidth > aMaxWidth)
{ // the table doesn't fit in the available space
@ -501,7 +511,7 @@ PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPre
else if (aMaxTableWidth <= aMaxWidth)
{ // the max width of the table fits comfortably in the available space
if (gsDebug) printf (" * table desired size fits, calling BalanceColumnsTableFits\n");
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aTableFixedWidth);
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aMaxWidth, aTableFixedWidth);
}
else
{ // the table fits somewhere between its min and desired size
@ -511,9 +521,9 @@ PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPre
}
}
else
{
{ // tables with fixed-width have their own rules
if (aTableFixedWidth<aMinTableWidth)
{ // the table doesn't fit in the available space
{ // the table's specified width doesn't fit in the available space
if (gsDebug) printf (" * specified width table with width<minTableWidth, calling SetColumnsToMinWidth\n");
result = SetColumnsToMinWidth(aPresContext);
}
@ -526,7 +536,7 @@ PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPre
else
{ // the table's specified width is >= its max width, so give each column its max requested size
if (gsDebug) printf (" * specified width table > maxTableWidth, calling BalanceColumnsTableFits\n");
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aTableFixedWidth);
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aMaxWidth, aTableFixedWidth);
}
}
return result;
@ -550,7 +560,7 @@ PRBool BasicTableLayoutStrategy::SetColumnsToMinWidth(nsIPresContext* aPresConte
// XXX need column frame to ask this question
nsStylePosition* colPosition = nsnull;
if (PR_TRUE==IsProportionalWidth(colPosition))
if (PR_FALSE==IsFixedWidth(colPosition))
{
for (PRInt32 cellIndex = 0; cellIndex<numCells; cellIndex++)
{ // this col has proportional width, so determine its width requirements
@ -574,7 +584,7 @@ PRBool BasicTableLayoutStrategy::SetColumnsToMinWidth(nsIPresContext* aPresConte
if (gsDebug==PR_TRUE)
{
printf (" for determining width of col %d %s:\n",
colIndex, IsProportionalWidth(colPosition)? "(P)":"(A)");
colIndex, !IsFixedWidth(colPosition)? "(P)":"(A)");
printf (" minColWidth = %d and maxColWidth = %d\n", minColWidth, maxColWidth);
}
@ -587,7 +597,8 @@ PRBool BasicTableLayoutStrategy::SetColumnsToMinWidth(nsIPresContext* aPresConte
}
PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresContext,
PRInt32 aAvailWidth,
nscoord aAvailWidth,
nscoord aMaxWidth,
nscoord aTableFixedWidth)
{
#ifdef DEBUG
@ -597,25 +608,32 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
#endif
PRBool result = PR_TRUE;
nscoord tableWidth=0;
nscoord numProportionalColumns = 0;
nsVoidArray *spanList=nsnull;
nscoord tableWidth=0; // the width of the table as a result of setting column widths
nscoord numProportionalColumns = 0; // the total number of proportional-width columns
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
nsVoidArray *spanList=nsnull; // a list of the cells that span columns
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
PRInt32 numCols = columnLayoutData->Count();
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
{
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
PRInt32 minColWidth = 0;
PRInt32 maxColWidth = 0;
// Get column information
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
nsTableColPtr col = colData->GetCol(); // col: ADDREF++
nsVoidArray *cells = colData->GetCells();
PRInt32 minColWidth = 0;
PRInt32 maxColWidth = 0;
PRInt32 numCells = cells->Count();
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
// XXX Need columnFrame to ask the style question
nsStylePosition* colPosition = nsnull;
// Get the columns's style
nsTableColFrame *colFrame = colData->GetColFrame();
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
nsIStyleContextPtr colSC;
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
nsStylePosition* colPosition = (nsStylePosition*) colSC->GetData(eStyleStruct_Position);
if (PR_TRUE==IsProportionalWidth(colPosition))
if (PR_FALSE==IsFixedWidth(colPosition))
{
numProportionalColumns++;
// first, deal with any cells that span into this column from a pervious column
@ -683,60 +701,115 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
if (gsDebug==PR_TRUE)
{
printf (" for determining width of col %d %s:\n",
colIndex, IsProportionalWidth(colPosition)? "(P)":"(A)");
colIndex, !IsFixedWidth(colPosition)? "(P)":"(A)");
printf (" minColWidth = %d and maxColWidth = %d\n", minColWidth, maxColWidth);
printf (" aAvailWidth = %d\n", aAvailWidth);
}
// Get column width if it has one
nscoord specifiedProportion = -1;
float specifiedPercentageColWidth = -1.0f;
PRBool isAutoWidth = PR_FALSE;
switch (colPosition->mWidth.GetUnit()) {
case eStyleUnit_Percent:
specifiedPercentageColWidth = colPosition->mWidth.GetPercentValue();
break;
case eStyleUnit_Proportional:
specifiedProportion = colPosition->mWidth.GetIntValue();
break;
case eStyleUnit_Auto:
isAutoWidth = PR_TRUE;
break;
default:
break;
}
#if XXX_bug_kipp_about_this
if (0==colStyle->proportionalWidth)
/* set the column width, knowing that the table fits in the available space */
if (0==specifiedProportion || 0.0==specifiedPercentageColWidth)
{ // col width is specified to be the minimum
mTableFrame->SetColumnWidth(colIndex, minColWidth);
if (gsDebug==PR_TRUE)
printf (" 3 (0): col %d set to min width = %d because style set proportionalWidth=0\n",
colIndex, mTableFrame->GetColumnWidth(colIndex));
}
else // BUG? else? other code below has the else
#endif
if (PR_TRUE==IsAutoWidth(colPosition))
{ // give each remaining column it's desired width
else if (PR_TRUE==isAutoWidth)
{ // col width is determined by the cells' content,
// so give each remaining column it's desired width (because we know we fit.)
// if there is width left over, we'll factor that in after this loop is complete
mTableFrame->SetColumnWidth(colIndex, maxColWidth);
if (gsDebug==PR_TRUE)
printf (" 3a: col %d with availWidth %d, set to width = %d\n",
colIndex, aAvailWidth, mTableFrame->GetColumnWidth(colIndex));
}
else if (0!=specifiedProportion)
{ // we need to save these and do them after all other columns have been calculated
/* the calculation will be:
sum up n, the total number of slices for the columns with proportional width
compute the table "required" width, fixed-width + percentage-width +
the sum of the proportional column's max widths (especially because in this routine I know the table fits)
compute the remaining width: the required width - the used width (fixed + percentage)
compute the width per slice
set the width of each proportional-width column to it's number of slices * width per slice
*/
mTableFrame->SetColumnWidth(colIndex, 0); // set the column width to 0, since it isn't computed yet
if (nsnull==proportionalColumnsList)
proportionalColumnsList = new nsVoidArray();
ProportionalColumnLayoutStruct * info =
new ProportionalColumnLayoutStruct(colIndex, minColWidth, maxColWidth, specifiedProportion);
proportionalColumnsList->AppendElement(info);
totalSlices += specifiedProportion;
}
else
{ // give each remaining column an equal percentage of the remaining space
{ // give each remaining column a percentage of the remaining space
PRInt32 percentage = -1;
if (NS_UNCONSTRAINEDSIZE==aAvailWidth)
{
{ // since the "remaining space" is infinite, give the column it's max requested size
mTableFrame->SetColumnWidth(colIndex, maxColWidth);
}
else
{
#if XXX_bug_kipp_about_this
percentage = colStyle->proportionalWidth;
if (-1.0f != specifiedPercentageColWidth)
percentage = (PRInt32)(specifiedPercentageColWidth*100.0f); // TODO: rounding errors?
if (-1==percentage)
#endif
percentage = 100/numCols;
mTableFrame->SetColumnWidth(colIndex, (percentage*aAvailWidth)/100);
// base the % on the total max width
mTableFrame->SetColumnWidth(colIndex, (percentage*aMaxWidth)/100);
// if the column was computed to be too small, enlarge the column
if (mTableFrame->GetColumnWidth(colIndex) <= minColWidth)
mTableFrame->SetColumnWidth(colIndex, minColWidth);
}
if (gsDebug==PR_TRUE)
printf (" 3b: col %d given %d percent of availWidth %d, set to width = %d\n",
colIndex, percentage, aAvailWidth, mTableFrame->GetColumnWidth(colIndex));
printf (" 3b: col %d given %d percent of aMaxWidth %d, set to width = %d\n",
colIndex, percentage, aMaxWidth, mTableFrame->GetColumnWidth(colIndex));
}
}
tableWidth += mTableFrame->GetColumnWidth(colIndex);
}
// post-process if necessary
/* --- post-process if necessary --- */
// first, assign a width to proportional-width columns
if (nsnull!=proportionalColumnsList)
{
// first, figure out the amount of space per slice
nscoord widthRemaining = aMaxWidth - tableWidth;
nscoord widthPerSlice = widthRemaining/totalSlices;
PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count();
for (PRInt32 i=0; i<numSpecifiedProportionalColumns; i++)
{
ProportionalColumnLayoutStruct * info =
(ProportionalColumnLayoutStruct *)(proportionalColumnsList->ElementAt(i));
nscoord computedColWidth = info->mProportion*widthPerSlice;
mTableFrame->SetColumnWidth(info->mColIndex, computedColWidth);
if (gsDebug==PR_TRUE)
printf (" 3c: col %d given %d proportion of remaining space %d, set to width = %d\n",
info->mColIndex, info->mProportion, widthRemaining, computedColWidth);
tableWidth += computedColWidth;
delete info;
}
delete proportionalColumnsList;
}
// if the specified width of the table is greater than the table's computed width, expand the
// next, if the specified width of the table is greater than the table's computed width, expand the
// table's computed width to match the specified width, giving the extra space to proportionately-sized
// columns if possible.
if (aTableFixedWidth > tableWidth)
@ -750,7 +823,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
{
// need the column style here!
if (PR_TRUE==IsProportionalWidth(nsnull))
if (PR_FALSE==IsFixedWidth(nsnull))
{
nscoord colWidth = excessPerColumn+mTableFrame->GetColumnWidth(colIndex);
mTableFrame->SetColumnWidth(colIndex, colWidth);
@ -788,31 +861,33 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
#endif
PRBool result = PR_TRUE;
PRBool equalWidthColumns=PR_FALSE; // TODO: compute this via style system
PRInt32 maxOfAllMinColWidths = 0;
nsVoidArray *spanList=nsnull;
PRInt32 maxOfAllMinColWidths = 0; // for the case where we have equal column widths, this is the smallest a column can be
nscoord tableWidth=0; // the width of the table as a result of setting column widths
nscoord numProportionalColumns = 0; // the total number of proportional-width columns
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
nsVoidArray *spanList=nsnull; // a list of the cells that span columns
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
PRInt32 numCols = columnLayoutData->Count();
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
{
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
nsTableColPtr col = colData->GetCol(); // col: ADDREF++
#if XXX_bug_kipp_about_this
// XXX BUG: mStyleContext is for the table frame not for the column.
nsStyleMolecule* colStyle =
(nsStyleMolecule*)mStyleContext->GetData(eStyleStruct_Molecule);
#else
nsStylePosition* colPosition = nsnull;
#endif
nsVoidArray *cells = colData->GetCells();
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
PRInt32 minColWidth = 0;
PRInt32 maxColWidth = 0;
// Get column information
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
nsTableColPtr col = colData->GetCol(); // col: ADDREF++
nsVoidArray *cells = colData->GetCells();
PRInt32 numCells = cells->Count();
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
if (PR_TRUE==IsProportionalWidth(colPosition))
// Get the columns's style
nsTableColFrame *colFrame = colData->GetColFrame();
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
nsIStyleContextPtr colSC;
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
nsStylePosition* colPosition = (nsStylePosition*) colSC->GetData(eStyleStruct_Position);
if (PR_FALSE==IsFixedWidth(colPosition))
{
// first, deal with any cells that span into this column from a pervious column
if (nsnull!=spanList)
@ -873,31 +948,45 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
if (gsDebug==PR_TRUE)
{
printf (" for determining width of col %d %s:\n",
colIndex, IsProportionalWidth(colPosition)? "(P)":"(A)");
colIndex, !IsFixedWidth(colPosition)? "(P)":"(A)");
printf (" minTableWidth = %d and maxTableWidth = %d\n", aMinTableWidth, aMaxTableWidth);
printf (" minColWidth = %d and maxColWidth = %d\n", minColWidth, maxColWidth);
printf (" aAvailWidth = %d\n", aAvailWidth);
}
// this col has proportional width, so set its width based on the table width
// Get column width if it has one
nscoord specifiedProportion = -1;
float specifiedPercentageColWidth = -1.0f;
PRBool isAutoWidth = PR_FALSE;
switch (colPosition->mWidth.GetUnit()) {
case eStyleUnit_Percent:
specifiedPercentageColWidth = colPosition->mWidth.GetPercentValue();
break;
case eStyleUnit_Proportional:
specifiedProportion = colPosition->mWidth.GetIntValue();
break;
case eStyleUnit_Auto:
isAutoWidth = PR_TRUE;
break;
default:
break;
}
// the table fits in the space somewhere between its min and max size
// so dole out the available space appropriately
#if XXX_bug_kipp_about_this
if (0==colStyle->proportionalWidth)
if (0==specifiedProportion || 0.0==specifiedPercentageColWidth)
{ // col width is specified to be the minimum
mTableFrame->SetColumnWidth(colIndex, minColWidth);
if (gsDebug==PR_TRUE)
printf (" 4 (0): col %d set to min width = %d because style set proportionalWidth=0\n",
colIndex, mTableFrame->GetColumnWidth(colIndex));
}
else
#endif
if (1==numCols)
else if (1==numCols)
{ // there is only one column, so it should be as wide as the available space allows it to be
if (gsDebug==PR_TRUE) printf (" 4 one-column: col %d set to width = %d\n", colIndex, aAvailWidth);
mTableFrame->SetColumnWidth(colIndex, aAvailWidth);
}
else if (IsAutoWidth(colPosition))
else if (PR_TRUE==isAutoWidth)
{ // column's width is determined by its content
PRUint32 W = aMaxWidth - aMinTableWidth;
PRUint32 D = aMaxTableWidth - aMinTableWidth;
@ -910,34 +999,81 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
printf (" 4 auto-width: col %d W=%d D=%d d=%d, set to width = %d\n",
colIndex, W, D, d, mTableFrame->GetColumnWidth(colIndex));
}
else if (0!=specifiedProportion)
{ // we need to save these and do them after all other columns have been calculated
/* the calculation will be:
sum up n, the total number of slices for the columns with proportional width
compute the table "required" width, fixed-width + percentage-width +
the sum of the proportional column's max widths (especially because in this routine I know the table fits)
compute the remaining width: the required width - the used width (fixed + percentage)
compute the width per slice
set the width of each proportional-width column to it's number of slices * width per slice
*/
mTableFrame->SetColumnWidth(colIndex, 0); // set the column width to 0, since it isn't computed yet
if (nsnull==proportionalColumnsList)
proportionalColumnsList = new nsVoidArray();
ProportionalColumnLayoutStruct * info =
new ProportionalColumnLayoutStruct(colIndex, minColWidth, maxColWidth, specifiedProportion);
proportionalColumnsList->AppendElement(info);
totalSlices += specifiedProportion;
}
else
{ // give each remaining column an equal percentage of the remaining space
#if XXX_bug_kipp_about_this
PRInt32 percentage = colStyle->proportionalWidth;
if (-1==percentage)
#endif
PRInt32 percentage = 100/numCols;
mTableFrame->SetColumnWidth(colIndex, (percentage*aAvailWidth)/100);
// if the column was computed to be too small, enlarge the column
if (mTableFrame->GetColumnWidth(colIndex) <= minColWidth)
{ // give each remaining column a percentage of the remaining space
PRInt32 percentage = -1;
if (NS_UNCONSTRAINEDSIZE==aAvailWidth)
{ // since the "remaining space" is infinite, give the column it's max requested size
mTableFrame->SetColumnWidth(colIndex, maxColWidth);
}
else
{
mTableFrame->SetColumnWidth(colIndex, minColWidth);
if (maxOfAllMinColWidths < minColWidth)
maxOfAllMinColWidths = minColWidth;
if (-1.0f != specifiedPercentageColWidth)
percentage = (PRInt32)(specifiedPercentageColWidth*100.0f); // TODO: rounding errors?
if (-1==percentage)
percentage = 100/numCols;
// base the % on the total max width
mTableFrame->SetColumnWidth(colIndex, (percentage*aMaxWidth)/100);
// if the column was computed to be too small, enlarge the column
if (mTableFrame->GetColumnWidth(colIndex) <= minColWidth)
{
mTableFrame->SetColumnWidth(colIndex, minColWidth);
if (maxOfAllMinColWidths < minColWidth)
maxOfAllMinColWidths = minColWidth;
}
}
if (gsDebug==PR_TRUE)
{
printf (" 4 equal width: col %d given %d percent of availWidth %d, set to width = %d\n",
colIndex, percentage, aAvailWidth, mTableFrame->GetColumnWidth(colIndex));
printf (" 4b: col %d given %d percent of maxWidth %d, set to width = %d\n",
colIndex, percentage, aMaxWidth, mTableFrame->GetColumnWidth(colIndex));
if (0!=maxOfAllMinColWidths)
printf(" and setting maxOfAllMins to %d\n", maxOfAllMinColWidths);
}
}
}
}
/* --- post-process if necessary --- */
// first, assign a width to proportional-width columns
if (nsnull!=proportionalColumnsList)
{
// first, figure out the amount of space per slice
nscoord widthRemaining = aMaxWidth - tableWidth;
nscoord widthPerSlice = widthRemaining/totalSlices;
PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count();
for (PRInt32 i=0; i<numSpecifiedProportionalColumns; i++)
{
ProportionalColumnLayoutStruct * info =
(ProportionalColumnLayoutStruct *)(proportionalColumnsList->ElementAt(i));
nscoord computedColWidth = info->mProportion*widthPerSlice;
mTableFrame->SetColumnWidth(info->mColIndex, computedColWidth);
if (gsDebug==PR_TRUE)
printf (" 3c: col %d given %d proportion of remaining space %d, set to width = %d\n",
info->mColIndex, info->mProportion, widthRemaining, computedColWidth);
tableWidth += computedColWidth;
delete info;
}
delete proportionalColumnsList;
}
// post-process if necessary
/*
// if columns have equal width, and some column's content couldn't squeeze into the computed size,
// then expand every column to the min size of the column with the largest min size
if (equalWidthColumns && 0!=maxOfAllMinColWidths)
@ -946,6 +1082,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
mTableFrame->SetColumnWidth(colIndex, maxOfAllMinColWidths);
}
*/
if (nsnull!=spanList)
delete spanList;

View File

@ -124,13 +124,15 @@ public:
*
* @param aPresContext the presentation context
* @param aAvailWidth the remaining amount of horizontal space available
* @param aMaxWidth the total amount of horizontal space available
* @param aTableFixedWidth the specified width of the table. If there is none,
* this param is 0
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*/
virtual PRBool BalanceColumnsTableFits(nsIPresContext* aPresContext,
PRInt32 aAvailWidth,
nscoord aAvailWidth,
nscoord aMaxWidth,
nscoord aTableFixedWidth);
/** assign widths for each column that has proportional width inside a table that
@ -155,10 +157,11 @@ public:
PRInt32 aMinTableWidth,
PRInt32 aMaxTableWidth);
/** return true if the style indicates that the width is proportional
* for the purposes of column width determination
/** return true if the style indicates that the width is a specific width
* for the purposes of column width determination.
* return false if the width changes based on content, parent size, etc.
*/
virtual PRBool IsProportionalWidth(nsStylePosition* aStylePosition);
virtual PRBool IsFixedWidth(nsStylePosition* aStylePosition);
virtual PRBool IsAutoWidth(nsStylePosition* aStylePosition);

View File

@ -44,99 +44,6 @@ public:
PRInt32 &aMinTableWidth,
PRInt32 &aMaxTableWidth,
nsSize* aMaxElementSize)=0;
/** assign widths for each column that has fixed width.
* Computes the minimum and maximum table widths.
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
* @param aMaxWidth the maximum width of the table
* @param aNumCols the total number of columns in the table
* @param aTableStyle the resolved style for the table
* @param aTotalFixedWidth out param, the sum of the fixed width columns
* @param aMinTableWidth out param, the min possible table width
* @param aMaxTableWidth out param, the max table width
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*
* TODO: should be renamed to "AssignKnownWidthInformation
*/
virtual PRBool AssignFixedColumnWidths(nsIPresContext* aPresContext,
PRInt32 aMaxWidth,
PRInt32 aNumCols,
PRInt32 & aTotalFixedWidth,
PRInt32 & aMinTableWidth,
PRInt32 & aMaxTableWidth)=0;
/** assign widths for each column that has proportional width inside a table that
* has auto width (width set by the content and available space.)
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
* @param aTableStyle the resolved style for the table
* @param aAvailWidth the remaining amount of horizontal space available
* @param aMaxWidth the total amount of horizontal space available
* @param aMinTableWidth the min possible table width
* @param aMaxTableWidth the max table width
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*/
virtual PRBool BalanceProportionalColumns(nsIPresContext* aPresContext,
PRInt32 aAvailWidth,
PRInt32 aMaxWidth,
PRInt32 aMinTableWidth,
PRInt32 aMaxTableWidth,
nscoord aTableFixedWidth)=0;
/** assign the minimum allowed width for each column that has proportional width.
* Typically called when the min table width doesn't fit in the available space.
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*/
virtual PRBool SetColumnsToMinWidth(nsIPresContext* aPresContext)=0;
/** assign the maximum allowed width for each column that has proportional width.
* Typically called when the desired max table width fits in the available space.
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
* @param aTableStyle the resolved style for the table
* @param aAvailWidth the remaining amount of horizontal space available
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*/
virtual PRBool BalanceColumnsTableFits(nsIPresContext* aPresContext,
PRInt32 aAvailWidth,
nscoord aTableFixedWidth)=0;
/** assign widths for each column that has proportional width inside a table that
* has auto width (width set by the content and available space) according to the
* HTML 4 specification.
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
* @param aTableStyle the resolved style for the table
* @param aAvailWidth the remaining amount of horizontal space available
* @param aMaxWidth the total amount of horizontal space available
* @param aMinTableWidth the min possible table width
* @param aMaxTableWidth the max table width
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*
* TODO: rename this method to reflect that it is a Nav4 compatibility method
*/
virtual PRBool BalanceColumnsConstrained(nsIPresContext* aPresContext,
PRInt32 aAvailWidth,
PRInt32 aMaxWidth,
PRInt32 aMinTableWidth,
PRInt32 aMaxTableWidth)=0;
};
#endif

View File

@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsTableColFrame_h__
#define nsTableColFrame_h__
#include "nscore.h"
#include "nsContainerFrame.h"
class nsTableColFrame : public nsFrame {
public:
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
nsIContent* aContent,
nsIFrame* aParent);
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
NS_IMETHOD Reflow(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState,
nsReflowStatus& aStatus);
protected:
nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame);
~nsTableColFrame();
};
#endif

View File

@ -135,48 +135,52 @@ NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext* aPre
result = table->GetAttribute(nsHTMLAtoms::cols, value);
// if COLS is set, then map it into the COL frames
// chicken and egg problem here. I don't have any children yet, so I
// don't know how many columns there are, so I can't do this!
// I need to just set some state, and let the individual columns query up into me
// in their own hooks
PRInt32 numCols;
if (result == eContentAttr_NoValue)
ChildCount(numCols);
else if (result == eContentAttr_HasValue)
if (eContentAttr_NotThere != result)
{
nsHTMLUnit unit = value.GetUnit();
if (eHTMLUnit_Empty==unit)
PRInt32 numCols=0;
if (eContentAttr_NoValue == result)
ChildCount(numCols);
else
numCols = value.GetIntValue();
}
else if (eContentAttr_HasValue == result)
{
nsHTMLUnit unit = value.GetUnit();
if (eHTMLUnit_Empty==unit)
ChildCount(numCols);
else
numCols = value.GetIntValue();
}
PRInt32 colIndex=0;
nsIFrame *colFrame;
FirstChild(colFrame);
for (; colIndex<numCols; colIndex++)
{
if (nsnull==colFrame)
break; // the attribute value specified was greater than the actual number of columns
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
nsStyleCoord width (1, eStyleUnit_Proportional);
colPosition->mWidth = width;
colFrame->GetNextSibling(colFrame);
}
// if there are more columns, there width is set to "minimum"
PRInt32 numChildFrames;
ChildCount(numChildFrames);
for (; colIndex<numChildFrames; colIndex++)
{
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
nsStyleCoord width (0, eStyleUnit_Integer);
colPosition->mWidth = width;
colFrame->GetNextSibling(colFrame);
}
PRInt32 colIndex=0;
nsIFrame *colFrame=nsnull;
nsIStyleContext *colStyleContext;
for (; colIndex<numCols; colIndex++)
{
ChildAt(colIndex, colFrame);
if (nsnull==colFrame)
break; // the attribute value specified was greater than the actual number of columns
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
nsStyleCoord width (1, eStyleUnit_Proportional);
colPosition->mWidth = width;
colFrame->GetStyleContext(aPresContext, colStyleContext);
colStyleContext->RecalcAutomaticData(aPresContext);
}
// if there are more columns, there width is set to "minimum"
PRInt32 numChildFrames;
ChildCount(numChildFrames);
for (; colIndex<numChildFrames; colIndex++)
{
ChildAt(colIndex, colFrame);
NS_ASSERTION(nsnull!=colFrame, "bad first column frame");
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
nsStyleCoord width (0, eStyleUnit_Integer);
colPosition->mWidth = width;
colFrame->GetStyleContext(aPresContext, colStyleContext);
colStyleContext->RecalcAutomaticData(aPresContext);
}
mStyleContext->RecalcAutomaticData(aPresContext);
mStyleContext->RecalcAutomaticData(aPresContext);
}
return NS_OK;
}

View File

@ -630,40 +630,6 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext,
mLastContentIsComplete = PR_TRUE;
const PRInt32 contentType = ((nsTableContent *)(nsIContent*)kid)->GetType();
/*
if (contentType==nsITableContent::kTableColGroupType)
{
// Resolve style
nsIStyleContextPtr kidStyleContext =
aPresContext->ResolveStyleContextFor(kid, this);
NS_ASSERTION(kidStyleContext.IsNotNull(), "null style context for kid");
// SEC: TODO: when content is appended or deleted, be sure to clear out the frame hierarchy!!!!
// get next frame, creating one if needed
nsIFrame* kidFrame=nsnull;
if (nsnull!=prevKidFrame)
prevKidFrame->GetNextSibling(kidFrame); // no need to check for an error, just see if it returned null...
else
ChildAt(0, kidFrame);
// if this is the first time, allocate the frame
if (nsnull==kidFrame)
{
nsIContentDelegate* kidDel;
kidDel = kid->GetDelegate(aPresContext);
nsresult rv = kidDel->CreateFrame(aPresContext, kid,
this, kidStyleContext, kidFrame);
NS_RELEASE(kidDel);
}
// reflow the column group
nsReflowState kidReflowState(eReflowReason_Resize, availSize);
result = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState);
kidFrame->SetRect(0,0,0,0);
}
else */
//if (contentType==nsITableContent::kTableRowGroupType)
if (contentType!=nsITableContent::kTableCaptionType)
{
// Resolve style
@ -1983,6 +1949,7 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
nsTablePart * tablePart = (nsTablePart *)mContent;
PRInt32 cols = tablePart->GetMaxColumns();
PRInt32 tableKidCount = tablePart->ChildCount();
nsIFrame * colGroupFrame = mFirstChild;
for (PRInt32 i=0; i<tableKidCount; i++)
{
nsTableContentPtr tableKid = (nsTableContent *)tablePart->ChildAt(i);
@ -1996,6 +1963,9 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
nsTableColPtr col = (nsTableCol *)tableKid->ChildAt(j);
NS_ASSERTION(col.IsNotNull(), "bad content");
nsColLayoutData *colData = new nsColLayoutData(col);
nsTableColFrame *colFrame=nsnull;
colGroupFrame->ChildAt(j, (nsIFrame *&)colFrame);
colData->SetColFrame(colFrame);
mColumnLayoutData->AppendElement((void *)colData);
}
}
@ -2004,6 +1974,7 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
{
break;
}
ChildAt(i, colGroupFrame); // can't use colGroupFrame->GetNextSibling because it hasn't been set yet
}
}

View File

@ -129,15 +129,14 @@ public:
* DEBUG METHOD
*
*/
void ListColumnLayoutData(FILE* out = stdout, PRInt32 aIndent = 0) const;
virtual void ListColumnLayoutData(FILE* out = stdout, PRInt32 aIndent = 0) const;
/** return the width of the column at aColIndex */
PRInt32 GetColumnWidth(PRInt32 aColIndex);
virtual PRInt32 GetColumnWidth(PRInt32 aColIndex);
/** set the width of the column at aColIndex to aWidth */
void SetColumnWidth(PRInt32 aColIndex, PRInt32 aWidth);
virtual void SetColumnWidth(PRInt32 aColIndex, PRInt32 aWidth);
/**
* Calculate Layout Information