mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
cell width calculations are working (not for colspan cells yet)
some bug fixes and optimizations some of the more elaborate test cases are closer to Nav4-compatible
This commit is contained in:
parent
6c6643b04c
commit
07076ff7cf
@ -118,6 +118,7 @@ A:visited IMG { border: 2px solid purple; text-decoration: underline }
|
||||
A:active IMG { border: 2px solid lime; text-decoration: underline }
|
||||
A:out-of-date IMG { border: 2px solid red; text-decoration: underline }
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// The real stuff
|
||||
|
||||
|
@ -116,112 +116,6 @@ PRBool BasicTableLayoutStrategy::IsAutoWidth(nsStylePosition* aStylePosition)
|
||||
}
|
||||
|
||||
|
||||
// aSpecifiedTableWidth is filled if the table witdth is not auto
|
||||
PRBool BasicTableLayoutStrategy::TableIsAutoWidth(nsIStyleContext *aTableStyle,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord& aSpecifiedTableWidth)
|
||||
{
|
||||
NS_ASSERTION(nsnull!=aTableStyle, "bad arg - aTableStyle");
|
||||
PRBool result = PR_TRUE; // the default
|
||||
if (nsnull!=aTableStyle)
|
||||
{
|
||||
//nsStylePosition* tablePosition = (nsStylePosition*)aTableStyle->GetData(eStyleStruct_Position);
|
||||
/* this is sick and wrong, but what the hell
|
||||
we grab the style of our parent (nsTableOuterFrame) and ask it for width info,
|
||||
until the style resolution stuff does the cool stuff about splitting style between outer and inner
|
||||
*/
|
||||
// begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED!
|
||||
nsIStyleContext* parentStyle = nsnull;
|
||||
nsIFrame * parent = nsnull;
|
||||
mTableFrame->GetGeometricParent(parent);
|
||||
parent->GetStyleContext(nsnull, parentStyle);
|
||||
nsStylePosition* tablePosition = (nsStylePosition*)parentStyle->GetData(eStyleStruct_Position);
|
||||
// end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED!
|
||||
switch (tablePosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Auto: // specified auto width
|
||||
case eStyleUnit_Proportional: // illegal for table, so ignored
|
||||
break;
|
||||
|
||||
case eStyleUnit_Inherit:
|
||||
// get width of parent and see if it is a specified value or not
|
||||
// XXX for now, just return true
|
||||
break;
|
||||
|
||||
case eStyleUnit_Coord:
|
||||
aSpecifiedTableWidth = tablePosition->mWidth.GetCoordValue();
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
#ifdef STEVES_WAY
|
||||
case eStyleUnit_Percent:
|
||||
// get the parent's width (available only from parent frames that claim they can provide it)
|
||||
// note that we start with our parent's parent (the outer table frame's parent)
|
||||
nscoord parentWidth = 0;
|
||||
NS_ASSERTION(nsnull!=aReflowState.parentReflowState, "bad outer table reflow state.");
|
||||
NS_ASSERTION(nsnull!=aReflowState.parentReflowState->parentReflowState, "bad table parent reflow state.");
|
||||
if ((nsnull!=aReflowState.parentReflowState) &&
|
||||
(nsnull!=aReflowState.parentReflowState->parentReflowState))
|
||||
{
|
||||
const nsReflowState *parentReflowState = aReflowState.parentReflowState->parentReflowState;
|
||||
nsIFrame *parentFrame=parentReflowState->frame;
|
||||
NS_ASSERTION(nsnull!=parentFrame, "bad parent frame in reflow state struct.");
|
||||
while(nsnull!=parentFrame)
|
||||
{
|
||||
PRBool isPercentageBase=PR_FALSE;
|
||||
parentFrame->IsPercentageBase(isPercentageBase);
|
||||
if (PR_TRUE==isPercentageBase)
|
||||
{ // found the ancestor who claims to be the container to base my percentage width on
|
||||
parentWidth = parentReflowState->maxSize.width;
|
||||
if (PR_TRUE==gsDebug) printf(" ** width for parent frame %p = %d\n", parentFrame, parentWidth);
|
||||
break;
|
||||
}
|
||||
parentReflowState = parentReflowState->parentReflowState; // get next ancestor
|
||||
if (nsnull!=parentReflowState)
|
||||
parentFrame = parentReflowState->frame;
|
||||
else
|
||||
parentFrame = nsnull; // terminates loop.
|
||||
// TODO: do we need a backstop in case there are no IsPercentageBase==true frames?
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
case eStyleUnit_Percent:
|
||||
// Get the parent's width (available only from parent frames
|
||||
// that claim they can provide it, and assuming it's already
|
||||
// specified; that is, top-down layout sets the widths on the
|
||||
// way down.)
|
||||
nscoord parentWidth = aReflowState.maxSize.width;
|
||||
|
||||
// Walk up the reflow state chain until we find a block
|
||||
// frame. Our width is computed relative to there.
|
||||
const nsReflowState* rs = &aReflowState;
|
||||
while (nsnull != rs) {
|
||||
nsIFrame* block = nsnull;
|
||||
rs->frame->QueryInterface(kBlockFrameCID, (void**) &block);
|
||||
if (nsnull != block) {
|
||||
// We found the nearest containing block which defines what
|
||||
// a percentage size is relative to. Use the width that it
|
||||
// will reflow to as the basis for computing our width.
|
||||
parentWidth = rs->maxSize.width;
|
||||
break;
|
||||
}
|
||||
rs = rs->parentReflowState;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// set aSpecifiedTableWidth to be the given percent of the parent.
|
||||
float percent = tablePosition->mWidth.GetPercentValue();
|
||||
aSpecifiedTableWidth = (PRInt32)(parentWidth*percent);
|
||||
if (PR_TRUE==gsDebug) printf(" ** aSpecifiedTableWidth = %d\n", aSpecifiedTableWidth);
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame)
|
||||
{
|
||||
mTableFrame = aFrame;
|
||||
@ -260,12 +154,12 @@ PRBool BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresContex
|
||||
// Step 2 - determine how much space is really available
|
||||
PRInt32 availWidth = aMaxWidth - aTotalFixedWidth;
|
||||
nscoord tableWidth = 0;
|
||||
if (PR_FALSE==TableIsAutoWidth(aTableStyle, aReflowState, tableWidth))
|
||||
if (PR_FALSE==nsTableFrame::TableIsAutoWidth(mTableFrame, aTableStyle, aReflowState, tableWidth))
|
||||
availWidth = tableWidth - aTotalFixedWidth;
|
||||
|
||||
// Step 3 - assign the width of all proportional-width columns in the remaining space
|
||||
if (gsDebug==PR_TRUE) printf ("Step 2...\n availWidth = %d\n", availWidth);
|
||||
result = BalanceProportionalColumns(aPresContext,
|
||||
result = BalanceProportionalColumns(aPresContext, aReflowState,
|
||||
availWidth, aMaxWidth,
|
||||
aMinTableWidth, aMaxTableWidth,
|
||||
tableWidth);
|
||||
@ -525,6 +419,7 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
||||
|
||||
|
||||
PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPresContext,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord aAvailWidth,
|
||||
nscoord aMaxWidth,
|
||||
nscoord aMinTableWidth,
|
||||
@ -538,7 +433,7 @@ PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPre
|
||||
if (NS_UNCONSTRAINEDSIZE==aMaxWidth || NS_UNCONSTRAINEDSIZE==aMinTableWidth)
|
||||
{ // 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, aMaxWidth, aTableFixedWidth);
|
||||
result = BalanceColumnsTableFits(aPresContext, aReflowState, aAvailWidth, aMaxWidth, aTableFixedWidth);
|
||||
}
|
||||
else if (aMinTableWidth > aMaxWidth)
|
||||
{ // the table doesn't fit in the available space
|
||||
@ -548,7 +443,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, aMaxWidth, aTableFixedWidth);
|
||||
result = BalanceColumnsTableFits(aPresContext, aReflowState, aAvailWidth, aMaxWidth, aTableFixedWidth);
|
||||
}
|
||||
else
|
||||
{ // the table fits somewhere between its min and desired size
|
||||
@ -562,7 +457,7 @@ PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPre
|
||||
if (NS_UNCONSTRAINEDSIZE==aMinTableWidth)
|
||||
{ // the table has empty content, and needs to be streched to the specified width
|
||||
if (gsDebug) printf (" * specified width table > maxTableWidth, calling BalanceColumnsTableFits\n");
|
||||
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aMaxWidth, aTableFixedWidth);
|
||||
result = BalanceColumnsTableFits(aPresContext, aReflowState, aAvailWidth, aMaxWidth, aTableFixedWidth);
|
||||
}
|
||||
else if (aTableFixedWidth<aMinTableWidth)
|
||||
{ // the table's specified width doesn't fit in the available space
|
||||
@ -579,7 +474,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, aMaxWidth, aTableFixedWidth);
|
||||
result = BalanceColumnsTableFits(aPresContext, aReflowState, aAvailWidth, aMaxWidth, aTableFixedWidth);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -639,7 +534,8 @@ PRBool BasicTableLayoutStrategy::SetColumnsToMinWidth(nsIPresContext* aPresConte
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresContext,
|
||||
PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresContext,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord aAvailWidth,
|
||||
nscoord aMaxWidth,
|
||||
nscoord aTableFixedWidth)
|
||||
@ -652,7 +548,6 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
|
||||
PRBool result = PR_TRUE;
|
||||
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
|
||||
@ -675,10 +570,11 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
nsIStyleContextPtr colSC;
|
||||
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
|
||||
nsStylePosition* colPosition = (nsStylePosition*) colSC->GetData(eStyleStruct_Position);
|
||||
if (gsDebug) printf("col %d has frame %p with style %p and pos %p\n",
|
||||
colIndex, colFrame, (nsIStyleContext *)colSC, colPosition);
|
||||
|
||||
if (PR_FALSE==IsFixedWidth(colPosition))
|
||||
{
|
||||
numProportionalColumns++;
|
||||
// first, deal with any cells that span into this column from a pervious column
|
||||
if (nsnull!=spanList)
|
||||
{
|
||||
@ -720,7 +616,48 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
nsresult result = data->GetMargin(margin);
|
||||
nscoord marginWidth = margin.left + margin.right;
|
||||
PRInt32 cellMinWidth = cellMinSize->width/colSpan + marginWidth;
|
||||
PRInt32 cellDesiredWidth = cellDesiredSize->width/colSpan + marginWidth;
|
||||
// first get the desired size info from reflow pass 1
|
||||
PRInt32 cellDesiredWidth = cellDesiredSize->width/colSpan + marginWidth;
|
||||
// then get the desired size info factoring in the cell style attributes
|
||||
nscoord specifiedCellWidth=-1;
|
||||
nsIStyleContextPtr cellSC;
|
||||
data->GetCellFrame()->GetStyleContext(aPresContext, cellSC.AssignRef());
|
||||
nsStylePosition* cellPosition = (nsStylePosition*)
|
||||
cellSC->GetData(eStyleStruct_Position);
|
||||
switch (cellPosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
specifiedCellWidth = cellPosition->mWidth.GetCoordValue();
|
||||
if (gsDebug) printf("cell has specified coord width = %d\n", specifiedCellWidth);
|
||||
break;
|
||||
|
||||
case eStyleUnit_Percent:
|
||||
{
|
||||
nscoord tableWidth=0;
|
||||
nsIStyleContextPtr tableSC;
|
||||
mTableFrame->GetStyleContext(aPresContext, tableSC.AssignRef());
|
||||
PRBool tableIsAutoWidth = nsTableFrame::TableIsAutoWidth(mTableFrame, tableSC, aReflowState, tableWidth);
|
||||
float percent = cellPosition->mWidth.GetPercentValue();
|
||||
specifiedCellWidth = (PRInt32)(tableWidth*percent);
|
||||
if (gsDebug) printf("specified percent width %f of %d = %d\n",
|
||||
percent, tableWidth, specifiedCellWidth);
|
||||
break;
|
||||
}
|
||||
|
||||
case eStyleUnit_Inherit:
|
||||
// XXX for now, do nothing
|
||||
default:
|
||||
case eStyleUnit_Auto:
|
||||
break;
|
||||
}
|
||||
if (-1!=specifiedCellWidth)
|
||||
{
|
||||
if (specifiedCellWidth>cellMinWidth)
|
||||
{
|
||||
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
|
||||
cellDesiredWidth, specifiedCellWidth);
|
||||
cellDesiredWidth = specifiedCellWidth; // TODO: some math needed here for colspans
|
||||
}
|
||||
}
|
||||
|
||||
if (PR_TRUE==gsDebug)
|
||||
printf("factoring in cell %d with colSpan=%d\n factoring in min=%d and desired=%d\n",
|
||||
@ -750,15 +687,22 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
}
|
||||
|
||||
// Get column width if it has one
|
||||
nscoord specifiedProportion = -1;
|
||||
nscoord specifiedProportionColumnWidth = -1;
|
||||
float specifiedPercentageColWidth = -1.0f;
|
||||
nscoord specifiedFixedColumnWidth = -1;
|
||||
PRBool isAutoWidth = PR_FALSE;
|
||||
switch (colPosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
specifiedFixedColumnWidth = colPosition->mWidth.GetCoordValue();
|
||||
if (gsDebug) printf("column %d has specified coord width = %d\n", colIndex, specifiedFixedColumnWidth);
|
||||
break;
|
||||
case eStyleUnit_Percent:
|
||||
specifiedPercentageColWidth = colPosition->mWidth.GetPercentValue();
|
||||
if (gsDebug) printf("column %d has specified percent width = %f\n", colIndex, specifiedPercentageColWidth);
|
||||
break;
|
||||
case eStyleUnit_Proportional:
|
||||
specifiedProportion = colPosition->mWidth.GetIntValue();
|
||||
specifiedProportionColumnWidth = colPosition->mWidth.GetIntValue();
|
||||
if (gsDebug) printf("column %d has specified percent width = %d\n", colIndex, specifiedProportionColumnWidth);
|
||||
break;
|
||||
case eStyleUnit_Auto:
|
||||
isAutoWidth = PR_TRUE;
|
||||
@ -768,11 +712,11 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
}
|
||||
|
||||
/* set the column width, knowing that the table fits in the available space */
|
||||
if (0==specifiedProportion || 0.0==specifiedPercentageColWidth)
|
||||
if (0==specifiedProportionColumnWidth || 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",
|
||||
printf (" 3 min: col %d set to min width = %d because style set proportionalWidth=0\n",
|
||||
colIndex, mTableFrame->GetColumnWidth(colIndex));
|
||||
}
|
||||
else if (PR_TRUE==isAutoWidth)
|
||||
@ -781,10 +725,10 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
// 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",
|
||||
printf (" 3 auto: col %d with availWidth %d, set to width = %d\n",
|
||||
colIndex, aAvailWidth, mTableFrame->GetColumnWidth(colIndex));
|
||||
}
|
||||
else if (0!=specifiedProportion)
|
||||
else if (-1!=specifiedProportionColumnWidth)
|
||||
{ // 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
|
||||
@ -798,9 +742,23 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
if (nsnull==proportionalColumnsList)
|
||||
proportionalColumnsList = new nsVoidArray();
|
||||
ProportionalColumnLayoutStruct * info =
|
||||
new ProportionalColumnLayoutStruct(colIndex, minColWidth, maxColWidth, specifiedProportion);
|
||||
new ProportionalColumnLayoutStruct(colIndex, minColWidth,
|
||||
maxColWidth, specifiedProportionColumnWidth);
|
||||
proportionalColumnsList->AppendElement(info);
|
||||
totalSlices += specifiedProportion;
|
||||
totalSlices += specifiedProportionColumnWidth; // keep track of the total number of proportions
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf (" 3 proportional: col %d with availWidth %d, gets %d slices with %d slices so far.\n",
|
||||
colIndex, aAvailWidth, specifiedProportionColumnWidth, totalSlices);
|
||||
}
|
||||
else if (-1!=specifiedFixedColumnWidth)
|
||||
{
|
||||
// if the column was computed to be too small, enlarge the column
|
||||
nscoord resolvedWidth = specifiedFixedColumnWidth;
|
||||
if (specifiedFixedColumnWidth <= minColWidth)
|
||||
resolvedWidth = minColWidth;
|
||||
mTableFrame->SetColumnWidth(colIndex, resolvedWidth);
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf (" 3 fixed: col %d given %d\n", colIndex, resolvedWidth);
|
||||
}
|
||||
else
|
||||
{ // give each remaining column a percentage of the remaining space
|
||||
@ -816,14 +774,14 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
if (-1==percentage)
|
||||
percentage = 100/numCols;
|
||||
// base the % on the total max width
|
||||
mTableFrame->SetColumnWidth(colIndex, (percentage*aMaxWidth)/100);
|
||||
mTableFrame->SetColumnWidth(colIndex, (percentage*aAvailWidth)/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 aMaxWidth %d, set to width = %d\n",
|
||||
colIndex, percentage, aMaxWidth, mTableFrame->GetColumnWidth(colIndex));
|
||||
printf (" 3 percent: col %d given %d percent of aAvailWidth %d, set to width = %d\n",
|
||||
colIndex, percentage, aAvailWidth, mTableFrame->GetColumnWidth(colIndex));
|
||||
}
|
||||
}
|
||||
tableWidth += mTableFrame->GetColumnWidth(colIndex);
|
||||
@ -845,7 +803,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
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",
|
||||
printf (" 3 proportional step 2: col %d given %d proportion of remaining space %d, set to width = %d\n",
|
||||
info->mColIndex, info->mProportion, widthRemaining, computedColWidth);
|
||||
tableWidth += computedColWidth;
|
||||
delete info;
|
||||
@ -859,26 +817,34 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
if (aTableFixedWidth > tableWidth)
|
||||
{
|
||||
nscoord excess = aTableFixedWidth - tableWidth;
|
||||
// if there are proportionally-sized columns, give them the extra space
|
||||
if (0!=numProportionalColumns)
|
||||
if (gsDebug) printf ("fixed width %d > computed table width %d, excess = %d\n",
|
||||
aTableFixedWidth, tableWidth, excess);
|
||||
// if there are auto-sized columns, give them the extra space
|
||||
PRInt32 numAutoColumns;
|
||||
PRInt32 *autoColumns;
|
||||
mTableFrame->GetColumnsByType(eStyleUnit_Auto, numAutoColumns, autoColumns);
|
||||
if (0!=numAutoColumns)
|
||||
{
|
||||
nscoord excessPerColumn = excess/numProportionalColumns;
|
||||
if (gsDebug==PR_TRUE) printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess);
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
// TODO - should extra space be proportionately distributed?
|
||||
nscoord excessPerColumn = excess/numAutoColumns;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess);
|
||||
for (PRInt32 i = 0; i<numAutoColumns; i++)
|
||||
{
|
||||
// need the column style here!
|
||||
if (PR_FALSE==IsFixedWidth(nsnull))
|
||||
{
|
||||
nscoord colWidth = excessPerColumn+mTableFrame->GetColumnWidth(colIndex);
|
||||
mTableFrame->SetColumnWidth(colIndex, colWidth);
|
||||
}
|
||||
PRInt32 colIndex = autoColumns[i];
|
||||
nscoord colWidth = excessPerColumn+mTableFrame->GetColumnWidth(colIndex);
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" column %d was %d, now set to %d\n", colIndex, mTableFrame->GetColumnWidth(colIndex), colWidth);
|
||||
mTableFrame->SetColumnWidth(colIndex, colWidth);
|
||||
}
|
||||
}
|
||||
// otherwise, distribute the space evenly between all the columns
|
||||
// otherwise, distribute the space evenly between all the columns (they must be all fixed and percentage-width columns)
|
||||
// TODO - should extra space be proportionately distributed?
|
||||
else
|
||||
{
|
||||
nscoord excessPerColumn = excess/numCols;
|
||||
if (gsDebug==PR_TRUE) printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess);
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess);
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
{
|
||||
nscoord colWidth = excessPerColumn+mTableFrame->GetColumnWidth(colIndex);
|
||||
@ -907,7 +873,6 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
||||
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=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
|
||||
PRBool equalWidthColumns = PR_TRUE; // remember if we're in the special case where all
|
||||
|
@ -103,6 +103,7 @@ public:
|
||||
*
|
||||
*/
|
||||
virtual PRBool BalanceProportionalColumns(nsIPresContext* aPresContext,
|
||||
const nsReflowState& aReflowState,
|
||||
PRInt32 aAvailWidth,
|
||||
PRInt32 aMaxWidth,
|
||||
PRInt32 aMinTableWidth,
|
||||
@ -132,6 +133,7 @@ public:
|
||||
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
|
||||
*/
|
||||
virtual PRBool BalanceColumnsTableFits(nsIPresContext* aPresContext,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord aAvailWidth,
|
||||
nscoord aMaxWidth,
|
||||
nscoord aTableFixedWidth);
|
||||
@ -166,10 +168,6 @@ public:
|
||||
|
||||
virtual PRBool IsAutoWidth(nsStylePosition* aStylePosition);
|
||||
|
||||
virtual PRBool TableIsAutoWidth(nsIStyleContext *aTableStyle,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord& aSpecifiedTableWidth);
|
||||
|
||||
protected:
|
||||
nsTableFrame * mTableFrame;
|
||||
|
||||
|
@ -160,6 +160,11 @@ void nsTableCell::SetAttribute(nsIAtom* aAttribute, const nsString& aValue)
|
||||
nsHTMLTagContent::SetAttribute(aAttribute, val);
|
||||
return;
|
||||
}
|
||||
if ((aAttribute == nsHTMLAtoms::valign) &&
|
||||
ParseAlignParam(aValue, val)) {
|
||||
nsHTMLTagContent::SetAttribute(aAttribute, val);
|
||||
return;
|
||||
}
|
||||
if (aAttribute == nsHTMLAtoms::background) {
|
||||
nsAutoString href(aValue);
|
||||
href.StripWhitespace();
|
||||
@ -191,6 +196,11 @@ void nsTableCell::SetAttribute(nsIAtom* aAttribute, const nsString& aValue)
|
||||
nsHTMLTagContent::SetAttribute(aAttribute, val);
|
||||
return;
|
||||
}
|
||||
if (aAttribute == nsHTMLAtoms::nowrap) {
|
||||
val.SetEmptyValue();
|
||||
nsHTMLTagContent::SetAttribute(aAttribute, val);
|
||||
return;
|
||||
}
|
||||
// Use default attribute catching code
|
||||
nsTableContent::SetAttribute(aAttribute, aValue);
|
||||
}
|
||||
@ -212,6 +222,15 @@ void nsTableCell::MapAttributesInto(nsIStyleContext* aContext,
|
||||
nsStyleText* text = (nsStyleText*)aContext->GetData(eStyleStruct_Text);
|
||||
text->mTextAlign = value.GetIntValue();
|
||||
}
|
||||
|
||||
// valign: enum
|
||||
GetAttribute(nsHTMLAtoms::valign, value);
|
||||
if (value.GetUnit() == eHTMLUnit_Enumerated)
|
||||
{
|
||||
nsStyleText* text = (nsStyleText*)aContext->GetData(eStyleStruct_Text);
|
||||
text->mTextAlign = value.GetIntValue();
|
||||
}
|
||||
|
||||
MapBackgroundAttributesInto(aContext, aPresContext);
|
||||
|
||||
// width: pixel
|
||||
@ -223,6 +242,9 @@ void nsTableCell::MapAttributesInto(nsIStyleContext* aContext,
|
||||
nscoord twips = nscoord(p2t * value.GetPixelValue());
|
||||
pos->mWidth.SetCoordValue(twips);
|
||||
}
|
||||
else if (value.GetUnit() == eHTMLUnit_Percent) {
|
||||
pos->mWidth.SetPercentValue(value.GetPercentValue());
|
||||
}
|
||||
|
||||
// height: pixel
|
||||
GetAttribute(nsHTMLAtoms::height, value);
|
||||
|
@ -27,8 +27,12 @@
|
||||
#include "nsIContentDelegate.h"
|
||||
#include "nsCSSLayout.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsIPtr.h"
|
||||
#include "nsIView.h"
|
||||
|
||||
NS_DEF_PTR(nsIStyleContext);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gsDebug = PR_FALSE;
|
||||
//#define NOISY_STYLE
|
||||
@ -297,6 +301,42 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
CreatePsuedoFrame(aPresContext);
|
||||
}
|
||||
|
||||
// Determine the width we have to work with
|
||||
nscoord cellWidth = -1;
|
||||
if (NS_UNCONSTRAINEDSIZE!=availSize.width)
|
||||
{
|
||||
/*
|
||||
nsStylePosition* kidPosition = (nsStylePosition*)
|
||||
mStyleContext->GetData(eStyleStruct_Position);
|
||||
switch (kidPosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
cellWidth = kidPosition->mWidth.GetCoordValue();
|
||||
break;
|
||||
|
||||
case eStyleUnit_Percent:
|
||||
{
|
||||
nscoord tableWidth=0;
|
||||
const nsReflowState *tableReflowState = aReflowState.parentReflowState->parentReflowState->parentReflowState;
|
||||
nsTableFrame *tableFrame = (nsTableFrame *)(tableReflowState->frame);
|
||||
nsIStyleContextPtr tableSC;
|
||||
tableFrame->GetStyleContext(aPresContext, tableSC.AssignRef());
|
||||
PRBool tableIsAutoWidth = nsTableFrame::TableIsAutoWidth(tableFrame, tableSC, *tableReflowState, tableWidth);
|
||||
float percent = kidPosition->mWidth.GetPercentValue();
|
||||
cellWidth = (PRInt32)(tableWidth*percent);
|
||||
break;
|
||||
}
|
||||
|
||||
case eStyleUnit_Inherit:
|
||||
// XXX for now, do nothing
|
||||
default:
|
||||
case eStyleUnit_Auto:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
if (-1!=cellWidth)
|
||||
availSize.width = cellWidth;
|
||||
}
|
||||
|
||||
// Try to reflow the child into the available space. It might not
|
||||
// fit or might need continuing.
|
||||
if (availSize.height < 0)
|
||||
@ -325,14 +365,13 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
SetFirstContentOffset(mFirstChild);
|
||||
if (gsDebug) printf("CELL: set first content offset to %d\n", GetFirstContentOffset()); //@@@
|
||||
//if (gsDebug) printf("CELL: set first content offset to %d\n", GetFirstContentOffset()); //@@@
|
||||
SetLastContentOffset(mFirstChild);
|
||||
if (gsDebug) printf("CELL: set last content offset to %d\n", GetLastContentOffset()); //@@@
|
||||
//if (gsDebug) printf("CELL: set last content offset to %d\n", GetLastContentOffset()); //@@@
|
||||
|
||||
// Place the child since some of it's content fit in us.
|
||||
// Place the child
|
||||
mFirstChild->SetRect(nsRect(leftInset, topInset,
|
||||
kidSize.width, kidSize.height));
|
||||
|
||||
kidSize.width, kidSize.height));
|
||||
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||
// If the child didn't finish layout then it means that it used
|
||||
@ -341,19 +380,22 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
// Return our size and our result
|
||||
PRInt32 kidWidth = kidSize.width;
|
||||
if (NS_UNCONSTRAINEDSIZE!=kidSize.width) //&& NS_UNCONSTRAINEDSIZE!=aMaxSize.width)
|
||||
kidWidth += leftInset + rightInset;
|
||||
PRInt32 kidHeight = kidSize.height;
|
||||
|
||||
// height can be set w/o being restricted by aMaxSize.height
|
||||
if (NS_UNCONSTRAINEDSIZE!=kidSize.height)
|
||||
kidHeight += topInset + bottomInset;
|
||||
aDesiredSize.width = kidWidth;
|
||||
aDesiredSize.height = kidHeight;
|
||||
// first, compute the height
|
||||
// the height can be set w/o being restricted by aMaxSize.height
|
||||
nscoord cellHeight = kidSize.height;
|
||||
if (NS_UNCONSTRAINEDSIZE!=cellHeight)
|
||||
cellHeight += topInset + bottomInset;
|
||||
// next determine the cell's width
|
||||
cellWidth = kidSize.width; // at this point, we've factored in the cell's style attributes
|
||||
if (NS_UNCONSTRAINEDSIZE!=cellWidth)
|
||||
cellWidth += leftInset + rightInset;
|
||||
|
||||
// set the cell's desired size and max element size
|
||||
aDesiredSize.width = cellWidth;
|
||||
aDesiredSize.height = cellHeight;
|
||||
aDesiredSize.ascent = topInset;
|
||||
aDesiredSize.descent = bottomInset;
|
||||
|
||||
if (nsnull!=aDesiredSize.maxElementSize)
|
||||
{
|
||||
*aDesiredSize.maxElementSize = *pMaxElementSize;
|
||||
|
@ -36,7 +36,11 @@ static const PRBool gsDebug = PR_FALSE;
|
||||
static const PRBool gsNoisyRefs = PR_FALSE;
|
||||
#endif
|
||||
|
||||
|
||||
// hack, remove when hack in nsTableCol constructor is removed
|
||||
static PRInt32 HACKcounter=0;
|
||||
static nsIAtom *HACKattribute=nsnull;
|
||||
#include "prprf.h" // remove when nsTableCol constructor hack is removed
|
||||
// end hack code
|
||||
|
||||
nsTableColFrame::nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame)
|
||||
: nsFrame(aContent, aParentFrame)
|
||||
@ -75,6 +79,17 @@ NS_METHOD nsTableColFrame::Reflow(nsIPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt32 nsTableColFrame::GetColumnIndex()
|
||||
{
|
||||
if (nsnull!=mContent)
|
||||
return ((nsTableCol *)mContent)->GetColumnIndex();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ----- static methods ------ */
|
||||
|
||||
nsresult nsTableColFrame::NewFrame(nsIFrame** aInstancePtrResult,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent)
|
||||
@ -99,6 +114,7 @@ nsTableCol::nsTableCol(nsIAtom* aTag)
|
||||
mColIndex(0),
|
||||
mRepeat(0)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
nsTableCol::nsTableCol()
|
||||
@ -107,6 +123,7 @@ nsTableCol::nsTableCol()
|
||||
mColIndex(0),
|
||||
mRepeat(0)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
nsTableCol::nsTableCol (PRBool aImplicit)
|
||||
@ -116,6 +133,22 @@ nsTableCol::nsTableCol (PRBool aImplicit)
|
||||
mRepeat(0)
|
||||
{
|
||||
mImplicit = aImplicit;
|
||||
Init();
|
||||
}
|
||||
|
||||
void nsTableCol::Init()
|
||||
{
|
||||
/* begin hack */
|
||||
// temporary hack to get around style sheet optimization that folds all
|
||||
// col style context into one, unless there is a unique HTML attribute set
|
||||
char out[40];
|
||||
PR_snprintf(out, 40, "%d", HACKcounter);
|
||||
const nsString value(out);
|
||||
if (nsnull==HACKattribute)
|
||||
HACKattribute = NS_NewAtom("Steve's unbelievable hack attribute");
|
||||
SetAttribute(HACKattribute, value);
|
||||
HACKcounter++;
|
||||
/* end hack */
|
||||
}
|
||||
|
||||
nsTableCol::~nsTableCol()
|
||||
|
@ -105,6 +105,9 @@ public:
|
||||
|
||||
virtual void ResetColumns ();
|
||||
|
||||
private:
|
||||
void Init();
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@ -37,6 +37,9 @@ public:
|
||||
const nsReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
/** return the index of the column this content object represents. always >= 0 */
|
||||
virtual int GetColumnIndex ();
|
||||
|
||||
protected:
|
||||
|
||||
nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame);
|
||||
|
@ -35,6 +35,12 @@ static const PRBool gsDebug = PR_FALSE;
|
||||
static const PRBool gsNoisyRefs = PR_FALSE;
|
||||
#endif
|
||||
|
||||
// hack, remove when hack in nsTableCol constructor is removed
|
||||
static PRInt32 HACKcounter=0;
|
||||
static nsIAtom *HACKattribute=nsnull;
|
||||
#include "prprf.h" // remove when nsTableCol constructor hack is removed
|
||||
// end hack code
|
||||
|
||||
|
||||
nsTableColGroup::nsTableColGroup(nsIAtom* aTag, int aSpan)
|
||||
: nsTableContent(aTag),
|
||||
@ -42,6 +48,17 @@ nsTableColGroup::nsTableColGroup(nsIAtom* aTag, int aSpan)
|
||||
mStartColIndex(0),
|
||||
mColCount(0)
|
||||
{
|
||||
/* begin hack */
|
||||
// temporary hack to get around style sheet optimization that folds all
|
||||
// col style context into one, unless there is a unique HTML attribute set
|
||||
char out[40];
|
||||
PR_snprintf(out, 40, "%d", HACKcounter);
|
||||
const nsString value(out);
|
||||
if (nsnull==HACKattribute)
|
||||
HACKattribute = NS_NewAtom("Steve's unbelievable hack attribute");
|
||||
SetAttribute(HACKattribute, value);
|
||||
HACKcounter++;
|
||||
/* end hack */
|
||||
}
|
||||
|
||||
nsTableColGroup::nsTableColGroup (PRBool aImplicit)
|
||||
@ -51,6 +68,17 @@ nsTableColGroup::nsTableColGroup (PRBool aImplicit)
|
||||
mColCount(0)
|
||||
{
|
||||
mImplicit = aImplicit;
|
||||
/* begin hack */
|
||||
// temporary hack to get around style sheet optimization that folds all
|
||||
// col style context into one, unless there is a unique HTML attribute set
|
||||
char out[40];
|
||||
PR_snprintf(out, 40, "%d", HACKcounter);
|
||||
const nsString value(out);
|
||||
if (nsnull==HACKattribute)
|
||||
HACKattribute = NS_NewAtom("Steve's unbelievable hack attribute");
|
||||
SetAttribute(HACKattribute, value);
|
||||
HACKcounter++;
|
||||
/* end hack */
|
||||
}
|
||||
|
||||
|
||||
@ -163,7 +191,7 @@ nsTableColGroup::AppendChild (nsIContent *aContent, PRBool aNotify)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool result = PR_FALSE;
|
||||
nsresult result = NS_ERROR_FAILURE;
|
||||
PRBool contentHandled = PR_FALSE;
|
||||
// SEC: TODO verify that aContent is table content
|
||||
nsTableContent *tableContent = (nsTableContent *)aContent;
|
||||
@ -188,9 +216,10 @@ nsTableColGroup::AppendChild (nsIContent *aContent, PRBool aNotify)
|
||||
}
|
||||
if (PR_FALSE==contentHandled)
|
||||
result = nsTableContent::AppendChild (aContent, aNotify);
|
||||
if (result)
|
||||
if (NS_OK==result)
|
||||
{
|
||||
((nsTableCol *)aContent)->SetColGroup (this);
|
||||
((nsTableCol *)aContent)->SetColumnIndex (mStartColIndex + mColCount);
|
||||
ResetColumns ();
|
||||
}
|
||||
|
||||
@ -214,8 +243,8 @@ nsTableColGroup::InsertChildAt (nsIContent *aContent, PRInt32 aIndex,
|
||||
}
|
||||
|
||||
// if so, add the row to this group
|
||||
PRBool result = nsTableContent::InsertChildAt (aContent, aIndex, aNotify);
|
||||
if (result)
|
||||
nsresult result = nsTableContent::InsertChildAt (aContent, aIndex, aNotify);
|
||||
if (NS_OK==result)
|
||||
{
|
||||
((nsTableCol *)aContent)->SetColGroup (this);
|
||||
ResetColumns ();
|
||||
@ -245,8 +274,8 @@ nsTableColGroup::ReplaceChildAt (nsIContent * aContent, PRInt32 aIndex,
|
||||
|
||||
nsIContent * lastChild = ChildAt (aIndex); // lastChild : REFCNT++
|
||||
NS_ASSERTION(nsnull!=lastChild, "bad child");
|
||||
PRBool result = nsTableContent::ReplaceChildAt (aContent, aIndex, aNotify);
|
||||
if (result)
|
||||
nsresult result = nsTableContent::ReplaceChildAt (aContent, aIndex, aNotify);
|
||||
if (NS_OK==result)
|
||||
{
|
||||
((nsTableCol *)aContent)->SetColGroup (this);
|
||||
if (nsnull != lastChild)
|
||||
@ -268,8 +297,8 @@ nsTableColGroup::RemoveChildAt (PRInt32 aIndex, PRBool aNotify)
|
||||
NS_ASSERTION((0<=aIndex && ChildCount()>aIndex), "bad arg");
|
||||
nsIContent * lastChild = ChildAt (aIndex); // lastChild: REFCNT++
|
||||
NS_ASSERTION(nsnull!=lastChild, "bad child");
|
||||
PRBool result = nsTableContent::RemoveChildAt (aIndex, aNotify);
|
||||
if (result)
|
||||
nsresult result = nsTableContent::RemoveChildAt (aIndex, aNotify);
|
||||
if (NS_OK==result)
|
||||
{
|
||||
if (nsnull != lastChild)
|
||||
((nsTableCol *)lastChild)->SetColGroup (nsnull);
|
||||
|
@ -135,15 +135,10 @@ PRBool nsTableContent::IsImplicit () const
|
||||
return mImplicit;
|
||||
}
|
||||
|
||||
|
||||
/* ----- overridable methods from nsHTMLContainer ----- */
|
||||
|
||||
/**
|
||||
*
|
||||
* If the content is a nsTableContent then call SetTable on
|
||||
* aContent, otherwise, do nothing.
|
||||
*
|
||||
*/
|
||||
* If the content is a nsTableContent then call SetTable on
|
||||
* aContent, otherwise, do nothing.
|
||||
*/
|
||||
void nsTableContent::SetTableForTableContent(nsIContent* aContent, nsTablePart *aTable)
|
||||
{
|
||||
if (aContent != nsnull)
|
||||
@ -159,6 +154,8 @@ void nsTableContent::SetTableForTableContent(nsIContent* aContent, nsTablePart *
|
||||
}
|
||||
|
||||
|
||||
/* ----- overridable methods from nsHTMLContainer ----- */
|
||||
|
||||
void nsTableContent::List(FILE* out, PRInt32 aIndent) const
|
||||
{
|
||||
PRInt32 i;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "nsTableCell.h"
|
||||
#include "nsTableCellFrame.h"
|
||||
#include "nsTableCol.h"
|
||||
#include "nsTableColFrame.h"
|
||||
#include "nsTableRowFrame.h"
|
||||
#include "nsTableRowGroupFrame.h"
|
||||
#include "nsColLayoutData.h"
|
||||
@ -41,6 +42,7 @@
|
||||
#include "nsIPtr.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gsDebug = PR_FALSE;
|
||||
@ -135,6 +137,117 @@ struct InnerTableReflowState {
|
||||
}
|
||||
};
|
||||
|
||||
/* ----------- ColumnInfoCache ---------- */
|
||||
|
||||
static const PRInt32 NUM_COL_WIDTH_TYPES=4;
|
||||
|
||||
class ColumnInfoCache
|
||||
{
|
||||
public:
|
||||
ColumnInfoCache(PRInt32 aNumColumns);
|
||||
~ColumnInfoCache();
|
||||
|
||||
void AddColumnInfo(const nsStyleUnit aType,
|
||||
PRInt32 aColumnIndex);
|
||||
|
||||
void GetColumnsByType(const nsStyleUnit aType,
|
||||
PRInt32& aOutNumColumns,
|
||||
PRInt32 *& aOutColumnIndexes);
|
||||
enum ColWidthType {
|
||||
eColWidthType_Auto = 0, // width based on contents
|
||||
eColWidthType_Percent = 1, // (float) 1.0 == 100%
|
||||
eColWidthType_Coord = 2, // (nscoord) value is twips
|
||||
eColWidthType_Proportional = 3, // (int) value has proportional meaning
|
||||
};
|
||||
|
||||
private:
|
||||
PRInt32 mColCounts [4];
|
||||
PRInt32 *mColIndexes[4];
|
||||
PRInt32 mNumColumns;
|
||||
};
|
||||
|
||||
ColumnInfoCache::ColumnInfoCache(PRInt32 aNumColumns)
|
||||
{
|
||||
mNumColumns = aNumColumns;
|
||||
for (PRInt32 i=0; i<NUM_COL_WIDTH_TYPES; i++)
|
||||
{
|
||||
mColCounts[i] = 0;
|
||||
mColIndexes[i] = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
ColumnInfoCache::~ColumnInfoCache()
|
||||
{
|
||||
for (PRInt32 i=0; i<NUM_COL_WIDTH_TYPES; i++)
|
||||
{
|
||||
if (nsnull!=mColIndexes[i])
|
||||
{
|
||||
delete [] mColIndexes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ColumnInfoCache::AddColumnInfo(const nsStyleUnit aType,
|
||||
PRInt32 aColumnIndex)
|
||||
{
|
||||
switch (aType)
|
||||
{
|
||||
case eStyleUnit_Auto:
|
||||
if (nsnull==mColIndexes[eColWidthType_Auto])
|
||||
mColIndexes[eColWidthType_Auto] = new PRInt32[mNumColumns]; // TODO : be much more efficient
|
||||
mColIndexes[eColWidthType_Auto][mColCounts[eColWidthType_Auto]] = aColumnIndex;
|
||||
mColCounts[eColWidthType_Auto]++;
|
||||
break;
|
||||
|
||||
case eStyleUnit_Percent:
|
||||
if (nsnull==mColIndexes[eColWidthType_Percent])
|
||||
mColIndexes[eColWidthType_Percent] = new PRInt32[mNumColumns]; // TODO : be much more efficient
|
||||
mColIndexes[eColWidthType_Percent][mColCounts[eColWidthType_Percent]] = aColumnIndex;
|
||||
mColCounts[eColWidthType_Percent]++;
|
||||
break;
|
||||
|
||||
case eStyleUnit_Coord:
|
||||
if (nsnull==mColIndexes[eColWidthType_Coord])
|
||||
mColIndexes[eColWidthType_Coord] = new PRInt32[mNumColumns]; // TODO : be much more efficient
|
||||
mColIndexes[eColWidthType_Coord][mColCounts[eColWidthType_Coord]] = aColumnIndex;
|
||||
mColCounts[eColWidthType_Coord]++;
|
||||
break;
|
||||
|
||||
case eStyleUnit_Proportional:
|
||||
if (nsnull==mColIndexes[eColWidthType_Proportional])
|
||||
mColIndexes[eColWidthType_Proportional] = new PRInt32[mNumColumns]; // TODO : be much more efficient
|
||||
mColIndexes[eColWidthType_Proportional][mColCounts[eColWidthType_Proportional]] = aColumnIndex;
|
||||
mColCounts[eColWidthType_Proportional]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ColumnInfoCache::GetColumnsByType(const nsStyleUnit aType,
|
||||
PRInt32& aOutNumColumns,
|
||||
PRInt32 *& aOutColumnIndexes)
|
||||
{
|
||||
switch (aType)
|
||||
{
|
||||
case eStyleUnit_Auto:
|
||||
aOutNumColumns = mColCounts[eColWidthType_Auto];
|
||||
aOutColumnIndexes = mColIndexes[eColWidthType_Auto];
|
||||
break;
|
||||
case eStyleUnit_Percent:
|
||||
aOutNumColumns = mColCounts[eColWidthType_Percent];
|
||||
aOutColumnIndexes = mColIndexes[eColWidthType_Percent];
|
||||
break;
|
||||
case eStyleUnit_Coord:
|
||||
aOutNumColumns = mColCounts[eColWidthType_Coord];
|
||||
aOutColumnIndexes = mColIndexes[eColWidthType_Coord];
|
||||
break;
|
||||
case eStyleUnit_Proportional:
|
||||
aOutNumColumns = mColCounts[eColWidthType_Proportional];
|
||||
aOutColumnIndexes = mColIndexes[eColWidthType_Proportional];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ----------- nsTableFrame ---------- */
|
||||
@ -143,6 +256,7 @@ struct InnerTableReflowState {
|
||||
nsTableFrame::nsTableFrame(nsIContent* aContent, nsIFrame* aParentFrame)
|
||||
: nsContainerFrame(aContent, aParentFrame),
|
||||
mColumnLayoutData(nsnull),
|
||||
mColCache(nsnull),
|
||||
mColumnWidths(nsnull),
|
||||
mTableLayoutStrategy(nsnull),
|
||||
mFirstPassValid(PR_FALSE),
|
||||
@ -177,6 +291,8 @@ nsTableFrame::~nsTableFrame()
|
||||
delete [] mColumnWidths;
|
||||
if (nsnull!=mTableLayoutStrategy)
|
||||
delete mTableLayoutStrategy;
|
||||
if (nsnull!=mColCache)
|
||||
delete mColCache;
|
||||
}
|
||||
|
||||
|
||||
@ -1891,6 +2007,8 @@ void nsTableFrame::ShrinkWrapChildren(nsIPresContext* aPresContext,
|
||||
rowGroupFrame->GetSize(rowGroupFrameSize);
|
||||
rowGroupFrame->SizeTo(rowGroupFrameSize.width, rowGroupHeight);
|
||||
tableHeight += rowGroupHeight;
|
||||
if (nsnull!=rowHeights)
|
||||
delete [] rowHeights;
|
||||
}
|
||||
}
|
||||
if (0!=tableHeight)
|
||||
@ -1904,12 +2022,61 @@ void nsTableFrame::ShrinkWrapChildren(nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
void nsTableFrame::VerticallyAlignChildren(nsIPresContext* aPresContext,
|
||||
nscoord* aAscents,
|
||||
nscoord aMaxAscent,
|
||||
nscoord aMaxHeight)
|
||||
nscoord* aAscents,
|
||||
nscoord aMaxAscent,
|
||||
nscoord aMaxHeight)
|
||||
{
|
||||
}
|
||||
|
||||
/* there's an easy way and a hard way. The easy way is to look in our
|
||||
* cache and pull the frame from there.
|
||||
* If the cache isn't built yet, then we have to go hunting.
|
||||
*/
|
||||
NS_METHOD nsTableFrame::GetColumnFrame(PRInt32 aColIndex, nsTableColFrame *&aColFrame)
|
||||
{
|
||||
aColFrame = nsnull; // initialize out parameter
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
if (nsnull!=firstInFlow->mColumnLayoutData)
|
||||
{ // hooray, we get to do this the easy way because the info is cached
|
||||
nsColLayoutData * colData = (nsColLayoutData *)
|
||||
(firstInFlow->mColumnLayoutData->ElementAt(aColIndex));
|
||||
NS_ASSERTION(nsnull != colData, "bad column data");
|
||||
aColFrame = colData->GetColFrame();
|
||||
NS_ASSERTION(nsnull!=aColFrame, "bad col frame");
|
||||
}
|
||||
else
|
||||
{ // ah shucks, we have to go hunt for the column frame brute-force style
|
||||
nsIFrame *childFrame;
|
||||
FirstChild(childFrame);
|
||||
for (;;)
|
||||
{
|
||||
if (nsnull==childFrame)
|
||||
{
|
||||
NS_ASSERTION (PR_FALSE, "scanned the frame hierarchy and no column frame could be found.");
|
||||
break;
|
||||
}
|
||||
nsIContentPtr kid;
|
||||
childFrame->GetContent(kid.AssignRef());
|
||||
const PRInt32 contentType = ((nsTableContent *)(nsIContent*)kid)->GetType();
|
||||
if (contentType==nsITableContent::kTableColGroupType)
|
||||
{
|
||||
nsTableColGroup *colGroup = (nsTableColGroup *)((nsIContent*)kid);
|
||||
PRInt32 colGroupStartingIndex = colGroup->GetStartColumnIndex();
|
||||
if (aColIndex >= colGroupStartingIndex)
|
||||
{ // the cell's col might be in this col group
|
||||
if (aColIndex < colGroupStartingIndex + colGroup->ChildCount())
|
||||
{ // yep, we've found it
|
||||
childFrame->ChildAt(aColIndex-colGroupStartingIndex, (nsIFrame *&)aColFrame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
childFrame->GetNextSibling(childFrame);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsVoidArray * nsTableFrame::GetColumnLayoutData()
|
||||
{
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
@ -1922,7 +2089,8 @@ nsVoidArray * nsTableFrame::GetColumnLayoutData()
|
||||
* @return PR_TRUE if the data was successfully associated with a Cell
|
||||
* PR_FALSE if there was an error, such as aRow or aCol being invalid
|
||||
*/
|
||||
PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aCell)
|
||||
PRBool nsTableFrame::SetCellLayoutData(nsIPresContext* aPresContext,
|
||||
nsCellLayoutData * aData, nsTableCell *aCell)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aData, "bad arg");
|
||||
NS_ASSERTION(nsnull != aCell, "bad arg");
|
||||
@ -1932,7 +2100,7 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
||||
if (this!=firstInFlow)
|
||||
result = firstInFlow->SetCellLayoutData(aData, aCell);
|
||||
result = firstInFlow->SetCellLayoutData(aPresContext, aData, aCell);
|
||||
else
|
||||
{
|
||||
if (kPASS_FIRST==GetReflowPass())
|
||||
@ -1943,6 +2111,7 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
|
||||
NS_ASSERTION(nsnull != mColumnLayoutData, "bad alloc");
|
||||
nsTablePart * tablePart = (nsTablePart *)mContent;
|
||||
PRInt32 cols = tablePart->GetMaxColumns();
|
||||
mColCache = new ColumnInfoCache(cols);
|
||||
PRInt32 tableKidCount = tablePart->ChildCount();
|
||||
nsIFrame * colGroupFrame = mFirstChild;
|
||||
for (PRInt32 i=0; i<tableKidCount; i++)
|
||||
@ -1955,6 +2124,9 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
|
||||
PRInt32 colsInGroup = tableKid->ChildCount();
|
||||
for (PRInt32 j=0; j<colsInGroup; j++)
|
||||
{
|
||||
// TODO: unify these 2 kinds of column data
|
||||
// TODO: cache more column data, like the mWidth.GetUnit and what its value
|
||||
|
||||
nsTableColPtr col = (nsTableCol *)tableKid->ChildAt(j);
|
||||
NS_ASSERTION(col.IsNotNull(), "bad content");
|
||||
nsColLayoutData *colData = new nsColLayoutData(col);
|
||||
@ -1962,6 +2134,13 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
|
||||
colGroupFrame->ChildAt(j, (nsIFrame *&)colFrame);
|
||||
colData->SetColFrame(colFrame);
|
||||
mColumnLayoutData->AppendElement((void *)colData);
|
||||
|
||||
// also add the column to the column cache
|
||||
// assumes that the col style has been twiddled to account for first cell width attribute
|
||||
nsIStyleContextPtr colSC;
|
||||
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
|
||||
nsStylePosition* colPosition = (nsStylePosition*)colSC->GetData(eStyleStruct_Position);
|
||||
mColCache->AddColumnInfo(colPosition->mWidth.GetUnit(), colFrame->GetColumnIndex());
|
||||
}
|
||||
}
|
||||
// can't have col groups after row groups, so stop if you find a row group
|
||||
@ -2349,6 +2528,14 @@ NS_METHOD nsTableFrame::GetCellMarginData(nsIFrame* aKidFrame, nsMargin& aMargin
|
||||
return result;
|
||||
}
|
||||
|
||||
void nsTableFrame::GetColumnsByType(const nsStyleUnit aType,
|
||||
PRInt32& aOutNumColumns,
|
||||
PRInt32 *& aOutColumnIndexes)
|
||||
{
|
||||
mColCache->GetColumnsByType(aType, aOutNumColumns, aOutColumnIndexes);
|
||||
}
|
||||
|
||||
|
||||
/* ---------- static methods ---------- */
|
||||
|
||||
nsresult nsTableFrame::NewFrame(nsIFrame** aInstancePtrResult,
|
||||
@ -2367,6 +2554,115 @@ nsresult nsTableFrame::NewFrame(nsIFrame** aInstancePtrResult,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* helper method for getting the width of the table's containing block */
|
||||
nscoord nsTableFrame::GetTableContainerWidth(const nsReflowState& aReflowState)
|
||||
{
|
||||
#ifdef STEVES_WAY // from BasicTableLayoutStrategy::TableIsAutoWidth()
|
||||
// get the parent's width (available only from parent frames that claim they can provide it)
|
||||
// note that we start with our parent's parent (the outer table frame's parent)
|
||||
nscoord parentWidth = 0;
|
||||
NS_ASSERTION(nsnull!=aReflowState.parentReflowState, "bad outer table reflow state.");
|
||||
NS_ASSERTION(nsnull!=aReflowState.parentReflowState->parentReflowState, "bad table parent reflow state.");
|
||||
if ((nsnull!=aReflowState.parentReflowState) &&
|
||||
(nsnull!=aReflowState.parentReflowState->parentReflowState))
|
||||
{
|
||||
const nsReflowState *parentReflowState = aReflowState.parentReflowState->parentReflowState;
|
||||
nsIFrame *parentFrame=parentReflowState->frame;
|
||||
NS_ASSERTION(nsnull!=parentFrame, "bad parent frame in reflow state struct.");
|
||||
while(nsnull!=parentFrame)
|
||||
{
|
||||
PRBool isPercentageBase=PR_FALSE;
|
||||
parentFrame->IsPercentageBase(isPercentageBase);
|
||||
if (PR_TRUE==isPercentageBase)
|
||||
{ // found the ancestor who claims to be the container to base my percentage width on
|
||||
parentWidth = parentReflowState->maxSize.width;
|
||||
if (PR_TRUE==gsDebug) printf(" ** width for parent frame %p = %d\n", parentFrame, parentWidth);
|
||||
break;
|
||||
}
|
||||
parentReflowState = parentReflowState->parentReflowState; // get next ancestor
|
||||
if (nsnull!=parentReflowState)
|
||||
parentFrame = parentReflowState->frame;
|
||||
else
|
||||
parentFrame = nsnull; // terminates loop.
|
||||
// TODO: do we need a backstop in case there are no IsPercentageBase==true frames?
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
nscoord parentWidth = aReflowState.maxSize.width;
|
||||
|
||||
// Walk up the reflow state chain until we find a block
|
||||
// frame. Our width is computed relative to there.
|
||||
const nsReflowState* rs = &aReflowState;
|
||||
while (nsnull != rs) {
|
||||
nsIFrame* block = nsnull;
|
||||
rs->frame->QueryInterface(kBlockFrameCID, (void**) &block);
|
||||
if (nsnull != block) {
|
||||
// We found the nearest containing block which defines what
|
||||
// a percentage size is relative to. Use the width that it
|
||||
// will reflow to as the basis for computing our width.
|
||||
parentWidth = rs->maxSize.width;
|
||||
break;
|
||||
}
|
||||
rs = rs->parentReflowState;
|
||||
}
|
||||
|
||||
#endif
|
||||
return parentWidth;
|
||||
}
|
||||
|
||||
// aSpecifiedTableWidth is filled if the table witdth is not auto
|
||||
PRBool nsTableFrame::TableIsAutoWidth(nsTableFrame *aTableFrame,
|
||||
nsIStyleContext *aTableStyle,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord& aSpecifiedTableWidth)
|
||||
{
|
||||
NS_ASSERTION(nsnull!=aTableStyle, "bad arg - aTableStyle");
|
||||
PRBool result = PR_TRUE; // the default
|
||||
if (nsnull!=aTableStyle)
|
||||
{
|
||||
//nsStylePosition* tablePosition = (nsStylePosition*)aTableStyle->GetData(eStyleStruct_Position);
|
||||
/* this is sick and wrong, but what the hell
|
||||
we grab the style of our parent (nsTableOuterFrame) and ask it for width info,
|
||||
until the style resolution stuff does the cool stuff about splitting style between outer and inner
|
||||
*/
|
||||
// begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED!
|
||||
nsIStyleContext* parentStyle = nsnull;
|
||||
nsIFrame * parent = nsnull;
|
||||
aTableFrame->GetGeometricParent(parent);
|
||||
parent->GetStyleContext(nsnull, parentStyle);
|
||||
nsStylePosition* tablePosition = (nsStylePosition*)parentStyle->GetData(eStyleStruct_Position);
|
||||
// end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED!
|
||||
switch (tablePosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Auto: // specified auto width
|
||||
case eStyleUnit_Proportional: // illegal for table, so ignored
|
||||
break;
|
||||
|
||||
case eStyleUnit_Inherit:
|
||||
// get width of parent and see if it is a specified value or not
|
||||
// XXX for now, just return true
|
||||
break;
|
||||
|
||||
case eStyleUnit_Coord:
|
||||
aSpecifiedTableWidth = tablePosition->mWidth.GetCoordValue();
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
|
||||
case eStyleUnit_Percent:
|
||||
// set aSpecifiedTableWidth to be the given percent of the parent.
|
||||
nscoord parentWidth = nsTableFrame::GetTableContainerWidth(aReflowState);
|
||||
float percent = tablePosition->mWidth.GetPercentValue();
|
||||
aSpecifiedTableWidth = (PRInt32)(parentWidth*percent);
|
||||
if (PR_TRUE==gsDebug) printf(" ** aSpecifiedTableWidth = %d\n", aSpecifiedTableWidth);
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* valuable code not yet used anywhere
|
||||
|
||||
// since the table is a specified width, we need to expand the columns to fill the table
|
||||
|
@ -25,12 +25,15 @@ class nsCellLayoutData;
|
||||
class nsTableCell;
|
||||
class nsVoidArray;
|
||||
class nsTableCellFrame;
|
||||
class nsTableColFrame;
|
||||
class CellData;
|
||||
class nsITableLayoutStrategy;
|
||||
class nsHTMLValue;
|
||||
class ColumnInfoCache;
|
||||
struct InnerTableReflowState;
|
||||
struct nsStylePosition;
|
||||
struct nsStyleSpacing;
|
||||
enum nsStyleUnit;
|
||||
|
||||
/** nsTableFrame maps the inner portion of a table (everything except captions.)
|
||||
* Used as a pseudo-frame within nsTableOuterFrame,
|
||||
@ -59,6 +62,15 @@ public:
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent);
|
||||
|
||||
/** helper method for getting the width of the table's containing block */
|
||||
static nscoord GetTableContainerWidth(const nsReflowState& aState);
|
||||
|
||||
|
||||
static PRBool TableIsAutoWidth(nsTableFrame *aTableFrame,
|
||||
nsIStyleContext *aTableStyle,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord& aSpecifiedTableWidth);
|
||||
|
||||
/** @see nsIFrame::Paint */
|
||||
NS_IMETHOD Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
@ -108,16 +120,29 @@ public:
|
||||
nsReflowMetrics& aDesiredSize,
|
||||
nsSize* aMaxElementSize);
|
||||
|
||||
/** return the column frame corresponding to the given column index
|
||||
* there are two ways to do this, depending on whether we have cached
|
||||
* column information yet.
|
||||
*/
|
||||
NS_METHOD GetColumnFrame(PRInt32 aColIndex, nsTableColFrame *&aColFrame);
|
||||
|
||||
/** return the column layout data for this inner table frame.
|
||||
* if this is a continuing frame, return the first-in-flow's column layout data.
|
||||
*/
|
||||
virtual nsVoidArray *GetColumnLayoutData();
|
||||
|
||||
/** Associate aData with the cell at (aRow,aCol)
|
||||
*
|
||||
* @param aPresContext -- used to resolve style when initializing caches
|
||||
* @param aData -- the info to cache
|
||||
* @param aCell -- the content object for which layout info is being cached
|
||||
*
|
||||
* @return PR_TRUE if the data was successfully associated with a Cell
|
||||
* PR_FALSE if there was an error, such as aRow or aCol being invalid
|
||||
*/
|
||||
virtual PRBool SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aCell);
|
||||
virtual PRBool SetCellLayoutData(nsIPresContext* aPresContext,
|
||||
nsCellLayoutData * aData,
|
||||
nsTableCell *aCell);
|
||||
|
||||
/** Get the layout data associated with the cell at (aRow,aCol)
|
||||
* @return PR_NULL if there was an error, such as aRow or aCol being invalid
|
||||
@ -154,6 +179,18 @@ public:
|
||||
// Get cell margin information
|
||||
NS_IMETHOD GetCellMarginData(nsIFrame* aKidFrame, nsMargin& aMargin);
|
||||
|
||||
/** get cached column information for a subset of the columns
|
||||
*
|
||||
* @param aType -- information is returned for the subset of columns with aType style
|
||||
* @param aOutNumColumns -- out param, the number of columns matching aType
|
||||
* @param aOutColumnIndexes -- out param, the indexes of the columns matching aType
|
||||
*
|
||||
* TODO : make aOutColumnIndexes safe
|
||||
*/
|
||||
void GetColumnsByType(const nsStyleUnit aType,
|
||||
PRInt32& aOutNumColumns,
|
||||
PRInt32 *& aOutColumnIndexes);
|
||||
|
||||
// For DEBUGGING Purposes Only
|
||||
NS_IMETHOD MoveTo(nscoord aX, nscoord aY);
|
||||
NS_IMETHOD SizeTo(nscoord aWidth, nscoord aHeight);
|
||||
@ -304,6 +341,8 @@ private:
|
||||
|
||||
nsVoidArray *mColumnLayoutData; // array of array of cellLayoutData's
|
||||
PRInt32 *mColumnWidths; // widths of each column
|
||||
//TODO: move all column info into this object
|
||||
ColumnInfoCache *mColCache; // cached information about the table columns
|
||||
PRBool mFirstPassValid; // PR_TRUE if first pass data is still legit
|
||||
PRInt32 mPass; // which Reflow pass are we currently in?
|
||||
PRBool mIsInvariantWidth; // PR_TRUE if table width cannot change
|
||||
|
@ -342,19 +342,18 @@ NS_IMETHODIMP
|
||||
nsTablePart::AppendChild (nsIContent * aContent, PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION(nsnull!=aContent, "bad arg");
|
||||
PRBool result = PR_FALSE;
|
||||
PRBool newCells = PR_FALSE;
|
||||
PRBool contentHandled = PR_FALSE;
|
||||
|
||||
// wait, stop! need to check to see if this is really tableContent or not!
|
||||
nsITableContent *tableContentInterface = nsnull;
|
||||
PRBool result = PR_TRUE; // to be removed when called methods are COM-ized
|
||||
nsresult rv = aContent->QueryInterface(kITableContentIID,
|
||||
(void **)&tableContentInterface); // tableContentInterface: REFCNT++
|
||||
if (NS_FAILED(rv))
|
||||
{ // create an implicit cell and return the result of adding it to the table
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf ("*** bad HTML in table, not yet implemented.\n");
|
||||
return PR_FALSE;
|
||||
NS_ASSERTION(PR_FALSE, "non-table content insertion not implemented");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -394,18 +393,20 @@ nsTablePart::AppendChild (nsIContent * aContent, PRBool aNotify)
|
||||
nsIAtom * rowGroupTag = NS_NewAtom(kRowGroupBodyTagString); // rowGroupTag: REFCNT++
|
||||
group = new nsTableRowGroup (rowGroupTag, PR_TRUE);
|
||||
NS_ADDREF(group); // group: REFCNT++
|
||||
AppendChild (group, PR_FALSE);
|
||||
group->SetTable(this);
|
||||
rv = AppendChild (group, PR_FALSE);
|
||||
if (NS_OK==rv)
|
||||
group->SetTable(this);
|
||||
NS_RELEASE(rowGroupTag); // rowGroupTag: REFCNT--
|
||||
}
|
||||
// group is guaranteed to be allocated at this point
|
||||
result = group->AppendChild(aContent, PR_FALSE);
|
||||
newCells = result;
|
||||
rv = group->AppendChild(aContent, PR_FALSE);
|
||||
newCells = (PRBool)(NS_OK==rv);
|
||||
contentHandled = PR_TRUE;
|
||||
NS_RELEASE(group); // group: REFCNT--
|
||||
}
|
||||
else if (contentType == nsITableContent::kTableColType)
|
||||
{
|
||||
// TODO: switch Append* to COM interfaces
|
||||
result = AppendColumn((nsTableCol *)aContent);
|
||||
newCells = result;
|
||||
contentHandled = PR_TRUE;
|
||||
@ -422,6 +423,8 @@ nsTablePart::AppendChild (nsIContent * aContent, PRBool aNotify)
|
||||
{
|
||||
newCells = PR_TRUE;
|
||||
}
|
||||
else
|
||||
rv=NS_ERROR_FAILURE;
|
||||
contentHandled = PR_TRUE; // whether we succeeded or not, we've "handled" this request
|
||||
}
|
||||
else if (contentType == nsITableContent::kTableColGroupType)
|
||||
@ -431,6 +434,8 @@ nsTablePart::AppendChild (nsIContent * aContent, PRBool aNotify)
|
||||
{
|
||||
newCells = PR_TRUE;
|
||||
}
|
||||
else
|
||||
rv = NS_ERROR_FAILURE;
|
||||
contentHandled = PR_TRUE; // whether we succeeded or not, we've "handled" this request
|
||||
}
|
||||
|
||||
@ -452,7 +457,8 @@ nsTablePart::AppendChild (nsIContent * aContent, PRBool aNotify)
|
||||
{
|
||||
if (gsDebug==PR_TRUE) printf ("nsTablePart::AppendChild -- adding an implicit caption.\n");
|
||||
caption = new nsTableCaption (PR_TRUE);
|
||||
AppendCaption (caption);
|
||||
result = AppendCaption (caption);
|
||||
// check result
|
||||
}
|
||||
result = caption->AppendChild (aContent, PR_FALSE);
|
||||
}
|
||||
@ -625,8 +631,11 @@ PRBool nsTablePart::AppendRowGroup (nsTableRowGroup *aContent)
|
||||
NS_RELEASE(tHeadTag);
|
||||
NS_RELEASE(tBodyTag);
|
||||
|
||||
nsHTMLContainer::InsertChildAt(aContent, childIndex, PR_FALSE);
|
||||
((nsTableContent *)aContent)->SetTable (this);
|
||||
nsresult rv = nsHTMLContainer::InsertChildAt(aContent, childIndex, PR_FALSE);
|
||||
if (NS_OK==rv)
|
||||
((nsTableContent *)aContent)->SetTable (this);
|
||||
else
|
||||
result = PR_FALSE;
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -634,6 +643,7 @@ PRBool nsTablePart::AppendRowGroup (nsTableRowGroup *aContent)
|
||||
/** protected method for appending a column group to this table */
|
||||
PRBool nsTablePart::AppendColGroup(nsTableColGroup *aContent)
|
||||
{
|
||||
PRBool result = PR_TRUE; // to be removed when I'm COM-ized
|
||||
PRInt32 childIndex;
|
||||
NS_PRECONDITION(nsnull!=aContent, "null arg.");
|
||||
if (gsDebug==PR_TRUE)
|
||||
@ -651,27 +661,39 @@ PRBool nsTablePart::AppendColGroup(nsTableColGroup *aContent)
|
||||
(tableChildType == nsITableContent::kTableColGroupType)))
|
||||
break;
|
||||
}
|
||||
nsHTMLContainer::InsertChildAt(aContent, childIndex, PR_FALSE);
|
||||
((nsTableContent *)aContent)->SetTable (this);
|
||||
nsresult rv = nsHTMLContainer::InsertChildAt(aContent, childIndex, PR_FALSE);
|
||||
if (NS_OK==rv)
|
||||
((nsTableContent *)aContent)->SetTable (this);
|
||||
else
|
||||
result = PR_FALSE;
|
||||
|
||||
// if col group has a SPAN attribute, create implicit columns for
|
||||
// the value of SPAN what sucks is if we then get a COL for this
|
||||
// COLGROUP, we have to delete all the COLs we created for SPAN, and
|
||||
// just contain the explicit COLs.
|
||||
|
||||
// TODO: move this into the OK clause above
|
||||
|
||||
PRInt32 span = 0; // SEC: TODO find a way to really get this
|
||||
for (PRInt32 i=0; i<span; i++)
|
||||
{
|
||||
nsTableCol *col = new nsTableCol(PR_TRUE);
|
||||
aContent->AppendChild (col, PR_FALSE);
|
||||
rv = aContent->AppendChild (col, PR_FALSE);
|
||||
if (NS_OK!=rv)
|
||||
{
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** protected method for appending a column group to this table */
|
||||
PRBool nsTablePart::AppendColumn(nsTableCol *aContent)
|
||||
{
|
||||
NS_PRECONDITION(nsnull!=aContent, "null arg.");
|
||||
nsresult rv = NS_OK;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf ("nsTablePart::AppendColumn -- adding a column.\n");
|
||||
// find last col group, if ! implicit, make one, append there
|
||||
@ -694,17 +716,20 @@ PRBool nsTablePart::AppendColumn(nsTableCol *aContent)
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf ("nsTablePart::AppendChild -- creating an implicit column group.\n");
|
||||
group = new nsTableColGroup (PR_TRUE);
|
||||
AppendChild (group, PR_FALSE);
|
||||
group->SetTable(this);
|
||||
rv = AppendChild (group, PR_FALSE);
|
||||
if (NS_OK==rv)
|
||||
group->SetTable(this);
|
||||
}
|
||||
group->AppendChild (aContent, PR_FALSE);
|
||||
if (NS_OK==rv)
|
||||
rv = group->AppendChild (aContent, PR_FALSE);
|
||||
|
||||
return PR_TRUE;
|
||||
return (PRBool)(NS_OK==rv);
|
||||
}
|
||||
|
||||
/** protected method for appending a column group to this table */
|
||||
PRBool nsTablePart::AppendCaption(nsTableCaption *aContent)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
PRInt32 childIndex;
|
||||
NS_PRECONDITION(nsnull!=aContent, "null arg.");
|
||||
if (gsDebug==PR_TRUE)
|
||||
@ -720,10 +745,11 @@ PRBool nsTablePart::AppendCaption(nsTableCaption *aContent)
|
||||
if (tableChildType != nsITableContent::kTableCaptionType)
|
||||
break;
|
||||
}
|
||||
nsHTMLContainer::InsertChildAt(aContent, childIndex, PR_FALSE);
|
||||
((nsTableContent *)aContent)->SetTable (this);
|
||||
rv = nsHTMLContainer::InsertChildAt(aContent, childIndex, PR_FALSE);
|
||||
if (NS_OK==rv)
|
||||
((nsTableContent *)aContent)->SetTable (this);
|
||||
|
||||
return PR_TRUE;
|
||||
return (PRBool)(NS_OK==rv);
|
||||
}
|
||||
|
||||
/* return the index of the first row group after aStartIndex */
|
||||
|
@ -167,8 +167,10 @@ nsTableRow::InsertChildAt (nsIContent *aContent, PRInt32 aIndex,
|
||||
nsTableContent *tableContent = (nsTableContent *)aContent;
|
||||
const int contentType = tableContent->GetType();
|
||||
if (contentType != nsITableContent::kTableCellType)
|
||||
{
|
||||
return NS_OK;
|
||||
{ // I only insert cells for now
|
||||
// TODO: wrap whatever I'm given here in a cell and insert it
|
||||
NS_ASSERTION(PR_FALSE, "unimplemented attempt to insert a non-cell into a row");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -193,17 +195,22 @@ nsTableRow::ReplaceChildAt (nsIContent *aContent, PRInt32 aIndex,
|
||||
NS_PRECONDITION(nsnull!=aContent, "bad aContent arg to ReplaceChildAt");
|
||||
NS_PRECONDITION(0<=aIndex && aIndex<ChildCount(), "bad aIndex arg to ReplaceChildAt");
|
||||
if ((nsnull==aContent) || !(0<=aIndex && aIndex<ChildCount()))
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
else
|
||||
{
|
||||
nsTableContent *tableContent = (nsTableContent *)aContent;
|
||||
const int contentType = tableContent->GetType();
|
||||
if (contentType != nsITableContent::kTableCellType)
|
||||
{
|
||||
return NS_OK;
|
||||
{ // I only insert cells for now
|
||||
// TODO: wrap whatever I'm given here in a cell and insert it
|
||||
NS_ASSERTION(PR_FALSE, "unimplemented attempt to insert a non-cell into a row");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else
|
||||
return NS_OK;
|
||||
{
|
||||
NS_ASSERTION(PR_FALSE, "unimplemented attempt to replace a cell in a row");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#if XXX
|
||||
nsIContent * oldChild = ChildAt (aIndex); // oldChild: REFCNT++
|
||||
result = nsTableContent::ReplaceChildAt (aContent, aIndex, aNotify);
|
||||
@ -229,7 +236,7 @@ nsTableRow::RemoveChildAt (int aIndex, PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION(0<=aIndex && aIndex<ChildCount(), "bad aIndex arg to ReplaceChildAt");
|
||||
if (!(0<=aIndex && aIndex<ChildCount()))
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsIContent * oldChild = ChildAt (aIndex); // oldChild: REFCNT++
|
||||
|
@ -23,9 +23,11 @@
|
||||
#include "nsIContent.h"
|
||||
#include "nsIContentDelegate.h"
|
||||
#include "nsTableFrame.h"
|
||||
#include "nsTableColFrame.h"
|
||||
#include "nsTableCellFrame.h"
|
||||
#include "nsTableCell.h"
|
||||
#include "nsCellLayoutData.h"
|
||||
#include "nsColLayoutData.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIPtr.h"
|
||||
|
||||
@ -360,7 +362,7 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext,
|
||||
status = ReflowChild(kidFrame, aPresContext, desiredSize,
|
||||
kidReflowState);
|
||||
nsCellLayoutData kidLayoutData((nsTableCellFrame *)kidFrame, &desiredSize, pKidMaxElementSize);
|
||||
aState.tableFrame->SetCellLayoutData(&kidLayoutData, cell);
|
||||
aState.tableFrame->SetCellLayoutData(aPresContext, &kidLayoutData, cell);
|
||||
}
|
||||
else
|
||||
{ // we're in a constrained situation, so get the avail width from the known column widths
|
||||
@ -428,13 +430,11 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext,
|
||||
case eStyleUnit_Coord:
|
||||
specifiedHeight = kidPosition->mHeight.GetCoordValue();
|
||||
break;
|
||||
case eStyleUnit_Percent:
|
||||
case eStyleUnit_Proportional:
|
||||
// XXX for now these fall through
|
||||
|
||||
case eStyleUnit_Inherit:
|
||||
// XXX for now, do nothing
|
||||
default:
|
||||
case eStyleUnit_Auto:
|
||||
case eStyleUnit_Inherit:
|
||||
break;
|
||||
}
|
||||
if (specifiedHeight>cellHeight)
|
||||
@ -893,10 +893,9 @@ nsTableRowFrame::ReflowUnmappedChildren( nsIPresContext* aPresContext,
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
nsIFrame* kidFrame;
|
||||
|
||||
// Create a child frame
|
||||
// Create a child frame -- always an nsTableCell frame
|
||||
nsIStyleContext* kidStyleContext = aPresContext->ResolveStyleContextFor(cell, this);
|
||||
if (nsnull == kidPrevInFlow) {
|
||||
nsIContentDelegate* kidDel = nsnull;
|
||||
@ -908,6 +907,11 @@ nsTableRowFrame::ReflowUnmappedChildren( nsIPresContext* aPresContext,
|
||||
kidPrevInFlow->CreateContinuingFrame(aPresContext, this,
|
||||
kidStyleContext, kidFrame);
|
||||
}
|
||||
/* since I'm creating the cell frame, this is the first time through reflow
|
||||
* it's a good time to set the column style from the cell's width attribute
|
||||
* if this is the first row
|
||||
*/
|
||||
SetColumnStyleFromCell(aPresContext, (nsTableCellFrame *)kidFrame, kidStyleContext);
|
||||
NS_RELEASE(kidStyleContext);
|
||||
|
||||
|
||||
@ -937,7 +941,7 @@ nsTableRowFrame::ReflowUnmappedChildren( nsIPresContext* aPresContext,
|
||||
kidFrame->WillReflow(*aPresContext);
|
||||
status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState);
|
||||
nsCellLayoutData kidLayoutData((nsTableCellFrame *)kidFrame, &desiredSize, pKidMaxElementSize);
|
||||
aState.tableFrame->SetCellLayoutData(&kidLayoutData, (nsTableCell *)cell);
|
||||
aState.tableFrame->SetCellLayoutData(aPresContext, &kidLayoutData, (nsTableCell *)cell);
|
||||
}
|
||||
else
|
||||
{ // we're in a constrained situation, so get the avail width from the known column widths
|
||||
@ -1146,6 +1150,54 @@ nsTableRowFrame::CreateContinuingFrame(nsIPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsTableRowFrame::SetColumnStyleFromCell(nsIPresContext* aPresContext,
|
||||
nsTableCellFrame* aCellFrame,
|
||||
nsIStyleContext* aCellSC)
|
||||
{
|
||||
// if this cell is in the first row, then the width attribute
|
||||
// also acts as the width attribute for the entire column
|
||||
if ((nsnull!=aCellSC) && (nsnull!=aCellFrame))
|
||||
{
|
||||
PRInt32 rowIndex = ((nsTableRow*)mContent)->GetRowIndex();
|
||||
if (0==rowIndex)
|
||||
{
|
||||
// get the cell style info
|
||||
nsStylePosition* cellPosition = (nsStylePosition*) aCellSC->GetData(eStyleStruct_Position);
|
||||
if ((eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) ||
|
||||
(eStyleUnit_Percent==cellPosition->mWidth.GetUnit())) {
|
||||
|
||||
// compute the width per column spanned
|
||||
PRInt32 colSpan = aCellFrame->GetColSpan();
|
||||
// get the appropriate column frame
|
||||
nsTableFrame *tableFrame;
|
||||
mGeometricParent->GetGeometricParent((nsIFrame *&)tableFrame);
|
||||
nsTableColFrame *colFrame;
|
||||
tableFrame->GetColumnFrame(aCellFrame->GetColIndex(), colFrame);
|
||||
// get the column style and set the width attribute
|
||||
nsIStyleContextPtr colSC;
|
||||
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
|
||||
nsStylePosition* colPosition = (nsStylePosition*) colSC->GetData(eStyleStruct_Position);
|
||||
// set the column width attribute
|
||||
colPosition->mWidth = cellPosition->mWidth;
|
||||
/*
|
||||
if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit())
|
||||
{
|
||||
nscoord width = cellPosition->mWidth.GetCoordValue();
|
||||
colPosition->mWidth.SetCoordValue(width);
|
||||
}
|
||||
else
|
||||
{
|
||||
float width = cellPosition->mWidth.GetPercentValue();
|
||||
colPosition->mWidth.SetPercentValue(width);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsTableRowFrame::NewFrame( nsIFrame** aInstancePtrResult,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent)
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
class nsTableFrame;
|
||||
class nsTableCellFrame;
|
||||
struct RowReflowState;
|
||||
|
||||
/**
|
||||
@ -160,6 +161,9 @@ protected:
|
||||
RowReflowState& aState,
|
||||
nsSize* aMaxElementSize);
|
||||
|
||||
NS_METHOD SetColumnStyleFromCell(nsIPresContext * aPresContext,
|
||||
nsTableCellFrame* aCellFrame,
|
||||
nsIStyleContext * aCellSC);
|
||||
|
||||
private:
|
||||
nscoord mTallestCell; // not my height, but the height of my tallest child
|
||||
|
@ -42,10 +42,27 @@ static const PRBool gsNoisyRefs = PR_FALSE;
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kITableContentIID, NS_ITABLECONTENT_IID);
|
||||
|
||||
// hack, remove when hack in nsTableCol constructor is removed
|
||||
static PRInt32 HACKcounter=0;
|
||||
static nsIAtom *HACKattribute=nsnull;
|
||||
#include "prprf.h" // remove when nsTableCol constructor hack is removed
|
||||
// end hack code
|
||||
|
||||
// nsTableContent checks aTag
|
||||
nsTableRowGroup::nsTableRowGroup(nsIAtom* aTag)
|
||||
: nsTableContent(aTag)
|
||||
{
|
||||
/* begin hack */
|
||||
// temporary hack to get around style sheet optimization that folds all
|
||||
// col style context into one, unless there is a unique HTML attribute set
|
||||
char out[40];
|
||||
PR_snprintf(out, 40, "%d", HACKcounter);
|
||||
const nsString value(out);
|
||||
if (nsnull==HACKattribute)
|
||||
HACKattribute = NS_NewAtom("Steve's unbelievable hack attribute");
|
||||
SetAttribute(HACKattribute, value);
|
||||
HACKcounter++;
|
||||
/* end hack */
|
||||
}
|
||||
|
||||
// nsTableContent checks aTag
|
||||
@ -53,6 +70,17 @@ nsTableRowGroup::nsTableRowGroup(nsIAtom* aTag, PRBool aImplicit)
|
||||
: nsTableContent(aTag)
|
||||
{
|
||||
mImplicit = aImplicit;
|
||||
/* begin hack */
|
||||
// temporary hack to get around style sheet optimization that folds all
|
||||
// col style context into one, unless there is a unique HTML attribute set
|
||||
char out[40];
|
||||
PR_snprintf(out, 40, "%d", HACKcounter);
|
||||
const nsString value(out);
|
||||
if (nsnull==HACKattribute)
|
||||
HACKattribute = NS_NewAtom("Steve's unbelievable hack attribute");
|
||||
SetAttribute(HACKattribute, value);
|
||||
HACKcounter++;
|
||||
/* end hack */
|
||||
}
|
||||
|
||||
nsTableRowGroup::~nsTableRowGroup()
|
||||
@ -124,7 +152,7 @@ NS_IMETHODIMP
|
||||
nsTableRowGroup::AppendChild (nsIContent *aContent, PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION(nsnull!=aContent, "bad arg to AppendChild");
|
||||
PRBool result = PR_TRUE;
|
||||
nsresult result = NS_OK;
|
||||
|
||||
// is aContent a TableRow?
|
||||
PRBool isRow = IsRow(aContent);
|
||||
@ -134,9 +162,16 @@ nsTableRowGroup::AppendChild (nsIContent *aContent, PRBool aNotify)
|
||||
{
|
||||
if (gsDebug==PR_TRUE) printf ("nsTableRowGroup::AppendChild -- inserting a row into this row group.\n");
|
||||
// if it is, we'll add it here
|
||||
nsTableContent::AppendChild (aContent, PR_FALSE);
|
||||
((nsTableRow *)aContent)->SetRowGroup (this);
|
||||
ResetCellMap ();
|
||||
result = nsTableContent::AppendChild (aContent, PR_FALSE);
|
||||
if (NS_OK==result)
|
||||
{
|
||||
((nsTableRow *)aContent)->SetRowGroup (this);
|
||||
// after each row insertion, make sure we have corresponding column content objects
|
||||
if (nsnull!=mTable)
|
||||
mTable->EnsureColumns();
|
||||
// also make sure the table cell map gets rebuilt
|
||||
ResetCellMap ();
|
||||
}
|
||||
}
|
||||
// otherwise, if it's a cell, create an implicit row for it
|
||||
else
|
||||
@ -165,20 +200,20 @@ nsTableRowGroup::AppendChild (nsIContent *aContent, PRBool aNotify)
|
||||
nsIAtom * trDefaultTag = NS_NewAtom(nsTablePart::kRowTagString); // trDefaultTag: REFCNT++
|
||||
row = new nsTableRow (trDefaultTag, PR_TRUE);
|
||||
NS_RELEASE(trDefaultTag); // trDefaultTag: REFCNT--
|
||||
AppendChild (row, PR_FALSE);
|
||||
result = AppendChild (row, PR_FALSE);
|
||||
// SEC: check result
|
||||
}
|
||||
// group is guaranteed to be allocated at this point
|
||||
row->AppendChild(aContent, PR_FALSE);
|
||||
result = row->AppendChild(aContent, PR_FALSE);
|
||||
}
|
||||
// otherwise, punt and let the table try to insert it. Or maybe just return a failure?
|
||||
else
|
||||
{
|
||||
// you should go talk to my parent if you want to insert something other than a row
|
||||
result = PR_FALSE;
|
||||
result = NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -194,15 +229,18 @@ nsTableRowGroup::InsertChildAt (nsIContent *aContent, PRInt32 aIndex,
|
||||
if (PR_FALSE==isRow)
|
||||
{
|
||||
// you should go talk to my parent if you want to insert something other than a column
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// if so, add the row to this group
|
||||
nsTableContent::InsertChildAt (aContent, aIndex, PR_FALSE);
|
||||
((nsTableRow *)aContent)->SetRowGroup (this);
|
||||
ResetCellMap ();
|
||||
nsresult result = nsTableContent::InsertChildAt (aContent, aIndex, PR_FALSE);
|
||||
if (NS_OK==result)
|
||||
{
|
||||
((nsTableRow *)aContent)->SetRowGroup (this);
|
||||
ResetCellMap ();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -213,19 +251,21 @@ nsTableRowGroup::ReplaceChildAt (nsIContent *aContent, PRInt32 aIndex,
|
||||
NS_PRECONDITION(nsnull!=aContent, "bad aContent arg to ReplaceChildAt");
|
||||
NS_PRECONDITION(0<=aIndex && aIndex<ChildCount(), "bad aIndex arg to ReplaceChildAt");
|
||||
if ((nsnull==aContent) || !(0<=aIndex && aIndex<ChildCount()))
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// is aContent a TableRow?
|
||||
PRBool isRow = IsRow(aContent);
|
||||
|
||||
// if not, ignore the request to replace the child at aIndex
|
||||
if (PR_FALSE==isRow)
|
||||
{
|
||||
// you should go talk to my parent if you want to insert something other than a column
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsIContent * lastChild = ChildAt (aIndex); // lastChild: REFCNT++
|
||||
nsTableContent::ReplaceChildAt (aContent, aIndex, PR_FALSE);
|
||||
nsresult result = nsTableContent::ReplaceChildAt (aContent, aIndex, PR_FALSE);
|
||||
if (NS_OK==result)
|
||||
{
|
||||
((nsTableRow *)aContent)->SetRowGroup (this);
|
||||
if (nsnull != lastChild)
|
||||
@ -233,7 +273,7 @@ nsTableRowGroup::ReplaceChildAt (nsIContent *aContent, PRInt32 aIndex,
|
||||
ResetCellMap ();
|
||||
}
|
||||
NS_IF_RELEASE(lastChild); // lastChild: REFCNT--
|
||||
return NS_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -245,17 +285,18 @@ nsTableRowGroup::RemoveChildAt (PRInt32 aIndex, PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION(0<=aIndex && aIndex<ChildCount(), "bad aIndex arg to RemoveChildAt");
|
||||
if (!(0<=aIndex && aIndex<ChildCount()))
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIContent * lastChild = ChildAt (aIndex); // lastChild: REFCNT++
|
||||
nsTableContent::RemoveChildAt (aIndex, PR_FALSE);
|
||||
nsresult result = nsTableContent::RemoveChildAt (aIndex, PR_FALSE);
|
||||
if (NS_OK==result)
|
||||
{
|
||||
if (nsnull != lastChild)
|
||||
((nsTableRow *)lastChild)->SetRowGroup (nsnull);
|
||||
ResetCellMap ();
|
||||
}
|
||||
NS_IF_RELEASE(lastChild); // lastChild: REFCNT--
|
||||
return NS_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** support method to determine if the param aContent is a TableRow object */
|
||||
|
@ -118,6 +118,7 @@ A:visited IMG { border: 2px solid purple; text-decoration: underline }
|
||||
A:active IMG { border: 2px solid lime; text-decoration: underline }
|
||||
A:out-of-date IMG { border: 2px solid red; text-decoration: underline }
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// The real stuff
|
||||
|
||||
|
@ -116,112 +116,6 @@ PRBool BasicTableLayoutStrategy::IsAutoWidth(nsStylePosition* aStylePosition)
|
||||
}
|
||||
|
||||
|
||||
// aSpecifiedTableWidth is filled if the table witdth is not auto
|
||||
PRBool BasicTableLayoutStrategy::TableIsAutoWidth(nsIStyleContext *aTableStyle,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord& aSpecifiedTableWidth)
|
||||
{
|
||||
NS_ASSERTION(nsnull!=aTableStyle, "bad arg - aTableStyle");
|
||||
PRBool result = PR_TRUE; // the default
|
||||
if (nsnull!=aTableStyle)
|
||||
{
|
||||
//nsStylePosition* tablePosition = (nsStylePosition*)aTableStyle->GetData(eStyleStruct_Position);
|
||||
/* this is sick and wrong, but what the hell
|
||||
we grab the style of our parent (nsTableOuterFrame) and ask it for width info,
|
||||
until the style resolution stuff does the cool stuff about splitting style between outer and inner
|
||||
*/
|
||||
// begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED!
|
||||
nsIStyleContext* parentStyle = nsnull;
|
||||
nsIFrame * parent = nsnull;
|
||||
mTableFrame->GetGeometricParent(parent);
|
||||
parent->GetStyleContext(nsnull, parentStyle);
|
||||
nsStylePosition* tablePosition = (nsStylePosition*)parentStyle->GetData(eStyleStruct_Position);
|
||||
// end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED!
|
||||
switch (tablePosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Auto: // specified auto width
|
||||
case eStyleUnit_Proportional: // illegal for table, so ignored
|
||||
break;
|
||||
|
||||
case eStyleUnit_Inherit:
|
||||
// get width of parent and see if it is a specified value or not
|
||||
// XXX for now, just return true
|
||||
break;
|
||||
|
||||
case eStyleUnit_Coord:
|
||||
aSpecifiedTableWidth = tablePosition->mWidth.GetCoordValue();
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
#ifdef STEVES_WAY
|
||||
case eStyleUnit_Percent:
|
||||
// get the parent's width (available only from parent frames that claim they can provide it)
|
||||
// note that we start with our parent's parent (the outer table frame's parent)
|
||||
nscoord parentWidth = 0;
|
||||
NS_ASSERTION(nsnull!=aReflowState.parentReflowState, "bad outer table reflow state.");
|
||||
NS_ASSERTION(nsnull!=aReflowState.parentReflowState->parentReflowState, "bad table parent reflow state.");
|
||||
if ((nsnull!=aReflowState.parentReflowState) &&
|
||||
(nsnull!=aReflowState.parentReflowState->parentReflowState))
|
||||
{
|
||||
const nsReflowState *parentReflowState = aReflowState.parentReflowState->parentReflowState;
|
||||
nsIFrame *parentFrame=parentReflowState->frame;
|
||||
NS_ASSERTION(nsnull!=parentFrame, "bad parent frame in reflow state struct.");
|
||||
while(nsnull!=parentFrame)
|
||||
{
|
||||
PRBool isPercentageBase=PR_FALSE;
|
||||
parentFrame->IsPercentageBase(isPercentageBase);
|
||||
if (PR_TRUE==isPercentageBase)
|
||||
{ // found the ancestor who claims to be the container to base my percentage width on
|
||||
parentWidth = parentReflowState->maxSize.width;
|
||||
if (PR_TRUE==gsDebug) printf(" ** width for parent frame %p = %d\n", parentFrame, parentWidth);
|
||||
break;
|
||||
}
|
||||
parentReflowState = parentReflowState->parentReflowState; // get next ancestor
|
||||
if (nsnull!=parentReflowState)
|
||||
parentFrame = parentReflowState->frame;
|
||||
else
|
||||
parentFrame = nsnull; // terminates loop.
|
||||
// TODO: do we need a backstop in case there are no IsPercentageBase==true frames?
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
case eStyleUnit_Percent:
|
||||
// Get the parent's width (available only from parent frames
|
||||
// that claim they can provide it, and assuming it's already
|
||||
// specified; that is, top-down layout sets the widths on the
|
||||
// way down.)
|
||||
nscoord parentWidth = aReflowState.maxSize.width;
|
||||
|
||||
// Walk up the reflow state chain until we find a block
|
||||
// frame. Our width is computed relative to there.
|
||||
const nsReflowState* rs = &aReflowState;
|
||||
while (nsnull != rs) {
|
||||
nsIFrame* block = nsnull;
|
||||
rs->frame->QueryInterface(kBlockFrameCID, (void**) &block);
|
||||
if (nsnull != block) {
|
||||
// We found the nearest containing block which defines what
|
||||
// a percentage size is relative to. Use the width that it
|
||||
// will reflow to as the basis for computing our width.
|
||||
parentWidth = rs->maxSize.width;
|
||||
break;
|
||||
}
|
||||
rs = rs->parentReflowState;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// set aSpecifiedTableWidth to be the given percent of the parent.
|
||||
float percent = tablePosition->mWidth.GetPercentValue();
|
||||
aSpecifiedTableWidth = (PRInt32)(parentWidth*percent);
|
||||
if (PR_TRUE==gsDebug) printf(" ** aSpecifiedTableWidth = %d\n", aSpecifiedTableWidth);
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame)
|
||||
{
|
||||
mTableFrame = aFrame;
|
||||
@ -260,12 +154,12 @@ PRBool BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresContex
|
||||
// Step 2 - determine how much space is really available
|
||||
PRInt32 availWidth = aMaxWidth - aTotalFixedWidth;
|
||||
nscoord tableWidth = 0;
|
||||
if (PR_FALSE==TableIsAutoWidth(aTableStyle, aReflowState, tableWidth))
|
||||
if (PR_FALSE==nsTableFrame::TableIsAutoWidth(mTableFrame, aTableStyle, aReflowState, tableWidth))
|
||||
availWidth = tableWidth - aTotalFixedWidth;
|
||||
|
||||
// Step 3 - assign the width of all proportional-width columns in the remaining space
|
||||
if (gsDebug==PR_TRUE) printf ("Step 2...\n availWidth = %d\n", availWidth);
|
||||
result = BalanceProportionalColumns(aPresContext,
|
||||
result = BalanceProportionalColumns(aPresContext, aReflowState,
|
||||
availWidth, aMaxWidth,
|
||||
aMinTableWidth, aMaxTableWidth,
|
||||
tableWidth);
|
||||
@ -525,6 +419,7 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
||||
|
||||
|
||||
PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPresContext,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord aAvailWidth,
|
||||
nscoord aMaxWidth,
|
||||
nscoord aMinTableWidth,
|
||||
@ -538,7 +433,7 @@ PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPre
|
||||
if (NS_UNCONSTRAINEDSIZE==aMaxWidth || NS_UNCONSTRAINEDSIZE==aMinTableWidth)
|
||||
{ // 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, aMaxWidth, aTableFixedWidth);
|
||||
result = BalanceColumnsTableFits(aPresContext, aReflowState, aAvailWidth, aMaxWidth, aTableFixedWidth);
|
||||
}
|
||||
else if (aMinTableWidth > aMaxWidth)
|
||||
{ // the table doesn't fit in the available space
|
||||
@ -548,7 +443,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, aMaxWidth, aTableFixedWidth);
|
||||
result = BalanceColumnsTableFits(aPresContext, aReflowState, aAvailWidth, aMaxWidth, aTableFixedWidth);
|
||||
}
|
||||
else
|
||||
{ // the table fits somewhere between its min and desired size
|
||||
@ -562,7 +457,7 @@ PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPre
|
||||
if (NS_UNCONSTRAINEDSIZE==aMinTableWidth)
|
||||
{ // the table has empty content, and needs to be streched to the specified width
|
||||
if (gsDebug) printf (" * specified width table > maxTableWidth, calling BalanceColumnsTableFits\n");
|
||||
result = BalanceColumnsTableFits(aPresContext, aAvailWidth, aMaxWidth, aTableFixedWidth);
|
||||
result = BalanceColumnsTableFits(aPresContext, aReflowState, aAvailWidth, aMaxWidth, aTableFixedWidth);
|
||||
}
|
||||
else if (aTableFixedWidth<aMinTableWidth)
|
||||
{ // the table's specified width doesn't fit in the available space
|
||||
@ -579,7 +474,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, aMaxWidth, aTableFixedWidth);
|
||||
result = BalanceColumnsTableFits(aPresContext, aReflowState, aAvailWidth, aMaxWidth, aTableFixedWidth);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -639,7 +534,8 @@ PRBool BasicTableLayoutStrategy::SetColumnsToMinWidth(nsIPresContext* aPresConte
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresContext,
|
||||
PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresContext,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord aAvailWidth,
|
||||
nscoord aMaxWidth,
|
||||
nscoord aTableFixedWidth)
|
||||
@ -652,7 +548,6 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
|
||||
PRBool result = PR_TRUE;
|
||||
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
|
||||
@ -675,10 +570,11 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
nsIStyleContextPtr colSC;
|
||||
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
|
||||
nsStylePosition* colPosition = (nsStylePosition*) colSC->GetData(eStyleStruct_Position);
|
||||
if (gsDebug) printf("col %d has frame %p with style %p and pos %p\n",
|
||||
colIndex, colFrame, (nsIStyleContext *)colSC, colPosition);
|
||||
|
||||
if (PR_FALSE==IsFixedWidth(colPosition))
|
||||
{
|
||||
numProportionalColumns++;
|
||||
// first, deal with any cells that span into this column from a pervious column
|
||||
if (nsnull!=spanList)
|
||||
{
|
||||
@ -720,7 +616,48 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
nsresult result = data->GetMargin(margin);
|
||||
nscoord marginWidth = margin.left + margin.right;
|
||||
PRInt32 cellMinWidth = cellMinSize->width/colSpan + marginWidth;
|
||||
PRInt32 cellDesiredWidth = cellDesiredSize->width/colSpan + marginWidth;
|
||||
// first get the desired size info from reflow pass 1
|
||||
PRInt32 cellDesiredWidth = cellDesiredSize->width/colSpan + marginWidth;
|
||||
// then get the desired size info factoring in the cell style attributes
|
||||
nscoord specifiedCellWidth=-1;
|
||||
nsIStyleContextPtr cellSC;
|
||||
data->GetCellFrame()->GetStyleContext(aPresContext, cellSC.AssignRef());
|
||||
nsStylePosition* cellPosition = (nsStylePosition*)
|
||||
cellSC->GetData(eStyleStruct_Position);
|
||||
switch (cellPosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
specifiedCellWidth = cellPosition->mWidth.GetCoordValue();
|
||||
if (gsDebug) printf("cell has specified coord width = %d\n", specifiedCellWidth);
|
||||
break;
|
||||
|
||||
case eStyleUnit_Percent:
|
||||
{
|
||||
nscoord tableWidth=0;
|
||||
nsIStyleContextPtr tableSC;
|
||||
mTableFrame->GetStyleContext(aPresContext, tableSC.AssignRef());
|
||||
PRBool tableIsAutoWidth = nsTableFrame::TableIsAutoWidth(mTableFrame, tableSC, aReflowState, tableWidth);
|
||||
float percent = cellPosition->mWidth.GetPercentValue();
|
||||
specifiedCellWidth = (PRInt32)(tableWidth*percent);
|
||||
if (gsDebug) printf("specified percent width %f of %d = %d\n",
|
||||
percent, tableWidth, specifiedCellWidth);
|
||||
break;
|
||||
}
|
||||
|
||||
case eStyleUnit_Inherit:
|
||||
// XXX for now, do nothing
|
||||
default:
|
||||
case eStyleUnit_Auto:
|
||||
break;
|
||||
}
|
||||
if (-1!=specifiedCellWidth)
|
||||
{
|
||||
if (specifiedCellWidth>cellMinWidth)
|
||||
{
|
||||
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
|
||||
cellDesiredWidth, specifiedCellWidth);
|
||||
cellDesiredWidth = specifiedCellWidth; // TODO: some math needed here for colspans
|
||||
}
|
||||
}
|
||||
|
||||
if (PR_TRUE==gsDebug)
|
||||
printf("factoring in cell %d with colSpan=%d\n factoring in min=%d and desired=%d\n",
|
||||
@ -750,15 +687,22 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
}
|
||||
|
||||
// Get column width if it has one
|
||||
nscoord specifiedProportion = -1;
|
||||
nscoord specifiedProportionColumnWidth = -1;
|
||||
float specifiedPercentageColWidth = -1.0f;
|
||||
nscoord specifiedFixedColumnWidth = -1;
|
||||
PRBool isAutoWidth = PR_FALSE;
|
||||
switch (colPosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
specifiedFixedColumnWidth = colPosition->mWidth.GetCoordValue();
|
||||
if (gsDebug) printf("column %d has specified coord width = %d\n", colIndex, specifiedFixedColumnWidth);
|
||||
break;
|
||||
case eStyleUnit_Percent:
|
||||
specifiedPercentageColWidth = colPosition->mWidth.GetPercentValue();
|
||||
if (gsDebug) printf("column %d has specified percent width = %f\n", colIndex, specifiedPercentageColWidth);
|
||||
break;
|
||||
case eStyleUnit_Proportional:
|
||||
specifiedProportion = colPosition->mWidth.GetIntValue();
|
||||
specifiedProportionColumnWidth = colPosition->mWidth.GetIntValue();
|
||||
if (gsDebug) printf("column %d has specified percent width = %d\n", colIndex, specifiedProportionColumnWidth);
|
||||
break;
|
||||
case eStyleUnit_Auto:
|
||||
isAutoWidth = PR_TRUE;
|
||||
@ -768,11 +712,11 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
}
|
||||
|
||||
/* set the column width, knowing that the table fits in the available space */
|
||||
if (0==specifiedProportion || 0.0==specifiedPercentageColWidth)
|
||||
if (0==specifiedProportionColumnWidth || 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",
|
||||
printf (" 3 min: col %d set to min width = %d because style set proportionalWidth=0\n",
|
||||
colIndex, mTableFrame->GetColumnWidth(colIndex));
|
||||
}
|
||||
else if (PR_TRUE==isAutoWidth)
|
||||
@ -781,10 +725,10 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
// 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",
|
||||
printf (" 3 auto: col %d with availWidth %d, set to width = %d\n",
|
||||
colIndex, aAvailWidth, mTableFrame->GetColumnWidth(colIndex));
|
||||
}
|
||||
else if (0!=specifiedProportion)
|
||||
else if (-1!=specifiedProportionColumnWidth)
|
||||
{ // 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
|
||||
@ -798,9 +742,23 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
if (nsnull==proportionalColumnsList)
|
||||
proportionalColumnsList = new nsVoidArray();
|
||||
ProportionalColumnLayoutStruct * info =
|
||||
new ProportionalColumnLayoutStruct(colIndex, minColWidth, maxColWidth, specifiedProportion);
|
||||
new ProportionalColumnLayoutStruct(colIndex, minColWidth,
|
||||
maxColWidth, specifiedProportionColumnWidth);
|
||||
proportionalColumnsList->AppendElement(info);
|
||||
totalSlices += specifiedProportion;
|
||||
totalSlices += specifiedProportionColumnWidth; // keep track of the total number of proportions
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf (" 3 proportional: col %d with availWidth %d, gets %d slices with %d slices so far.\n",
|
||||
colIndex, aAvailWidth, specifiedProportionColumnWidth, totalSlices);
|
||||
}
|
||||
else if (-1!=specifiedFixedColumnWidth)
|
||||
{
|
||||
// if the column was computed to be too small, enlarge the column
|
||||
nscoord resolvedWidth = specifiedFixedColumnWidth;
|
||||
if (specifiedFixedColumnWidth <= minColWidth)
|
||||
resolvedWidth = minColWidth;
|
||||
mTableFrame->SetColumnWidth(colIndex, resolvedWidth);
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf (" 3 fixed: col %d given %d\n", colIndex, resolvedWidth);
|
||||
}
|
||||
else
|
||||
{ // give each remaining column a percentage of the remaining space
|
||||
@ -816,14 +774,14 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
if (-1==percentage)
|
||||
percentage = 100/numCols;
|
||||
// base the % on the total max width
|
||||
mTableFrame->SetColumnWidth(colIndex, (percentage*aMaxWidth)/100);
|
||||
mTableFrame->SetColumnWidth(colIndex, (percentage*aAvailWidth)/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 aMaxWidth %d, set to width = %d\n",
|
||||
colIndex, percentage, aMaxWidth, mTableFrame->GetColumnWidth(colIndex));
|
||||
printf (" 3 percent: col %d given %d percent of aAvailWidth %d, set to width = %d\n",
|
||||
colIndex, percentage, aAvailWidth, mTableFrame->GetColumnWidth(colIndex));
|
||||
}
|
||||
}
|
||||
tableWidth += mTableFrame->GetColumnWidth(colIndex);
|
||||
@ -845,7 +803,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
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",
|
||||
printf (" 3 proportional step 2: col %d given %d proportion of remaining space %d, set to width = %d\n",
|
||||
info->mColIndex, info->mProportion, widthRemaining, computedColWidth);
|
||||
tableWidth += computedColWidth;
|
||||
delete info;
|
||||
@ -859,26 +817,34 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
||||
if (aTableFixedWidth > tableWidth)
|
||||
{
|
||||
nscoord excess = aTableFixedWidth - tableWidth;
|
||||
// if there are proportionally-sized columns, give them the extra space
|
||||
if (0!=numProportionalColumns)
|
||||
if (gsDebug) printf ("fixed width %d > computed table width %d, excess = %d\n",
|
||||
aTableFixedWidth, tableWidth, excess);
|
||||
// if there are auto-sized columns, give them the extra space
|
||||
PRInt32 numAutoColumns;
|
||||
PRInt32 *autoColumns;
|
||||
mTableFrame->GetColumnsByType(eStyleUnit_Auto, numAutoColumns, autoColumns);
|
||||
if (0!=numAutoColumns)
|
||||
{
|
||||
nscoord excessPerColumn = excess/numProportionalColumns;
|
||||
if (gsDebug==PR_TRUE) printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess);
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
// TODO - should extra space be proportionately distributed?
|
||||
nscoord excessPerColumn = excess/numAutoColumns;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess);
|
||||
for (PRInt32 i = 0; i<numAutoColumns; i++)
|
||||
{
|
||||
// need the column style here!
|
||||
if (PR_FALSE==IsFixedWidth(nsnull))
|
||||
{
|
||||
nscoord colWidth = excessPerColumn+mTableFrame->GetColumnWidth(colIndex);
|
||||
mTableFrame->SetColumnWidth(colIndex, colWidth);
|
||||
}
|
||||
PRInt32 colIndex = autoColumns[i];
|
||||
nscoord colWidth = excessPerColumn+mTableFrame->GetColumnWidth(colIndex);
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" column %d was %d, now set to %d\n", colIndex, mTableFrame->GetColumnWidth(colIndex), colWidth);
|
||||
mTableFrame->SetColumnWidth(colIndex, colWidth);
|
||||
}
|
||||
}
|
||||
// otherwise, distribute the space evenly between all the columns
|
||||
// otherwise, distribute the space evenly between all the columns (they must be all fixed and percentage-width columns)
|
||||
// TODO - should extra space be proportionately distributed?
|
||||
else
|
||||
{
|
||||
nscoord excessPerColumn = excess/numCols;
|
||||
if (gsDebug==PR_TRUE) printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess);
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess);
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
{
|
||||
nscoord colWidth = excessPerColumn+mTableFrame->GetColumnWidth(colIndex);
|
||||
@ -907,7 +873,6 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
||||
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=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
|
||||
PRBool equalWidthColumns = PR_TRUE; // remember if we're in the special case where all
|
||||
|
@ -103,6 +103,7 @@ public:
|
||||
*
|
||||
*/
|
||||
virtual PRBool BalanceProportionalColumns(nsIPresContext* aPresContext,
|
||||
const nsReflowState& aReflowState,
|
||||
PRInt32 aAvailWidth,
|
||||
PRInt32 aMaxWidth,
|
||||
PRInt32 aMinTableWidth,
|
||||
@ -132,6 +133,7 @@ public:
|
||||
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
|
||||
*/
|
||||
virtual PRBool BalanceColumnsTableFits(nsIPresContext* aPresContext,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord aAvailWidth,
|
||||
nscoord aMaxWidth,
|
||||
nscoord aTableFixedWidth);
|
||||
@ -166,10 +168,6 @@ public:
|
||||
|
||||
virtual PRBool IsAutoWidth(nsStylePosition* aStylePosition);
|
||||
|
||||
virtual PRBool TableIsAutoWidth(nsIStyleContext *aTableStyle,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord& aSpecifiedTableWidth);
|
||||
|
||||
protected:
|
||||
nsTableFrame * mTableFrame;
|
||||
|
||||
|
@ -27,8 +27,12 @@
|
||||
#include "nsIContentDelegate.h"
|
||||
#include "nsCSSLayout.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsIPtr.h"
|
||||
#include "nsIView.h"
|
||||
|
||||
NS_DEF_PTR(nsIStyleContext);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gsDebug = PR_FALSE;
|
||||
//#define NOISY_STYLE
|
||||
@ -297,6 +301,42 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
CreatePsuedoFrame(aPresContext);
|
||||
}
|
||||
|
||||
// Determine the width we have to work with
|
||||
nscoord cellWidth = -1;
|
||||
if (NS_UNCONSTRAINEDSIZE!=availSize.width)
|
||||
{
|
||||
/*
|
||||
nsStylePosition* kidPosition = (nsStylePosition*)
|
||||
mStyleContext->GetData(eStyleStruct_Position);
|
||||
switch (kidPosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
cellWidth = kidPosition->mWidth.GetCoordValue();
|
||||
break;
|
||||
|
||||
case eStyleUnit_Percent:
|
||||
{
|
||||
nscoord tableWidth=0;
|
||||
const nsReflowState *tableReflowState = aReflowState.parentReflowState->parentReflowState->parentReflowState;
|
||||
nsTableFrame *tableFrame = (nsTableFrame *)(tableReflowState->frame);
|
||||
nsIStyleContextPtr tableSC;
|
||||
tableFrame->GetStyleContext(aPresContext, tableSC.AssignRef());
|
||||
PRBool tableIsAutoWidth = nsTableFrame::TableIsAutoWidth(tableFrame, tableSC, *tableReflowState, tableWidth);
|
||||
float percent = kidPosition->mWidth.GetPercentValue();
|
||||
cellWidth = (PRInt32)(tableWidth*percent);
|
||||
break;
|
||||
}
|
||||
|
||||
case eStyleUnit_Inherit:
|
||||
// XXX for now, do nothing
|
||||
default:
|
||||
case eStyleUnit_Auto:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
if (-1!=cellWidth)
|
||||
availSize.width = cellWidth;
|
||||
}
|
||||
|
||||
// Try to reflow the child into the available space. It might not
|
||||
// fit or might need continuing.
|
||||
if (availSize.height < 0)
|
||||
@ -325,14 +365,13 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
SetFirstContentOffset(mFirstChild);
|
||||
if (gsDebug) printf("CELL: set first content offset to %d\n", GetFirstContentOffset()); //@@@
|
||||
//if (gsDebug) printf("CELL: set first content offset to %d\n", GetFirstContentOffset()); //@@@
|
||||
SetLastContentOffset(mFirstChild);
|
||||
if (gsDebug) printf("CELL: set last content offset to %d\n", GetLastContentOffset()); //@@@
|
||||
//if (gsDebug) printf("CELL: set last content offset to %d\n", GetLastContentOffset()); //@@@
|
||||
|
||||
// Place the child since some of it's content fit in us.
|
||||
// Place the child
|
||||
mFirstChild->SetRect(nsRect(leftInset, topInset,
|
||||
kidSize.width, kidSize.height));
|
||||
|
||||
kidSize.width, kidSize.height));
|
||||
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||
// If the child didn't finish layout then it means that it used
|
||||
@ -341,19 +380,22 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
// Return our size and our result
|
||||
PRInt32 kidWidth = kidSize.width;
|
||||
if (NS_UNCONSTRAINEDSIZE!=kidSize.width) //&& NS_UNCONSTRAINEDSIZE!=aMaxSize.width)
|
||||
kidWidth += leftInset + rightInset;
|
||||
PRInt32 kidHeight = kidSize.height;
|
||||
|
||||
// height can be set w/o being restricted by aMaxSize.height
|
||||
if (NS_UNCONSTRAINEDSIZE!=kidSize.height)
|
||||
kidHeight += topInset + bottomInset;
|
||||
aDesiredSize.width = kidWidth;
|
||||
aDesiredSize.height = kidHeight;
|
||||
// first, compute the height
|
||||
// the height can be set w/o being restricted by aMaxSize.height
|
||||
nscoord cellHeight = kidSize.height;
|
||||
if (NS_UNCONSTRAINEDSIZE!=cellHeight)
|
||||
cellHeight += topInset + bottomInset;
|
||||
// next determine the cell's width
|
||||
cellWidth = kidSize.width; // at this point, we've factored in the cell's style attributes
|
||||
if (NS_UNCONSTRAINEDSIZE!=cellWidth)
|
||||
cellWidth += leftInset + rightInset;
|
||||
|
||||
// set the cell's desired size and max element size
|
||||
aDesiredSize.width = cellWidth;
|
||||
aDesiredSize.height = cellHeight;
|
||||
aDesiredSize.ascent = topInset;
|
||||
aDesiredSize.descent = bottomInset;
|
||||
|
||||
if (nsnull!=aDesiredSize.maxElementSize)
|
||||
{
|
||||
*aDesiredSize.maxElementSize = *pMaxElementSize;
|
||||
|
@ -37,6 +37,9 @@ public:
|
||||
const nsReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
/** return the index of the column this content object represents. always >= 0 */
|
||||
virtual int GetColumnIndex ();
|
||||
|
||||
protected:
|
||||
|
||||
nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "nsTableCell.h"
|
||||
#include "nsTableCellFrame.h"
|
||||
#include "nsTableCol.h"
|
||||
#include "nsTableColFrame.h"
|
||||
#include "nsTableRowFrame.h"
|
||||
#include "nsTableRowGroupFrame.h"
|
||||
#include "nsColLayoutData.h"
|
||||
@ -41,6 +42,7 @@
|
||||
#include "nsIPtr.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gsDebug = PR_FALSE;
|
||||
@ -135,6 +137,117 @@ struct InnerTableReflowState {
|
||||
}
|
||||
};
|
||||
|
||||
/* ----------- ColumnInfoCache ---------- */
|
||||
|
||||
static const PRInt32 NUM_COL_WIDTH_TYPES=4;
|
||||
|
||||
class ColumnInfoCache
|
||||
{
|
||||
public:
|
||||
ColumnInfoCache(PRInt32 aNumColumns);
|
||||
~ColumnInfoCache();
|
||||
|
||||
void AddColumnInfo(const nsStyleUnit aType,
|
||||
PRInt32 aColumnIndex);
|
||||
|
||||
void GetColumnsByType(const nsStyleUnit aType,
|
||||
PRInt32& aOutNumColumns,
|
||||
PRInt32 *& aOutColumnIndexes);
|
||||
enum ColWidthType {
|
||||
eColWidthType_Auto = 0, // width based on contents
|
||||
eColWidthType_Percent = 1, // (float) 1.0 == 100%
|
||||
eColWidthType_Coord = 2, // (nscoord) value is twips
|
||||
eColWidthType_Proportional = 3, // (int) value has proportional meaning
|
||||
};
|
||||
|
||||
private:
|
||||
PRInt32 mColCounts [4];
|
||||
PRInt32 *mColIndexes[4];
|
||||
PRInt32 mNumColumns;
|
||||
};
|
||||
|
||||
ColumnInfoCache::ColumnInfoCache(PRInt32 aNumColumns)
|
||||
{
|
||||
mNumColumns = aNumColumns;
|
||||
for (PRInt32 i=0; i<NUM_COL_WIDTH_TYPES; i++)
|
||||
{
|
||||
mColCounts[i] = 0;
|
||||
mColIndexes[i] = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
ColumnInfoCache::~ColumnInfoCache()
|
||||
{
|
||||
for (PRInt32 i=0; i<NUM_COL_WIDTH_TYPES; i++)
|
||||
{
|
||||
if (nsnull!=mColIndexes[i])
|
||||
{
|
||||
delete [] mColIndexes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ColumnInfoCache::AddColumnInfo(const nsStyleUnit aType,
|
||||
PRInt32 aColumnIndex)
|
||||
{
|
||||
switch (aType)
|
||||
{
|
||||
case eStyleUnit_Auto:
|
||||
if (nsnull==mColIndexes[eColWidthType_Auto])
|
||||
mColIndexes[eColWidthType_Auto] = new PRInt32[mNumColumns]; // TODO : be much more efficient
|
||||
mColIndexes[eColWidthType_Auto][mColCounts[eColWidthType_Auto]] = aColumnIndex;
|
||||
mColCounts[eColWidthType_Auto]++;
|
||||
break;
|
||||
|
||||
case eStyleUnit_Percent:
|
||||
if (nsnull==mColIndexes[eColWidthType_Percent])
|
||||
mColIndexes[eColWidthType_Percent] = new PRInt32[mNumColumns]; // TODO : be much more efficient
|
||||
mColIndexes[eColWidthType_Percent][mColCounts[eColWidthType_Percent]] = aColumnIndex;
|
||||
mColCounts[eColWidthType_Percent]++;
|
||||
break;
|
||||
|
||||
case eStyleUnit_Coord:
|
||||
if (nsnull==mColIndexes[eColWidthType_Coord])
|
||||
mColIndexes[eColWidthType_Coord] = new PRInt32[mNumColumns]; // TODO : be much more efficient
|
||||
mColIndexes[eColWidthType_Coord][mColCounts[eColWidthType_Coord]] = aColumnIndex;
|
||||
mColCounts[eColWidthType_Coord]++;
|
||||
break;
|
||||
|
||||
case eStyleUnit_Proportional:
|
||||
if (nsnull==mColIndexes[eColWidthType_Proportional])
|
||||
mColIndexes[eColWidthType_Proportional] = new PRInt32[mNumColumns]; // TODO : be much more efficient
|
||||
mColIndexes[eColWidthType_Proportional][mColCounts[eColWidthType_Proportional]] = aColumnIndex;
|
||||
mColCounts[eColWidthType_Proportional]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ColumnInfoCache::GetColumnsByType(const nsStyleUnit aType,
|
||||
PRInt32& aOutNumColumns,
|
||||
PRInt32 *& aOutColumnIndexes)
|
||||
{
|
||||
switch (aType)
|
||||
{
|
||||
case eStyleUnit_Auto:
|
||||
aOutNumColumns = mColCounts[eColWidthType_Auto];
|
||||
aOutColumnIndexes = mColIndexes[eColWidthType_Auto];
|
||||
break;
|
||||
case eStyleUnit_Percent:
|
||||
aOutNumColumns = mColCounts[eColWidthType_Percent];
|
||||
aOutColumnIndexes = mColIndexes[eColWidthType_Percent];
|
||||
break;
|
||||
case eStyleUnit_Coord:
|
||||
aOutNumColumns = mColCounts[eColWidthType_Coord];
|
||||
aOutColumnIndexes = mColIndexes[eColWidthType_Coord];
|
||||
break;
|
||||
case eStyleUnit_Proportional:
|
||||
aOutNumColumns = mColCounts[eColWidthType_Proportional];
|
||||
aOutColumnIndexes = mColIndexes[eColWidthType_Proportional];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ----------- nsTableFrame ---------- */
|
||||
@ -143,6 +256,7 @@ struct InnerTableReflowState {
|
||||
nsTableFrame::nsTableFrame(nsIContent* aContent, nsIFrame* aParentFrame)
|
||||
: nsContainerFrame(aContent, aParentFrame),
|
||||
mColumnLayoutData(nsnull),
|
||||
mColCache(nsnull),
|
||||
mColumnWidths(nsnull),
|
||||
mTableLayoutStrategy(nsnull),
|
||||
mFirstPassValid(PR_FALSE),
|
||||
@ -177,6 +291,8 @@ nsTableFrame::~nsTableFrame()
|
||||
delete [] mColumnWidths;
|
||||
if (nsnull!=mTableLayoutStrategy)
|
||||
delete mTableLayoutStrategy;
|
||||
if (nsnull!=mColCache)
|
||||
delete mColCache;
|
||||
}
|
||||
|
||||
|
||||
@ -1891,6 +2007,8 @@ void nsTableFrame::ShrinkWrapChildren(nsIPresContext* aPresContext,
|
||||
rowGroupFrame->GetSize(rowGroupFrameSize);
|
||||
rowGroupFrame->SizeTo(rowGroupFrameSize.width, rowGroupHeight);
|
||||
tableHeight += rowGroupHeight;
|
||||
if (nsnull!=rowHeights)
|
||||
delete [] rowHeights;
|
||||
}
|
||||
}
|
||||
if (0!=tableHeight)
|
||||
@ -1904,12 +2022,61 @@ void nsTableFrame::ShrinkWrapChildren(nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
void nsTableFrame::VerticallyAlignChildren(nsIPresContext* aPresContext,
|
||||
nscoord* aAscents,
|
||||
nscoord aMaxAscent,
|
||||
nscoord aMaxHeight)
|
||||
nscoord* aAscents,
|
||||
nscoord aMaxAscent,
|
||||
nscoord aMaxHeight)
|
||||
{
|
||||
}
|
||||
|
||||
/* there's an easy way and a hard way. The easy way is to look in our
|
||||
* cache and pull the frame from there.
|
||||
* If the cache isn't built yet, then we have to go hunting.
|
||||
*/
|
||||
NS_METHOD nsTableFrame::GetColumnFrame(PRInt32 aColIndex, nsTableColFrame *&aColFrame)
|
||||
{
|
||||
aColFrame = nsnull; // initialize out parameter
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
if (nsnull!=firstInFlow->mColumnLayoutData)
|
||||
{ // hooray, we get to do this the easy way because the info is cached
|
||||
nsColLayoutData * colData = (nsColLayoutData *)
|
||||
(firstInFlow->mColumnLayoutData->ElementAt(aColIndex));
|
||||
NS_ASSERTION(nsnull != colData, "bad column data");
|
||||
aColFrame = colData->GetColFrame();
|
||||
NS_ASSERTION(nsnull!=aColFrame, "bad col frame");
|
||||
}
|
||||
else
|
||||
{ // ah shucks, we have to go hunt for the column frame brute-force style
|
||||
nsIFrame *childFrame;
|
||||
FirstChild(childFrame);
|
||||
for (;;)
|
||||
{
|
||||
if (nsnull==childFrame)
|
||||
{
|
||||
NS_ASSERTION (PR_FALSE, "scanned the frame hierarchy and no column frame could be found.");
|
||||
break;
|
||||
}
|
||||
nsIContentPtr kid;
|
||||
childFrame->GetContent(kid.AssignRef());
|
||||
const PRInt32 contentType = ((nsTableContent *)(nsIContent*)kid)->GetType();
|
||||
if (contentType==nsITableContent::kTableColGroupType)
|
||||
{
|
||||
nsTableColGroup *colGroup = (nsTableColGroup *)((nsIContent*)kid);
|
||||
PRInt32 colGroupStartingIndex = colGroup->GetStartColumnIndex();
|
||||
if (aColIndex >= colGroupStartingIndex)
|
||||
{ // the cell's col might be in this col group
|
||||
if (aColIndex < colGroupStartingIndex + colGroup->ChildCount())
|
||||
{ // yep, we've found it
|
||||
childFrame->ChildAt(aColIndex-colGroupStartingIndex, (nsIFrame *&)aColFrame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
childFrame->GetNextSibling(childFrame);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsVoidArray * nsTableFrame::GetColumnLayoutData()
|
||||
{
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
@ -1922,7 +2089,8 @@ nsVoidArray * nsTableFrame::GetColumnLayoutData()
|
||||
* @return PR_TRUE if the data was successfully associated with a Cell
|
||||
* PR_FALSE if there was an error, such as aRow or aCol being invalid
|
||||
*/
|
||||
PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aCell)
|
||||
PRBool nsTableFrame::SetCellLayoutData(nsIPresContext* aPresContext,
|
||||
nsCellLayoutData * aData, nsTableCell *aCell)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aData, "bad arg");
|
||||
NS_ASSERTION(nsnull != aCell, "bad arg");
|
||||
@ -1932,7 +2100,7 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
||||
if (this!=firstInFlow)
|
||||
result = firstInFlow->SetCellLayoutData(aData, aCell);
|
||||
result = firstInFlow->SetCellLayoutData(aPresContext, aData, aCell);
|
||||
else
|
||||
{
|
||||
if (kPASS_FIRST==GetReflowPass())
|
||||
@ -1943,6 +2111,7 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
|
||||
NS_ASSERTION(nsnull != mColumnLayoutData, "bad alloc");
|
||||
nsTablePart * tablePart = (nsTablePart *)mContent;
|
||||
PRInt32 cols = tablePart->GetMaxColumns();
|
||||
mColCache = new ColumnInfoCache(cols);
|
||||
PRInt32 tableKidCount = tablePart->ChildCount();
|
||||
nsIFrame * colGroupFrame = mFirstChild;
|
||||
for (PRInt32 i=0; i<tableKidCount; i++)
|
||||
@ -1955,6 +2124,9 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
|
||||
PRInt32 colsInGroup = tableKid->ChildCount();
|
||||
for (PRInt32 j=0; j<colsInGroup; j++)
|
||||
{
|
||||
// TODO: unify these 2 kinds of column data
|
||||
// TODO: cache more column data, like the mWidth.GetUnit and what its value
|
||||
|
||||
nsTableColPtr col = (nsTableCol *)tableKid->ChildAt(j);
|
||||
NS_ASSERTION(col.IsNotNull(), "bad content");
|
||||
nsColLayoutData *colData = new nsColLayoutData(col);
|
||||
@ -1962,6 +2134,13 @@ PRBool nsTableFrame::SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aC
|
||||
colGroupFrame->ChildAt(j, (nsIFrame *&)colFrame);
|
||||
colData->SetColFrame(colFrame);
|
||||
mColumnLayoutData->AppendElement((void *)colData);
|
||||
|
||||
// also add the column to the column cache
|
||||
// assumes that the col style has been twiddled to account for first cell width attribute
|
||||
nsIStyleContextPtr colSC;
|
||||
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
|
||||
nsStylePosition* colPosition = (nsStylePosition*)colSC->GetData(eStyleStruct_Position);
|
||||
mColCache->AddColumnInfo(colPosition->mWidth.GetUnit(), colFrame->GetColumnIndex());
|
||||
}
|
||||
}
|
||||
// can't have col groups after row groups, so stop if you find a row group
|
||||
@ -2349,6 +2528,14 @@ NS_METHOD nsTableFrame::GetCellMarginData(nsIFrame* aKidFrame, nsMargin& aMargin
|
||||
return result;
|
||||
}
|
||||
|
||||
void nsTableFrame::GetColumnsByType(const nsStyleUnit aType,
|
||||
PRInt32& aOutNumColumns,
|
||||
PRInt32 *& aOutColumnIndexes)
|
||||
{
|
||||
mColCache->GetColumnsByType(aType, aOutNumColumns, aOutColumnIndexes);
|
||||
}
|
||||
|
||||
|
||||
/* ---------- static methods ---------- */
|
||||
|
||||
nsresult nsTableFrame::NewFrame(nsIFrame** aInstancePtrResult,
|
||||
@ -2367,6 +2554,115 @@ nsresult nsTableFrame::NewFrame(nsIFrame** aInstancePtrResult,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* helper method for getting the width of the table's containing block */
|
||||
nscoord nsTableFrame::GetTableContainerWidth(const nsReflowState& aReflowState)
|
||||
{
|
||||
#ifdef STEVES_WAY // from BasicTableLayoutStrategy::TableIsAutoWidth()
|
||||
// get the parent's width (available only from parent frames that claim they can provide it)
|
||||
// note that we start with our parent's parent (the outer table frame's parent)
|
||||
nscoord parentWidth = 0;
|
||||
NS_ASSERTION(nsnull!=aReflowState.parentReflowState, "bad outer table reflow state.");
|
||||
NS_ASSERTION(nsnull!=aReflowState.parentReflowState->parentReflowState, "bad table parent reflow state.");
|
||||
if ((nsnull!=aReflowState.parentReflowState) &&
|
||||
(nsnull!=aReflowState.parentReflowState->parentReflowState))
|
||||
{
|
||||
const nsReflowState *parentReflowState = aReflowState.parentReflowState->parentReflowState;
|
||||
nsIFrame *parentFrame=parentReflowState->frame;
|
||||
NS_ASSERTION(nsnull!=parentFrame, "bad parent frame in reflow state struct.");
|
||||
while(nsnull!=parentFrame)
|
||||
{
|
||||
PRBool isPercentageBase=PR_FALSE;
|
||||
parentFrame->IsPercentageBase(isPercentageBase);
|
||||
if (PR_TRUE==isPercentageBase)
|
||||
{ // found the ancestor who claims to be the container to base my percentage width on
|
||||
parentWidth = parentReflowState->maxSize.width;
|
||||
if (PR_TRUE==gsDebug) printf(" ** width for parent frame %p = %d\n", parentFrame, parentWidth);
|
||||
break;
|
||||
}
|
||||
parentReflowState = parentReflowState->parentReflowState; // get next ancestor
|
||||
if (nsnull!=parentReflowState)
|
||||
parentFrame = parentReflowState->frame;
|
||||
else
|
||||
parentFrame = nsnull; // terminates loop.
|
||||
// TODO: do we need a backstop in case there are no IsPercentageBase==true frames?
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
nscoord parentWidth = aReflowState.maxSize.width;
|
||||
|
||||
// Walk up the reflow state chain until we find a block
|
||||
// frame. Our width is computed relative to there.
|
||||
const nsReflowState* rs = &aReflowState;
|
||||
while (nsnull != rs) {
|
||||
nsIFrame* block = nsnull;
|
||||
rs->frame->QueryInterface(kBlockFrameCID, (void**) &block);
|
||||
if (nsnull != block) {
|
||||
// We found the nearest containing block which defines what
|
||||
// a percentage size is relative to. Use the width that it
|
||||
// will reflow to as the basis for computing our width.
|
||||
parentWidth = rs->maxSize.width;
|
||||
break;
|
||||
}
|
||||
rs = rs->parentReflowState;
|
||||
}
|
||||
|
||||
#endif
|
||||
return parentWidth;
|
||||
}
|
||||
|
||||
// aSpecifiedTableWidth is filled if the table witdth is not auto
|
||||
PRBool nsTableFrame::TableIsAutoWidth(nsTableFrame *aTableFrame,
|
||||
nsIStyleContext *aTableStyle,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord& aSpecifiedTableWidth)
|
||||
{
|
||||
NS_ASSERTION(nsnull!=aTableStyle, "bad arg - aTableStyle");
|
||||
PRBool result = PR_TRUE; // the default
|
||||
if (nsnull!=aTableStyle)
|
||||
{
|
||||
//nsStylePosition* tablePosition = (nsStylePosition*)aTableStyle->GetData(eStyleStruct_Position);
|
||||
/* this is sick and wrong, but what the hell
|
||||
we grab the style of our parent (nsTableOuterFrame) and ask it for width info,
|
||||
until the style resolution stuff does the cool stuff about splitting style between outer and inner
|
||||
*/
|
||||
// begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED!
|
||||
nsIStyleContext* parentStyle = nsnull;
|
||||
nsIFrame * parent = nsnull;
|
||||
aTableFrame->GetGeometricParent(parent);
|
||||
parent->GetStyleContext(nsnull, parentStyle);
|
||||
nsStylePosition* tablePosition = (nsStylePosition*)parentStyle->GetData(eStyleStruct_Position);
|
||||
// end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED!
|
||||
switch (tablePosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Auto: // specified auto width
|
||||
case eStyleUnit_Proportional: // illegal for table, so ignored
|
||||
break;
|
||||
|
||||
case eStyleUnit_Inherit:
|
||||
// get width of parent and see if it is a specified value or not
|
||||
// XXX for now, just return true
|
||||
break;
|
||||
|
||||
case eStyleUnit_Coord:
|
||||
aSpecifiedTableWidth = tablePosition->mWidth.GetCoordValue();
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
|
||||
case eStyleUnit_Percent:
|
||||
// set aSpecifiedTableWidth to be the given percent of the parent.
|
||||
nscoord parentWidth = nsTableFrame::GetTableContainerWidth(aReflowState);
|
||||
float percent = tablePosition->mWidth.GetPercentValue();
|
||||
aSpecifiedTableWidth = (PRInt32)(parentWidth*percent);
|
||||
if (PR_TRUE==gsDebug) printf(" ** aSpecifiedTableWidth = %d\n", aSpecifiedTableWidth);
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* valuable code not yet used anywhere
|
||||
|
||||
// since the table is a specified width, we need to expand the columns to fill the table
|
||||
|
@ -25,12 +25,15 @@ class nsCellLayoutData;
|
||||
class nsTableCell;
|
||||
class nsVoidArray;
|
||||
class nsTableCellFrame;
|
||||
class nsTableColFrame;
|
||||
class CellData;
|
||||
class nsITableLayoutStrategy;
|
||||
class nsHTMLValue;
|
||||
class ColumnInfoCache;
|
||||
struct InnerTableReflowState;
|
||||
struct nsStylePosition;
|
||||
struct nsStyleSpacing;
|
||||
enum nsStyleUnit;
|
||||
|
||||
/** nsTableFrame maps the inner portion of a table (everything except captions.)
|
||||
* Used as a pseudo-frame within nsTableOuterFrame,
|
||||
@ -59,6 +62,15 @@ public:
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent);
|
||||
|
||||
/** helper method for getting the width of the table's containing block */
|
||||
static nscoord GetTableContainerWidth(const nsReflowState& aState);
|
||||
|
||||
|
||||
static PRBool TableIsAutoWidth(nsTableFrame *aTableFrame,
|
||||
nsIStyleContext *aTableStyle,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord& aSpecifiedTableWidth);
|
||||
|
||||
/** @see nsIFrame::Paint */
|
||||
NS_IMETHOD Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
@ -108,16 +120,29 @@ public:
|
||||
nsReflowMetrics& aDesiredSize,
|
||||
nsSize* aMaxElementSize);
|
||||
|
||||
/** return the column frame corresponding to the given column index
|
||||
* there are two ways to do this, depending on whether we have cached
|
||||
* column information yet.
|
||||
*/
|
||||
NS_METHOD GetColumnFrame(PRInt32 aColIndex, nsTableColFrame *&aColFrame);
|
||||
|
||||
/** return the column layout data for this inner table frame.
|
||||
* if this is a continuing frame, return the first-in-flow's column layout data.
|
||||
*/
|
||||
virtual nsVoidArray *GetColumnLayoutData();
|
||||
|
||||
/** Associate aData with the cell at (aRow,aCol)
|
||||
*
|
||||
* @param aPresContext -- used to resolve style when initializing caches
|
||||
* @param aData -- the info to cache
|
||||
* @param aCell -- the content object for which layout info is being cached
|
||||
*
|
||||
* @return PR_TRUE if the data was successfully associated with a Cell
|
||||
* PR_FALSE if there was an error, such as aRow or aCol being invalid
|
||||
*/
|
||||
virtual PRBool SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aCell);
|
||||
virtual PRBool SetCellLayoutData(nsIPresContext* aPresContext,
|
||||
nsCellLayoutData * aData,
|
||||
nsTableCell *aCell);
|
||||
|
||||
/** Get the layout data associated with the cell at (aRow,aCol)
|
||||
* @return PR_NULL if there was an error, such as aRow or aCol being invalid
|
||||
@ -154,6 +179,18 @@ public:
|
||||
// Get cell margin information
|
||||
NS_IMETHOD GetCellMarginData(nsIFrame* aKidFrame, nsMargin& aMargin);
|
||||
|
||||
/** get cached column information for a subset of the columns
|
||||
*
|
||||
* @param aType -- information is returned for the subset of columns with aType style
|
||||
* @param aOutNumColumns -- out param, the number of columns matching aType
|
||||
* @param aOutColumnIndexes -- out param, the indexes of the columns matching aType
|
||||
*
|
||||
* TODO : make aOutColumnIndexes safe
|
||||
*/
|
||||
void GetColumnsByType(const nsStyleUnit aType,
|
||||
PRInt32& aOutNumColumns,
|
||||
PRInt32 *& aOutColumnIndexes);
|
||||
|
||||
// For DEBUGGING Purposes Only
|
||||
NS_IMETHOD MoveTo(nscoord aX, nscoord aY);
|
||||
NS_IMETHOD SizeTo(nscoord aWidth, nscoord aHeight);
|
||||
@ -304,6 +341,8 @@ private:
|
||||
|
||||
nsVoidArray *mColumnLayoutData; // array of array of cellLayoutData's
|
||||
PRInt32 *mColumnWidths; // widths of each column
|
||||
//TODO: move all column info into this object
|
||||
ColumnInfoCache *mColCache; // cached information about the table columns
|
||||
PRBool mFirstPassValid; // PR_TRUE if first pass data is still legit
|
||||
PRInt32 mPass; // which Reflow pass are we currently in?
|
||||
PRBool mIsInvariantWidth; // PR_TRUE if table width cannot change
|
||||
|
@ -23,9 +23,11 @@
|
||||
#include "nsIContent.h"
|
||||
#include "nsIContentDelegate.h"
|
||||
#include "nsTableFrame.h"
|
||||
#include "nsTableColFrame.h"
|
||||
#include "nsTableCellFrame.h"
|
||||
#include "nsTableCell.h"
|
||||
#include "nsCellLayoutData.h"
|
||||
#include "nsColLayoutData.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIPtr.h"
|
||||
|
||||
@ -360,7 +362,7 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext,
|
||||
status = ReflowChild(kidFrame, aPresContext, desiredSize,
|
||||
kidReflowState);
|
||||
nsCellLayoutData kidLayoutData((nsTableCellFrame *)kidFrame, &desiredSize, pKidMaxElementSize);
|
||||
aState.tableFrame->SetCellLayoutData(&kidLayoutData, cell);
|
||||
aState.tableFrame->SetCellLayoutData(aPresContext, &kidLayoutData, cell);
|
||||
}
|
||||
else
|
||||
{ // we're in a constrained situation, so get the avail width from the known column widths
|
||||
@ -428,13 +430,11 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext,
|
||||
case eStyleUnit_Coord:
|
||||
specifiedHeight = kidPosition->mHeight.GetCoordValue();
|
||||
break;
|
||||
case eStyleUnit_Percent:
|
||||
case eStyleUnit_Proportional:
|
||||
// XXX for now these fall through
|
||||
|
||||
case eStyleUnit_Inherit:
|
||||
// XXX for now, do nothing
|
||||
default:
|
||||
case eStyleUnit_Auto:
|
||||
case eStyleUnit_Inherit:
|
||||
break;
|
||||
}
|
||||
if (specifiedHeight>cellHeight)
|
||||
@ -893,10 +893,9 @@ nsTableRowFrame::ReflowUnmappedChildren( nsIPresContext* aPresContext,
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
nsIFrame* kidFrame;
|
||||
|
||||
// Create a child frame
|
||||
// Create a child frame -- always an nsTableCell frame
|
||||
nsIStyleContext* kidStyleContext = aPresContext->ResolveStyleContextFor(cell, this);
|
||||
if (nsnull == kidPrevInFlow) {
|
||||
nsIContentDelegate* kidDel = nsnull;
|
||||
@ -908,6 +907,11 @@ nsTableRowFrame::ReflowUnmappedChildren( nsIPresContext* aPresContext,
|
||||
kidPrevInFlow->CreateContinuingFrame(aPresContext, this,
|
||||
kidStyleContext, kidFrame);
|
||||
}
|
||||
/* since I'm creating the cell frame, this is the first time through reflow
|
||||
* it's a good time to set the column style from the cell's width attribute
|
||||
* if this is the first row
|
||||
*/
|
||||
SetColumnStyleFromCell(aPresContext, (nsTableCellFrame *)kidFrame, kidStyleContext);
|
||||
NS_RELEASE(kidStyleContext);
|
||||
|
||||
|
||||
@ -937,7 +941,7 @@ nsTableRowFrame::ReflowUnmappedChildren( nsIPresContext* aPresContext,
|
||||
kidFrame->WillReflow(*aPresContext);
|
||||
status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState);
|
||||
nsCellLayoutData kidLayoutData((nsTableCellFrame *)kidFrame, &desiredSize, pKidMaxElementSize);
|
||||
aState.tableFrame->SetCellLayoutData(&kidLayoutData, (nsTableCell *)cell);
|
||||
aState.tableFrame->SetCellLayoutData(aPresContext, &kidLayoutData, (nsTableCell *)cell);
|
||||
}
|
||||
else
|
||||
{ // we're in a constrained situation, so get the avail width from the known column widths
|
||||
@ -1146,6 +1150,54 @@ nsTableRowFrame::CreateContinuingFrame(nsIPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsTableRowFrame::SetColumnStyleFromCell(nsIPresContext* aPresContext,
|
||||
nsTableCellFrame* aCellFrame,
|
||||
nsIStyleContext* aCellSC)
|
||||
{
|
||||
// if this cell is in the first row, then the width attribute
|
||||
// also acts as the width attribute for the entire column
|
||||
if ((nsnull!=aCellSC) && (nsnull!=aCellFrame))
|
||||
{
|
||||
PRInt32 rowIndex = ((nsTableRow*)mContent)->GetRowIndex();
|
||||
if (0==rowIndex)
|
||||
{
|
||||
// get the cell style info
|
||||
nsStylePosition* cellPosition = (nsStylePosition*) aCellSC->GetData(eStyleStruct_Position);
|
||||
if ((eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) ||
|
||||
(eStyleUnit_Percent==cellPosition->mWidth.GetUnit())) {
|
||||
|
||||
// compute the width per column spanned
|
||||
PRInt32 colSpan = aCellFrame->GetColSpan();
|
||||
// get the appropriate column frame
|
||||
nsTableFrame *tableFrame;
|
||||
mGeometricParent->GetGeometricParent((nsIFrame *&)tableFrame);
|
||||
nsTableColFrame *colFrame;
|
||||
tableFrame->GetColumnFrame(aCellFrame->GetColIndex(), colFrame);
|
||||
// get the column style and set the width attribute
|
||||
nsIStyleContextPtr colSC;
|
||||
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
|
||||
nsStylePosition* colPosition = (nsStylePosition*) colSC->GetData(eStyleStruct_Position);
|
||||
// set the column width attribute
|
||||
colPosition->mWidth = cellPosition->mWidth;
|
||||
/*
|
||||
if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit())
|
||||
{
|
||||
nscoord width = cellPosition->mWidth.GetCoordValue();
|
||||
colPosition->mWidth.SetCoordValue(width);
|
||||
}
|
||||
else
|
||||
{
|
||||
float width = cellPosition->mWidth.GetPercentValue();
|
||||
colPosition->mWidth.SetPercentValue(width);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsTableRowFrame::NewFrame( nsIFrame** aInstancePtrResult,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent)
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
class nsTableFrame;
|
||||
class nsTableCellFrame;
|
||||
struct RowReflowState;
|
||||
|
||||
/**
|
||||
@ -160,6 +161,9 @@ protected:
|
||||
RowReflowState& aState,
|
||||
nsSize* aMaxElementSize);
|
||||
|
||||
NS_METHOD SetColumnStyleFromCell(nsIPresContext * aPresContext,
|
||||
nsTableCellFrame* aCellFrame,
|
||||
nsIStyleContext * aCellSC);
|
||||
|
||||
private:
|
||||
nscoord mTallestCell; // not my height, but the height of my tallest child
|
||||
|
Loading…
Reference in New Issue
Block a user