From 73b4846430ec8012e46bf343ea3f69241b47f0df Mon Sep 17 00:00:00 2001 From: "buster%netscape.com" Date: Thu, 15 Oct 1998 07:46:16 +0000 Subject: [PATCH] progress on table incremental reflow of row group insert/append/delete --- layout/html/table/src/nsTableFrame.cpp | 50 +++++++++---------- layout/html/table/src/nsTableFrame.h | 14 ++++-- .../html/table/src/nsTableRowGroupFrame.cpp | 7 ++- layout/html/tests/TableIncrementalReflow.html | 24 +++++++++ layout/tables/nsTableFrame.cpp | 50 +++++++++---------- layout/tables/nsTableFrame.h | 14 ++++-- layout/tables/nsTableRowGroupFrame.cpp | 7 ++- 7 files changed, 104 insertions(+), 62 deletions(-) diff --git a/layout/html/table/src/nsTableFrame.cpp b/layout/html/table/src/nsTableFrame.cpp index 3c14a479f3b5..bc1202e3d86c 100644 --- a/layout/html/table/src/nsTableFrame.cpp +++ b/layout/html/table/src/nsTableFrame.cpp @@ -1575,7 +1575,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext, if (PR_FALSE==IsFirstPassValid()) { if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: first pass is invalid\n"); - rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, aStatus); + rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, aStatus, nsnull, aReflowState.reason); if (NS_FAILED(rv)) return rv; needsRecalc=PR_TRUE; @@ -1641,10 +1641,12 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext, * NOTE: should never get called on a continuing frame! All cached pass1 state * is stored in the inner table first-in-flow. */ -NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) +NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus, + nsTableRowGroupFrame * aStartingFrame, + nsReflowReason aReason) { NS_PRECONDITION(aReflowState.frame == this, "bad reflow state"); NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent, @@ -1680,13 +1682,15 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, nscoord rightInset = borderPadding.right; nscoord bottomInset = borderPadding.bottom; nscoord leftInset = borderPadding.left; - nsReflowReason reflowReason = aReflowState.reason; nsStyleTable* tableStyle; GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle); if (NS_STYLE_TABLE_LAYOUT_FIXED!=tableStyle->mLayoutStrategy) { - for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) + nsIFrame* kidFrame = aStartingFrame; + if (nsnull==kidFrame) + kidFrame=mFirstChild; + for ( ; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) { const nsStyleDisplay *childDisplay; kidFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay)); @@ -1699,8 +1703,7 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, } nsSize maxKidElementSize(0,0); nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState, - availSize); - + availSize, aReason); PRInt32 yCoord = y; if (NS_UNCONSTRAINEDSIZE!=yCoord) yCoord+= topInset; @@ -2166,7 +2169,8 @@ NS_METHOD nsTableFrame::IR_RowGroupInserted(nsIPresContext& aPresContext, nsTableRowGroupFrame * aInsertedFrame, PRBool aReplace) { - nsresult rv; + nsresult rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, + aStatus, (nsIFrame*)aInsertedFrame, aReplace); // inserting the rowgroup only effects reflow if the rowgroup includes at least one row return rv; } @@ -2179,26 +2183,22 @@ NS_METHOD nsTableFrame::IR_RowGroupAppended(nsIPresContext& aPresContext, nsTableRowGroupFrame * aAppendedFrame) { // hook aAppendedFrame into the child list - nsIFrame *lastChild = mFirstChild; - nsIFrame *nextChild = lastChild; - while (nsnull!=nextChild) - { - lastChild = nextChild; - nextChild->GetNextSibling(nextChild); - } - if (nsnull==lastChild) - mFirstChild = aAppendedFrame; - else - lastChild->SetNextSibling(aAppendedFrame); + nsresult rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, + aStatus, (nsIFrame*)aAppendedFrame, PR_FALSE); + if (NS_FAILED(rv)) + return rv; // account for the cells in the rows that are children of aAppendedFrame - nsresult rv = DidAppendRowGroup((nsTableRowGroupFrame*)aAppendedFrame); + rv = DidAppendRowGroup((nsTableRowGroupFrame*)aAppendedFrame); // do a pass-1 layout of all the cells in all the rows of the rowgroup - InvalidateFirstPassCache(); + rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.reflowState, aStatus, + aAppendedFrame, eReflowReason_Initial); + if (NS_FAILED(rv)) + return rv; - // if any column widths have to change due to this, re-init the layout strategy - // mTableLayoutStrategy->Initialize(aDesiredSize.aMaxElementSize); //XXX for now, we're just doing the whole enchelada + // if any column widths have to change due to this, rebalance column widths + mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize); return rv; } diff --git a/layout/html/table/src/nsTableFrame.h b/layout/html/table/src/nsTableFrame.h index 05aacc6df15a..021aca9fc3a1 100644 --- a/layout/html/table/src/nsTableFrame.h +++ b/layout/html/table/src/nsTableFrame.h @@ -22,6 +22,8 @@ #include "nsContainerFrame.h" #include "nsStyleCoord.h" #include "nsStyleConsts.h" +#include "nsIFrameReflow.h" // for nsReflowReason enum + class nsCellMap; class nsVoidArray; @@ -269,13 +271,17 @@ protected: * Pass 1 only needs to be executed once no matter how many times the table is resized, * as long as content and style don't change. This is managed in the member variable mFirstPassIsValid. * The layout information for each cell is cached in mColumLayoutData. + * Incremental layout can take advantage of aStartingFrame to pick up where a previous + * ResizeReflowPass1 left off. * * @see Reflow */ NS_IMETHOD ResizeReflowPass1(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); + nsReflowStatus& aStatus, + nsTableRowGroupFrame * aStartingFrame, + nsReflowReason aReason); /** second pass of ResizeReflow. * lays out all table content with aMaxSize(computed_table_width, given_table_height) @@ -298,10 +304,10 @@ protected: * * @see Reflow */ - NS_IMETHOD IncrementalReflow(nsIPresContext& aPresContext, - nsHTMLReflowMetrics& aDesiredSize, + NS_IMETHOD IncrementalReflow(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); + nsReflowStatus& aStatus); NS_IMETHOD IR_TargetIsChild(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, diff --git a/layout/html/table/src/nsTableRowGroupFrame.cpp b/layout/html/table/src/nsTableRowGroupFrame.cpp index 09df6333da17..8ffa859632ac 100644 --- a/layout/html/table/src/nsTableRowGroupFrame.cpp +++ b/layout/html/table/src/nsTableRowGroupFrame.cpp @@ -606,8 +606,11 @@ void nsTableRowGroupFrame::ShrinkWrapChildren(nsIPresContext* aPresContext, cellFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay)); if (NS_STYLE_DISPLAY_TABLE_CELL == childDisplay->mDisplay) { - PRInt32 rowSpan = ((nsTableFrame*)mGeometricParent)-> - GetEffectiveRowSpan(rowIndex,(nsTableCellFrame*)cellFrame); + nsTableFrame *tableFrame=nsnull; + nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame); + if (NS_FAILED(rv) || nsnull==tableFrame) + return; + PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(rowIndex,(nsTableCellFrame*)cellFrame); if (rowSpan > 1) { // found a cell with rowspan > 1, determine its height nscoord heightOfRowsSpanned = 0; diff --git a/layout/html/tests/TableIncrementalReflow.html b/layout/html/tests/TableIncrementalReflow.html index e363cda487b6..a09d34b76942 100644 --- a/layout/html/tests/TableIncrementalReflow.html +++ b/layout/html/tests/TableIncrementalReflow.html @@ -67,10 +67,33 @@ function deleteCol() { table.removeChild(col); } + function insertRowGroup() { + var table = document.getElementsByTagName("TABLE")[0]; + var refRowGroup = document.getElementsByTagName("TBODY")[0]; + var rowGroup = document.createElement("TBODY", null); + table.insertBefore(rowGroup, refRowGroup); + dump("inserted empty ROWGROUP as first rowgroup in table"); +} + +function appendRowGroup() { var table = document.getElementsByTagName("TABLE")[0]; var rowGroup = document.createElement("TBODY", null); table.appendChild(rowGroup); + dump("appended empty ROWGROUP"); +} + +function appendRowGroupWithContent() { + var table = document.getElementsByTagName("TABLE")[0]; + var rowGroup = document.createElement("TBODY", null); + var row = document.createElement("TR", null); + var cell = document.createElement("TD", null); + var text = document.createTextNode("here is content in the cell from the script"); + cell.appendChild(text); + row.appendChild(cell); + rowGroup.appendChild(row); + table.appendChild(rowGroup); + dump("appended ROWGROUP with 1 row and 1 cell"); } function deleteRowGroup() { @@ -122,6 +145,7 @@ all delete buttons currently remove the first item of found +
diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 3c14a479f3b5..bc1202e3d86c 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -1575,7 +1575,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext, if (PR_FALSE==IsFirstPassValid()) { if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: first pass is invalid\n"); - rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, aStatus); + rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, aStatus, nsnull, aReflowState.reason); if (NS_FAILED(rv)) return rv; needsRecalc=PR_TRUE; @@ -1641,10 +1641,12 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext, * NOTE: should never get called on a continuing frame! All cached pass1 state * is stored in the inner table first-in-flow. */ -NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) +NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus, + nsTableRowGroupFrame * aStartingFrame, + nsReflowReason aReason) { NS_PRECONDITION(aReflowState.frame == this, "bad reflow state"); NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent, @@ -1680,13 +1682,15 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, nscoord rightInset = borderPadding.right; nscoord bottomInset = borderPadding.bottom; nscoord leftInset = borderPadding.left; - nsReflowReason reflowReason = aReflowState.reason; nsStyleTable* tableStyle; GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle); if (NS_STYLE_TABLE_LAYOUT_FIXED!=tableStyle->mLayoutStrategy) { - for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) + nsIFrame* kidFrame = aStartingFrame; + if (nsnull==kidFrame) + kidFrame=mFirstChild; + for ( ; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) { const nsStyleDisplay *childDisplay; kidFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay)); @@ -1699,8 +1703,7 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext, } nsSize maxKidElementSize(0,0); nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState, - availSize); - + availSize, aReason); PRInt32 yCoord = y; if (NS_UNCONSTRAINEDSIZE!=yCoord) yCoord+= topInset; @@ -2166,7 +2169,8 @@ NS_METHOD nsTableFrame::IR_RowGroupInserted(nsIPresContext& aPresContext, nsTableRowGroupFrame * aInsertedFrame, PRBool aReplace) { - nsresult rv; + nsresult rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, + aStatus, (nsIFrame*)aInsertedFrame, aReplace); // inserting the rowgroup only effects reflow if the rowgroup includes at least one row return rv; } @@ -2179,26 +2183,22 @@ NS_METHOD nsTableFrame::IR_RowGroupAppended(nsIPresContext& aPresContext, nsTableRowGroupFrame * aAppendedFrame) { // hook aAppendedFrame into the child list - nsIFrame *lastChild = mFirstChild; - nsIFrame *nextChild = lastChild; - while (nsnull!=nextChild) - { - lastChild = nextChild; - nextChild->GetNextSibling(nextChild); - } - if (nsnull==lastChild) - mFirstChild = aAppendedFrame; - else - lastChild->SetNextSibling(aAppendedFrame); + nsresult rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, + aStatus, (nsIFrame*)aAppendedFrame, PR_FALSE); + if (NS_FAILED(rv)) + return rv; // account for the cells in the rows that are children of aAppendedFrame - nsresult rv = DidAppendRowGroup((nsTableRowGroupFrame*)aAppendedFrame); + rv = DidAppendRowGroup((nsTableRowGroupFrame*)aAppendedFrame); // do a pass-1 layout of all the cells in all the rows of the rowgroup - InvalidateFirstPassCache(); + rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.reflowState, aStatus, + aAppendedFrame, eReflowReason_Initial); + if (NS_FAILED(rv)) + return rv; - // if any column widths have to change due to this, re-init the layout strategy - // mTableLayoutStrategy->Initialize(aDesiredSize.aMaxElementSize); //XXX for now, we're just doing the whole enchelada + // if any column widths have to change due to this, rebalance column widths + mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize); return rv; } diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index 05aacc6df15a..021aca9fc3a1 100644 --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -22,6 +22,8 @@ #include "nsContainerFrame.h" #include "nsStyleCoord.h" #include "nsStyleConsts.h" +#include "nsIFrameReflow.h" // for nsReflowReason enum + class nsCellMap; class nsVoidArray; @@ -269,13 +271,17 @@ protected: * Pass 1 only needs to be executed once no matter how many times the table is resized, * as long as content and style don't change. This is managed in the member variable mFirstPassIsValid. * The layout information for each cell is cached in mColumLayoutData. + * Incremental layout can take advantage of aStartingFrame to pick up where a previous + * ResizeReflowPass1 left off. * * @see Reflow */ NS_IMETHOD ResizeReflowPass1(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); + nsReflowStatus& aStatus, + nsTableRowGroupFrame * aStartingFrame, + nsReflowReason aReason); /** second pass of ResizeReflow. * lays out all table content with aMaxSize(computed_table_width, given_table_height) @@ -298,10 +304,10 @@ protected: * * @see Reflow */ - NS_IMETHOD IncrementalReflow(nsIPresContext& aPresContext, - nsHTMLReflowMetrics& aDesiredSize, + NS_IMETHOD IncrementalReflow(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); + nsReflowStatus& aStatus); NS_IMETHOD IR_TargetIsChild(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index 09df6333da17..8ffa859632ac 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -606,8 +606,11 @@ void nsTableRowGroupFrame::ShrinkWrapChildren(nsIPresContext* aPresContext, cellFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay)); if (NS_STYLE_DISPLAY_TABLE_CELL == childDisplay->mDisplay) { - PRInt32 rowSpan = ((nsTableFrame*)mGeometricParent)-> - GetEffectiveRowSpan(rowIndex,(nsTableCellFrame*)cellFrame); + nsTableFrame *tableFrame=nsnull; + nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame); + if (NS_FAILED(rv) || nsnull==tableFrame) + return; + PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(rowIndex,(nsTableCellFrame*)cellFrame); if (rowSpan > 1) { // found a cell with rowspan > 1, determine its height nscoord heightOfRowsSpanned = 0;