From 6f5b201dbec30ef2d57ce76ecd480cbdc3a3f564 Mon Sep 17 00:00:00 2001 From: "buster%netscape.com" Date: Fri, 20 Nov 1998 01:01:25 +0000 Subject: [PATCH] implemented table height algorithms. also made a slight modification to the way a table finds its container's width. git-svn-id: svn://10.0.0.236/trunk@14973 18797224-902f-48f8-a5cc-f745e15eee43 --- .../html/table/src/nsTableCellFrame.cpp | 15 +- .../layout/html/table/src/nsTableCellFrame.h | 2 +- .../layout/html/table/src/nsTableFrame.cpp | 220 ++++++++++++++---- mozilla/layout/html/table/src/nsTableFrame.h | 12 +- .../layout/html/table/src/nsTableRowFrame.cpp | 114 +++++---- .../layout/html/table/src/nsTableRowFrame.h | 7 +- .../html/table/src/nsTableRowGroupFrame.cpp | 34 ++- .../html/table/src/nsTableRowGroupFrame.h | 5 +- mozilla/layout/tables/nsTableCellFrame.cpp | 15 +- mozilla/layout/tables/nsTableCellFrame.h | 2 +- mozilla/layout/tables/nsTableFrame.cpp | 220 ++++++++++++++---- mozilla/layout/tables/nsTableFrame.h | 12 +- mozilla/layout/tables/nsTableRowFrame.cpp | 114 +++++---- mozilla/layout/tables/nsTableRowFrame.h | 7 +- .../layout/tables/nsTableRowGroupFrame.cpp | 34 ++- mozilla/layout/tables/nsTableRowGroupFrame.h | 5 +- 16 files changed, 588 insertions(+), 230 deletions(-) diff --git a/mozilla/layout/html/table/src/nsTableCellFrame.cpp b/mozilla/layout/html/table/src/nsTableCellFrame.cpp index eed86fa971f..3e349deba89 100644 --- a/mozilla/layout/html/table/src/nsTableCellFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableCellFrame.cpp @@ -159,7 +159,7 @@ nsTableCellFrame::GetSkipSides() const * Align the cell's child frame within the cell * */ -void nsTableCellFrame::VerticallyAlignChild(nsIPresContext* aPresContext) +void nsTableCellFrame::VerticallyAlignChild() { const nsStyleSpacing* spacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); @@ -174,12 +174,10 @@ void nsTableCellFrame::VerticallyAlignChild(nsIPresContext* aPresContext) if (textStyle->mVerticalAlign.GetUnit() == eStyleUnit_Enumerated) { verticalAlignFlags = textStyle->mVerticalAlign.GetIntValue(); } - - nscoord height = mRect.height; - - nsRect kidRect; + nscoord height = mRect.height; + nsRect kidRect; mFirstChild->GetRect(kidRect); - nscoord childHeight = kidRect.height; + nscoord childHeight = kidRect.height; // Vertically align the child @@ -618,8 +616,7 @@ void nsTableCellFrame::MapBorderMarginPadding(nsIPresContext* aPresContext) nsTableFrame* tableFrame; nsTableFrame::GetTableFrame(this, tableFrame); - //tableFrame->GetGeometricParent((nsIFrame *&)tableFrame); // get the outer frame - NS_ASSERTION(tableFrame,"Table Must not be null"); + NS_ASSERTION(tableFrame,"Table must not be null"); if (!tableFrame) return; @@ -654,6 +651,8 @@ void nsTableCellFrame::MapBorderMarginPadding(nsIPresContext* aPresContext) border = NSIntPixelsToTwips(1, p2t); MapHTMLBorderStyle(aPresContext, *spacingData, border, tableFrame); } + + // TODO: map the align attributes here } diff --git a/mozilla/layout/html/table/src/nsTableCellFrame.h b/mozilla/layout/html/table/src/nsTableCellFrame.h index 80f92b684a2..aa3bca8ce78 100644 --- a/mozilla/layout/html/table/src/nsTableCellFrame.h +++ b/mozilla/layout/html/table/src/nsTableCellFrame.h @@ -76,7 +76,7 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; - void VerticallyAlignChild(nsIPresContext* aPresContext); + virtual void VerticallyAlignChild(); /** return the mapped cell's row span. Always >= 1. */ virtual PRInt32 GetRowSpan(); diff --git a/mozilla/layout/html/table/src/nsTableFrame.cpp b/mozilla/layout/html/table/src/nsTableFrame.cpp index a733033806e..c1f4b883796 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableFrame.cpp @@ -389,7 +389,7 @@ PRInt32 nsTableFrame::GetSpecifiedColumnCount () return mColCount; } -PRInt32 nsTableFrame::GetRowCount () +PRInt32 nsTableFrame::GetRowCount () const { PRInt32 rowCount = 0; nsCellMap *cellMap = GetCellMap(); @@ -1750,7 +1750,8 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext& aPresContext, // Return our size and our status aDesiredSize.width = ComputeDesiredWidth(aReflowState); - aDesiredSize.height = state.y + myBorderPadding.top + myBorderPadding.bottom; + nscoord defaultHeight = state.y + myBorderPadding.top + myBorderPadding.bottom; + aDesiredSize.height = ComputeDesiredHeight(aPresContext, aReflowState, defaultHeight); if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) { @@ -2764,6 +2765,151 @@ void nsTableFrame::SetTableWidth(nsIPresContext& aPresContext) SetRect(tableSize); } +/* get the height of this table's container. ignore all containers who have unconstrained height. + * take into account the possibility that this table is nested. + * if nested within an auto-height table, this method returns 0. + * this method may also return NS_UNCONSTRAINEDSIZE, meaning no container provided any height constraint + */ +nscoord nsTableFrame::GetEffectiveContainerHeight(const nsHTMLReflowState& aReflowState) +{ + nscoord result=-1; + const nsHTMLReflowState* rs = &aReflowState; + while (nsnull!=rs) + { + const nsStyleDisplay *display; + rs->frame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display); + if (NS_STYLE_DISPLAY_TABLE==display->mDisplay) + { + const nsStylePosition *position; + rs->frame->GetStyleData(eStyleStruct_Position, (nsStyleStruct *&)position); + nsStyleUnit unit = position->mHeight.GetUnit(); + if (eStyleUnit_Null==unit || eStyleUnit_Auto==unit) + { + result = 0; + break; + } + } + if (eHTMLFrameConstraint_Fixed==rs->heightConstraint || + eHTMLFrameConstraint_FixedContent==rs->heightConstraint) + { + result = rs->maxSize.height; + break; + } + // XXX: evil cast! + rs = (nsHTMLReflowState *)(rs->parentReflowState); + } + NS_ASSERTION(-1!=result, "bad state: no constrained height in reflow chain"); + return result; +} + +/** + get the table height attribute + if it is auto, table height = SUM(height of rowgroups) + else if (resolved table height attribute > SUM(height of rowgroups)) + proportionately distribute extra height to each row + we assume we are passed in the default table height==the sum of the heights of the table's rowgroups + in aDesiredSize.height. + */ +nscoord nsTableFrame::ComputeDesiredHeight(nsIPresContext& aPresContext, + const nsHTMLReflowState& aReflowState, + nscoord aDefaultHeight) +{ + NS_ASSERTION(nsnull==mPrevInFlow, "never ever call me on a continuing frame!"); + NS_ASSERTION(nsnull!=mCellMap, "never ever call me until the cell map is built!"); + nsresult rv = NS_OK; + nscoord result = aDefaultHeight; + const nsStylePosition* tablePosition; + GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)tablePosition); + if (eStyleUnit_Auto == tablePosition->mHeight.GetUnit()) + return result; // auto width tables are sized by the row heights, which we already have + + nscoord tableSpecifiedHeight=-1; + if (eStyleUnit_Coord == tablePosition->mHeight.GetUnit()) + tableSpecifiedHeight = tablePosition->mHeight.GetCoordValue(); + else if (eStyleUnit_Percent == tablePosition->mHeight.GetUnit()) + { + float percent = tablePosition->mHeight.GetPercentValue(); + nscoord parentHeight = GetEffectiveContainerHeight(aReflowState); + if (NS_UNCONSTRAINEDSIZE!=parentHeight && 0!=parentHeight) + tableSpecifiedHeight = NSToCoordRound((float)parentHeight * percent); + } + if (-1!=tableSpecifiedHeight) + { + if (tableSpecifiedHeight>aDefaultHeight) + { // proportionately distribute the excess height to each row + result = tableSpecifiedHeight; + nscoord excess = tableSpecifiedHeight-aDefaultHeight; + nscoord sumOfRowHeights=0; + nsIFrame * rowGroupFrame=mFirstChild; + while (nsnull!=rowGroupFrame) + { + const nsStyleDisplay *rowGroupDisplay; + rowGroupFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)rowGroupDisplay)); + if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay)) + { // the rows in rowGroupFrame need to be expanded by rowHeightDelta[i] + // and the rowgroup itself needs to be expanded by SUM(row height deltas) + nscoord excessForRowGroup=0; + nsIFrame * rowFrame=nsnull; + rv = rowGroupFrame->FirstChild(nsnull, rowFrame); + while ((NS_SUCCEEDED(rv)) && (nsnull!=rowFrame)) + { + const nsStyleDisplay *rowDisplay; + rowFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)rowDisplay)); + if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) + { // the row needs to be expanded by the proportion this row contributed to the original height + nsRect rowRect; + rowFrame->GetRect(rowRect); + sumOfRowHeights += rowRect.height; + } + rowFrame->GetNextSibling(rowFrame); + } + } + rowGroupFrame->GetNextSibling(rowGroupFrame); + } + rowGroupFrame=mFirstChild; + nscoord y=0; + while (nsnull!=rowGroupFrame) + { + const nsStyleDisplay *rowGroupDisplay; + rowGroupFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)rowGroupDisplay)); + if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay)) + { // the rows in rowGroupFrame need to be expanded by rowHeightDelta[i] + // and the rowgroup itself needs to be expanded by SUM(row height deltas) + nscoord excessForRowGroup=0; + nsIFrame * rowFrame=nsnull; + rv = rowGroupFrame->FirstChild(nsnull, rowFrame); + while ((NS_SUCCEEDED(rv)) && (nsnull!=rowFrame)) + { + const nsStyleDisplay *rowDisplay; + rowFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)rowDisplay)); + if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) + { // the row needs to be expanded by the proportion this row contributed to the original height + nsRect rowRect; + rowFrame->GetRect(rowRect); + float percent = ((float)(rowRect.height)) / ((float)(sumOfRowHeights)); + nscoord excessForRow = NSToCoordRound((float)excess*percent); + nsRect newRowRect(rowRect.x, y, rowRect.width, excessForRow+rowRect.height); + rowFrame->SetRect(newRowRect); + // resize cells, too + ((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState); + // better if this were part of an overloaded row::SetRect + y += excessForRow+rowRect.height; + excessForRowGroup += excessForRow; + } + rowFrame->GetNextSibling(rowFrame); + } + nsRect rowGroupRect; + rowGroupFrame->GetRect(rowGroupRect); + nsRect newRowGroupRect(rowGroupRect.x, rowGroupRect.y, rowGroupRect.width, excessForRowGroup+rowGroupRect.height); + rowGroupFrame->SetRect(newRowGroupRect); + } + rowGroupFrame->GetNextSibling(rowGroupFrame); + } + } + } + return result; +} + void nsTableFrame::AdjustColumnsForCOLSAttribute() { nsCellMap *cellMap = GetCellMap(); @@ -2979,7 +3125,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext& aPresContext, mColCache = new ColumnInfoCache(GetColCount()); nsIFrame * childFrame = mFirstChild; while (nsnull!=childFrame) - { // in this loop, we cache column info and set column style info from cells in first row + { // in this loop, we cache column info and set column style info from cells const nsStyleDisplay *childDisplay; childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay)); @@ -3038,7 +3184,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext& aPresContext, } // second time through, set column cache info for each column - // we can't do this until the loop above has set the column style info from the cells in the first row + // we can't do this until the loop above has set the column style info from the cells childFrame = mFirstChild; while (nsnull!=childFrame) { // for every child, if it's a col group then get the columns @@ -3512,9 +3658,7 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta // Walk up the reflow state chain until we find a block // frame. Our width is computed relative to there. const nsReflowState* rs = &aReflowState; - nsIFrame *childFrame=nsnull; - nsIFrame *grandchildFrame=nsnull; - nsIFrame *greatgrandchildFrame=nsnull; + nsTableCellFrame *lastCellFrame=nsnull; while (nsnull != rs) { // if it's a block, use its max width @@ -3560,17 +3704,18 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta if (NS_STYLE_DISPLAY_TABLE_CELL==display->mDisplay) { // if it's a cell and the cell has a specified width, use it // Compute and subtract out the insets (sum of border and padding) for the table + lastCellFrame = (nsTableCellFrame*)(rs->frame); const nsStylePosition* cellPosition; - rs->frame->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)cellPosition)); + lastCellFrame->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)cellPosition)); if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) { nsTableFrame *tableParent; - nsresult rv=GetTableFrame(rs->frame, tableParent); + nsresult rv=GetTableFrame(lastCellFrame, tableParent); if ((NS_OK==rv) && (nsnull!=tableParent) && (nsnull!=tableParent->mColumnWidths)) { parentWidth=0; - PRInt32 colIndex = ((nsTableCellFrame *)rs->frame)->GetColIndex(); - PRInt32 colSpan = tableParent->GetEffectiveColSpan(colIndex, (nsTableCellFrame *)rs->frame); + PRInt32 colIndex = lastCellFrame->GetColIndex(); + PRInt32 colSpan = tableParent->GetEffectiveColSpan(colIndex, lastCellFrame); for (PRInt32 i=0; iGetColumnWidth(colIndex); break; @@ -3581,12 +3726,12 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta { parentWidth = cellPosition->mWidth.GetCoordValue(); // subtract out cell border and padding - rs->frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); - spacing->CalcBorderPaddingFor(rs->frame, borderPadding); + lastCellFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(lastCellFrame, borderPadding); parentWidth -= (borderPadding.right + borderPadding.left); if (PR_TRUE==gsDebugNT) printf("%p: found a cell frame %p with fixed coord width %d, returning parentWidth %d\n", - aReflowState.frame, rs->frame, cellPosition->mWidth.GetCoordValue(), parentWidth); + aReflowState.frame, lastCellFrame, cellPosition->mWidth.GetCoordValue(), parentWidth); break; } } @@ -3618,16 +3763,16 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta if (eStyleUnit_Auto == tablePosition->mWidth.GetUnit()) { parentWidth = NS_UNCONSTRAINEDSIZE; - if (nsnull != ((nsTableFrame*)rs->frame)->mColumnWidths) + if (nsnull != ((nsTableFrame*)(rs->frame))->mColumnWidths) { parentWidth=0; - PRInt32 colIndex = ((nsTableCellFrame *)greatgrandchildFrame)->GetColIndex(); - PRInt32 colSpan = ((nsTableFrame*)rs->frame)->GetEffectiveColSpan(colIndex, ((nsTableCellFrame *)greatgrandchildFrame)); + PRInt32 colIndex = lastCellFrame->GetColIndex(); + PRInt32 colSpan = ((nsTableFrame*)(rs->frame))->GetEffectiveColSpan(colIndex, lastCellFrame); for (PRInt32 i = 0; iframe)->GetColumnWidth(i+colIndex); + parentWidth += ((nsTableFrame*)(rs->frame))->GetColumnWidth(i+colIndex); // subtract out cell border and padding - greatgrandchildFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); - spacing->CalcBorderPaddingFor(greatgrandchildFrame, borderPadding); + lastCellFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(lastCellFrame, borderPadding); parentWidth -= (borderPadding.right + borderPadding.left); if (PR_TRUE==gsDebugNT) printf("%p: found a table frame %p with auto width, returning parentWidth %d from cell in col %d with span %d\n", @@ -3642,13 +3787,13 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta } else { - if (nsnull!=((nsTableFrame*)rs->frame)->mColumnWidths) + if (nsnull!=((nsTableFrame*)(rs->frame))->mColumnWidths) { parentWidth=0; - PRInt32 colIndex = ((nsTableCellFrame*)greatgrandchildFrame)->GetColIndex(); - PRInt32 colSpan = ((nsTableFrame*)rs->frame)->GetEffectiveColSpan(colIndex, ((nsTableCellFrame *)greatgrandchildFrame)); + PRInt32 colIndex = lastCellFrame->GetColIndex(); + PRInt32 colSpan = ((nsTableFrame*)(rs->frame))->GetEffectiveColSpan(colIndex, lastCellFrame); for (PRInt32 i = 0; iframe)->GetColumnWidth(i+colIndex); + parentWidth += ((nsTableFrame*)(rs->frame))->GetColumnWidth(i+colIndex); } else { @@ -3659,17 +3804,9 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta { // the table has been sized, so we can compute the available space for the child 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); + // factor in the cell + lastCellFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(lastCellFrame, borderPadding); parentWidth -= (borderPadding.right + borderPadding.left); } else @@ -3693,19 +3830,6 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta } } - 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; } diff --git a/mozilla/layout/html/table/src/nsTableFrame.h b/mozilla/layout/html/table/src/nsTableFrame.h index 716664e3c18..97ef0dc38fc 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.h +++ b/mozilla/layout/html/table/src/nsTableFrame.h @@ -90,7 +90,7 @@ public: /** return PR_TRUE if aDisplayType represents a rowgroup of any sort * (header, footer, or body) */ - PRBool IsRowGroup(PRInt32 aDisplayType); + PRBool IsRowGroup(PRInt32 aDisplayType) const; NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, nsIAtom* aListName, @@ -368,6 +368,12 @@ protected: */ nscoord ComputeDesiredWidth(const nsHTMLReflowState& aReflowState) const; + nscoord ComputeDesiredHeight(nsIPresContext& aPresContext, + const nsHTMLReflowState& aReflowState, + nscoord aDefaultHeight); + + nscoord GetEffectiveContainerHeight(const nsHTMLReflowState& aReflowState); + nscoord GetTopMarginFor(nsIPresContext& aCX, InnerTableReflowState& aReflowState, const nsMargin& aKidMargin); @@ -524,7 +530,7 @@ public: /* ----- Cell Map public methods ----- */ * if mCellMap has been created, it is asked for the number of rows.
* otherwise, the content is enumerated and the rows are counted. */ - virtual PRInt32 GetRowCount(); + virtual PRInt32 GetRowCount() const; /** returns the number of columns in this table. */ virtual PRInt32 GetColCount(); @@ -605,7 +611,7 @@ private: }; -inline PRBool nsTableFrame::IsRowGroup(PRInt32 aDisplayType) +inline PRBool nsTableFrame::IsRowGroup(PRInt32 aDisplayType) const { return PRBool((NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == aDisplayType) || (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == aDisplayType) || diff --git a/mozilla/layout/html/table/src/nsTableRowFrame.cpp b/mozilla/layout/html/table/src/nsTableRowFrame.cpp index 7929a818c98..2aca5b9f45c 100644 --- a/mozilla/layout/html/table/src/nsTableRowFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableRowFrame.cpp @@ -174,55 +174,61 @@ nsTableRowFrame::InitChildren(PRInt32 aRowIndex) /** * Post-reflow hook. This is where the table row does its post-processing */ -NS_METHOD -nsTableRowFrame::DidReflow(nsIPresContext& aPresContext, - nsDidReflowStatus aStatus) +void +nsTableRowFrame::DidResize(nsIPresContext& aPresContext, + const nsHTMLReflowState& aReflowState) { - if (gsDebug) printf("Row %p DidReflow: begin mRect.h=%d, mCellMTM=%d, mCellMBM=%d\n", + if (gsDebug) printf("Row %p DidResize: begin mRect.h=%d, mCellMTM=%d, mCellMBM=%d\n", this, mRect.height, mCellMaxTopMargin, mCellMaxBottomMargin); - if (NS_FRAME_REFLOW_FINISHED == aStatus) { - // Resize and re-align the cell frames based on our row height - nscoord cellHeight = mRect.height - mCellMaxTopMargin - mCellMaxBottomMargin; - if (gsDebug) printf("Row DidReflow: cellHeight=%d\n", cellHeight); - nsIFrame *cellFrame = mFirstChild; - nsTableFrame* tableFrame; - nsTableFrame::GetTableFrame(this, tableFrame); - while (nsnull != cellFrame) + // Resize and re-align the cell frames based on our row height + nscoord cellHeight = mRect.height - mCellMaxTopMargin - mCellMaxBottomMargin; + if (gsDebug) printf("Row DidReflow: cellHeight=%d\n", cellHeight); + nsIFrame *cellFrame = mFirstChild; + nsTableFrame* tableFrame; + nsTableFrame::GetTableFrame(this, tableFrame); + while (nsnull != cellFrame) + { + const nsStyleDisplay *kidDisplay; + cellFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)kidDisplay)); + if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay) { - const nsStyleDisplay *kidDisplay; - cellFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)kidDisplay)); - if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay) + PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(mRowIndex, (nsTableCellFrame *)cellFrame); + if (gsDebug) printf("Row DidReflow: cellFrame %p ", cellFrame); + if (1==rowSpan) { - PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(mRowIndex, (nsTableCellFrame *)cellFrame); - if (gsDebug) printf("Row DidReflow: cellFrame %p ", cellFrame); - if (1==rowSpan) + // resize the cell's height + nsSize cellFrameSize; + cellFrame->GetSize(cellFrameSize); + if (cellFrameSize.height!=cellHeight) { - // resize the cell's height - nsSize cellFrameSize; - cellFrame->GetSize(cellFrameSize); cellFrame->SizeTo(cellFrameSize.width, cellHeight); if (gsDebug) printf("given height %d\n", cellHeight); // realign cell content based on the new height - ((nsTableCellFrame *)cellFrame)->VerticallyAlignChild(&aPresContext); - } - else - { - if (gsDebug) - { - nsSize cellFrameSize; - cellFrame->GetSize(cellFrameSize); - printf("has rowspan %d and height %d, unchanged.\n", rowSpan, cellFrameSize.height); - } + nsHTMLReflowMetrics desiredSize(nsnull); + nsHTMLReflowState kidReflowState(aPresContext, cellFrame, + aReflowState, nsSize(cellFrameSize.width, cellHeight), + eReflowReason_Resize); + nsReflowStatus status; + ReflowChild(cellFrame, aPresContext, desiredSize, kidReflowState, status); + ((nsTableCellFrame *)cellFrame)->VerticallyAlignChild(); + } + } + else + { + if (gsDebug) + { + nsSize cellFrameSize; + cellFrame->GetSize(cellFrameSize); + printf("has rowspan %d and height %d, unchanged.\n", rowSpan, cellFrameSize.height); } } - // Get the next cell - cellFrame->GetNextSibling(cellFrame); } + // Get the next cell + cellFrame->GetNextSibling(cellFrame); } // Let our base class do the usual work - if (gsDebug) printf("Row DidReflow: returning superclass DidReflow.\n"); - return nsContainerFrame::DidReflow(aPresContext, aStatus); + if (gsDebug) printf("Row DidResize: returning NS_OK.\n"); } void nsTableRowFrame::ResetMaxChildHeight() @@ -449,6 +455,22 @@ void nsTableRowFrame::PlaceChild(nsIPresContext& aPresContext, } } +nsIFrame * nsTableRowFrame::GetNextChildForDirection(PRUint8 aDir, nsIFrame *aCurrentChild) +{ + NS_ASSERTION(nsnull!=aCurrentChild, "bad arg"); + + nsIFrame *result=nsnull; + aCurrentChild->GetNextSibling(result); + return result; +} + +nsIFrame * nsTableRowFrame::GetFirstChildForDirection(PRUint8 aDir) +{ + nsIFrame *result=nsnull; + result = mFirstChild; + return result; +} + /** * Called for a resize reflow. Typically because the column widths have * changed. Reflows all the existing table cell frames @@ -461,18 +483,22 @@ NS_METHOD nsTableRowFrame::ResizeReflow(nsIPresContext& aPresContext, if (nsnull == mFirstChild) return NS_OK; - nsresult rv=NS_OK; - nsSize kidMaxElementSize; - PRInt32 prevColIndex = -1; // remember the col index of the previous cell to handle rowspans into this row - nsSize* pKidMaxElementSize = (nsnull != aDesiredSize.maxElementSize) ? - &kidMaxElementSize : nsnull; - nscoord maxCellTopMargin = 0; - nscoord maxCellBottomMargin = 0; + nsresult rv=NS_OK; + nsSize kidMaxElementSize; + PRInt32 prevColIndex = -1; // remember the col index of the previous cell to handle rowspans into this row + nsSize* pKidMaxElementSize = (nsnull != aDesiredSize.maxElementSize) ? + &kidMaxElementSize : nsnull; + nscoord maxCellTopMargin = 0; + nscoord maxCellBottomMargin = 0; nscoord cellSpacing = aReflowState.tableFrame->GetCellSpacing(); PRInt32 cellColSpan=1; // must be defined here so it's set properly for non-cell kids if (PR_TRUE==gsDebug) printf("Row %p: Resize Reflow\n", this); + // Reflow each of our existing cell frames - for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) + const nsStyleDisplay *rowDisplay; + GetStyleData(eStyleStruct_Display, (nsStyleStruct*&)rowDisplay); + nsIFrame* kidFrame=GetFirstChildForDirection(rowDisplay->mDirection); + for (kidFrame; nsnull != kidFrame; ) { const nsStyleDisplay *kidDisplay; kidFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)kidDisplay)); @@ -621,7 +647,7 @@ NS_METHOD nsTableRowFrame::ResizeReflow(nsIPresContext& aPresContext, } // Get the next child - kidFrame->GetNextSibling(kidFrame); + kidFrame = GetNextChildForDirection(rowDisplay->mDirection, kidFrame); // if this was the last child, and it had a colspan>1, add in the cellSpacing for the colspan // if the last kid wasn't a colspan, then we still have the colspan of the last real cell if ((nsnull==kidFrame) && (cellColSpan>1)) diff --git a/mozilla/layout/html/table/src/nsTableRowFrame.h b/mozilla/layout/html/table/src/nsTableRowFrame.h index 9625fa66992..65d6d169818 100644 --- a/mozilla/layout/html/table/src/nsTableRowFrame.h +++ b/mozilla/layout/html/table/src/nsTableRowFrame.h @@ -93,8 +93,8 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); - NS_IMETHOD DidReflow(nsIPresContext& aPresContext, - nsDidReflowStatus aStatus); + virtual void DidResize(nsIPresContext& aPresContext, + const nsHTMLReflowState& aReflowState); /** @see nsContainerFrame::CreateContinuingFrame */ NS_IMETHOD CreateContinuingFrame(nsIPresContext& aPresContext, @@ -214,6 +214,9 @@ protected: nscoord ComputeCellAvailWidth(const RowReflowState& aState, nsIFrame* aKidFrame) const; + nsIFrame * GetFirstChildForDirection(PRUint8 aDir); + nsIFrame * GetNextChildForDirection(PRUint8 aDir, nsIFrame *aCurrentChild); + /** * Called for a resize reflow. Typically because the column widths have * changed. Reflows all the existing table cell frames diff --git a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp index be496ce96e2..8bae925ef96 100644 --- a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp @@ -601,12 +601,15 @@ NS_METHOD nsTableRowGroupFrame::PullUpChildren(nsIPresContext& aPresContext return rv; } -/** - */ -void nsTableRowGroupFrame::ShrinkWrapChildren(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize) +/* CalculateRowHeights provides default heights for all rows in the rowgroup. + * Actual row heights are ultimately determined by the table, when the table + * height attribute is factored in. + */ +void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState) { - if (gsDebug) printf("TRGF ShrinkWrapChildren begin\n"); + if (gsDebug) printf("TRGF CalculateRowHeights begin\n"); // iterate children and for each row get its height PRBool atLeastOneRowSpanningCell = PR_FALSE; nscoord topInnerMargin = 0; @@ -717,7 +720,7 @@ void nsTableRowGroupFrame::ShrinkWrapChildren(nsIPresContext* aPresContext, cellFrameSize.height, heightOfRowsSpanned); cellFrame->SizeTo(cellFrameSize.width, heightOfRowsSpanned); // Realign cell content based on new height - ((nsTableCellFrame*)cellFrame)->VerticallyAlignChild(aPresContext); + ((nsTableCellFrame*)cellFrame)->VerticallyAlignChild(); } /* otherwise, distribute the excess height to the rows effected. * push all subsequent rows down by the total change in height of all the rows above it @@ -781,6 +784,20 @@ void nsTableRowGroupFrame::ShrinkWrapChildren(nsIPresContext* aPresContext, } } + // finally, notify the rows of their new heights + rowFrame = mFirstChild; + while (nsnull != rowFrame) + { + const nsStyleDisplay *childDisplay; + rowFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay)); + if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay) + { + ((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState); + } + // Get the next row + rowFrame->GetNextSibling(rowFrame); + } + // Adjust our desired size aDesiredSize.height = rowGroupHeight; @@ -907,7 +924,9 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext, aDesiredSize.height = state.y; // shrink wrap rows to height of tallest cell in that row - ShrinkWrapChildren(&aPresContext, aDesiredSize); + if (eReflowReason_Initial != aReflowState.reason) { + CalculateRowHeights(aPresContext, aDesiredSize, aReflowState); + } } if (gsDebug==PR_TRUE) @@ -1337,3 +1356,4 @@ nsTableRowGroupFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("TableRowGroup", aResult); } + diff --git a/mozilla/layout/html/table/src/nsTableRowGroupFrame.h b/mozilla/layout/html/table/src/nsTableRowGroupFrame.h index c2bfd335b03..12bbfbb8dfd 100644 --- a/mozilla/layout/html/table/src/nsTableRowGroupFrame.h +++ b/mozilla/layout/html/table/src/nsTableRowGroupFrame.h @@ -133,8 +133,9 @@ protected: nsSize* aMaxElementSize, nsSize& aKidMaxElementSize); - void ShrinkWrapChildren(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize); + void CalculateRowHeights(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState); /** Incremental Reflow attempts to do column balancing with the minimum number of reflow diff --git a/mozilla/layout/tables/nsTableCellFrame.cpp b/mozilla/layout/tables/nsTableCellFrame.cpp index eed86fa971f..3e349deba89 100644 --- a/mozilla/layout/tables/nsTableCellFrame.cpp +++ b/mozilla/layout/tables/nsTableCellFrame.cpp @@ -159,7 +159,7 @@ nsTableCellFrame::GetSkipSides() const * Align the cell's child frame within the cell * */ -void nsTableCellFrame::VerticallyAlignChild(nsIPresContext* aPresContext) +void nsTableCellFrame::VerticallyAlignChild() { const nsStyleSpacing* spacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); @@ -174,12 +174,10 @@ void nsTableCellFrame::VerticallyAlignChild(nsIPresContext* aPresContext) if (textStyle->mVerticalAlign.GetUnit() == eStyleUnit_Enumerated) { verticalAlignFlags = textStyle->mVerticalAlign.GetIntValue(); } - - nscoord height = mRect.height; - - nsRect kidRect; + nscoord height = mRect.height; + nsRect kidRect; mFirstChild->GetRect(kidRect); - nscoord childHeight = kidRect.height; + nscoord childHeight = kidRect.height; // Vertically align the child @@ -618,8 +616,7 @@ void nsTableCellFrame::MapBorderMarginPadding(nsIPresContext* aPresContext) nsTableFrame* tableFrame; nsTableFrame::GetTableFrame(this, tableFrame); - //tableFrame->GetGeometricParent((nsIFrame *&)tableFrame); // get the outer frame - NS_ASSERTION(tableFrame,"Table Must not be null"); + NS_ASSERTION(tableFrame,"Table must not be null"); if (!tableFrame) return; @@ -654,6 +651,8 @@ void nsTableCellFrame::MapBorderMarginPadding(nsIPresContext* aPresContext) border = NSIntPixelsToTwips(1, p2t); MapHTMLBorderStyle(aPresContext, *spacingData, border, tableFrame); } + + // TODO: map the align attributes here } diff --git a/mozilla/layout/tables/nsTableCellFrame.h b/mozilla/layout/tables/nsTableCellFrame.h index 80f92b684a2..aa3bca8ce78 100644 --- a/mozilla/layout/tables/nsTableCellFrame.h +++ b/mozilla/layout/tables/nsTableCellFrame.h @@ -76,7 +76,7 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; - void VerticallyAlignChild(nsIPresContext* aPresContext); + virtual void VerticallyAlignChild(); /** return the mapped cell's row span. Always >= 1. */ virtual PRInt32 GetRowSpan(); diff --git a/mozilla/layout/tables/nsTableFrame.cpp b/mozilla/layout/tables/nsTableFrame.cpp index a733033806e..c1f4b883796 100644 --- a/mozilla/layout/tables/nsTableFrame.cpp +++ b/mozilla/layout/tables/nsTableFrame.cpp @@ -389,7 +389,7 @@ PRInt32 nsTableFrame::GetSpecifiedColumnCount () return mColCount; } -PRInt32 nsTableFrame::GetRowCount () +PRInt32 nsTableFrame::GetRowCount () const { PRInt32 rowCount = 0; nsCellMap *cellMap = GetCellMap(); @@ -1750,7 +1750,8 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext& aPresContext, // Return our size and our status aDesiredSize.width = ComputeDesiredWidth(aReflowState); - aDesiredSize.height = state.y + myBorderPadding.top + myBorderPadding.bottom; + nscoord defaultHeight = state.y + myBorderPadding.top + myBorderPadding.bottom; + aDesiredSize.height = ComputeDesiredHeight(aPresContext, aReflowState, defaultHeight); if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) { @@ -2764,6 +2765,151 @@ void nsTableFrame::SetTableWidth(nsIPresContext& aPresContext) SetRect(tableSize); } +/* get the height of this table's container. ignore all containers who have unconstrained height. + * take into account the possibility that this table is nested. + * if nested within an auto-height table, this method returns 0. + * this method may also return NS_UNCONSTRAINEDSIZE, meaning no container provided any height constraint + */ +nscoord nsTableFrame::GetEffectiveContainerHeight(const nsHTMLReflowState& aReflowState) +{ + nscoord result=-1; + const nsHTMLReflowState* rs = &aReflowState; + while (nsnull!=rs) + { + const nsStyleDisplay *display; + rs->frame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display); + if (NS_STYLE_DISPLAY_TABLE==display->mDisplay) + { + const nsStylePosition *position; + rs->frame->GetStyleData(eStyleStruct_Position, (nsStyleStruct *&)position); + nsStyleUnit unit = position->mHeight.GetUnit(); + if (eStyleUnit_Null==unit || eStyleUnit_Auto==unit) + { + result = 0; + break; + } + } + if (eHTMLFrameConstraint_Fixed==rs->heightConstraint || + eHTMLFrameConstraint_FixedContent==rs->heightConstraint) + { + result = rs->maxSize.height; + break; + } + // XXX: evil cast! + rs = (nsHTMLReflowState *)(rs->parentReflowState); + } + NS_ASSERTION(-1!=result, "bad state: no constrained height in reflow chain"); + return result; +} + +/** + get the table height attribute + if it is auto, table height = SUM(height of rowgroups) + else if (resolved table height attribute > SUM(height of rowgroups)) + proportionately distribute extra height to each row + we assume we are passed in the default table height==the sum of the heights of the table's rowgroups + in aDesiredSize.height. + */ +nscoord nsTableFrame::ComputeDesiredHeight(nsIPresContext& aPresContext, + const nsHTMLReflowState& aReflowState, + nscoord aDefaultHeight) +{ + NS_ASSERTION(nsnull==mPrevInFlow, "never ever call me on a continuing frame!"); + NS_ASSERTION(nsnull!=mCellMap, "never ever call me until the cell map is built!"); + nsresult rv = NS_OK; + nscoord result = aDefaultHeight; + const nsStylePosition* tablePosition; + GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)tablePosition); + if (eStyleUnit_Auto == tablePosition->mHeight.GetUnit()) + return result; // auto width tables are sized by the row heights, which we already have + + nscoord tableSpecifiedHeight=-1; + if (eStyleUnit_Coord == tablePosition->mHeight.GetUnit()) + tableSpecifiedHeight = tablePosition->mHeight.GetCoordValue(); + else if (eStyleUnit_Percent == tablePosition->mHeight.GetUnit()) + { + float percent = tablePosition->mHeight.GetPercentValue(); + nscoord parentHeight = GetEffectiveContainerHeight(aReflowState); + if (NS_UNCONSTRAINEDSIZE!=parentHeight && 0!=parentHeight) + tableSpecifiedHeight = NSToCoordRound((float)parentHeight * percent); + } + if (-1!=tableSpecifiedHeight) + { + if (tableSpecifiedHeight>aDefaultHeight) + { // proportionately distribute the excess height to each row + result = tableSpecifiedHeight; + nscoord excess = tableSpecifiedHeight-aDefaultHeight; + nscoord sumOfRowHeights=0; + nsIFrame * rowGroupFrame=mFirstChild; + while (nsnull!=rowGroupFrame) + { + const nsStyleDisplay *rowGroupDisplay; + rowGroupFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)rowGroupDisplay)); + if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay)) + { // the rows in rowGroupFrame need to be expanded by rowHeightDelta[i] + // and the rowgroup itself needs to be expanded by SUM(row height deltas) + nscoord excessForRowGroup=0; + nsIFrame * rowFrame=nsnull; + rv = rowGroupFrame->FirstChild(nsnull, rowFrame); + while ((NS_SUCCEEDED(rv)) && (nsnull!=rowFrame)) + { + const nsStyleDisplay *rowDisplay; + rowFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)rowDisplay)); + if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) + { // the row needs to be expanded by the proportion this row contributed to the original height + nsRect rowRect; + rowFrame->GetRect(rowRect); + sumOfRowHeights += rowRect.height; + } + rowFrame->GetNextSibling(rowFrame); + } + } + rowGroupFrame->GetNextSibling(rowGroupFrame); + } + rowGroupFrame=mFirstChild; + nscoord y=0; + while (nsnull!=rowGroupFrame) + { + const nsStyleDisplay *rowGroupDisplay; + rowGroupFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)rowGroupDisplay)); + if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay)) + { // the rows in rowGroupFrame need to be expanded by rowHeightDelta[i] + // and the rowgroup itself needs to be expanded by SUM(row height deltas) + nscoord excessForRowGroup=0; + nsIFrame * rowFrame=nsnull; + rv = rowGroupFrame->FirstChild(nsnull, rowFrame); + while ((NS_SUCCEEDED(rv)) && (nsnull!=rowFrame)) + { + const nsStyleDisplay *rowDisplay; + rowFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)rowDisplay)); + if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) + { // the row needs to be expanded by the proportion this row contributed to the original height + nsRect rowRect; + rowFrame->GetRect(rowRect); + float percent = ((float)(rowRect.height)) / ((float)(sumOfRowHeights)); + nscoord excessForRow = NSToCoordRound((float)excess*percent); + nsRect newRowRect(rowRect.x, y, rowRect.width, excessForRow+rowRect.height); + rowFrame->SetRect(newRowRect); + // resize cells, too + ((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState); + // better if this were part of an overloaded row::SetRect + y += excessForRow+rowRect.height; + excessForRowGroup += excessForRow; + } + rowFrame->GetNextSibling(rowFrame); + } + nsRect rowGroupRect; + rowGroupFrame->GetRect(rowGroupRect); + nsRect newRowGroupRect(rowGroupRect.x, rowGroupRect.y, rowGroupRect.width, excessForRowGroup+rowGroupRect.height); + rowGroupFrame->SetRect(newRowGroupRect); + } + rowGroupFrame->GetNextSibling(rowGroupFrame); + } + } + } + return result; +} + void nsTableFrame::AdjustColumnsForCOLSAttribute() { nsCellMap *cellMap = GetCellMap(); @@ -2979,7 +3125,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext& aPresContext, mColCache = new ColumnInfoCache(GetColCount()); nsIFrame * childFrame = mFirstChild; while (nsnull!=childFrame) - { // in this loop, we cache column info and set column style info from cells in first row + { // in this loop, we cache column info and set column style info from cells const nsStyleDisplay *childDisplay; childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay)); @@ -3038,7 +3184,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext& aPresContext, } // second time through, set column cache info for each column - // we can't do this until the loop above has set the column style info from the cells in the first row + // we can't do this until the loop above has set the column style info from the cells childFrame = mFirstChild; while (nsnull!=childFrame) { // for every child, if it's a col group then get the columns @@ -3512,9 +3658,7 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta // Walk up the reflow state chain until we find a block // frame. Our width is computed relative to there. const nsReflowState* rs = &aReflowState; - nsIFrame *childFrame=nsnull; - nsIFrame *grandchildFrame=nsnull; - nsIFrame *greatgrandchildFrame=nsnull; + nsTableCellFrame *lastCellFrame=nsnull; while (nsnull != rs) { // if it's a block, use its max width @@ -3560,17 +3704,18 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta if (NS_STYLE_DISPLAY_TABLE_CELL==display->mDisplay) { // if it's a cell and the cell has a specified width, use it // Compute and subtract out the insets (sum of border and padding) for the table + lastCellFrame = (nsTableCellFrame*)(rs->frame); const nsStylePosition* cellPosition; - rs->frame->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)cellPosition)); + lastCellFrame->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)cellPosition)); if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) { nsTableFrame *tableParent; - nsresult rv=GetTableFrame(rs->frame, tableParent); + nsresult rv=GetTableFrame(lastCellFrame, tableParent); if ((NS_OK==rv) && (nsnull!=tableParent) && (nsnull!=tableParent->mColumnWidths)) { parentWidth=0; - PRInt32 colIndex = ((nsTableCellFrame *)rs->frame)->GetColIndex(); - PRInt32 colSpan = tableParent->GetEffectiveColSpan(colIndex, (nsTableCellFrame *)rs->frame); + PRInt32 colIndex = lastCellFrame->GetColIndex(); + PRInt32 colSpan = tableParent->GetEffectiveColSpan(colIndex, lastCellFrame); for (PRInt32 i=0; iGetColumnWidth(colIndex); break; @@ -3581,12 +3726,12 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta { parentWidth = cellPosition->mWidth.GetCoordValue(); // subtract out cell border and padding - rs->frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); - spacing->CalcBorderPaddingFor(rs->frame, borderPadding); + lastCellFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(lastCellFrame, borderPadding); parentWidth -= (borderPadding.right + borderPadding.left); if (PR_TRUE==gsDebugNT) printf("%p: found a cell frame %p with fixed coord width %d, returning parentWidth %d\n", - aReflowState.frame, rs->frame, cellPosition->mWidth.GetCoordValue(), parentWidth); + aReflowState.frame, lastCellFrame, cellPosition->mWidth.GetCoordValue(), parentWidth); break; } } @@ -3618,16 +3763,16 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta if (eStyleUnit_Auto == tablePosition->mWidth.GetUnit()) { parentWidth = NS_UNCONSTRAINEDSIZE; - if (nsnull != ((nsTableFrame*)rs->frame)->mColumnWidths) + if (nsnull != ((nsTableFrame*)(rs->frame))->mColumnWidths) { parentWidth=0; - PRInt32 colIndex = ((nsTableCellFrame *)greatgrandchildFrame)->GetColIndex(); - PRInt32 colSpan = ((nsTableFrame*)rs->frame)->GetEffectiveColSpan(colIndex, ((nsTableCellFrame *)greatgrandchildFrame)); + PRInt32 colIndex = lastCellFrame->GetColIndex(); + PRInt32 colSpan = ((nsTableFrame*)(rs->frame))->GetEffectiveColSpan(colIndex, lastCellFrame); for (PRInt32 i = 0; iframe)->GetColumnWidth(i+colIndex); + parentWidth += ((nsTableFrame*)(rs->frame))->GetColumnWidth(i+colIndex); // subtract out cell border and padding - greatgrandchildFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); - spacing->CalcBorderPaddingFor(greatgrandchildFrame, borderPadding); + lastCellFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(lastCellFrame, borderPadding); parentWidth -= (borderPadding.right + borderPadding.left); if (PR_TRUE==gsDebugNT) printf("%p: found a table frame %p with auto width, returning parentWidth %d from cell in col %d with span %d\n", @@ -3642,13 +3787,13 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta } else { - if (nsnull!=((nsTableFrame*)rs->frame)->mColumnWidths) + if (nsnull!=((nsTableFrame*)(rs->frame))->mColumnWidths) { parentWidth=0; - PRInt32 colIndex = ((nsTableCellFrame*)greatgrandchildFrame)->GetColIndex(); - PRInt32 colSpan = ((nsTableFrame*)rs->frame)->GetEffectiveColSpan(colIndex, ((nsTableCellFrame *)greatgrandchildFrame)); + PRInt32 colIndex = lastCellFrame->GetColIndex(); + PRInt32 colSpan = ((nsTableFrame*)(rs->frame))->GetEffectiveColSpan(colIndex, lastCellFrame); for (PRInt32 i = 0; iframe)->GetColumnWidth(i+colIndex); + parentWidth += ((nsTableFrame*)(rs->frame))->GetColumnWidth(i+colIndex); } else { @@ -3659,17 +3804,9 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta { // the table has been sized, so we can compute the available space for the child 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); + // factor in the cell + lastCellFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + spacing->CalcBorderPaddingFor(lastCellFrame, borderPadding); parentWidth -= (borderPadding.right + borderPadding.left); } else @@ -3693,19 +3830,6 @@ nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowSta } } - 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; } diff --git a/mozilla/layout/tables/nsTableFrame.h b/mozilla/layout/tables/nsTableFrame.h index 716664e3c18..97ef0dc38fc 100644 --- a/mozilla/layout/tables/nsTableFrame.h +++ b/mozilla/layout/tables/nsTableFrame.h @@ -90,7 +90,7 @@ public: /** return PR_TRUE if aDisplayType represents a rowgroup of any sort * (header, footer, or body) */ - PRBool IsRowGroup(PRInt32 aDisplayType); + PRBool IsRowGroup(PRInt32 aDisplayType) const; NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, nsIAtom* aListName, @@ -368,6 +368,12 @@ protected: */ nscoord ComputeDesiredWidth(const nsHTMLReflowState& aReflowState) const; + nscoord ComputeDesiredHeight(nsIPresContext& aPresContext, + const nsHTMLReflowState& aReflowState, + nscoord aDefaultHeight); + + nscoord GetEffectiveContainerHeight(const nsHTMLReflowState& aReflowState); + nscoord GetTopMarginFor(nsIPresContext& aCX, InnerTableReflowState& aReflowState, const nsMargin& aKidMargin); @@ -524,7 +530,7 @@ public: /* ----- Cell Map public methods ----- */ * if mCellMap has been created, it is asked for the number of rows.
* otherwise, the content is enumerated and the rows are counted. */ - virtual PRInt32 GetRowCount(); + virtual PRInt32 GetRowCount() const; /** returns the number of columns in this table. */ virtual PRInt32 GetColCount(); @@ -605,7 +611,7 @@ private: }; -inline PRBool nsTableFrame::IsRowGroup(PRInt32 aDisplayType) +inline PRBool nsTableFrame::IsRowGroup(PRInt32 aDisplayType) const { return PRBool((NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == aDisplayType) || (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == aDisplayType) || diff --git a/mozilla/layout/tables/nsTableRowFrame.cpp b/mozilla/layout/tables/nsTableRowFrame.cpp index 7929a818c98..2aca5b9f45c 100644 --- a/mozilla/layout/tables/nsTableRowFrame.cpp +++ b/mozilla/layout/tables/nsTableRowFrame.cpp @@ -174,55 +174,61 @@ nsTableRowFrame::InitChildren(PRInt32 aRowIndex) /** * Post-reflow hook. This is where the table row does its post-processing */ -NS_METHOD -nsTableRowFrame::DidReflow(nsIPresContext& aPresContext, - nsDidReflowStatus aStatus) +void +nsTableRowFrame::DidResize(nsIPresContext& aPresContext, + const nsHTMLReflowState& aReflowState) { - if (gsDebug) printf("Row %p DidReflow: begin mRect.h=%d, mCellMTM=%d, mCellMBM=%d\n", + if (gsDebug) printf("Row %p DidResize: begin mRect.h=%d, mCellMTM=%d, mCellMBM=%d\n", this, mRect.height, mCellMaxTopMargin, mCellMaxBottomMargin); - if (NS_FRAME_REFLOW_FINISHED == aStatus) { - // Resize and re-align the cell frames based on our row height - nscoord cellHeight = mRect.height - mCellMaxTopMargin - mCellMaxBottomMargin; - if (gsDebug) printf("Row DidReflow: cellHeight=%d\n", cellHeight); - nsIFrame *cellFrame = mFirstChild; - nsTableFrame* tableFrame; - nsTableFrame::GetTableFrame(this, tableFrame); - while (nsnull != cellFrame) + // Resize and re-align the cell frames based on our row height + nscoord cellHeight = mRect.height - mCellMaxTopMargin - mCellMaxBottomMargin; + if (gsDebug) printf("Row DidReflow: cellHeight=%d\n", cellHeight); + nsIFrame *cellFrame = mFirstChild; + nsTableFrame* tableFrame; + nsTableFrame::GetTableFrame(this, tableFrame); + while (nsnull != cellFrame) + { + const nsStyleDisplay *kidDisplay; + cellFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)kidDisplay)); + if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay) { - const nsStyleDisplay *kidDisplay; - cellFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)kidDisplay)); - if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay) + PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(mRowIndex, (nsTableCellFrame *)cellFrame); + if (gsDebug) printf("Row DidReflow: cellFrame %p ", cellFrame); + if (1==rowSpan) { - PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(mRowIndex, (nsTableCellFrame *)cellFrame); - if (gsDebug) printf("Row DidReflow: cellFrame %p ", cellFrame); - if (1==rowSpan) + // resize the cell's height + nsSize cellFrameSize; + cellFrame->GetSize(cellFrameSize); + if (cellFrameSize.height!=cellHeight) { - // resize the cell's height - nsSize cellFrameSize; - cellFrame->GetSize(cellFrameSize); cellFrame->SizeTo(cellFrameSize.width, cellHeight); if (gsDebug) printf("given height %d\n", cellHeight); // realign cell content based on the new height - ((nsTableCellFrame *)cellFrame)->VerticallyAlignChild(&aPresContext); - } - else - { - if (gsDebug) - { - nsSize cellFrameSize; - cellFrame->GetSize(cellFrameSize); - printf("has rowspan %d and height %d, unchanged.\n", rowSpan, cellFrameSize.height); - } + nsHTMLReflowMetrics desiredSize(nsnull); + nsHTMLReflowState kidReflowState(aPresContext, cellFrame, + aReflowState, nsSize(cellFrameSize.width, cellHeight), + eReflowReason_Resize); + nsReflowStatus status; + ReflowChild(cellFrame, aPresContext, desiredSize, kidReflowState, status); + ((nsTableCellFrame *)cellFrame)->VerticallyAlignChild(); + } + } + else + { + if (gsDebug) + { + nsSize cellFrameSize; + cellFrame->GetSize(cellFrameSize); + printf("has rowspan %d and height %d, unchanged.\n", rowSpan, cellFrameSize.height); } } - // Get the next cell - cellFrame->GetNextSibling(cellFrame); } + // Get the next cell + cellFrame->GetNextSibling(cellFrame); } // Let our base class do the usual work - if (gsDebug) printf("Row DidReflow: returning superclass DidReflow.\n"); - return nsContainerFrame::DidReflow(aPresContext, aStatus); + if (gsDebug) printf("Row DidResize: returning NS_OK.\n"); } void nsTableRowFrame::ResetMaxChildHeight() @@ -449,6 +455,22 @@ void nsTableRowFrame::PlaceChild(nsIPresContext& aPresContext, } } +nsIFrame * nsTableRowFrame::GetNextChildForDirection(PRUint8 aDir, nsIFrame *aCurrentChild) +{ + NS_ASSERTION(nsnull!=aCurrentChild, "bad arg"); + + nsIFrame *result=nsnull; + aCurrentChild->GetNextSibling(result); + return result; +} + +nsIFrame * nsTableRowFrame::GetFirstChildForDirection(PRUint8 aDir) +{ + nsIFrame *result=nsnull; + result = mFirstChild; + return result; +} + /** * Called for a resize reflow. Typically because the column widths have * changed. Reflows all the existing table cell frames @@ -461,18 +483,22 @@ NS_METHOD nsTableRowFrame::ResizeReflow(nsIPresContext& aPresContext, if (nsnull == mFirstChild) return NS_OK; - nsresult rv=NS_OK; - nsSize kidMaxElementSize; - PRInt32 prevColIndex = -1; // remember the col index of the previous cell to handle rowspans into this row - nsSize* pKidMaxElementSize = (nsnull != aDesiredSize.maxElementSize) ? - &kidMaxElementSize : nsnull; - nscoord maxCellTopMargin = 0; - nscoord maxCellBottomMargin = 0; + nsresult rv=NS_OK; + nsSize kidMaxElementSize; + PRInt32 prevColIndex = -1; // remember the col index of the previous cell to handle rowspans into this row + nsSize* pKidMaxElementSize = (nsnull != aDesiredSize.maxElementSize) ? + &kidMaxElementSize : nsnull; + nscoord maxCellTopMargin = 0; + nscoord maxCellBottomMargin = 0; nscoord cellSpacing = aReflowState.tableFrame->GetCellSpacing(); PRInt32 cellColSpan=1; // must be defined here so it's set properly for non-cell kids if (PR_TRUE==gsDebug) printf("Row %p: Resize Reflow\n", this); + // Reflow each of our existing cell frames - for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) + const nsStyleDisplay *rowDisplay; + GetStyleData(eStyleStruct_Display, (nsStyleStruct*&)rowDisplay); + nsIFrame* kidFrame=GetFirstChildForDirection(rowDisplay->mDirection); + for (kidFrame; nsnull != kidFrame; ) { const nsStyleDisplay *kidDisplay; kidFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)kidDisplay)); @@ -621,7 +647,7 @@ NS_METHOD nsTableRowFrame::ResizeReflow(nsIPresContext& aPresContext, } // Get the next child - kidFrame->GetNextSibling(kidFrame); + kidFrame = GetNextChildForDirection(rowDisplay->mDirection, kidFrame); // if this was the last child, and it had a colspan>1, add in the cellSpacing for the colspan // if the last kid wasn't a colspan, then we still have the colspan of the last real cell if ((nsnull==kidFrame) && (cellColSpan>1)) diff --git a/mozilla/layout/tables/nsTableRowFrame.h b/mozilla/layout/tables/nsTableRowFrame.h index 9625fa66992..65d6d169818 100644 --- a/mozilla/layout/tables/nsTableRowFrame.h +++ b/mozilla/layout/tables/nsTableRowFrame.h @@ -93,8 +93,8 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); - NS_IMETHOD DidReflow(nsIPresContext& aPresContext, - nsDidReflowStatus aStatus); + virtual void DidResize(nsIPresContext& aPresContext, + const nsHTMLReflowState& aReflowState); /** @see nsContainerFrame::CreateContinuingFrame */ NS_IMETHOD CreateContinuingFrame(nsIPresContext& aPresContext, @@ -214,6 +214,9 @@ protected: nscoord ComputeCellAvailWidth(const RowReflowState& aState, nsIFrame* aKidFrame) const; + nsIFrame * GetFirstChildForDirection(PRUint8 aDir); + nsIFrame * GetNextChildForDirection(PRUint8 aDir, nsIFrame *aCurrentChild); + /** * Called for a resize reflow. Typically because the column widths have * changed. Reflows all the existing table cell frames diff --git a/mozilla/layout/tables/nsTableRowGroupFrame.cpp b/mozilla/layout/tables/nsTableRowGroupFrame.cpp index be496ce96e2..8bae925ef96 100644 --- a/mozilla/layout/tables/nsTableRowGroupFrame.cpp +++ b/mozilla/layout/tables/nsTableRowGroupFrame.cpp @@ -601,12 +601,15 @@ NS_METHOD nsTableRowGroupFrame::PullUpChildren(nsIPresContext& aPresContext return rv; } -/** - */ -void nsTableRowGroupFrame::ShrinkWrapChildren(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize) +/* CalculateRowHeights provides default heights for all rows in the rowgroup. + * Actual row heights are ultimately determined by the table, when the table + * height attribute is factored in. + */ +void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState) { - if (gsDebug) printf("TRGF ShrinkWrapChildren begin\n"); + if (gsDebug) printf("TRGF CalculateRowHeights begin\n"); // iterate children and for each row get its height PRBool atLeastOneRowSpanningCell = PR_FALSE; nscoord topInnerMargin = 0; @@ -717,7 +720,7 @@ void nsTableRowGroupFrame::ShrinkWrapChildren(nsIPresContext* aPresContext, cellFrameSize.height, heightOfRowsSpanned); cellFrame->SizeTo(cellFrameSize.width, heightOfRowsSpanned); // Realign cell content based on new height - ((nsTableCellFrame*)cellFrame)->VerticallyAlignChild(aPresContext); + ((nsTableCellFrame*)cellFrame)->VerticallyAlignChild(); } /* otherwise, distribute the excess height to the rows effected. * push all subsequent rows down by the total change in height of all the rows above it @@ -781,6 +784,20 @@ void nsTableRowGroupFrame::ShrinkWrapChildren(nsIPresContext* aPresContext, } } + // finally, notify the rows of their new heights + rowFrame = mFirstChild; + while (nsnull != rowFrame) + { + const nsStyleDisplay *childDisplay; + rowFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay)); + if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay) + { + ((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState); + } + // Get the next row + rowFrame->GetNextSibling(rowFrame); + } + // Adjust our desired size aDesiredSize.height = rowGroupHeight; @@ -907,7 +924,9 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext, aDesiredSize.height = state.y; // shrink wrap rows to height of tallest cell in that row - ShrinkWrapChildren(&aPresContext, aDesiredSize); + if (eReflowReason_Initial != aReflowState.reason) { + CalculateRowHeights(aPresContext, aDesiredSize, aReflowState); + } } if (gsDebug==PR_TRUE) @@ -1337,3 +1356,4 @@ nsTableRowGroupFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("TableRowGroup", aResult); } + diff --git a/mozilla/layout/tables/nsTableRowGroupFrame.h b/mozilla/layout/tables/nsTableRowGroupFrame.h index c2bfd335b03..12bbfbb8dfd 100644 --- a/mozilla/layout/tables/nsTableRowGroupFrame.h +++ b/mozilla/layout/tables/nsTableRowGroupFrame.h @@ -133,8 +133,9 @@ protected: nsSize* aMaxElementSize, nsSize& aKidMaxElementSize); - void ShrinkWrapChildren(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize); + void CalculateRowHeights(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState); /** Incremental Reflow attempts to do column balancing with the minimum number of reflow