diff --git a/layout/html/base/src/nsHTMLIIDs.cpp b/layout/html/base/src/nsHTMLIIDs.cpp index 5b1d1e900575..c80af44dc4ad 100644 --- a/layout/html/base/src/nsHTMLIIDs.cpp +++ b/layout/html/base/src/nsHTMLIIDs.cpp @@ -22,3 +22,4 @@ const nsIID kIHTMLContentIID = NS_IHTMLCONTENT_IID; const nsIID kBlockFrameCID = NS_BLOCKFRAME_CID; const nsIID kIInlineFrameIID = NS_IINLINE_FRAME_IID; + diff --git a/layout/html/table/src/BasicTableLayoutStrategy.cpp b/layout/html/table/src/BasicTableLayoutStrategy.cpp index 4274d31e4c19..50c5c910fa7c 100644 --- a/layout/html/table/src/BasicTableLayoutStrategy.cpp +++ b/layout/html/table/src/BasicTableLayoutStrategy.cpp @@ -115,9 +115,20 @@ PRBool BasicTableLayoutStrategy::IsAutoWidth(const nsStylePosition* aStylePositi } -BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame) +BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame, PRInt32 aNumCols) { + NS_ASSERTION(nsnull!=aFrame, "bad frame arg"); + mTableFrame = aFrame; + mNumCols = aNumCols; + //cache the value of the cols attribute + nsIFrame * tableFrame = mTableFrame; +// begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! XXX + tableFrame->GetGeometricParent(tableFrame); +// end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! XXX + nsStyleTable *tableStyle; + tableFrame->GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle); + mCols = tableStyle->mCols; } BasicTableLayoutStrategy::~BasicTableLayoutStrategy() @@ -128,7 +139,6 @@ PRBool BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresContex nsIStyleContext *aTableStyle, const nsReflowState& aReflowState, PRInt32 aMaxWidth, - PRInt32 aNumCols, PRInt32 &aTotalFixedWidth, PRInt32 &aMinTableWidth, PRInt32 &aMaxTableWidth, @@ -139,8 +149,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresContex aTotalFixedWidth=aMinTableWidth=aMaxTableWidth=0; // Step 1 - assign the width of all fixed-width columns - AssignFixedColumnWidths(aPresContext, aMaxWidth, aNumCols, - aTotalFixedWidth, aMinTableWidth, aMaxTableWidth); + AssignFixedColumnWidths(aPresContext, aMaxWidth, aTotalFixedWidth, aMinTableWidth, aMaxTableWidth); if (nsnull!=aMaxElementSize) { // this is where we initialize maxElementSize if it is non-null @@ -209,7 +218,6 @@ if there is space left over // and calculate min/max table width PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresContext, PRInt32 maxWidth, - PRInt32 aNumCols, PRInt32 &aTotalFixedWidth, PRInt32 &aMinTableWidth, PRInt32 &aMaxTableWidth) @@ -222,7 +230,20 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo if (gsDebug==PR_TRUE) printf (" AssignFixedColumnWidths\n"); nsVoidArray *spanList=nsnull; - for (PRInt32 colIndex = 0; colIndexGetColumnLayoutData(); nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex)); @@ -300,9 +321,10 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo NS_ASSERTION(nsnull != cellDesiredSize, "bad cellDesiredSize"); PRInt32 colSpan = data->GetCellFrame()->GetColSpan(); if (gsDebug==PR_TRUE) - printf (" for cell %d with colspan=%d, min = %d,%d and des = %d,%d\n", + printf (" for cell %d with colspan=%d, min = %d,%d and des = %d,%d, margins %d %d\n", cellIndex, colSpan, cellMinSize->width, cellMinSize->height, - cellDesiredSize->width, cellDesiredSize->height); + cellDesiredSize->width, cellDesiredSize->height, + margin.left, margin.right); switch (colPosition->mWidth.GetUnit()) { case eStyleUnit_Coord: @@ -330,8 +352,10 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo nscoord cellMinWidth = cellMinSize->width/colSpan; nscoord cellDesiredWidth = cellDesiredSize->width/colSpan; - cellMinWidth += margin.left + margin.right; - cellDesiredWidth += margin.left + margin.right; + if (NS_UNCONSTRAINEDSIZE!=cellMinWidth) + cellMinWidth += margin.left + margin.right; + if (NS_UNCONSTRAINEDSIZE!=cellDesiredWidth) + cellDesiredWidth += margin.left + margin.right; if (minColWidth < cellMinWidth) minColWidth = cellMinWidth; @@ -369,16 +393,82 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo aMaxTableWidth += maxColWidth; // SEC: insets! if (aMaxTableWidth<=0) aMaxTableWidth = NS_UNCONSTRAINEDSIZE; // handle overflow + if (PR_TRUE==hasColsAttribute) + { + minColWidthArray[colIndex] = minColWidth; + maxColWidthArray[colIndex] = maxColWidth; + } if (gsDebug==PR_TRUE) - printf (" after this col, minTableWidth = %d and maxTableWidth = %d\n", aMinTableWidth, aMaxTableWidth); + printf (" after col %d, minTableWidth = %d and maxTableWidth = %d\n", + colIndex, aMinTableWidth, aMaxTableWidth); } // end Step 1 for fixed-width columns + + // now, post-process the computed values based on the table attributes + // if there is a COLS attribute, fix up aMinTableWidth and aMaxTableWidth + if (PR_TRUE==hasColsAttribute) + { + // for every effected column, subtract out its prior contribution and add back in the new value + PRInt32 numColsEffected = mNumCols; + if (NS_STYLE_TABLE_COLS_ALL!=mCols) + numColsEffected = mCols; + PRInt32 maxOfMinColWidths=0; + PRInt32 maxOfMaxColWidths=0; + for (PRInt32 effectedColIndex=0; effectedColIndexGetColumnLayoutData(); PRInt32 numCols = columnLayoutData->Count(); for (PRInt32 colIndex = 0; colIndexGetMargin(margin); nsSize * cellMinSize = data->GetMaxElementSize(); NS_ASSERTION(nsnull != cellMinSize, "bad cellMinSize"); - nsReflowMetrics * cellDesiredSize = data->GetDesiredSize(); - NS_ASSERTION(nsnull != cellDesiredSize, "bad cellDesiredSize"); - if (minColWidth < cellMinSize->width) - minColWidth = cellMinSize->width; - if (maxColWidth < cellDesiredSize->width) - maxColWidth = cellDesiredSize->width; - /* - if (gsDebug==PR_TRUE) - printf (" after cell %d, minColWidth = %d and maxColWidth = %d\n", - cellIndex, minColWidth, maxColWidth); - */ + nscoord cellMinWidth = cellMinSize->width; // do we need to take into account colSpan here? + cellMinWidth += margin.left + margin.right; + if (minColWidth < cellMinWidth) + minColWidth = cellMinWidth; + } + if (PR_TRUE==hasColsAttribute) + { + minColWidthArray[colIndex] = minColWidth; } if (gsDebug==PR_TRUE) { printf (" for determining width of col %d %s:\n", colIndex, !IsFixedWidth(colPosition)? "(P)":"(A)"); - printf (" minColWidth = %d and maxColWidth = %d\n", minColWidth, maxColWidth); + printf (" minColWidth = %d\n", minColWidth); } mTableFrame->SetColumnWidth(colIndex, minColWidth); @@ -494,6 +592,33 @@ PRBool BasicTableLayoutStrategy::SetColumnsToMinWidth(nsIPresContext* aPresConte printf (" 2: col %d, set to width = %d\n", colIndex, mTableFrame->GetColumnWidth(colIndex)); } } + + // now, post-process the computed values based on the table attributes + // if there is a COLS attribute, fix up aMinTableWidth and aMaxTableWidth + if (PR_TRUE==hasColsAttribute) + { + // for every effected column, subtract out its prior contribution and add back in the new value + PRInt32 numColsEffected = mNumCols; + if (NS_STYLE_TABLE_COLS_ALL!=mCols) + numColsEffected = mCols; + PRInt32 maxOfEffectedColWidths=0; + // XXX need to fix this and all similar code if any fixed-width columns intersect COLS + for (PRInt32 effectedColIndex=0; effectedColIndexSetColumnWidth(effectedColIndex, maxOfEffectedColWidths); + if (PR_TRUE==gsDebug) + printf(" 2 (cols): setting %d to %d\n", effectedColIndex, maxOfEffectedColWidths); + } + delete [] minColWidthArray; + } + + return result; } @@ -769,20 +894,46 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo { // first, figure out the amount of space per slice nscoord maxWidthForTable = (0!=aTableFixedWidth) ? aTableFixedWidth : aMaxWidth; - nscoord widthRemaining = maxWidthForTable - tableWidth; - nscoord widthPerSlice = widthRemaining/totalSlices; - PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count(); - for (PRInt32 i=0; iElementAt(i)); - nscoord computedColWidth = info->mProportion*widthPerSlice; - mTableFrame->SetColumnWidth(info->mColIndex, computedColWidth); - if (gsDebug==PR_TRUE) - 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; + nscoord widthRemaining = maxWidthForTable - tableWidth; + nscoord widthPerSlice = widthRemaining/totalSlices; + PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count(); + for (PRInt32 i=0; iElementAt(i)); + nscoord computedColWidth = info->mProportion*widthPerSlice; + mTableFrame->SetColumnWidth(info->mColIndex, computedColWidth); + if (gsDebug==PR_TRUE) + 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; + } + } + else + { + PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count(); + PRInt32 maxOfMaxColWidths = 0; + for (PRInt32 i=0; iElementAt(i)); + if (maxOfMaxColWidths < info->mMaxColWidth) + maxOfMaxColWidths = info->mMaxColWidth; + } + for (i=0; iElementAt(i)); + mTableFrame->SetColumnWidth(info->mColIndex, maxOfMaxColWidths); + if (gsDebug==PR_TRUE) + printf (" 3 proportional step 2 (unconstrained!): col %d set to width = %d\n", + info->mColIndex, maxOfMaxColWidths); + tableWidth += maxOfMaxColWidths; + delete info; + } } delete proportionalColumnsList; } diff --git a/layout/html/table/src/BasicTableLayoutStrategy.h b/layout/html/table/src/BasicTableLayoutStrategy.h index f0b26ad4b8dc..fa1b10ca5dc7 100644 --- a/layout/html/table/src/BasicTableLayoutStrategy.h +++ b/layout/html/table/src/BasicTableLayoutStrategy.h @@ -51,7 +51,11 @@ class BasicTableLayoutStrategy : public nsITableLayoutStrategy { public: - BasicTableLayoutStrategy(nsTableFrame *aFrame); + /** Public constructor. + * @paran aFrame the table frame for which this delegate will do layout + * @param aNumCols the total number of columns in the table + */ + BasicTableLayoutStrategy(nsTableFrame *aFrame, PRInt32 aNumCols); ~BasicTableLayoutStrategy(); @@ -59,7 +63,6 @@ public: nsIStyleContext *aTableStyle, const nsReflowState& aReflowState, nscoord aMaxWidth, - nscoord aNumCols, nscoord &aTotalFixedWidth, nscoord &aMinTableWidth, nscoord &aMaxTableWidth, @@ -71,7 +74,6 @@ public: * * @param aPresContext the presentation context * @param aMaxWidth the maximum width of the table - * @param aNumCols the total number of columns in the table * @param aTableStyle the resolved style for the table * @param aTotalFixedWidth out param, the sum of the fixed width columns * @param aMinTableWidth out param, the min possible table width @@ -83,7 +85,6 @@ public: */ virtual PRBool AssignFixedColumnWidths(nsIPresContext* aPresContext, nscoord aMaxWidth, - nscoord aNumCols, nscoord & aTotalFixedWidth, nscoord & aMinTableWidth, nscoord & aMaxTableWidth); @@ -171,6 +172,8 @@ public: protected: nsTableFrame * mTableFrame; + PRInt32 mCols; + PRInt32 mNumCols; }; diff --git a/layout/html/table/src/nsITableLayoutStrategy.h b/layout/html/table/src/nsITableLayoutStrategy.h index c524d88d78d9..861aa290f3b5 100644 --- a/layout/html/table/src/nsITableLayoutStrategy.h +++ b/layout/html/table/src/nsITableLayoutStrategy.h @@ -36,7 +36,6 @@ public: * @param aTableStyle the resolved style for the table * @param aReflowState the reflow state for the calling table frame * @param aMaxWidth the width constraint - * @param aNumCols the number of columns * @param aTotalFixedWidth [OUT] the computed fixed width of the table * @param aMinTableWidth [OUT] the computed min width of the table * @param aMinTableWidth [OUT] the computed max width of the table @@ -46,7 +45,6 @@ public: nsIStyleContext *aTableStyle, const nsReflowState& aReflowState, nscoord aMaxWidth, - PRInt32 aNumCols, nscoord &aTotalFixedWidth, nscoord &aMinTableWidth, nscoord &aMaxTableWidth, diff --git a/layout/html/table/src/nsTableCell.cpp b/layout/html/table/src/nsTableCell.cpp index acd342c3a405..9b31a81ecb5a 100644 --- a/layout/html/table/src/nsTableCell.cpp +++ b/layout/html/table/src/nsTableCell.cpp @@ -25,6 +25,13 @@ #include "nsHTMLAtoms.h" #include "nsIPtr.h" +// 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 + + NS_DEF_PTR(nsIStyleContext); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); @@ -46,6 +53,7 @@ nsTableCell::nsTableCell(nsIAtom* aTag) mColIndex(0) { mImplicit = PR_FALSE; + Init(); } nsTableCell::nsTableCell(PRBool aImplicit) @@ -56,6 +64,7 @@ nsTableCell::nsTableCell(PRBool aImplicit) mColIndex(0) { mImplicit = aImplicit; + Init(); } // nsTableContent checks aTag @@ -69,6 +78,22 @@ nsTableCell::nsTableCell (nsIAtom* aTag, int aRowSpan, int aColSpan) NS_ASSERTION(0mHeight.SetCoordValue(twips); } - - } nsContentAttr diff --git a/layout/html/table/src/nsTableCell.h b/layout/html/table/src/nsTableCell.h index 1b064d73d2f0..5720558281c7 100644 --- a/layout/html/table/src/nsTableCell.h +++ b/layout/html/table/src/nsTableCell.h @@ -126,6 +126,9 @@ public: virtual void SetColIndex (int aColIndex); protected: + + virtual void Init(); + virtual nsContentAttr AttributeToString(nsIAtom* aAttribute, nsHTMLValue& aValue, nsString& aResult) const; diff --git a/layout/html/table/src/nsTableCellFrame.cpp b/layout/html/table/src/nsTableCellFrame.cpp index 2d82095503a3..b90cdadf9ce9 100644 --- a/layout/html/table/src/nsTableCellFrame.cpp +++ b/layout/html/table/src/nsTableCellFrame.cpp @@ -37,12 +37,16 @@ NS_DEF_PTR(nsIStyleContext); +const nsIID kTableCellFrameCID = NS_TABLECELLFRAME_CID; + #ifdef NS_DEBUG static PRBool gsDebug = PR_FALSE; +static PRBool gsDebugNT = PR_FALSE; //#define NOISY_STYLE //#define NOISY_FLOW #else static const PRBool gsDebug = PR_FALSE; +static const PRBool gsDebugNT = PR_FALSE; #endif /** @@ -83,11 +87,6 @@ NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext, nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, aDirtyRect, mRect, *mySpacing, 0); - /* - printf("painting borders, size = %d %d %d %d\n", - myBorder->mSize.left, myBorder->mSize.top, - myBorder->mSize.right, myBorder->mSize.bottom); - */ } // for debug... @@ -228,9 +227,9 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, } aStatus = NS_FRAME_COMPLETE; - if (gsDebug==PR_TRUE) - printf("nsTableCellFrame::ResizeReflow: maxSize=%d,%d\n", - aReflowState.maxSize.width, aReflowState.maxSize.height); + if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT) + printf("%p nsTableCellFrame::Reflow: maxSize=%d,%d\n", + this, aReflowState.maxSize.width, aReflowState.maxSize.height); mFirstContentOffset = mLastContentOffset = 0; @@ -325,17 +324,17 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, mFirstChild->WillReflow(*aPresContext); aStatus = ReflowChild(mFirstChild, aPresContext, kidSize, kidReflowState); - if (gsDebug==PR_TRUE) + if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT) { if (nsnull!=pMaxElementSize) - printf(" nsTableCellFrame::ResizeReflow: child returned desiredSize=%d,%d,\ + printf(" %p cellFrame child returned desiredSize=%d,%d,\ and maxElementSize=%d,%d\n", - kidSize.width, kidSize.height, + this, kidSize.width, kidSize.height, pMaxElementSize->width, pMaxElementSize->height); else - printf(" nsTableCellFrame::ResizeReflow: child returned desiredSize=%d,%d,\ + printf(" %p cellFrame child returned desiredSize=%d,%d,\ and maxElementSize=nsnull\n", - kidSize.width, kidSize.height); + this, kidSize.width, kidSize.height); } SetFirstContentOffset(mFirstChild); @@ -359,7 +358,12 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, // the height can be set w/o being restricted by aMaxSize.height nscoord cellHeight = kidSize.height; if (NS_UNCONSTRAINEDSIZE!=cellHeight) + { cellHeight += topInset + bottomInset; + } + if (PR_TRUE==gsDebugNT) + printf(" %p cellFrame height set to %d from kidSize=%d and insets %d,%d\n", + this, cellHeight, kidSize.height, 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) @@ -373,13 +377,15 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, if (nsnull!=aDesiredSize.maxElementSize) { *aDesiredSize.maxElementSize = *pMaxElementSize; - aDesiredSize.maxElementSize->height += topInset + bottomInset; - aDesiredSize.maxElementSize->width += leftInset + rightInset; + if (NS_UNCONSTRAINEDSIZE != aDesiredSize.maxElementSize->height) + aDesiredSize.maxElementSize->height += topInset + bottomInset; + if (NS_UNCONSTRAINEDSIZE != aDesiredSize.maxElementSize->width) + aDesiredSize.maxElementSize->width += leftInset + rightInset; } - if (gsDebug==PR_TRUE) - printf(" nsTableCellFrame::ResizeReflow returning aDesiredSize=%d,%d\n", - aDesiredSize.width, aDesiredSize.height); + if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT) + printf(" %p cellFrame returning aDesiredSize=%d,%d\n", + this, aDesiredSize.width, aDesiredSize.height); #ifdef NS_DEBUG //PostReflowCheck(result); @@ -418,10 +424,10 @@ void nsTableCellFrame::MapHTMLBorderStyle(nsIPresContext* aPresContext, nsStyleS aSpacingStyle.mBorder.SetBottom(width); aSpacingStyle.mBorder.SetRight(width); - aSpacingStyle.mBorderStyle[NS_SIDE_TOP] = NS_STYLE_BORDER_STYLE_INSET; - aSpacingStyle.mBorderStyle[NS_SIDE_LEFT] = NS_STYLE_BORDER_STYLE_INSET; - aSpacingStyle.mBorderStyle[NS_SIDE_BOTTOM] = NS_STYLE_BORDER_STYLE_INSET; - aSpacingStyle.mBorderStyle[NS_SIDE_RIGHT] = NS_STYLE_BORDER_STYLE_INSET; + aSpacingStyle.mBorderStyle[NS_SIDE_TOP] = NS_STYLE_BORDER_STYLE_SOLID; + aSpacingStyle.mBorderStyle[NS_SIDE_LEFT] = NS_STYLE_BORDER_STYLE_SOLID; + aSpacingStyle.mBorderStyle[NS_SIDE_BOTTOM] = NS_STYLE_BORDER_STYLE_SOLID; + aSpacingStyle.mBorderStyle[NS_SIDE_RIGHT] = NS_STYLE_BORDER_STYLE_SOLID; nsTableFrame* tableFrame = GetTableFrame(); nsIStyleContext* styleContext = nsnull; @@ -523,13 +529,18 @@ void nsTableCellFrame::MapBorderMarginPadding(nsIPresContext* aPresContext) } // get border information from the table - if (tableSpacingStyle->mBorder.GetTopUnit() != eStyleUnit_Null) + if (tableSpacingStyle->mBorder.GetTopUnit() == eStyleUnit_Coord) { - nsStyleCoord borderSize; - tableSpacingStyle->mBorder.GetTop(borderSize); - border = borderSize.GetCoordValue(); + nsStyleCoord borderWidth; + tableSpacingStyle->mBorder.GetTop(borderWidth); + if (0!=borderWidth.GetCoordValue()) + { + // in HTML, cell borders are always 1 pixel by default + border = (nscoord)(1*(aPresContext->GetPixelsToTwips())); + MapHTMLBorderStyle(aPresContext, *spacingData, border); + } } - MapHTMLBorderStyle(aPresContext, *spacingData, border); + } void nsTableCellFrame::MapTextAttributes(nsIPresContext* aPresContext) @@ -559,6 +570,19 @@ NS_METHOD nsTableCellFrame::DidSetStyleContext(nsIPresContext* aPresContext) } +NS_METHOD +nsTableCellFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kTableCellFrameCID)) { + *aInstancePtr = (void*) (this); + return NS_OK; + } + return nsContainerFrame::QueryInterface(aIID, aInstancePtr); +} /* ----- static methods ----- */ diff --git a/layout/html/table/src/nsTableCellFrame.h b/layout/html/table/src/nsTableCellFrame.h index b0077954d25d..7576367f8dc7 100644 --- a/layout/html/table/src/nsTableCellFrame.h +++ b/layout/html/table/src/nsTableCellFrame.h @@ -25,6 +25,12 @@ class nsCellLayoutData; struct nsStyleSpacing; +/* eb42f7b0-079e-11d2-8f37-006008159b0c */ +#define NS_TABLECELLFRAME_CID \ + {0xeb42f7b0, 0x079e, 0x11d2, {0x8f, 0x37, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x0c}} + +extern const nsIID kTableCellFrameCID; + /** * nsTableCellFrame * data structure to maintain information about a single table cell's frame @@ -41,6 +47,9 @@ public: nsIContent* aContent, nsIFrame* aParent); + // nsISupports + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + NS_IMETHOD Paint(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect); diff --git a/layout/html/table/src/nsTableFrame.cpp b/layout/html/table/src/nsTableFrame.cpp index 078fc9eb3602..ace952fe5a5d 100644 --- a/layout/html/table/src/nsTableFrame.cpp +++ b/layout/html/table/src/nsTableFrame.cpp @@ -49,7 +49,7 @@ static PRBool gsDebug = PR_FALSE; static PRBool gsDebugCLD = PR_FALSE; static PRBool gsTiming = PR_FALSE; -static PRBool gsDebugMBP = PR_FALSE; +static PRBool gsDebugNT = PR_FALSE; //#define NOISY //#define NOISY_FLOW //#ifdef NOISY_STYLE @@ -57,7 +57,7 @@ static PRBool gsDebugMBP = PR_FALSE; static const PRBool gsDebug = PR_FALSE; static const PRBool gsDebugCLD = PR_FALSE; static const PRBool gsTiming = PR_FALSE; -static const PRBool gsDebugMBP = PR_FALSE; +static const PRBool gsDebugNT = PR_FALSE; #endif #ifndef max @@ -67,6 +67,8 @@ static const PRBool gsDebugMBP = PR_FALSE; NS_DEF_PTR(nsIStyleContext); NS_DEF_PTR(nsIContent); +const nsIID kTableFrameCID = NS_TABLEFRAME_CID; + /* ----------- CellData ---------- */ /* CellData is the info stored in the cell map */ @@ -1149,7 +1151,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext, NS_ASSERTION(nsnull==mPrevInFlow, "illegal call, cannot call pass 1 on a continuing frame."); NS_ASSERTION(nsnull != mContent, "null content"); - if (PR_TRUE==gsDebug) printf("nsTableFrame::ResizeReflow Pass1 for %p: maxSize=%d,%d\n", + if (PR_TRUE==gsDebugNT) printf("%p nsTableFrame::ResizeReflow Pass1: maxSize=%d,%d\n", this, aReflowState.maxSize.width, aReflowState.maxSize.height); nsReflowStatus result = NS_FRAME_COMPLETE; @@ -1227,9 +1229,9 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext, result = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState); // Place the child since some of it's content fit in us. - if (gsDebug) { - printf ("reflow of row group returned desired=%d,%d, max-element=%d,%d\n", - kidSize.width, kidSize.height, kidMaxSize.width, kidMaxSize.height); + if (PR_TRUE==gsDebugNT) { + printf ("%p: reflow of row group returned desired=%d,%d, max-element=%d,%d\n", + this, kidSize.width, kidSize.height, kidMaxSize.width, kidMaxSize.height); } PRInt32 yCoord = y; if (NS_UNCONSTRAINEDSIZE!=yCoord) @@ -1289,6 +1291,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext, if (gsDebug) printf("INNER: set last content offset to %d\n", GetLastContentOffset()); //@@@ } + aDesiredSize.width = kidSize.width; mFirstPassValid = PR_TRUE; return result; @@ -1305,8 +1308,8 @@ nsReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresContext, NS_PRECONDITION(aReflowState.frame == this, "bad reflow state"); NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent, "bad parent reflow state"); - if (gsDebug==PR_TRUE) - printf("nsTableFrame::ResizeReflow Pass2 %p: maxSize=%d,%d\n", + if (PR_TRUE==gsDebugNT) + printf("%p nsTableFrame::ResizeReflow Pass2: maxSize=%d,%d\n", this, aReflowState.maxSize.width, aReflowState.maxSize.height); nsReflowStatus result = NS_FRAME_COMPLETE; @@ -1394,15 +1397,15 @@ nsReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresContext, // shrink wrap rows to height of tallest cell in that row ShrinkWrapChildren(aPresContext, aDesiredSize, aDesiredSize.maxElementSize); - if (gsDebug==PR_TRUE) + if (gsDebugNT==PR_TRUE) { if (nsnull!=aDesiredSize.maxElementSize) - printf("Inner table reflow complete, returning aDesiredSize = %d,%d and aMaxElementSize=%d,%d\n", - aDesiredSize.width, aDesiredSize.height, + printf("%p: Inner table reflow complete, returning aDesiredSize = %d,%d and aMaxElementSize=%d,%d\n", + this, aDesiredSize.width, aDesiredSize.height, aDesiredSize.maxElementSize->width, aDesiredSize.maxElementSize->height); else - printf("Inner table reflow complete, returning aDesiredSize = %d,%d and NSNULL aMaxElementSize\n", - aDesiredSize.width, aDesiredSize.height); + printf("%p: Inner table reflow complete, returning aDesiredSize = %d,%d and NSNULL aMaxElementSize\n", + this, aDesiredSize.width, aDesiredSize.height); } // SEC: assign our real width and height based on this reflow step and return @@ -1520,9 +1523,9 @@ void nsTableFrame::PlaceChild(nsIPresContext* aPresContext, * @return true if we successfully reflowed all the mapped children and false * otherwise, e.g. we pushed children to the next in flow */ -PRBool nsTableFrame::ReflowMappedChildren( nsIPresContext* aPresContext, +PRBool nsTableFrame::ReflowMappedChildren( nsIPresContext* aPresContext, InnerTableReflowState& aState, - nsSize* aMaxElementSize) + nsSize* aMaxElementSize) { #ifdef NS_DEBUG VerifyLastIsComplete(); @@ -1592,7 +1595,8 @@ PRBool nsTableFrame::ReflowMappedChildren( nsIPresContext* aPresContext, eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); - + if (nsnull!=desiredSize.maxElementSize) + desiredSize.maxElementSize->width = desiredSize.width; // Did the child fit? if ((kidFrame != mFirstChild) && (desiredSize.height > kidAvailSize.height)) { @@ -2162,17 +2166,19 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext* aPresContext, maxWidth = 0; } - if (gsDebug) printf (" maxWidth=%d from aMaxSize=%d,%d\n", maxWidth, aMaxSize.width, aMaxSize.height); + if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT) + printf ("%p: maxWidth=%d from aMaxSize=%d,%d\n", + this, maxWidth, aMaxSize.width, aMaxSize.height); // based on the compatibility mode, create a table layout strategy if (nsnull==mTableLayoutStrategy) { // TODO: build a different strategy based on the compatibility mode - mTableLayoutStrategy = new BasicTableLayoutStrategy(this); + mTableLayoutStrategy = new BasicTableLayoutStrategy(this, numCols); } mTableLayoutStrategy->BalanceColumnWidths(aPresContext, mStyleContext, - aReflowState, - maxWidth, numCols, - totalFixedWidth, minTableWidth, maxTableWidth, + aReflowState, maxWidth, + totalFixedWidth, + minTableWidth, maxTableWidth, aMaxElementSize); } @@ -2193,7 +2199,8 @@ void nsTableFrame::SetTableWidth(nsIPresContext* aPresContext) for (PRInt32 i = 0; iframe->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; + if (nsnull != block) + { // we found a block, see if it's really a table cell (which means we're a nested table) + PRBool skipThisBlock=PR_FALSE; + if (PR_TRUE==((nsContainerFrame*)block)->IsPseudoFrame()) + { + const nsReflowState* parentRS = rs->parentReflowState; + if (nsnull!=parentRS) + { + parentRS = parentRS->parentReflowState; + if (nsnull!=parentRS) + { + nsIFrame* cell = nsnull; + parentRS->frame->QueryInterface(kTableCellFrameCID, (void**) &cell); + if (nsnull != cell) { + if (PR_TRUE==gsDebugNT) + printf("%p: found a block pframe %p in a cell, skipping it.\n", aReflowState.frame, block); + skipThisBlock = PR_TRUE; + } + } + } + } + // at this point, we know we have a block. If we're sure it's not a table cell pframe, + // then we can use it + if (PR_FALSE==skipThisBlock) + { + parentWidth = rs->maxSize.width; + if (PR_TRUE==gsDebugNT) + printf("%p: found a block frame %p, returning width %d\n", + aReflowState.frame, block, parentWidth); + break; + } + } + // or if it's another table (we're nested) use its computed width + nsIFrame* table = nsnull; + rs->frame->QueryInterface(kTableFrameCID, (void**) &table); + if (nsnull != table) { + /* We found the nearest containing table (actually, the inner table). + This defines what our percentage size is relative to. Use its desired width + as the basis for computing our width. + */ + // Compute and subtract out the insets (sum of border and padding) for the table + nsMargin borderPadding; + const nsStyleSpacing* spacing; + table->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + nsSize tableSize; + table->GetSize(tableSize); + parentWidth = tableSize.width; + spacing->CalcBorderPaddingFor(rs->frame, borderPadding); + parentWidth -= (borderPadding.right + borderPadding.left); + // same for the row group + childFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(childFrame, borderPadding); + parentWidth -= (borderPadding.right + borderPadding.left); + // same for the row + grandchildFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(grandchildFrame, borderPadding); + parentWidth -= (borderPadding.right + borderPadding.left); + // same for the cell + greatgrandchildFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(greatgrandchildFrame, borderPadding); + parentWidth -= (borderPadding.right + borderPadding.left); + + if (PR_TRUE==gsDebugNT) + printf("%p: found a table frame %p, returning parentWidth %d from frame width %d\n", + aReflowState.frame, table, parentWidth, tableSize.width); break; } + + if (nsnull==childFrame) + childFrame = rs->frame; + else if (nsnull==grandchildFrame) + { + grandchildFrame = childFrame; + childFrame = rs->frame; + } + else + { + greatgrandchildFrame = grandchildFrame; + grandchildFrame = childFrame; + childFrame = rs->frame; + } rs = rs->parentReflowState; } @@ -3163,6 +3265,8 @@ PRBool nsTableFrame::TableIsAutoWidth(nsTableFrame *aTableFrame, const nsStylePosition* tablePosition; parent->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)tablePosition)); // end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! + nsMargin borderPadding; + const nsStyleSpacing* spacing; switch (tablePosition->mWidth.GetUnit()) { case eStyleUnit_Auto: // specified auto width case eStyleUnit_Proportional: // illegal for table, so ignored @@ -3174,16 +3278,28 @@ PRBool nsTableFrame::TableIsAutoWidth(nsTableFrame *aTableFrame, break; case eStyleUnit_Coord: + // XXX: subtract out this table frame's borderpadding? aSpecifiedTableWidth = tablePosition->mWidth.GetCoordValue(); + aReflowState.frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(aReflowState.frame, borderPadding); + aSpecifiedTableWidth -= (borderPadding.right + borderPadding.left); result = PR_FALSE; break; case eStyleUnit_Percent: // set aSpecifiedTableWidth to be the given percent of the parent. + // first, get the effective parent width (parent width - insets) nscoord parentWidth = nsTableFrame::GetTableContainerWidth(aReflowState); + aReflowState.frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(aReflowState.frame, borderPadding); + parentWidth -= (borderPadding.right + borderPadding.left); + + // then set aSpecifiedTableWidth to the given percent of the computed parent width float percent = tablePosition->mWidth.GetPercentValue(); aSpecifiedTableWidth = (PRInt32)(parentWidth*percent); - if (PR_TRUE==gsDebug) printf(" ** aSpecifiedTableWidth = %d\n", aSpecifiedTableWidth); + if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT) + printf("%p: TableIsAutoWidth setting aSpecifiedTableWidth = %d with parentWidth = %d and percent = %f\n", + aTableFrame, aSpecifiedTableWidth, parentWidth, percent); result = PR_FALSE; break; } diff --git a/layout/html/table/src/nsTableFrame.h b/layout/html/table/src/nsTableFrame.h index 0c0c6fde1387..2611ea8ac2a2 100644 --- a/layout/html/table/src/nsTableFrame.h +++ b/layout/html/table/src/nsTableFrame.h @@ -36,6 +36,12 @@ struct InnerTableReflowState; struct nsStylePosition; struct nsStyleSpacing; +/* ff1d2780-06d6-11d2-8f37-006008159b0c */ +#define NS_TABLEFRAME_CID \ + {0xff1d2780, 0x06d6, 0x11d2, {0x8f, 0x37, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x0c}} + +extern const nsIID kTableFrameCID; + /** nsTableFrame maps the inner portion of a table (everything except captions.) * Used as a pseudo-frame within nsTableOuterFrame, * it may also be used stand-alone as the top-level frame. @@ -63,6 +69,9 @@ public: nsIContent* aContent, nsIFrame* aParent); + // nsISupports + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + /** helper method for getting the width of the table's containing block */ static nscoord GetTableContainerWidth(const nsReflowState& aState); diff --git a/layout/html/table/src/nsTableOuterFrame.cpp b/layout/html/table/src/nsTableOuterFrame.cpp index 615353c21c31..d3fd003968b2 100644 --- a/layout/html/table/src/nsTableOuterFrame.cpp +++ b/layout/html/table/src/nsTableOuterFrame.cpp @@ -330,11 +330,9 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext, const nsReflowState& aReflowState, nsReflowStatus& aStatus) { - if (PR_TRUE==gsDebug) - printf ("***table outer frame reflow \t\t%p\n", this); if (PR_TRUE==gsDebug) - printf("nsTableOuterFrame::Reflow : maxSize=%d,%d\n", - aReflowState.maxSize.width, aReflowState.maxSize.height); + printf("%p: nsTableOuterFrame::Reflow : maxSize=%d,%d\n", + this, aReflowState.maxSize.width, aReflowState.maxSize.height); #ifdef NS_DEBUG // replace with a check that does not assume linear placement of children @@ -479,13 +477,13 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext, if (gsDebug==PR_TRUE) { if (nsnull!=aDesiredSize.maxElementSize) - printf("Outer frame Reflow complete, returning %s with aDesiredSize = %d,%d and aMaxElementSize=%d,%d\n", - NS_FRAME_IS_COMPLETE(aStatus)? "Complete" : "Not Complete", + printf("%p: Outer frame Reflow complete, returning %s with aDesiredSize = %d,%d and aMaxElementSize=%d,%d\n", + this, NS_FRAME_IS_COMPLETE(aStatus)? "Complete" : "Not Complete", aDesiredSize.width, aDesiredSize.height, aDesiredSize.maxElementSize->width, aDesiredSize.maxElementSize->height); else - printf("Outer frame Reflow complete, returning %s with aDesiredSize = %d,%d and NSNULL aMaxElementSize\n", - NS_FRAME_IS_COMPLETE(aStatus)? "Complete" : "Not Complete", + printf("%p: Outer frame Reflow complete, returning %s with aDesiredSize = %d,%d and NSNULL aMaxElementSize\n", + this, NS_FRAME_IS_COMPLETE(aStatus)? "Complete" : "Not Complete", aDesiredSize.width, aDesiredSize.height); } diff --git a/layout/html/table/src/nsTablePart.cpp b/layout/html/table/src/nsTablePart.cpp index 0adf91436a00..8be96887f1d7 100644 --- a/layout/html/table/src/nsTablePart.cpp +++ b/layout/html/table/src/nsTablePart.cpp @@ -677,7 +677,7 @@ void nsTablePart::MapAttributesInto(nsIStyleContext* aContext, } } // border - GetTableBorder(this, aContext, aPresContext, PR_FALSE); + GetTableBorder(this, aContext, aPresContext); // align GetAttribute(nsHTMLAtoms::align, value); @@ -711,6 +711,12 @@ void nsTablePart::MapAttributesInto(nsIStyleContext* aContext, tableStyle = (nsStyleTable*)aContext->GetMutableStyleData(eStyleStruct_Table); tableStyle->mCellSpacing.SetCoordValue((nscoord)(p2t*(float)(value.GetPixelValue()))); } + else + { // XXX: remove me as soon as we get this from the style sheet + if (nsnull==tableStyle) + tableStyle = (nsStyleTable*)aContext->GetMutableStyleData(eStyleStruct_Table); + tableStyle->mCellSpacing.SetCoordValue((nscoord)(p2t*(float)2)); + } // cols GetAttribute(nsHTMLAtoms::cols, value); @@ -727,8 +733,7 @@ void nsTablePart::MapAttributesInto(nsIStyleContext* aContext, void nsTablePart::GetTableBorder(nsIHTMLContent* aContent, nsIStyleContext* aContext, - nsIPresContext* aPresContext, - PRBool aForCell) + nsIPresContext* aPresContext) { NS_PRECONDITION(nsnull!=aContent, "bad content arg"); NS_PRECONDITION(nsnull!=aContext, "bad style context arg"); @@ -743,7 +748,7 @@ void nsTablePart::GetTableBorder(nsIHTMLContent* aContent, aContext->GetMutableStyleData(eStyleStruct_Spacing); float p2t = aPresContext->GetPixelsToTwips(); nsStyleCoord twips; - if (aForCell || (value.GetUnit() == eHTMLUnit_Empty)) { + if (value.GetUnit() == eHTMLUnit_Empty) { twips.SetCoordValue(nscoord(NS_INT_PIXELS_TO_TWIPS(1, p2t))); } else { diff --git a/layout/html/table/src/nsTablePart.h b/layout/html/table/src/nsTablePart.h index 36ec3e3c09fe..3ba28a8ea9ca 100644 --- a/layout/html/table/src/nsTablePart.h +++ b/layout/html/table/src/nsTablePart.h @@ -114,8 +114,7 @@ public: static void GetTableBorder(nsIHTMLContent* aContent, nsIStyleContext* aContext, - nsIPresContext* aPresContext, - PRBool aForCell); + nsIPresContext* aPresContext); protected: /** destructor diff --git a/layout/html/table/src/nsTableRowFrame.cpp b/layout/html/table/src/nsTableRowFrame.cpp index d471a081ede5..52b6d4e2c68c 100644 --- a/layout/html/table/src/nsTableRowFrame.cpp +++ b/layout/html/table/src/nsTableRowFrame.cpp @@ -33,6 +33,8 @@ NS_DEF_PTR(nsIStyleContext); +const nsIID kTableRowFrameCID = NS_TABLEROWFRAME_CID; + #ifdef NS_DEBUG static PRBool gsDebug1 = PR_FALSE; static PRBool gsDebug2 = PR_FALSE; @@ -429,7 +431,9 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext, aState.x = kidMargin.left; PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex(); for (PRInt32 colIndex=0; colIndexGetColumnWidth(colIndex); + { + aState.x += aState.tableFrame->GetColumnWidth(colIndex); + } // Place the child after taking into account it's margin and attributes nscoord specifiedHeight = 0; nscoord cellHeight = desiredSize.height; @@ -450,9 +454,20 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext, } if (specifiedHeight>cellHeight) cellHeight = specifiedHeight; - nsRect kidRect (aState.x, kidMargin.top, desiredSize.width, cellHeight); + + nscoord cellWidth = desiredSize.width; + // begin special Nav4 compatibility code + if (0==cellWidth) + { + cellWidth = aState.tableFrame->GetColumnWidth(cellColIndex); + } + // end special Nav4 compatibility code + + nsRect kidRect (aState.x, kidMargin.top, cellWidth, cellHeight); + PlaceChild(aPresContext, aState, kidFrame, kidRect, aMaxElementSize, kidMaxElementSize); + if (kidMargin.bottom < 0) { aState.prevMaxNegBottomMargin = -kidMargin.bottom; @@ -1193,6 +1208,19 @@ nsresult nsTableRowFrame::NewFrame( nsIFrame** aInstancePtrResult, return NS_OK; } +NS_METHOD +nsTableRowFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kTableRowFrameCID)) { + *aInstancePtr = (void*) (this); + return NS_OK; + } + return nsContainerFrame::QueryInterface(aIID, aInstancePtr); +} // For Debugging ONLY NS_METHOD nsTableRowFrame::MoveTo(nscoord aX, nscoord aY) diff --git a/layout/html/table/src/nsTableRowFrame.h b/layout/html/table/src/nsTableRowFrame.h index f3aa68d79e12..91a42b11e286 100644 --- a/layout/html/table/src/nsTableRowFrame.h +++ b/layout/html/table/src/nsTableRowFrame.h @@ -25,6 +25,12 @@ class nsTableFrame; class nsTableCellFrame; struct RowReflowState; +/* e8417220-070b-11d2-8f37-006008159b0c */ +#define NS_TABLEROWFRAME_CID \ + {0xe8417220, 0x070b, 0x11d2, {0x8f, 0x37, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x0c}} + +extern const nsIID kTableRowFrameCID; + /** * nsTableRowFrame is the frame that maps table rows * (HTML tag TR). This class cannot be reused @@ -54,6 +60,9 @@ public: nsIContent* aContent, nsIFrame* aParent); + // nsISupports + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + /** @see nsIFrame::Paint */ NS_IMETHOD Paint(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, diff --git a/layout/tables/BasicTableLayoutStrategy.cpp b/layout/tables/BasicTableLayoutStrategy.cpp index 4274d31e4c19..50c5c910fa7c 100644 --- a/layout/tables/BasicTableLayoutStrategy.cpp +++ b/layout/tables/BasicTableLayoutStrategy.cpp @@ -115,9 +115,20 @@ PRBool BasicTableLayoutStrategy::IsAutoWidth(const nsStylePosition* aStylePositi } -BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame) +BasicTableLayoutStrategy::BasicTableLayoutStrategy(nsTableFrame *aFrame, PRInt32 aNumCols) { + NS_ASSERTION(nsnull!=aFrame, "bad frame arg"); + mTableFrame = aFrame; + mNumCols = aNumCols; + //cache the value of the cols attribute + nsIFrame * tableFrame = mTableFrame; +// begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! XXX + tableFrame->GetGeometricParent(tableFrame); +// end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! XXX + nsStyleTable *tableStyle; + tableFrame->GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle); + mCols = tableStyle->mCols; } BasicTableLayoutStrategy::~BasicTableLayoutStrategy() @@ -128,7 +139,6 @@ PRBool BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresContex nsIStyleContext *aTableStyle, const nsReflowState& aReflowState, PRInt32 aMaxWidth, - PRInt32 aNumCols, PRInt32 &aTotalFixedWidth, PRInt32 &aMinTableWidth, PRInt32 &aMaxTableWidth, @@ -139,8 +149,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresContex aTotalFixedWidth=aMinTableWidth=aMaxTableWidth=0; // Step 1 - assign the width of all fixed-width columns - AssignFixedColumnWidths(aPresContext, aMaxWidth, aNumCols, - aTotalFixedWidth, aMinTableWidth, aMaxTableWidth); + AssignFixedColumnWidths(aPresContext, aMaxWidth, aTotalFixedWidth, aMinTableWidth, aMaxTableWidth); if (nsnull!=aMaxElementSize) { // this is where we initialize maxElementSize if it is non-null @@ -209,7 +218,6 @@ if there is space left over // and calculate min/max table width PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresContext, PRInt32 maxWidth, - PRInt32 aNumCols, PRInt32 &aTotalFixedWidth, PRInt32 &aMinTableWidth, PRInt32 &aMaxTableWidth) @@ -222,7 +230,20 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo if (gsDebug==PR_TRUE) printf (" AssignFixedColumnWidths\n"); nsVoidArray *spanList=nsnull; - for (PRInt32 colIndex = 0; colIndexGetColumnLayoutData(); nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex)); @@ -300,9 +321,10 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo NS_ASSERTION(nsnull != cellDesiredSize, "bad cellDesiredSize"); PRInt32 colSpan = data->GetCellFrame()->GetColSpan(); if (gsDebug==PR_TRUE) - printf (" for cell %d with colspan=%d, min = %d,%d and des = %d,%d\n", + printf (" for cell %d with colspan=%d, min = %d,%d and des = %d,%d, margins %d %d\n", cellIndex, colSpan, cellMinSize->width, cellMinSize->height, - cellDesiredSize->width, cellDesiredSize->height); + cellDesiredSize->width, cellDesiredSize->height, + margin.left, margin.right); switch (colPosition->mWidth.GetUnit()) { case eStyleUnit_Coord: @@ -330,8 +352,10 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo nscoord cellMinWidth = cellMinSize->width/colSpan; nscoord cellDesiredWidth = cellDesiredSize->width/colSpan; - cellMinWidth += margin.left + margin.right; - cellDesiredWidth += margin.left + margin.right; + if (NS_UNCONSTRAINEDSIZE!=cellMinWidth) + cellMinWidth += margin.left + margin.right; + if (NS_UNCONSTRAINEDSIZE!=cellDesiredWidth) + cellDesiredWidth += margin.left + margin.right; if (minColWidth < cellMinWidth) minColWidth = cellMinWidth; @@ -369,16 +393,82 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo aMaxTableWidth += maxColWidth; // SEC: insets! if (aMaxTableWidth<=0) aMaxTableWidth = NS_UNCONSTRAINEDSIZE; // handle overflow + if (PR_TRUE==hasColsAttribute) + { + minColWidthArray[colIndex] = minColWidth; + maxColWidthArray[colIndex] = maxColWidth; + } if (gsDebug==PR_TRUE) - printf (" after this col, minTableWidth = %d and maxTableWidth = %d\n", aMinTableWidth, aMaxTableWidth); + printf (" after col %d, minTableWidth = %d and maxTableWidth = %d\n", + colIndex, aMinTableWidth, aMaxTableWidth); } // end Step 1 for fixed-width columns + + // now, post-process the computed values based on the table attributes + // if there is a COLS attribute, fix up aMinTableWidth and aMaxTableWidth + if (PR_TRUE==hasColsAttribute) + { + // for every effected column, subtract out its prior contribution and add back in the new value + PRInt32 numColsEffected = mNumCols; + if (NS_STYLE_TABLE_COLS_ALL!=mCols) + numColsEffected = mCols; + PRInt32 maxOfMinColWidths=0; + PRInt32 maxOfMaxColWidths=0; + for (PRInt32 effectedColIndex=0; effectedColIndexGetColumnLayoutData(); PRInt32 numCols = columnLayoutData->Count(); for (PRInt32 colIndex = 0; colIndexGetMargin(margin); nsSize * cellMinSize = data->GetMaxElementSize(); NS_ASSERTION(nsnull != cellMinSize, "bad cellMinSize"); - nsReflowMetrics * cellDesiredSize = data->GetDesiredSize(); - NS_ASSERTION(nsnull != cellDesiredSize, "bad cellDesiredSize"); - if (minColWidth < cellMinSize->width) - minColWidth = cellMinSize->width; - if (maxColWidth < cellDesiredSize->width) - maxColWidth = cellDesiredSize->width; - /* - if (gsDebug==PR_TRUE) - printf (" after cell %d, minColWidth = %d and maxColWidth = %d\n", - cellIndex, minColWidth, maxColWidth); - */ + nscoord cellMinWidth = cellMinSize->width; // do we need to take into account colSpan here? + cellMinWidth += margin.left + margin.right; + if (minColWidth < cellMinWidth) + minColWidth = cellMinWidth; + } + if (PR_TRUE==hasColsAttribute) + { + minColWidthArray[colIndex] = minColWidth; } if (gsDebug==PR_TRUE) { printf (" for determining width of col %d %s:\n", colIndex, !IsFixedWidth(colPosition)? "(P)":"(A)"); - printf (" minColWidth = %d and maxColWidth = %d\n", minColWidth, maxColWidth); + printf (" minColWidth = %d\n", minColWidth); } mTableFrame->SetColumnWidth(colIndex, minColWidth); @@ -494,6 +592,33 @@ PRBool BasicTableLayoutStrategy::SetColumnsToMinWidth(nsIPresContext* aPresConte printf (" 2: col %d, set to width = %d\n", colIndex, mTableFrame->GetColumnWidth(colIndex)); } } + + // now, post-process the computed values based on the table attributes + // if there is a COLS attribute, fix up aMinTableWidth and aMaxTableWidth + if (PR_TRUE==hasColsAttribute) + { + // for every effected column, subtract out its prior contribution and add back in the new value + PRInt32 numColsEffected = mNumCols; + if (NS_STYLE_TABLE_COLS_ALL!=mCols) + numColsEffected = mCols; + PRInt32 maxOfEffectedColWidths=0; + // XXX need to fix this and all similar code if any fixed-width columns intersect COLS + for (PRInt32 effectedColIndex=0; effectedColIndexSetColumnWidth(effectedColIndex, maxOfEffectedColWidths); + if (PR_TRUE==gsDebug) + printf(" 2 (cols): setting %d to %d\n", effectedColIndex, maxOfEffectedColWidths); + } + delete [] minColWidthArray; + } + + return result; } @@ -769,20 +894,46 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo { // first, figure out the amount of space per slice nscoord maxWidthForTable = (0!=aTableFixedWidth) ? aTableFixedWidth : aMaxWidth; - nscoord widthRemaining = maxWidthForTable - tableWidth; - nscoord widthPerSlice = widthRemaining/totalSlices; - PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count(); - for (PRInt32 i=0; iElementAt(i)); - nscoord computedColWidth = info->mProportion*widthPerSlice; - mTableFrame->SetColumnWidth(info->mColIndex, computedColWidth); - if (gsDebug==PR_TRUE) - 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; + nscoord widthRemaining = maxWidthForTable - tableWidth; + nscoord widthPerSlice = widthRemaining/totalSlices; + PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count(); + for (PRInt32 i=0; iElementAt(i)); + nscoord computedColWidth = info->mProportion*widthPerSlice; + mTableFrame->SetColumnWidth(info->mColIndex, computedColWidth); + if (gsDebug==PR_TRUE) + 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; + } + } + else + { + PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList->Count(); + PRInt32 maxOfMaxColWidths = 0; + for (PRInt32 i=0; iElementAt(i)); + if (maxOfMaxColWidths < info->mMaxColWidth) + maxOfMaxColWidths = info->mMaxColWidth; + } + for (i=0; iElementAt(i)); + mTableFrame->SetColumnWidth(info->mColIndex, maxOfMaxColWidths); + if (gsDebug==PR_TRUE) + printf (" 3 proportional step 2 (unconstrained!): col %d set to width = %d\n", + info->mColIndex, maxOfMaxColWidths); + tableWidth += maxOfMaxColWidths; + delete info; + } } delete proportionalColumnsList; } diff --git a/layout/tables/BasicTableLayoutStrategy.h b/layout/tables/BasicTableLayoutStrategy.h index f0b26ad4b8dc..fa1b10ca5dc7 100644 --- a/layout/tables/BasicTableLayoutStrategy.h +++ b/layout/tables/BasicTableLayoutStrategy.h @@ -51,7 +51,11 @@ class BasicTableLayoutStrategy : public nsITableLayoutStrategy { public: - BasicTableLayoutStrategy(nsTableFrame *aFrame); + /** Public constructor. + * @paran aFrame the table frame for which this delegate will do layout + * @param aNumCols the total number of columns in the table + */ + BasicTableLayoutStrategy(nsTableFrame *aFrame, PRInt32 aNumCols); ~BasicTableLayoutStrategy(); @@ -59,7 +63,6 @@ public: nsIStyleContext *aTableStyle, const nsReflowState& aReflowState, nscoord aMaxWidth, - nscoord aNumCols, nscoord &aTotalFixedWidth, nscoord &aMinTableWidth, nscoord &aMaxTableWidth, @@ -71,7 +74,6 @@ public: * * @param aPresContext the presentation context * @param aMaxWidth the maximum width of the table - * @param aNumCols the total number of columns in the table * @param aTableStyle the resolved style for the table * @param aTotalFixedWidth out param, the sum of the fixed width columns * @param aMinTableWidth out param, the min possible table width @@ -83,7 +85,6 @@ public: */ virtual PRBool AssignFixedColumnWidths(nsIPresContext* aPresContext, nscoord aMaxWidth, - nscoord aNumCols, nscoord & aTotalFixedWidth, nscoord & aMinTableWidth, nscoord & aMaxTableWidth); @@ -171,6 +172,8 @@ public: protected: nsTableFrame * mTableFrame; + PRInt32 mCols; + PRInt32 mNumCols; }; diff --git a/layout/tables/nsITableLayoutStrategy.h b/layout/tables/nsITableLayoutStrategy.h index c524d88d78d9..861aa290f3b5 100644 --- a/layout/tables/nsITableLayoutStrategy.h +++ b/layout/tables/nsITableLayoutStrategy.h @@ -36,7 +36,6 @@ public: * @param aTableStyle the resolved style for the table * @param aReflowState the reflow state for the calling table frame * @param aMaxWidth the width constraint - * @param aNumCols the number of columns * @param aTotalFixedWidth [OUT] the computed fixed width of the table * @param aMinTableWidth [OUT] the computed min width of the table * @param aMinTableWidth [OUT] the computed max width of the table @@ -46,7 +45,6 @@ public: nsIStyleContext *aTableStyle, const nsReflowState& aReflowState, nscoord aMaxWidth, - PRInt32 aNumCols, nscoord &aTotalFixedWidth, nscoord &aMinTableWidth, nscoord &aMaxTableWidth, diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index 2d82095503a3..b90cdadf9ce9 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -37,12 +37,16 @@ NS_DEF_PTR(nsIStyleContext); +const nsIID kTableCellFrameCID = NS_TABLECELLFRAME_CID; + #ifdef NS_DEBUG static PRBool gsDebug = PR_FALSE; +static PRBool gsDebugNT = PR_FALSE; //#define NOISY_STYLE //#define NOISY_FLOW #else static const PRBool gsDebug = PR_FALSE; +static const PRBool gsDebugNT = PR_FALSE; #endif /** @@ -83,11 +87,6 @@ NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext, nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, aDirtyRect, mRect, *mySpacing, 0); - /* - printf("painting borders, size = %d %d %d %d\n", - myBorder->mSize.left, myBorder->mSize.top, - myBorder->mSize.right, myBorder->mSize.bottom); - */ } // for debug... @@ -228,9 +227,9 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, } aStatus = NS_FRAME_COMPLETE; - if (gsDebug==PR_TRUE) - printf("nsTableCellFrame::ResizeReflow: maxSize=%d,%d\n", - aReflowState.maxSize.width, aReflowState.maxSize.height); + if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT) + printf("%p nsTableCellFrame::Reflow: maxSize=%d,%d\n", + this, aReflowState.maxSize.width, aReflowState.maxSize.height); mFirstContentOffset = mLastContentOffset = 0; @@ -325,17 +324,17 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, mFirstChild->WillReflow(*aPresContext); aStatus = ReflowChild(mFirstChild, aPresContext, kidSize, kidReflowState); - if (gsDebug==PR_TRUE) + if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT) { if (nsnull!=pMaxElementSize) - printf(" nsTableCellFrame::ResizeReflow: child returned desiredSize=%d,%d,\ + printf(" %p cellFrame child returned desiredSize=%d,%d,\ and maxElementSize=%d,%d\n", - kidSize.width, kidSize.height, + this, kidSize.width, kidSize.height, pMaxElementSize->width, pMaxElementSize->height); else - printf(" nsTableCellFrame::ResizeReflow: child returned desiredSize=%d,%d,\ + printf(" %p cellFrame child returned desiredSize=%d,%d,\ and maxElementSize=nsnull\n", - kidSize.width, kidSize.height); + this, kidSize.width, kidSize.height); } SetFirstContentOffset(mFirstChild); @@ -359,7 +358,12 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, // the height can be set w/o being restricted by aMaxSize.height nscoord cellHeight = kidSize.height; if (NS_UNCONSTRAINEDSIZE!=cellHeight) + { cellHeight += topInset + bottomInset; + } + if (PR_TRUE==gsDebugNT) + printf(" %p cellFrame height set to %d from kidSize=%d and insets %d,%d\n", + this, cellHeight, kidSize.height, 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) @@ -373,13 +377,15 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, if (nsnull!=aDesiredSize.maxElementSize) { *aDesiredSize.maxElementSize = *pMaxElementSize; - aDesiredSize.maxElementSize->height += topInset + bottomInset; - aDesiredSize.maxElementSize->width += leftInset + rightInset; + if (NS_UNCONSTRAINEDSIZE != aDesiredSize.maxElementSize->height) + aDesiredSize.maxElementSize->height += topInset + bottomInset; + if (NS_UNCONSTRAINEDSIZE != aDesiredSize.maxElementSize->width) + aDesiredSize.maxElementSize->width += leftInset + rightInset; } - if (gsDebug==PR_TRUE) - printf(" nsTableCellFrame::ResizeReflow returning aDesiredSize=%d,%d\n", - aDesiredSize.width, aDesiredSize.height); + if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT) + printf(" %p cellFrame returning aDesiredSize=%d,%d\n", + this, aDesiredSize.width, aDesiredSize.height); #ifdef NS_DEBUG //PostReflowCheck(result); @@ -418,10 +424,10 @@ void nsTableCellFrame::MapHTMLBorderStyle(nsIPresContext* aPresContext, nsStyleS aSpacingStyle.mBorder.SetBottom(width); aSpacingStyle.mBorder.SetRight(width); - aSpacingStyle.mBorderStyle[NS_SIDE_TOP] = NS_STYLE_BORDER_STYLE_INSET; - aSpacingStyle.mBorderStyle[NS_SIDE_LEFT] = NS_STYLE_BORDER_STYLE_INSET; - aSpacingStyle.mBorderStyle[NS_SIDE_BOTTOM] = NS_STYLE_BORDER_STYLE_INSET; - aSpacingStyle.mBorderStyle[NS_SIDE_RIGHT] = NS_STYLE_BORDER_STYLE_INSET; + aSpacingStyle.mBorderStyle[NS_SIDE_TOP] = NS_STYLE_BORDER_STYLE_SOLID; + aSpacingStyle.mBorderStyle[NS_SIDE_LEFT] = NS_STYLE_BORDER_STYLE_SOLID; + aSpacingStyle.mBorderStyle[NS_SIDE_BOTTOM] = NS_STYLE_BORDER_STYLE_SOLID; + aSpacingStyle.mBorderStyle[NS_SIDE_RIGHT] = NS_STYLE_BORDER_STYLE_SOLID; nsTableFrame* tableFrame = GetTableFrame(); nsIStyleContext* styleContext = nsnull; @@ -523,13 +529,18 @@ void nsTableCellFrame::MapBorderMarginPadding(nsIPresContext* aPresContext) } // get border information from the table - if (tableSpacingStyle->mBorder.GetTopUnit() != eStyleUnit_Null) + if (tableSpacingStyle->mBorder.GetTopUnit() == eStyleUnit_Coord) { - nsStyleCoord borderSize; - tableSpacingStyle->mBorder.GetTop(borderSize); - border = borderSize.GetCoordValue(); + nsStyleCoord borderWidth; + tableSpacingStyle->mBorder.GetTop(borderWidth); + if (0!=borderWidth.GetCoordValue()) + { + // in HTML, cell borders are always 1 pixel by default + border = (nscoord)(1*(aPresContext->GetPixelsToTwips())); + MapHTMLBorderStyle(aPresContext, *spacingData, border); + } } - MapHTMLBorderStyle(aPresContext, *spacingData, border); + } void nsTableCellFrame::MapTextAttributes(nsIPresContext* aPresContext) @@ -559,6 +570,19 @@ NS_METHOD nsTableCellFrame::DidSetStyleContext(nsIPresContext* aPresContext) } +NS_METHOD +nsTableCellFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kTableCellFrameCID)) { + *aInstancePtr = (void*) (this); + return NS_OK; + } + return nsContainerFrame::QueryInterface(aIID, aInstancePtr); +} /* ----- static methods ----- */ diff --git a/layout/tables/nsTableCellFrame.h b/layout/tables/nsTableCellFrame.h index b0077954d25d..7576367f8dc7 100644 --- a/layout/tables/nsTableCellFrame.h +++ b/layout/tables/nsTableCellFrame.h @@ -25,6 +25,12 @@ class nsCellLayoutData; struct nsStyleSpacing; +/* eb42f7b0-079e-11d2-8f37-006008159b0c */ +#define NS_TABLECELLFRAME_CID \ + {0xeb42f7b0, 0x079e, 0x11d2, {0x8f, 0x37, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x0c}} + +extern const nsIID kTableCellFrameCID; + /** * nsTableCellFrame * data structure to maintain information about a single table cell's frame @@ -41,6 +47,9 @@ public: nsIContent* aContent, nsIFrame* aParent); + // nsISupports + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + NS_IMETHOD Paint(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect); diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 078fc9eb3602..ace952fe5a5d 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -49,7 +49,7 @@ static PRBool gsDebug = PR_FALSE; static PRBool gsDebugCLD = PR_FALSE; static PRBool gsTiming = PR_FALSE; -static PRBool gsDebugMBP = PR_FALSE; +static PRBool gsDebugNT = PR_FALSE; //#define NOISY //#define NOISY_FLOW //#ifdef NOISY_STYLE @@ -57,7 +57,7 @@ static PRBool gsDebugMBP = PR_FALSE; static const PRBool gsDebug = PR_FALSE; static const PRBool gsDebugCLD = PR_FALSE; static const PRBool gsTiming = PR_FALSE; -static const PRBool gsDebugMBP = PR_FALSE; +static const PRBool gsDebugNT = PR_FALSE; #endif #ifndef max @@ -67,6 +67,8 @@ static const PRBool gsDebugMBP = PR_FALSE; NS_DEF_PTR(nsIStyleContext); NS_DEF_PTR(nsIContent); +const nsIID kTableFrameCID = NS_TABLEFRAME_CID; + /* ----------- CellData ---------- */ /* CellData is the info stored in the cell map */ @@ -1149,7 +1151,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext, NS_ASSERTION(nsnull==mPrevInFlow, "illegal call, cannot call pass 1 on a continuing frame."); NS_ASSERTION(nsnull != mContent, "null content"); - if (PR_TRUE==gsDebug) printf("nsTableFrame::ResizeReflow Pass1 for %p: maxSize=%d,%d\n", + if (PR_TRUE==gsDebugNT) printf("%p nsTableFrame::ResizeReflow Pass1: maxSize=%d,%d\n", this, aReflowState.maxSize.width, aReflowState.maxSize.height); nsReflowStatus result = NS_FRAME_COMPLETE; @@ -1227,9 +1229,9 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext, result = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState); // Place the child since some of it's content fit in us. - if (gsDebug) { - printf ("reflow of row group returned desired=%d,%d, max-element=%d,%d\n", - kidSize.width, kidSize.height, kidMaxSize.width, kidMaxSize.height); + if (PR_TRUE==gsDebugNT) { + printf ("%p: reflow of row group returned desired=%d,%d, max-element=%d,%d\n", + this, kidSize.width, kidSize.height, kidMaxSize.width, kidMaxSize.height); } PRInt32 yCoord = y; if (NS_UNCONSTRAINEDSIZE!=yCoord) @@ -1289,6 +1291,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext, if (gsDebug) printf("INNER: set last content offset to %d\n", GetLastContentOffset()); //@@@ } + aDesiredSize.width = kidSize.width; mFirstPassValid = PR_TRUE; return result; @@ -1305,8 +1308,8 @@ nsReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresContext, NS_PRECONDITION(aReflowState.frame == this, "bad reflow state"); NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent, "bad parent reflow state"); - if (gsDebug==PR_TRUE) - printf("nsTableFrame::ResizeReflow Pass2 %p: maxSize=%d,%d\n", + if (PR_TRUE==gsDebugNT) + printf("%p nsTableFrame::ResizeReflow Pass2: maxSize=%d,%d\n", this, aReflowState.maxSize.width, aReflowState.maxSize.height); nsReflowStatus result = NS_FRAME_COMPLETE; @@ -1394,15 +1397,15 @@ nsReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresContext, // shrink wrap rows to height of tallest cell in that row ShrinkWrapChildren(aPresContext, aDesiredSize, aDesiredSize.maxElementSize); - if (gsDebug==PR_TRUE) + if (gsDebugNT==PR_TRUE) { if (nsnull!=aDesiredSize.maxElementSize) - printf("Inner table reflow complete, returning aDesiredSize = %d,%d and aMaxElementSize=%d,%d\n", - aDesiredSize.width, aDesiredSize.height, + printf("%p: Inner table reflow complete, returning aDesiredSize = %d,%d and aMaxElementSize=%d,%d\n", + this, aDesiredSize.width, aDesiredSize.height, aDesiredSize.maxElementSize->width, aDesiredSize.maxElementSize->height); else - printf("Inner table reflow complete, returning aDesiredSize = %d,%d and NSNULL aMaxElementSize\n", - aDesiredSize.width, aDesiredSize.height); + printf("%p: Inner table reflow complete, returning aDesiredSize = %d,%d and NSNULL aMaxElementSize\n", + this, aDesiredSize.width, aDesiredSize.height); } // SEC: assign our real width and height based on this reflow step and return @@ -1520,9 +1523,9 @@ void nsTableFrame::PlaceChild(nsIPresContext* aPresContext, * @return true if we successfully reflowed all the mapped children and false * otherwise, e.g. we pushed children to the next in flow */ -PRBool nsTableFrame::ReflowMappedChildren( nsIPresContext* aPresContext, +PRBool nsTableFrame::ReflowMappedChildren( nsIPresContext* aPresContext, InnerTableReflowState& aState, - nsSize* aMaxElementSize) + nsSize* aMaxElementSize) { #ifdef NS_DEBUG VerifyLastIsComplete(); @@ -1592,7 +1595,8 @@ PRBool nsTableFrame::ReflowMappedChildren( nsIPresContext* aPresContext, eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); - + if (nsnull!=desiredSize.maxElementSize) + desiredSize.maxElementSize->width = desiredSize.width; // Did the child fit? if ((kidFrame != mFirstChild) && (desiredSize.height > kidAvailSize.height)) { @@ -2162,17 +2166,19 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext* aPresContext, maxWidth = 0; } - if (gsDebug) printf (" maxWidth=%d from aMaxSize=%d,%d\n", maxWidth, aMaxSize.width, aMaxSize.height); + if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT) + printf ("%p: maxWidth=%d from aMaxSize=%d,%d\n", + this, maxWidth, aMaxSize.width, aMaxSize.height); // based on the compatibility mode, create a table layout strategy if (nsnull==mTableLayoutStrategy) { // TODO: build a different strategy based on the compatibility mode - mTableLayoutStrategy = new BasicTableLayoutStrategy(this); + mTableLayoutStrategy = new BasicTableLayoutStrategy(this, numCols); } mTableLayoutStrategy->BalanceColumnWidths(aPresContext, mStyleContext, - aReflowState, - maxWidth, numCols, - totalFixedWidth, minTableWidth, maxTableWidth, + aReflowState, maxWidth, + totalFixedWidth, + minTableWidth, maxTableWidth, aMaxElementSize); } @@ -2193,7 +2199,8 @@ void nsTableFrame::SetTableWidth(nsIPresContext* aPresContext) for (PRInt32 i = 0; iframe->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; + if (nsnull != block) + { // we found a block, see if it's really a table cell (which means we're a nested table) + PRBool skipThisBlock=PR_FALSE; + if (PR_TRUE==((nsContainerFrame*)block)->IsPseudoFrame()) + { + const nsReflowState* parentRS = rs->parentReflowState; + if (nsnull!=parentRS) + { + parentRS = parentRS->parentReflowState; + if (nsnull!=parentRS) + { + nsIFrame* cell = nsnull; + parentRS->frame->QueryInterface(kTableCellFrameCID, (void**) &cell); + if (nsnull != cell) { + if (PR_TRUE==gsDebugNT) + printf("%p: found a block pframe %p in a cell, skipping it.\n", aReflowState.frame, block); + skipThisBlock = PR_TRUE; + } + } + } + } + // at this point, we know we have a block. If we're sure it's not a table cell pframe, + // then we can use it + if (PR_FALSE==skipThisBlock) + { + parentWidth = rs->maxSize.width; + if (PR_TRUE==gsDebugNT) + printf("%p: found a block frame %p, returning width %d\n", + aReflowState.frame, block, parentWidth); + break; + } + } + // or if it's another table (we're nested) use its computed width + nsIFrame* table = nsnull; + rs->frame->QueryInterface(kTableFrameCID, (void**) &table); + if (nsnull != table) { + /* We found the nearest containing table (actually, the inner table). + This defines what our percentage size is relative to. Use its desired width + as the basis for computing our width. + */ + // Compute and subtract out the insets (sum of border and padding) for the table + nsMargin borderPadding; + const nsStyleSpacing* spacing; + table->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + nsSize tableSize; + table->GetSize(tableSize); + parentWidth = tableSize.width; + spacing->CalcBorderPaddingFor(rs->frame, borderPadding); + parentWidth -= (borderPadding.right + borderPadding.left); + // same for the row group + childFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(childFrame, borderPadding); + parentWidth -= (borderPadding.right + borderPadding.left); + // same for the row + grandchildFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(grandchildFrame, borderPadding); + parentWidth -= (borderPadding.right + borderPadding.left); + // same for the cell + greatgrandchildFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(greatgrandchildFrame, borderPadding); + parentWidth -= (borderPadding.right + borderPadding.left); + + if (PR_TRUE==gsDebugNT) + printf("%p: found a table frame %p, returning parentWidth %d from frame width %d\n", + aReflowState.frame, table, parentWidth, tableSize.width); break; } + + if (nsnull==childFrame) + childFrame = rs->frame; + else if (nsnull==grandchildFrame) + { + grandchildFrame = childFrame; + childFrame = rs->frame; + } + else + { + greatgrandchildFrame = grandchildFrame; + grandchildFrame = childFrame; + childFrame = rs->frame; + } rs = rs->parentReflowState; } @@ -3163,6 +3265,8 @@ PRBool nsTableFrame::TableIsAutoWidth(nsTableFrame *aTableFrame, const nsStylePosition* tablePosition; parent->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)tablePosition)); // end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED! + nsMargin borderPadding; + const nsStyleSpacing* spacing; switch (tablePosition->mWidth.GetUnit()) { case eStyleUnit_Auto: // specified auto width case eStyleUnit_Proportional: // illegal for table, so ignored @@ -3174,16 +3278,28 @@ PRBool nsTableFrame::TableIsAutoWidth(nsTableFrame *aTableFrame, break; case eStyleUnit_Coord: + // XXX: subtract out this table frame's borderpadding? aSpecifiedTableWidth = tablePosition->mWidth.GetCoordValue(); + aReflowState.frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(aReflowState.frame, borderPadding); + aSpecifiedTableWidth -= (borderPadding.right + borderPadding.left); result = PR_FALSE; break; case eStyleUnit_Percent: // set aSpecifiedTableWidth to be the given percent of the parent. + // first, get the effective parent width (parent width - insets) nscoord parentWidth = nsTableFrame::GetTableContainerWidth(aReflowState); + aReflowState.frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(aReflowState.frame, borderPadding); + parentWidth -= (borderPadding.right + borderPadding.left); + + // then set aSpecifiedTableWidth to the given percent of the computed parent width float percent = tablePosition->mWidth.GetPercentValue(); aSpecifiedTableWidth = (PRInt32)(parentWidth*percent); - if (PR_TRUE==gsDebug) printf(" ** aSpecifiedTableWidth = %d\n", aSpecifiedTableWidth); + if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT) + printf("%p: TableIsAutoWidth setting aSpecifiedTableWidth = %d with parentWidth = %d and percent = %f\n", + aTableFrame, aSpecifiedTableWidth, parentWidth, percent); result = PR_FALSE; break; } diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index 0c0c6fde1387..2611ea8ac2a2 100644 --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -36,6 +36,12 @@ struct InnerTableReflowState; struct nsStylePosition; struct nsStyleSpacing; +/* ff1d2780-06d6-11d2-8f37-006008159b0c */ +#define NS_TABLEFRAME_CID \ + {0xff1d2780, 0x06d6, 0x11d2, {0x8f, 0x37, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x0c}} + +extern const nsIID kTableFrameCID; + /** nsTableFrame maps the inner portion of a table (everything except captions.) * Used as a pseudo-frame within nsTableOuterFrame, * it may also be used stand-alone as the top-level frame. @@ -63,6 +69,9 @@ public: nsIContent* aContent, nsIFrame* aParent); + // nsISupports + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + /** helper method for getting the width of the table's containing block */ static nscoord GetTableContainerWidth(const nsReflowState& aState); diff --git a/layout/tables/nsTableOuterFrame.cpp b/layout/tables/nsTableOuterFrame.cpp index 615353c21c31..d3fd003968b2 100644 --- a/layout/tables/nsTableOuterFrame.cpp +++ b/layout/tables/nsTableOuterFrame.cpp @@ -330,11 +330,9 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext, const nsReflowState& aReflowState, nsReflowStatus& aStatus) { - if (PR_TRUE==gsDebug) - printf ("***table outer frame reflow \t\t%p\n", this); if (PR_TRUE==gsDebug) - printf("nsTableOuterFrame::Reflow : maxSize=%d,%d\n", - aReflowState.maxSize.width, aReflowState.maxSize.height); + printf("%p: nsTableOuterFrame::Reflow : maxSize=%d,%d\n", + this, aReflowState.maxSize.width, aReflowState.maxSize.height); #ifdef NS_DEBUG // replace with a check that does not assume linear placement of children @@ -479,13 +477,13 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext, if (gsDebug==PR_TRUE) { if (nsnull!=aDesiredSize.maxElementSize) - printf("Outer frame Reflow complete, returning %s with aDesiredSize = %d,%d and aMaxElementSize=%d,%d\n", - NS_FRAME_IS_COMPLETE(aStatus)? "Complete" : "Not Complete", + printf("%p: Outer frame Reflow complete, returning %s with aDesiredSize = %d,%d and aMaxElementSize=%d,%d\n", + this, NS_FRAME_IS_COMPLETE(aStatus)? "Complete" : "Not Complete", aDesiredSize.width, aDesiredSize.height, aDesiredSize.maxElementSize->width, aDesiredSize.maxElementSize->height); else - printf("Outer frame Reflow complete, returning %s with aDesiredSize = %d,%d and NSNULL aMaxElementSize\n", - NS_FRAME_IS_COMPLETE(aStatus)? "Complete" : "Not Complete", + printf("%p: Outer frame Reflow complete, returning %s with aDesiredSize = %d,%d and NSNULL aMaxElementSize\n", + this, NS_FRAME_IS_COMPLETE(aStatus)? "Complete" : "Not Complete", aDesiredSize.width, aDesiredSize.height); } diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index d471a081ede5..52b6d4e2c68c 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -33,6 +33,8 @@ NS_DEF_PTR(nsIStyleContext); +const nsIID kTableRowFrameCID = NS_TABLEROWFRAME_CID; + #ifdef NS_DEBUG static PRBool gsDebug1 = PR_FALSE; static PRBool gsDebug2 = PR_FALSE; @@ -429,7 +431,9 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext, aState.x = kidMargin.left; PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex(); for (PRInt32 colIndex=0; colIndexGetColumnWidth(colIndex); + { + aState.x += aState.tableFrame->GetColumnWidth(colIndex); + } // Place the child after taking into account it's margin and attributes nscoord specifiedHeight = 0; nscoord cellHeight = desiredSize.height; @@ -450,9 +454,20 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext, } if (specifiedHeight>cellHeight) cellHeight = specifiedHeight; - nsRect kidRect (aState.x, kidMargin.top, desiredSize.width, cellHeight); + + nscoord cellWidth = desiredSize.width; + // begin special Nav4 compatibility code + if (0==cellWidth) + { + cellWidth = aState.tableFrame->GetColumnWidth(cellColIndex); + } + // end special Nav4 compatibility code + + nsRect kidRect (aState.x, kidMargin.top, cellWidth, cellHeight); + PlaceChild(aPresContext, aState, kidFrame, kidRect, aMaxElementSize, kidMaxElementSize); + if (kidMargin.bottom < 0) { aState.prevMaxNegBottomMargin = -kidMargin.bottom; @@ -1193,6 +1208,19 @@ nsresult nsTableRowFrame::NewFrame( nsIFrame** aInstancePtrResult, return NS_OK; } +NS_METHOD +nsTableRowFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kTableRowFrameCID)) { + *aInstancePtr = (void*) (this); + return NS_OK; + } + return nsContainerFrame::QueryInterface(aIID, aInstancePtr); +} // For Debugging ONLY NS_METHOD nsTableRowFrame::MoveTo(nscoord aX, nscoord aY) diff --git a/layout/tables/nsTableRowFrame.h b/layout/tables/nsTableRowFrame.h index f3aa68d79e12..91a42b11e286 100644 --- a/layout/tables/nsTableRowFrame.h +++ b/layout/tables/nsTableRowFrame.h @@ -25,6 +25,12 @@ class nsTableFrame; class nsTableCellFrame; struct RowReflowState; +/* e8417220-070b-11d2-8f37-006008159b0c */ +#define NS_TABLEROWFRAME_CID \ + {0xe8417220, 0x070b, 0x11d2, {0x8f, 0x37, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x0c}} + +extern const nsIID kTableRowFrameCID; + /** * nsTableRowFrame is the frame that maps table rows * (HTML tag TR). This class cannot be reused @@ -54,6 +60,9 @@ public: nsIContent* aContent, nsIFrame* aParent); + // nsISupports + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + /** @see nsIFrame::Paint */ NS_IMETHOD Paint(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext,