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:
buster 1998-06-05 02:36:25 +00:00
parent 6c6643b04c
commit 07076ff7cf
26 changed files with 1374 additions and 416 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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()

View File

@ -105,6 +105,9 @@ public:
virtual void ResetColumns ();
private:
void Init();
};

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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++

View File

@ -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)

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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