diff --git a/layout/html/document/src/ua.css b/layout/html/document/src/ua.css
index 141e80a30b19..ce7b1920e4e3 100644
--- a/layout/html/document/src/ua.css
+++ b/layout/html/document/src/ua.css
@@ -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
diff --git a/layout/html/table/src/BasicTableLayoutStrategy.cpp b/layout/html/table/src/BasicTableLayoutStrategy.cpp
index 3070448f1907..f726a4989aa2 100644
--- a/layout/html/table/src/BasicTableLayoutStrategy.cpp
+++ b/layout/html/table/src/BasicTableLayoutStrategy.cpp
@@ -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= 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; colIndexGetColumnWidth(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; colIndexGetColumnWidth(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
diff --git a/layout/html/table/src/BasicTableLayoutStrategy.h b/layout/html/table/src/BasicTableLayoutStrategy.h
index acba3cf2a6e0..1fe2a9066b9e 100644
--- a/layout/html/table/src/BasicTableLayoutStrategy.h
+++ b/layout/html/table/src/BasicTableLayoutStrategy.h
@@ -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;
diff --git a/layout/html/table/src/nsTableCell.cpp b/layout/html/table/src/nsTableCell.cpp
index 72c1a21792e5..53b312d04f93 100644
--- a/layout/html/table/src/nsTableCell.cpp
+++ b/layout/html/table/src/nsTableCell.cpp
@@ -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);
diff --git a/layout/html/table/src/nsTableCellFrame.cpp b/layout/html/table/src/nsTableCellFrame.cpp
index a1714692d267..24b28799bbed 100644
--- a/layout/html/table/src/nsTableCellFrame.cpp
+++ b/layout/html/table/src/nsTableCellFrame.cpp
@@ -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;
diff --git a/layout/html/table/src/nsTableCol.cpp b/layout/html/table/src/nsTableCol.cpp
index 1d29b5ad50a8..489dc655ef85 100644
--- a/layout/html/table/src/nsTableCol.cpp
+++ b/layout/html/table/src/nsTableCol.cpp
@@ -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()
diff --git a/layout/html/table/src/nsTableCol.h b/layout/html/table/src/nsTableCol.h
index 1109001d782e..ad43828399b7 100644
--- a/layout/html/table/src/nsTableCol.h
+++ b/layout/html/table/src/nsTableCol.h
@@ -105,6 +105,9 @@ public:
virtual void ResetColumns ();
+private:
+ void Init();
+
};
diff --git a/layout/html/table/src/nsTableColFrame.h b/layout/html/table/src/nsTableColFrame.h
index 80e0c761a4a5..29f554e1eb1d 100644
--- a/layout/html/table/src/nsTableColFrame.h
+++ b/layout/html/table/src/nsTableColFrame.h
@@ -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);
diff --git a/layout/html/table/src/nsTableColGroup.cpp b/layout/html/table/src/nsTableColGroup.cpp
index bc6ccadf32b4..6c43fedad2eb 100644
--- a/layout/html/table/src/nsTableColGroup.cpp
+++ b/layout/html/table/src/nsTableColGroup.cpp
@@ -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);
diff --git a/layout/html/table/src/nsTableContent.cpp b/layout/html/table/src/nsTableContent.cpp
index d8a19f9fddad..e531dfdb0b44 100644
--- a/layout/html/table/src/nsTableContent.cpp
+++ b/layout/html/table/src/nsTableContent.cpp
@@ -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;
diff --git a/layout/html/table/src/nsTableFrame.cpp b/layout/html/table/src/nsTableFrame.cpp
index 2ebcbdcc8f66..26db465bbc3f 100644
--- a/layout/html/table/src/nsTableFrame.cpp
+++ b/layout/html/table/src/nsTableFrame.cpp
@@ -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; iGetSize(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; iChildCount();
for (PRInt32 j=0; jChildAt(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
diff --git a/layout/html/table/src/nsTableFrame.h b/layout/html/table/src/nsTableFrame.h
index 7dbc1fb8c49d..70657556236b 100644
--- a/layout/html/table/src/nsTableFrame.h
+++ b/layout/html/table/src/nsTableFrame.h
@@ -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
diff --git a/layout/html/table/src/nsTablePart.cpp b/layout/html/table/src/nsTablePart.cpp
index 99b5048d48c5..faafdc1422ab 100644
--- a/layout/html/table/src/nsTablePart.cpp
+++ b/layout/html/table/src/nsTablePart.cpp
@@ -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; iAppendChild (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 */
diff --git a/layout/html/table/src/nsTableRow.cpp b/layout/html/table/src/nsTableRow.cpp
index a36e2da51bee..1f4d9bd1003b 100644
--- a/layout/html/table/src/nsTableRow.cpp
+++ b/layout/html/table/src/nsTableRow.cpp
@@ -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 && aIndexGetType();
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 && aIndexSetCellLayoutData(&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)
diff --git a/layout/html/table/src/nsTableRowFrame.h b/layout/html/table/src/nsTableRowFrame.h
index 952af3bd04ad..b19de1c7311d 100644
--- a/layout/html/table/src/nsTableRowFrame.h
+++ b/layout/html/table/src/nsTableRowFrame.h
@@ -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
diff --git a/layout/html/table/src/nsTableRowGroup.cpp b/layout/html/table/src/nsTableRowGroup.cpp
index 19ffaf6c71e4..dc0a4f42b615 100644
--- a/layout/html/table/src/nsTableRowGroup.cpp
+++ b/layout/html/table/src/nsTableRowGroup.cpp
@@ -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 && aIndexSetRowGroup (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 && aIndexSetRowGroup (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 */
diff --git a/layout/style/ua.css b/layout/style/ua.css
index 141e80a30b19..ce7b1920e4e3 100644
--- a/layout/style/ua.css
+++ b/layout/style/ua.css
@@ -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
diff --git a/layout/tables/BasicTableLayoutStrategy.cpp b/layout/tables/BasicTableLayoutStrategy.cpp
index 3070448f1907..f726a4989aa2 100644
--- a/layout/tables/BasicTableLayoutStrategy.cpp
+++ b/layout/tables/BasicTableLayoutStrategy.cpp
@@ -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= 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; colIndexGetColumnWidth(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; colIndexGetColumnWidth(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
diff --git a/layout/tables/BasicTableLayoutStrategy.h b/layout/tables/BasicTableLayoutStrategy.h
index acba3cf2a6e0..1fe2a9066b9e 100644
--- a/layout/tables/BasicTableLayoutStrategy.h
+++ b/layout/tables/BasicTableLayoutStrategy.h
@@ -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;
diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp
index a1714692d267..24b28799bbed 100644
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -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;
diff --git a/layout/tables/nsTableColFrame.h b/layout/tables/nsTableColFrame.h
index 80e0c761a4a5..29f554e1eb1d 100644
--- a/layout/tables/nsTableColFrame.h
+++ b/layout/tables/nsTableColFrame.h
@@ -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);
diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp
index 2ebcbdcc8f66..26db465bbc3f 100644
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -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; iGetSize(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; iChildCount();
for (PRInt32 j=0; jChildAt(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
diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h
index 7dbc1fb8c49d..70657556236b 100644
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -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
diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp
index e85a2639ea2b..114f5f424488 100644
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -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)
diff --git a/layout/tables/nsTableRowFrame.h b/layout/tables/nsTableRowFrame.h
index 952af3bd04ad..b19de1c7311d 100644
--- a/layout/tables/nsTableRowFrame.h
+++ b/layout/tables/nsTableRowFrame.h
@@ -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