Work-in-progress for table handling of reflow commands

This commit is contained in:
troy%netscape.com 1999-08-01 22:01:37 +00:00
parent d12fd4aaf3
commit 67534a54ff
8 changed files with 430 additions and 182 deletions

View File

@ -481,6 +481,28 @@ nsresult nsTableOuterFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
aReflowState.reflowState.reflowCommand->GetChildFrame(objectFrame);
TDBG_SD(gsDebugIR,"TOF IR: IncrementalReflow_TargetIsMe with type=%d\n", type);
switch (type) {
case nsIReflowCommand::ReflowDirty:
{
// Inner table is dirty so reflow it. Change the reflow state and set the
// reason to resize reflow.
// XXX It could also be the caption that is dirty...
((nsHTMLReflowState&)aReflowState.reflowState).reason = eReflowReason_Resize;
((nsHTMLReflowState&)aReflowState.reflowState).reflowCommand = nsnull;
// Get the inner table frame's current bounds. We'll use that when
// repainting it
// XXX It should really do the repainting, but because it think it's
// getting a resize reflow it won't know to...
nsRect dirtyRect;
mInnerTableFrame->GetRect(dirtyRect);
rv = IR_InnerTableReflow(aPresContext, aDesiredSize, aReflowState, aStatus);
// Repaint the inner table frame's entire visible area
dirtyRect.x = dirtyRect.y = 0;
Invalidate(dirtyRect);
break;
}
case nsIReflowCommand::FrameAppended :
case nsIReflowCommand::FrameInserted :
{
@ -975,9 +997,6 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext,
rv = IncrementalReflow(aPresContext, aDesiredSize, state, aStatus);
} else {
if (eReflowReason_Initial == aReflowState.reason) {
//KIPP/TROY: uncomment the following line for your own testing, do not check it in
// NS_ASSERTION(nsnull == mFirstChild, "unexpected reflow reason");
// Set up our kids. They're already present, on an overflow list,
// or there are none so we'll create them now
MoveOverflowToChildList();

View File

@ -1498,7 +1498,14 @@ nsTableRowFrame::Reflow(nsIPresContext& aPresContext,
RowReflowState state(aReflowState, tableFrame);
// Do the reflow
switch (aReflowState.reason) {
// XXX If the width is unconstrained, then treat it like we would treat the
// initial reflow instead. This needs to be cleaned up
nsReflowReason reason = aReflowState.reason;
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
reason = eReflowReason_Initial;
}
switch (reason) {
case eReflowReason_Initial:
rv = InitialReflow(aPresContext, aDesiredSize, state, aStatus, nsnull, PR_TRUE);
if (PR_FALSE==tableFrame->RequiresPass1Layout())

View File

@ -35,6 +35,7 @@
#include "nsIPresShell.h"
#include "nsLayoutAtoms.h"
#include "nsCSSRendering.h"
#include "nsHTMLParts.h"
#ifdef NS_DEBUG
static PRBool gsDebug = PR_FALSE;
@ -388,7 +389,8 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC
nsReflowStatus& aStatus,
nsTableRowFrame * aStartFrame,
nsReflowReason aReason,
PRBool aDoSiblings)
PRBool aDoSiblings,
PRBool aDirtyOnly)
{
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: ReflowMappedChildren\n");
nsSize kidMaxElementSize;
@ -410,77 +412,97 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC
for ( ; nsnull != kidFrame; )
{
nsSize kidAvailSize(aReflowState.availSize);
if (0>=kidAvailSize.height)
kidAvailSize.height = 1; // XXX: HaCk - we don't handle negative heights yet
nsHTMLReflowMetrics desiredSize(pKidMaxElementSize);
desiredSize.width=desiredSize.height=desiredSize.ascent=desiredSize.descent=0;
// Get the frame state bits
nsFrameState frameState;
kidFrame->GetFrameState(&frameState);
// Reflow the child into the available space, giving it as much room as
// it wants. We'll deal with splitting later after we've computed the row
// heights, taking into account cells with row spans...
kidAvailSize.height = NS_UNCONSTRAINEDSIZE;
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, kidFrame,
kidAvailSize, aReason);
if (aReflowState.tableFrame->RowGroupsShouldBeConstrained()) {
// Only applies to the tree widget.
const nsStyleDisplay *rowDisplay;
kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == rowDisplay->mDisplay &&
aReflowState.availSize.height != NS_UNCONSTRAINEDSIZE) {
kidReflowState.availableHeight = aReflowState.availSize.height;
// See if we should only reflow the dirty child frames
PRBool doReflowChild = PR_TRUE;
if (aDirtyOnly) {
if ((frameState & NS_FRAME_IS_DIRTY) == 0) {
doReflowChild = PR_FALSE;
}
}
if (kidFrame != GetFirstFrame()) {
// If this isn't the first row frame, then we can't be at the top of
// the page anymore...
kidReflowState.isTopOfPage = PR_FALSE;
}
if ((PR_TRUE==gsDebug) || (PR_TRUE==gsDebugIR))
printf("%p RG reflowing child %p with avail width = %d, reason = %d\n",
this, kidFrame, kidAvailSize.width, aReason);
rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus);
if (gsDebug) printf("%p RG child %p returned desired width = %d\n",
this, kidFrame, desiredSize.width);
nsRect kidRect (0, aReflowState.y, desiredSize.width, desiredSize.height);
PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize,
kidMaxElementSize);
/* if the table has collapsing borders, we need to reset the length of the shared vertical borders
* for the table and the cells that overlap this row
*/
if ((eReflowReason_Initial != aReflowState.reflowState.reason) && (NS_STYLE_BORDER_COLLAPSE==borderStyle))
{
const nsStyleDisplay *childDisplay;
kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
if (doReflowChild) {
nsSize kidAvailSize(aReflowState.availSize);
if (0>=kidAvailSize.height)
kidAvailSize.height = 1; // XXX: HaCk - we don't handle negative heights yet
nsHTMLReflowMetrics desiredSize(pKidMaxElementSize);
desiredSize.width=desiredSize.height=desiredSize.ascent=desiredSize.descent=0;
// Reflow the child into the available space, giving it as much room as
// it wants. We'll deal with splitting later after we've computed the row
// heights, taking into account cells with row spans...
kidAvailSize.height = NS_UNCONSTRAINEDSIZE;
if (aDirtyOnly) {
if (frameState & NS_FRAME_FIRST_REFLOW) {
// Newly inserted frame
aReason = eReflowReason_Initial;
}
}
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, kidFrame,
kidAvailSize, aReason);
if (aReflowState.tableFrame->RowGroupsShouldBeConstrained()) {
// Only applies to the tree widget.
const nsStyleDisplay *rowDisplay;
kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == rowDisplay->mDisplay &&
aReflowState.availSize.height != NS_UNCONSTRAINEDSIZE) {
kidReflowState.availableHeight = aReflowState.availSize.height;
}
}
if (kidFrame != GetFirstFrame()) {
// If this isn't the first row frame, then we can't be at the top of
// the page anymore...
kidReflowState.isTopOfPage = PR_FALSE;
}
if ((PR_TRUE==gsDebug) || (PR_TRUE==gsDebugIR))
printf("%p RG reflowing child %p with avail width = %d, reason = %d\n",
this, kidFrame, kidAvailSize.width, aReason);
rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus);
if (gsDebug) printf("%p RG child %p returned desired width = %d\n",
this, kidFrame, desiredSize.width);
nsRect kidRect (0, aReflowState.y, desiredSize.width, desiredSize.height);
PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize,
kidMaxElementSize);
/* if the table has collapsing borders, we need to reset the length of the shared vertical borders
* for the table and the cells that overlap this row
*/
if ((eReflowReason_Initial != aReflowState.reflowState.reason) && (NS_STYLE_BORDER_COLLAPSE==borderStyle))
{
PRInt32 rowIndex = ((nsTableRowFrame*)kidFrame)->GetRowIndex();
aReflowState.tableFrame->SetBorderEdgeLength(NS_SIDE_LEFT,
rowIndex,
kidRect.height);
aReflowState.tableFrame->SetBorderEdgeLength(NS_SIDE_RIGHT,
rowIndex,
kidRect.height);
PRInt32 colCount = aReflowState.tableFrame->GetColCount();
PRInt32 colIndex = 0;
nsIFrame *cellFrame;
for (colIndex = 0; colIndex < colCount; colIndex++) {
cellFrame = aReflowState.tableFrame->GetCellFrameAt(rowIndex, colIndex);
if (cellFrame) {
const nsStyleDisplay *cellDisplay;
cellFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)cellDisplay));
if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay) {
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_LEFT,
rowIndex,
kidRect.height);
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_RIGHT,
rowIndex,
kidRect.height);
const nsStyleDisplay *childDisplay;
kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
PRInt32 rowIndex = ((nsTableRowFrame*)kidFrame)->GetRowIndex();
aReflowState.tableFrame->SetBorderEdgeLength(NS_SIDE_LEFT,
rowIndex,
kidRect.height);
aReflowState.tableFrame->SetBorderEdgeLength(NS_SIDE_RIGHT,
rowIndex,
kidRect.height);
PRInt32 colCount = aReflowState.tableFrame->GetColCount();
PRInt32 colIndex = 0;
nsIFrame *cellFrame;
for (colIndex = 0; colIndex < colCount; colIndex++) {
cellFrame = aReflowState.tableFrame->GetCellFrameAt(rowIndex, colIndex);
if (cellFrame) {
const nsStyleDisplay *cellDisplay;
cellFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)cellDisplay));
if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay) {
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_LEFT,
rowIndex,
kidRect.height);
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_RIGHT,
rowIndex,
kidRect.height);
}
}
}
}
@ -1101,6 +1123,80 @@ NS_METHOD nsTableRowGroupFrame::IncrementalReflow(nsIPresContext& aPresContext,
return rv;
}
NS_IMETHODIMP
nsTableRowGroupFrame::AppendFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList)
{
// Get the table frame
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
// Append the frames
mFrames.AppendFrames(nsnull, aFrameList);
// See if the newly appended rows are the last rows in the table. Don't
// do this for appended row group frames. We probably should, but DidAppendRow()
// doesn't handle row group frames
const nsStyleDisplay *display;
aFrameList->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
if ((NS_STYLE_DISPLAY_TABLE_ROW == display->mDisplay) && NoRowsFollow()) {
// The rows we appended are the last rows in the table so incrementally
// add them to the cell map
for (nsIFrame* rowFrame = aFrameList; rowFrame; rowFrame->GetNextSibling(&rowFrame)) {
DidAppendRow((nsTableRowFrame*)rowFrame);
}
// Reflow the new frames. They're already marked dirty, so generate a reflow
// command that tells us to reflow our dirty child frames
nsIReflowCommand* reflowCmd;
if (NS_SUCCEEDED(NS_NewHTMLReflowCommand(&reflowCmd, this,
nsIReflowCommand::ReflowDirty))) {
aPresShell.AppendReflowCommand(reflowCmd);
NS_RELEASE(reflowCmd);
}
} else {
// We need to rebuild the cell map, because currently we can't insert
// new frames except at the end (append)
tableFrame->InvalidateCellMap();
// We should try and avoid doing a pass1 reflow on all the cells and just
// do it for the newly added frames, but we need to add these frames to the
// cell map before we reflow them
tableFrame->InvalidateFirstPassCache();
// Because the number of columns may have changed invalidate the column
// cache. Note that this has the side effect of recomputing the column
// widths, so we don't need to call InvalidateColumnWidths()
tableFrame->InvalidateColumnCache();
// Generate a reflow command so we reflow the table itself. This will
// do a pass-1 reflow of all the rows including any rows we just added
nsFrameState frameState;
nsIFrame* tableParentFrame;
nsIReflowCommand* reflowCmd;
// Mark the table frame as dirty
tableFrame->GetFrameState(&frameState);
frameState |= NS_FRAME_IS_DIRTY;
tableFrame->SetFrameState(frameState);
// Target the reflow comamnd at its parent frame
tableFrame->GetParent(&tableParentFrame);
if (NS_SUCCEEDED(NS_NewHTMLReflowCommand(&reflowCmd, tableParentFrame,
nsIReflowCommand::ReflowDirty))) {
// Add the reflow command
aPresShell.AppendReflowCommand(reflowCmd);
NS_RELEASE(reflowCmd);
}
}
return NS_OK;
}
NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
@ -1117,6 +1213,21 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
if (PR_TRUE==gsDebugIR) printf("TRGF IR: TargetIsMe with type=%d\n", type);
switch (type)
{
case nsIReflowCommand::ReflowDirty:
// Reflow the dirty child frames
// XXX What we really should do is do a pass-1 reflow of newly added
// frames (only if necessary--because the table isn't fixed layout), then
// see if column widtsh changed and decide whether to do the pass-2 reflow
// of just the dirty rows or have the table rebalance column widths and
// do a pass-2 reflow of all rows
rv = ReflowMappedChildren(aPresContext, aDesiredSize, aReflowState, aStatus,
nsnull, aReflowState.reflowState.reason, PR_TRUE, PR_TRUE);
// If any column widths have to change due to this, rebalance column widths
//XXX need to calculate this, but for now just do it
aReflowState.tableFrame->InvalidateColumnWidths();
break;
case nsIReflowCommand::FrameInserted :
NS_ASSERTION(nsnull!=objectFrame, "bad objectFrame");
NS_ASSERTION(nsnull!=childDisplay, "bad childDisplay");
@ -1136,25 +1247,6 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
}
break;
case nsIReflowCommand::FrameAppended :
NS_ASSERTION(nsnull!=objectFrame, "bad objectFrame");
NS_ASSERTION(nsnull!=childDisplay, "bad childDisplay");
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
rv = IR_RowAppended(aPresContext, aDesiredSize, aReflowState, aStatus,
(nsTableRowFrame *)objectFrame);
}
else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay)
{
rv = IR_RowGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus,
(nsTableRowGroupFrame*)objectFrame, PR_FALSE);
}
else
{ // no optimization to be done for Unknown frame types, so just reuse the Inserted method
rv = AddFrame(aReflowState.reflowState, objectFrame);
}
break;
/*
case nsIReflowCommand::FrameReplaced :

View File

@ -100,6 +100,11 @@ public:
NS_METHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList);
/** @see nsIFrame::Paint */
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
@ -276,7 +281,8 @@ protected:
nsReflowStatus& aStatus,
nsTableRowFrame * aStartFrame,
nsReflowReason aReason,
PRBool aDoSiblings);
PRBool aDoSiblings,
PRBool aDirtyOnly = PR_FALSE);
/**
* Pull-up all the row frames from our next-in-flow

View File

@ -481,6 +481,28 @@ nsresult nsTableOuterFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
aReflowState.reflowState.reflowCommand->GetChildFrame(objectFrame);
TDBG_SD(gsDebugIR,"TOF IR: IncrementalReflow_TargetIsMe with type=%d\n", type);
switch (type) {
case nsIReflowCommand::ReflowDirty:
{
// Inner table is dirty so reflow it. Change the reflow state and set the
// reason to resize reflow.
// XXX It could also be the caption that is dirty...
((nsHTMLReflowState&)aReflowState.reflowState).reason = eReflowReason_Resize;
((nsHTMLReflowState&)aReflowState.reflowState).reflowCommand = nsnull;
// Get the inner table frame's current bounds. We'll use that when
// repainting it
// XXX It should really do the repainting, but because it think it's
// getting a resize reflow it won't know to...
nsRect dirtyRect;
mInnerTableFrame->GetRect(dirtyRect);
rv = IR_InnerTableReflow(aPresContext, aDesiredSize, aReflowState, aStatus);
// Repaint the inner table frame's entire visible area
dirtyRect.x = dirtyRect.y = 0;
Invalidate(dirtyRect);
break;
}
case nsIReflowCommand::FrameAppended :
case nsIReflowCommand::FrameInserted :
{
@ -975,9 +997,6 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext,
rv = IncrementalReflow(aPresContext, aDesiredSize, state, aStatus);
} else {
if (eReflowReason_Initial == aReflowState.reason) {
//KIPP/TROY: uncomment the following line for your own testing, do not check it in
// NS_ASSERTION(nsnull == mFirstChild, "unexpected reflow reason");
// Set up our kids. They're already present, on an overflow list,
// or there are none so we'll create them now
MoveOverflowToChildList();

View File

@ -1498,7 +1498,14 @@ nsTableRowFrame::Reflow(nsIPresContext& aPresContext,
RowReflowState state(aReflowState, tableFrame);
// Do the reflow
switch (aReflowState.reason) {
// XXX If the width is unconstrained, then treat it like we would treat the
// initial reflow instead. This needs to be cleaned up
nsReflowReason reason = aReflowState.reason;
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
reason = eReflowReason_Initial;
}
switch (reason) {
case eReflowReason_Initial:
rv = InitialReflow(aPresContext, aDesiredSize, state, aStatus, nsnull, PR_TRUE);
if (PR_FALSE==tableFrame->RequiresPass1Layout())

View File

@ -35,6 +35,7 @@
#include "nsIPresShell.h"
#include "nsLayoutAtoms.h"
#include "nsCSSRendering.h"
#include "nsHTMLParts.h"
#ifdef NS_DEBUG
static PRBool gsDebug = PR_FALSE;
@ -388,7 +389,8 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC
nsReflowStatus& aStatus,
nsTableRowFrame * aStartFrame,
nsReflowReason aReason,
PRBool aDoSiblings)
PRBool aDoSiblings,
PRBool aDirtyOnly)
{
if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: ReflowMappedChildren\n");
nsSize kidMaxElementSize;
@ -410,77 +412,97 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC
for ( ; nsnull != kidFrame; )
{
nsSize kidAvailSize(aReflowState.availSize);
if (0>=kidAvailSize.height)
kidAvailSize.height = 1; // XXX: HaCk - we don't handle negative heights yet
nsHTMLReflowMetrics desiredSize(pKidMaxElementSize);
desiredSize.width=desiredSize.height=desiredSize.ascent=desiredSize.descent=0;
// Get the frame state bits
nsFrameState frameState;
kidFrame->GetFrameState(&frameState);
// Reflow the child into the available space, giving it as much room as
// it wants. We'll deal with splitting later after we've computed the row
// heights, taking into account cells with row spans...
kidAvailSize.height = NS_UNCONSTRAINEDSIZE;
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, kidFrame,
kidAvailSize, aReason);
if (aReflowState.tableFrame->RowGroupsShouldBeConstrained()) {
// Only applies to the tree widget.
const nsStyleDisplay *rowDisplay;
kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == rowDisplay->mDisplay &&
aReflowState.availSize.height != NS_UNCONSTRAINEDSIZE) {
kidReflowState.availableHeight = aReflowState.availSize.height;
// See if we should only reflow the dirty child frames
PRBool doReflowChild = PR_TRUE;
if (aDirtyOnly) {
if ((frameState & NS_FRAME_IS_DIRTY) == 0) {
doReflowChild = PR_FALSE;
}
}
if (kidFrame != GetFirstFrame()) {
// If this isn't the first row frame, then we can't be at the top of
// the page anymore...
kidReflowState.isTopOfPage = PR_FALSE;
}
if ((PR_TRUE==gsDebug) || (PR_TRUE==gsDebugIR))
printf("%p RG reflowing child %p with avail width = %d, reason = %d\n",
this, kidFrame, kidAvailSize.width, aReason);
rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus);
if (gsDebug) printf("%p RG child %p returned desired width = %d\n",
this, kidFrame, desiredSize.width);
nsRect kidRect (0, aReflowState.y, desiredSize.width, desiredSize.height);
PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize,
kidMaxElementSize);
/* if the table has collapsing borders, we need to reset the length of the shared vertical borders
* for the table and the cells that overlap this row
*/
if ((eReflowReason_Initial != aReflowState.reflowState.reason) && (NS_STYLE_BORDER_COLLAPSE==borderStyle))
{
const nsStyleDisplay *childDisplay;
kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
if (doReflowChild) {
nsSize kidAvailSize(aReflowState.availSize);
if (0>=kidAvailSize.height)
kidAvailSize.height = 1; // XXX: HaCk - we don't handle negative heights yet
nsHTMLReflowMetrics desiredSize(pKidMaxElementSize);
desiredSize.width=desiredSize.height=desiredSize.ascent=desiredSize.descent=0;
// Reflow the child into the available space, giving it as much room as
// it wants. We'll deal with splitting later after we've computed the row
// heights, taking into account cells with row spans...
kidAvailSize.height = NS_UNCONSTRAINEDSIZE;
if (aDirtyOnly) {
if (frameState & NS_FRAME_FIRST_REFLOW) {
// Newly inserted frame
aReason = eReflowReason_Initial;
}
}
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, kidFrame,
kidAvailSize, aReason);
if (aReflowState.tableFrame->RowGroupsShouldBeConstrained()) {
// Only applies to the tree widget.
const nsStyleDisplay *rowDisplay;
kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == rowDisplay->mDisplay &&
aReflowState.availSize.height != NS_UNCONSTRAINEDSIZE) {
kidReflowState.availableHeight = aReflowState.availSize.height;
}
}
if (kidFrame != GetFirstFrame()) {
// If this isn't the first row frame, then we can't be at the top of
// the page anymore...
kidReflowState.isTopOfPage = PR_FALSE;
}
if ((PR_TRUE==gsDebug) || (PR_TRUE==gsDebugIR))
printf("%p RG reflowing child %p with avail width = %d, reason = %d\n",
this, kidFrame, kidAvailSize.width, aReason);
rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus);
if (gsDebug) printf("%p RG child %p returned desired width = %d\n",
this, kidFrame, desiredSize.width);
nsRect kidRect (0, aReflowState.y, desiredSize.width, desiredSize.height);
PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize,
kidMaxElementSize);
/* if the table has collapsing borders, we need to reset the length of the shared vertical borders
* for the table and the cells that overlap this row
*/
if ((eReflowReason_Initial != aReflowState.reflowState.reason) && (NS_STYLE_BORDER_COLLAPSE==borderStyle))
{
PRInt32 rowIndex = ((nsTableRowFrame*)kidFrame)->GetRowIndex();
aReflowState.tableFrame->SetBorderEdgeLength(NS_SIDE_LEFT,
rowIndex,
kidRect.height);
aReflowState.tableFrame->SetBorderEdgeLength(NS_SIDE_RIGHT,
rowIndex,
kidRect.height);
PRInt32 colCount = aReflowState.tableFrame->GetColCount();
PRInt32 colIndex = 0;
nsIFrame *cellFrame;
for (colIndex = 0; colIndex < colCount; colIndex++) {
cellFrame = aReflowState.tableFrame->GetCellFrameAt(rowIndex, colIndex);
if (cellFrame) {
const nsStyleDisplay *cellDisplay;
cellFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)cellDisplay));
if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay) {
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_LEFT,
rowIndex,
kidRect.height);
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_RIGHT,
rowIndex,
kidRect.height);
const nsStyleDisplay *childDisplay;
kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
PRInt32 rowIndex = ((nsTableRowFrame*)kidFrame)->GetRowIndex();
aReflowState.tableFrame->SetBorderEdgeLength(NS_SIDE_LEFT,
rowIndex,
kidRect.height);
aReflowState.tableFrame->SetBorderEdgeLength(NS_SIDE_RIGHT,
rowIndex,
kidRect.height);
PRInt32 colCount = aReflowState.tableFrame->GetColCount();
PRInt32 colIndex = 0;
nsIFrame *cellFrame;
for (colIndex = 0; colIndex < colCount; colIndex++) {
cellFrame = aReflowState.tableFrame->GetCellFrameAt(rowIndex, colIndex);
if (cellFrame) {
const nsStyleDisplay *cellDisplay;
cellFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)cellDisplay));
if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay) {
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_LEFT,
rowIndex,
kidRect.height);
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_RIGHT,
rowIndex,
kidRect.height);
}
}
}
}
@ -1101,6 +1123,80 @@ NS_METHOD nsTableRowGroupFrame::IncrementalReflow(nsIPresContext& aPresContext,
return rv;
}
NS_IMETHODIMP
nsTableRowGroupFrame::AppendFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList)
{
// Get the table frame
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
// Append the frames
mFrames.AppendFrames(nsnull, aFrameList);
// See if the newly appended rows are the last rows in the table. Don't
// do this for appended row group frames. We probably should, but DidAppendRow()
// doesn't handle row group frames
const nsStyleDisplay *display;
aFrameList->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
if ((NS_STYLE_DISPLAY_TABLE_ROW == display->mDisplay) && NoRowsFollow()) {
// The rows we appended are the last rows in the table so incrementally
// add them to the cell map
for (nsIFrame* rowFrame = aFrameList; rowFrame; rowFrame->GetNextSibling(&rowFrame)) {
DidAppendRow((nsTableRowFrame*)rowFrame);
}
// Reflow the new frames. They're already marked dirty, so generate a reflow
// command that tells us to reflow our dirty child frames
nsIReflowCommand* reflowCmd;
if (NS_SUCCEEDED(NS_NewHTMLReflowCommand(&reflowCmd, this,
nsIReflowCommand::ReflowDirty))) {
aPresShell.AppendReflowCommand(reflowCmd);
NS_RELEASE(reflowCmd);
}
} else {
// We need to rebuild the cell map, because currently we can't insert
// new frames except at the end (append)
tableFrame->InvalidateCellMap();
// We should try and avoid doing a pass1 reflow on all the cells and just
// do it for the newly added frames, but we need to add these frames to the
// cell map before we reflow them
tableFrame->InvalidateFirstPassCache();
// Because the number of columns may have changed invalidate the column
// cache. Note that this has the side effect of recomputing the column
// widths, so we don't need to call InvalidateColumnWidths()
tableFrame->InvalidateColumnCache();
// Generate a reflow command so we reflow the table itself. This will
// do a pass-1 reflow of all the rows including any rows we just added
nsFrameState frameState;
nsIFrame* tableParentFrame;
nsIReflowCommand* reflowCmd;
// Mark the table frame as dirty
tableFrame->GetFrameState(&frameState);
frameState |= NS_FRAME_IS_DIRTY;
tableFrame->SetFrameState(frameState);
// Target the reflow comamnd at its parent frame
tableFrame->GetParent(&tableParentFrame);
if (NS_SUCCEEDED(NS_NewHTMLReflowCommand(&reflowCmd, tableParentFrame,
nsIReflowCommand::ReflowDirty))) {
// Add the reflow command
aPresShell.AppendReflowCommand(reflowCmd);
NS_RELEASE(reflowCmd);
}
}
return NS_OK;
}
NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
@ -1117,6 +1213,21 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
if (PR_TRUE==gsDebugIR) printf("TRGF IR: TargetIsMe with type=%d\n", type);
switch (type)
{
case nsIReflowCommand::ReflowDirty:
// Reflow the dirty child frames
// XXX What we really should do is do a pass-1 reflow of newly added
// frames (only if necessary--because the table isn't fixed layout), then
// see if column widtsh changed and decide whether to do the pass-2 reflow
// of just the dirty rows or have the table rebalance column widths and
// do a pass-2 reflow of all rows
rv = ReflowMappedChildren(aPresContext, aDesiredSize, aReflowState, aStatus,
nsnull, aReflowState.reflowState.reason, PR_TRUE, PR_TRUE);
// If any column widths have to change due to this, rebalance column widths
//XXX need to calculate this, but for now just do it
aReflowState.tableFrame->InvalidateColumnWidths();
break;
case nsIReflowCommand::FrameInserted :
NS_ASSERTION(nsnull!=objectFrame, "bad objectFrame");
NS_ASSERTION(nsnull!=childDisplay, "bad childDisplay");
@ -1136,25 +1247,6 @@ NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
}
break;
case nsIReflowCommand::FrameAppended :
NS_ASSERTION(nsnull!=objectFrame, "bad objectFrame");
NS_ASSERTION(nsnull!=childDisplay, "bad childDisplay");
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
rv = IR_RowAppended(aPresContext, aDesiredSize, aReflowState, aStatus,
(nsTableRowFrame *)objectFrame);
}
else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay)
{
rv = IR_RowGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus,
(nsTableRowGroupFrame*)objectFrame, PR_FALSE);
}
else
{ // no optimization to be done for Unknown frame types, so just reuse the Inserted method
rv = AddFrame(aReflowState.reflowState, objectFrame);
}
break;
/*
case nsIReflowCommand::FrameReplaced :

View File

@ -100,6 +100,11 @@ public:
NS_METHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList);
/** @see nsIFrame::Paint */
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
@ -276,7 +281,8 @@ protected:
nsReflowStatus& aStatus,
nsTableRowFrame * aStartFrame,
nsReflowReason aReason,
PRBool aDoSiblings);
PRBool aDoSiblings,
PRBool aDirtyOnly = PR_FALSE);
/**
* Pull-up all the row frames from our next-in-flow