diff --git a/layout/forms/nsHTMLButtonControlFrame.cpp b/layout/forms/nsHTMLButtonControlFrame.cpp
index b5b48d6df7be..cfb6a2f044d9 100644
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -445,12 +445,13 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext,
// reflow the child
nsIFrame* firstKid = mFrames.FirstChild();
- nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
+ nsSize availSize(aReflowState.mComputedWidth, NS_INTRINSICSIZE);
// indent the child inside us by the the focus border. We must do this separate from the
// regular border.
nsMargin focusPadding = mRenderer.GetAddedButtonBorderAndPadding();
+
if (NS_INTRINSICSIZE != availSize.width) {
availSize.width -= focusPadding.left + focusPadding.right;
availSize.width = PR_MAX(availSize.width,0);
@@ -459,8 +460,10 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext,
availSize.height -= focusPadding.top + focusPadding.bottom;
availSize.height = PR_MAX(availSize.height,0);
}
-
+
nsHTMLReflowState reflowState(aPresContext, aReflowState, firstKid, availSize);
+ //reflowState.computedWidth = availSize;
+
// XXX remove the following when the reflow state is fixed
//ButtonHack(reflowState, "html4 button's area");
@@ -471,7 +474,8 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext,
// See if it's targeted at us
aReflowState.reflowCommand->GetTarget(targetFrame);
if (this == targetFrame) {
- // XXX Handle this...
+ Invalidate(nsRect(0,0,mRect.width,mRect.height), PR_FALSE);
+
reflowState.reason = eReflowReason_Resize;
} else {
nsIFrame* nextFrame;
@@ -487,9 +491,16 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext,
nsRect rect = nsRect(focusPadding.left + aReflowState.mComputedBorderPadding.left, focusPadding.top + aReflowState.mComputedBorderPadding.top, aDesiredSize.width, aDesiredSize.height);
firstKid->SetRect(rect);
- // add in our border and padding to the size of the child
- aDesiredSize.width += focusPadding.left + focusPadding.right;
- aDesiredSize.height += focusPadding.top + focusPadding.bottom;
+ // if computed use the computed values.
+ if (aReflowState.mComputedWidth != NS_INTRINSICSIZE && (aDesiredSize.width < aReflowState.mComputedWidth))
+ aDesiredSize.width = aReflowState.mComputedWidth;
+ else
+ aDesiredSize.width += focusPadding.left + focusPadding.right;
+
+ if (aReflowState.mComputedHeight != NS_INTRINSICSIZE && (aDesiredSize.height < aReflowState.mComputedHeight))
+ aDesiredSize.height = aReflowState.mComputedHeight;
+ else
+ aDesiredSize.height += focusPadding.top + focusPadding.bottom;
aDesiredSize.width += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right;
aDesiredSize.height += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom;
@@ -502,6 +513,7 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext,
aDesiredSize.ascent = aDesiredSize.height;
aDesiredSize.descent = 0;
+
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
diff --git a/layout/html/forms/src/nsHTMLButtonControlFrame.cpp b/layout/html/forms/src/nsHTMLButtonControlFrame.cpp
index b5b48d6df7be..cfb6a2f044d9 100644
--- a/layout/html/forms/src/nsHTMLButtonControlFrame.cpp
+++ b/layout/html/forms/src/nsHTMLButtonControlFrame.cpp
@@ -445,12 +445,13 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext,
// reflow the child
nsIFrame* firstKid = mFrames.FirstChild();
- nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
+ nsSize availSize(aReflowState.mComputedWidth, NS_INTRINSICSIZE);
// indent the child inside us by the the focus border. We must do this separate from the
// regular border.
nsMargin focusPadding = mRenderer.GetAddedButtonBorderAndPadding();
+
if (NS_INTRINSICSIZE != availSize.width) {
availSize.width -= focusPadding.left + focusPadding.right;
availSize.width = PR_MAX(availSize.width,0);
@@ -459,8 +460,10 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext,
availSize.height -= focusPadding.top + focusPadding.bottom;
availSize.height = PR_MAX(availSize.height,0);
}
-
+
nsHTMLReflowState reflowState(aPresContext, aReflowState, firstKid, availSize);
+ //reflowState.computedWidth = availSize;
+
// XXX remove the following when the reflow state is fixed
//ButtonHack(reflowState, "html4 button's area");
@@ -471,7 +474,8 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext,
// See if it's targeted at us
aReflowState.reflowCommand->GetTarget(targetFrame);
if (this == targetFrame) {
- // XXX Handle this...
+ Invalidate(nsRect(0,0,mRect.width,mRect.height), PR_FALSE);
+
reflowState.reason = eReflowReason_Resize;
} else {
nsIFrame* nextFrame;
@@ -487,9 +491,16 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext,
nsRect rect = nsRect(focusPadding.left + aReflowState.mComputedBorderPadding.left, focusPadding.top + aReflowState.mComputedBorderPadding.top, aDesiredSize.width, aDesiredSize.height);
firstKid->SetRect(rect);
- // add in our border and padding to the size of the child
- aDesiredSize.width += focusPadding.left + focusPadding.right;
- aDesiredSize.height += focusPadding.top + focusPadding.bottom;
+ // if computed use the computed values.
+ if (aReflowState.mComputedWidth != NS_INTRINSICSIZE && (aDesiredSize.width < aReflowState.mComputedWidth))
+ aDesiredSize.width = aReflowState.mComputedWidth;
+ else
+ aDesiredSize.width += focusPadding.left + focusPadding.right;
+
+ if (aReflowState.mComputedHeight != NS_INTRINSICSIZE && (aDesiredSize.height < aReflowState.mComputedHeight))
+ aDesiredSize.height = aReflowState.mComputedHeight;
+ else
+ aDesiredSize.height += focusPadding.top + focusPadding.bottom;
aDesiredSize.width += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right;
aDesiredSize.height += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom;
@@ -502,6 +513,7 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext,
aDesiredSize.ascent = aDesiredSize.height;
aDesiredSize.descent = 0;
+
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
diff --git a/layout/xul/base/src/nsBoxFrame.cpp b/layout/xul/base/src/nsBoxFrame.cpp
index a056981c3192..f68da1df62d0 100644
--- a/layout/xul/base/src/nsBoxFrame.cpp
+++ b/layout/xul/base/src/nsBoxFrame.cpp
@@ -40,6 +40,8 @@
#include "nsIViewManager.h"
#define CONSTANT float(0.0)
+#define DEBUG_REFLOW 0
+#define DEBUG_REDRAW 0
nsresult
NS_NewBoxFrame ( nsIFrame** aNewFrame, PRUint32 aFlags )
@@ -107,12 +109,10 @@ nsBoxFrame::GetRedefinedMinPrefMax(nsIFrame* aFrame, nsBoxInfo& aSize)
// see if the width or height was specifically set
if (position->mWidth.GetUnit() == eStyleUnit_Coord) {
aSize.prefSize.width = position->mWidth.GetCoordValue();
- aSize.prefWidthIntrinsic = PR_FALSE;
}
if (position->mHeight.GetUnit() == eStyleUnit_Coord) {
aSize.prefSize.height = position->mHeight.GetCoordValue();
- aSize.prefHeightIntrinsic = PR_FALSE;
}
// same for min size. Unfortunately min size is always set to 0. So for now
@@ -179,12 +179,52 @@ nsBoxFrame::GetChildBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowStat
return NS_OK;
}
- // set the pref width and height to be intrinsic.
- aSize.prefWidthIntrinsic = PR_TRUE;
- aSize.prefHeightIntrinsic = PR_TRUE;
+ // start the preferred size as intrinsic
+ aSize.prefSize.width = NS_INTRINSICSIZE;
+ aSize.prefSize.height = NS_INTRINSICSIZE;
+ // redefine anything depending on css
GetRedefinedMinPrefMax(aFrame, aSize);
+ // subtract out the childs margin and border
+ const nsStyleSpacing* spacing;
+ nsresult rv = aFrame->GetStyleData(eStyleStruct_Spacing,
+ (const nsStyleStruct*&) spacing);
+
+ nsMargin margin;
+ spacing->GetMargin(margin);
+ nsMargin border;
+ spacing->GetBorderPadding(border);
+ nsMargin total = margin + border;
+
+ // add in childs margin and border
+ if (aSize.prefSize.height != NS_INTRINSICSIZE)
+ aSize.prefSize.height += (total.left + total.right);
+
+ if (aSize.prefSize.height != NS_INTRINSICSIZE)
+ aSize.prefSize.height += (total.top + total.bottom);
+
+ // flow child at preferred size
+ nsHTMLReflowMetrics desiredSize(nsnull);
+
+ nsCalculatedBoxInfo info(aSize);
+
+ info.calculatedSize = aSize.prefSize;
+
+ nsReflowStatus status;
+ PRBool redraw;
+ nsString reason("To get pref size");
+ FlowChildAt(aFrame, aPresContext, desiredSize, aReflowState, status, info, redraw, reason);
+
+ // remove margin and border
+ desiredSize.height -= (total.top + total.bottom);
+ desiredSize.width -= (total.left + total.right);
+
+ // get the size returned and the it as the preferredsize.
+ aSize.prefSize.width = desiredSize.width;
+ aSize.prefSize.height = desiredSize.height;
+
+
return NS_OK;
}
@@ -204,6 +244,12 @@ nsBoxFrame::Reflow(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
+
+#if DEBUG_REFLOW
+ if (NS_BLOCK_DOCUMENT_ROOT & mFlags)
+ printf("---------------- Begin Reflow ---------------\n");
+#endif
+
// If we have a space manager, then set it in the reflow state
if (mSpaceManager) {
// Modify the reflow state and set the space manager
@@ -282,7 +328,7 @@ printf("\n");
//-----------------------------------------------------------------------------------
// flow each child at the new sizes we have calculated.
- FlowChildren(aPresContext, aDesiredSize, aReflowState, aStatus, rect, incrementalChild);
+ FlowChildren(aPresContext, aDesiredSize, aReflowState, aStatus, rect);
//-----------------------------------------------------------------------------------
//------------------------- Adjust each childs x, y location-------------------------
@@ -312,9 +358,9 @@ printf("\n");
damageArea.height = aDesiredSize.height;
damageArea.width = aDesiredSize.width;
- if ((NS_BLOCK_DOCUMENT_ROOT & mFlags) && !damageArea.IsEmpty()) {
- Invalidate(damageArea);
- }
+ // if ((NS_BLOCK_DOCUMENT_ROOT & mFlags) && !damageArea.IsEmpty()) {
+ // Invalidate(damageArea);
+ // }
#if 0
ListTag(stdout); printf(": reflow done\n");
#endif
@@ -332,22 +378,26 @@ nsBoxFrame::FlowChildren(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus,
- nsRect& rect,
- nsIFrame*& incrementalChild)
+ nsRect& rect)
{
+ PRBool redraw = PR_FALSE;
+
//-----------------------------------
// first pass flow all fixed children
//-----------------------------------
- PRBool resized[100];
- int i;
- for (i=0; i < mSpringCount; i++)
- resized[i] = PR_FALSE;
-
PRBool finished;
nscoord passes = 0;
nscoord changedIndex = -1;
nscoord count = 0;
+ nsString reason="initial";
+ nsString nextReason = "initial";
+ PRBool resized[100];
+
+ for (int i=0; i < mSpringCount; i++)
+ resized[i] = PR_FALSE;
+
+ /*
nsIFrame* childFrame = mFrames.FirstChild();
while (nsnull != childFrame)
{
@@ -356,20 +406,25 @@ nsBoxFrame::FlowChildren(nsIPresContext& aPresContext,
{
// reflow only fixed children
if (mSprings[count].flex == 0.0) {
- FlowChildAt(childFrame, aPresContext, aDesiredSize, aReflowState, aStatus, count, incrementalChild);
+ FlowChildAt(childFrame, aPresContext, aDesiredSize, aReflowState, aStatus, mSprings[count], redraw, reason);
// if its height greater than the max. Set the max to this height and set a flag
// saying we will need to do another pass. But keep going there
// may be another child that is bigger
- if (!mHorizontal) {
- if (rect.height == NS_INTRINSICSIZE || aDesiredSize.height > mSprings[count].calculatedSize.height) {
- mSprings[count].calculatedSize.height = aDesiredSize.height;
- resized[count] = PR_TRUE;
+ if (mHorizontal) {
+ if (aDesiredSize.height > rect.height) {
+ rect.height = aDesiredSize.height;
+ InvalidateChildren();
+ LayoutChildrenInRect(rect);
+ nextReason = "child's height got bigger";
}
} else {
- if (rect.width == NS_INTRINSICSIZE || aDesiredSize.width > mSprings[count].calculatedSize.width) {
- mSprings[count].calculatedSize.width = aDesiredSize.width;
- resized[count] = PR_TRUE;
+ if (aDesiredSize.width > rect.width) {
+ mSprings[count].minSize.width = aDesiredSize.width;
+ rect.width = aDesiredSize.width;
+ InvalidateChildren();
+ LayoutChildrenInRect(rect);
+ nextReason = "child's width got bigger";
}
}
}
@@ -378,6 +433,9 @@ nsBoxFrame::FlowChildren(nsIPresContext& aPresContext,
NS_ASSERTION(rv == NS_OK,"failed to get next child");
count++;
}
+ */
+
+ //reason = nextReason;
// ----------------------
@@ -391,12 +449,8 @@ nsBoxFrame::FlowChildren(nsIPresContext& aPresContext,
changedIndex = -1;
InvalidateChildren();
-
- for (i=0; i < mSpringCount; i++)
- mSprings[i].sizeValid = resized[i];
-
LayoutChildrenInRect(rect);
-
+
passes = 0;
do
{
@@ -412,66 +466,17 @@ nsBoxFrame::FlowChildren(nsIPresContext& aPresContext,
if (!mSprings[count].collapsed)
{
// reflow if the child needs it or we are on a second pass
- // if (mSprings[count].needsReflow || passes > 0) {
- FlowChildAt(childFrame, aPresContext, aDesiredSize, aReflowState, aStatus, count, incrementalChild);
-
- // if its height greater than the max. Set the max to this height and set a flag
- // saying we will need to do another pass. But keep going there
- // may be another child that is bigger
- if (mHorizontal) {
- if (rect.height == NS_INTRINSICSIZE || aDesiredSize.height > rect.height) {
- rect.height = aDesiredSize.height;
- finished = PR_FALSE;
- changedIndex = count;
- for (int i=0; i < mSpringCount; i++)
- resized[i] = PR_FALSE;
- }
-
- // if we are wider than we anticipated then
- // then this child can't get smaller then the size returned
- // so set its minSize to be the desired and restretch. Then
- // just start over because the springs are all messed up
- // anyway.
- if (aDesiredSize.width > mSprings[count].calculatedSize.width) {
- mSprings[count].calculatedSize.width = aDesiredSize.width;
- resized[count] = PR_TRUE;
-
- for (int i=0; i < mSpringCount; i++)
- mSprings[i].sizeValid = resized[i];
+ FlowChildAt(childFrame, aPresContext, aDesiredSize, aReflowState, aStatus, mSprings[count], redraw, reason);
- finished = PR_FALSE;
- changedIndex = count;
- }
-
-
- } else {
- if (rect.width == NS_INTRINSICSIZE || aDesiredSize.width > rect.width) {
- rect.width = aDesiredSize.width;
- finished = PR_FALSE;
- changedIndex = count;
- for (int i=0; i < mSpringCount; i++)
- resized[i] = PR_FALSE;
- }
-
-
- if (aDesiredSize.height > mSprings[count].calculatedSize.height) {
- mSprings[count].calculatedSize.height = aDesiredSize.height;
-
- resized[count] = PR_TRUE;
-
- for (int i=0; i < mSpringCount; i++)
- mSprings[i].sizeValid = resized[i];
-
- LayoutChildrenInRect(rect);
- finished = PR_FALSE;
- changedIndex = count;
- }
+ // if the child got bigger then adjust our rect and all the children.
+ ChildResized(aDesiredSize, rect, mSprings[count], resized, changedIndex, finished, count, nextReason);
}
- }
+
nsresult rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(rv == NS_OK,"failed to get next child");
count++;
+ reason = nextReason;
}
// if we get over 10 passes something probably when wrong.
@@ -489,9 +494,184 @@ nsBoxFrame::FlowChildren(nsIPresContext& aPresContext,
} while (PR_FALSE == finished);
+ // redraw things if needed.
+ if (redraw) {
+#if DEBUG_REDRAW
+ ListTag(stdout);
+ printf("is being redrawn\n");
+#endif
+ Invalidate(nsRect(0,0,mRect.width, mRect.height), PR_FALSE);
+ }
+
return NS_OK;
}
+void
+nsBoxFrame::ChildResized(nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nsCalculatedBoxInfo& aInfo, PRBool* aResized, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex, nsString& aReason)
+{
+ if (mHorizontal) {
+ // if we are a horizontal box see if the child will fit inside us.
+ if ( aDesiredSize.height > aRect.height) {
+ // if we are a horizontal box and the the child it bigger than our height
+
+ // ok if the height changed then we need to reflow everyone but us at the new height
+ // so we will set the changed index to be us. And signal that we need a new pass.
+ aRect.height = aDesiredSize.height;
+
+ // remember we do not need to clear the resized list because changing the height of a horizontal box
+ // will not affect the width of any of its children because block flow left to right, top to bottom. Just trust me
+ // on this one.
+ aFinished = PR_FALSE;
+ aChangedIndex = aIndex;
+
+ // relayout everything
+ InvalidateChildren();
+ LayoutChildrenInRect(aRect);
+ aReason = "child's height got bigger";
+ } else if (aDesiredSize.width > aInfo.calculatedSize.width) {
+ // if the child is wider than we anticipated. This can happend for children that we were not able to get a
+ // take on their min width. Like text, or tables.
+
+ // because things flow from left to right top to bottom we know that
+ // if we get wider that we can set the min size. This will only work
+ // for width not height. Height must always be recalculated!
+ aInfo.minSize.width = aDesiredSize.width;
+
+ // our width now becomes the new size
+ aInfo.calculatedSize.width = aDesiredSize.width;
+
+ InvalidateChildren();
+
+ // our index resized
+ aResized[aIndex] = PR_TRUE;
+
+ // if the width changed. mark our child as being resized
+ for (int i=0; i < mSpringCount; i++)
+ mSprings[i].sizeValid = aResized[i];
+
+ LayoutChildrenInRect(aRect);
+ aFinished = PR_FALSE;
+ aChangedIndex = aIndex;
+ aReason = "child's width got bigger";
+ }
+ } else {
+ if ( aDesiredSize.width > aRect.width) {
+ // ok if the height changed then we need to reflow everyone but us at the new height
+ // so we will set the changed index to be us. And signal that we need a new pass.
+ aRect.width = aDesiredSize.width;
+
+ // because things flow from left to right top to bottom we know that
+ // if we get wider that we can set the min size. This will only work
+ // for width not height. Height must always be recalculated!
+ aInfo.minSize.width = aDesiredSize.width;
+
+ // if the width changed then clear out the resized list
+ // but only do this if we are vertical box. On a horizontal box increasing the height will not change the
+ // width of its children.
+ for (int i=0; i < mSpringCount; i++)
+ aResized[i] = PR_FALSE;
+
+ aFinished = PR_FALSE;
+ aChangedIndex = aIndex;
+
+ // relayout everything
+ InvalidateChildren();
+ LayoutChildrenInRect(aRect);
+ aReason = "child's height got bigger";
+ } else if (aDesiredSize.height > aInfo.calculatedSize.height) {
+ // our width now becomes the new size
+ aInfo.calculatedSize.height = aDesiredSize.height;
+
+ InvalidateChildren();
+
+ // our index resized
+ aResized[aIndex] = PR_TRUE;
+
+ // if the width changed. mark our child as being resized
+ for (int i=0; i < mSpringCount; i++)
+ mSprings[i].sizeValid = aResized[i];
+
+ LayoutChildrenInRect(aRect);
+ aFinished = PR_FALSE;
+ aChangedIndex = aIndex;
+ aReason = "child's width got bigger";
+ }
+ }
+}
+
+
+/*
+void
+nsBoxFrame::ChildResized(nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nsCalculatedBoxInfo& aInfo, PRBool[] aResized, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex)
+{
+ // this code is designed to work in both dimensions. It is written as if we were only dealing
+ // with a horizontal box. But if we get a vertical box the values will be inverted.
+ // width becomes height and height becomes width. The purpose of this code is to correctly relayout
+ // if a child get larger than what we told it to layout as. This can happend a lot with text. Say
+ // we have a div and we layout it out in a vertical box with a width of 100px. The text must wrap.
+ // this will make the height of the div taller than expected. We would normally only expect it to
+ // by its prefered height of 1 line. So we must shuffle things. The idea is to have a list of
+ // resized children. If a child gets gets bigger a bit will be set in the resized array. This
+ // tells the layout system not to recalculate the size of that child when we relayout out.
+
+ nscoord& desiredHeight = GET_HEIGHT(aDesiredSize);
+ nscoord& rectHeight = GET_HEIGHT(aRect);
+ nscoord& desiredWidth = GET_WIDTH(aDesiredSize);
+ nscoord& rectWidth = GET_WIDTH(aRect);
+ nscoord& calculatedWidth = GET_WIDTH(aInfo.calculatedSize);
+
+ if (desiredHeight > rectHeight) {
+ // ok if the height changed then we need to reflow everyone but us at the new height
+ // so we will set the changed index to be us. And signal that we need a new pass.
+ rectHeight = desiredHeight;
+
+ // because things flow from left to right top to bottom we know that
+ // if we get wider that we can set the min size. This will only work
+ // for width not height. Height must always be recalculated!
+ if (!mHorizontal)
+ aInfo.minSize.width = desiredHeight;
+
+ aFinished = PR_FALSE;
+ aChangedIndex = aIndex;
+
+ // if the height changed then clear out the resized list
+ // but only do this if we are horizontal box. In that case an increase in height
+ // can not affect
+ for (int i=0; i < mSprings; i++)
+ resized[i] = PR_FALSE;
+
+ // relayout everything
+ InvalidateChildren();
+ LayoutChildrenInRect(rect);
+ aReason = "child's height got bigger";
+ } else if (desiredWidth > calculatedWidth) {
+
+ // because things flow from left to right top to bottom we know that
+ // if we get wider that we can set the min size. This will only work
+ // for width not height. Height must always be recalculated!
+ if (mHorizontal)
+ aInfo.minSize.width = desiredWidth;
+
+ // our width now becomes the new size
+ calculatedWidth = desiredWidth;
+
+ InvalidateChildren();
+
+ // our index resized
+ resized[index] = PR_TRUE;
+
+ // if the width changed. mark our child as being resized
+ for (int i=0; i < mSprings; i++)
+ mSprings[i].sizeValid = resized[i];
+
+ LayoutChildrenInRect(rect);
+ aFinished = PR_FALSE;
+ aChangedIndex = count;
+ aReason = "child's width got bigger";
+ }
+}
+*/
+
/*
void CollapseChildren(nsIFrame* frame)
{
@@ -590,6 +770,7 @@ nsBoxFrame::PlaceChildren(nsRect& boxRect)
return NS_OK;
}
+
/**
* Flow an individual child. Special args:
* count: the spring that will be used to lay out the child
@@ -603,14 +784,21 @@ nsBoxFrame::FlowChildAt(nsIFrame* childFrame,
nsHTMLReflowMetrics& desiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus,
- nscoord spring,
- nsIFrame*& incrementalChild)
+ nsCalculatedBoxInfo& aInfo,
+ PRBool& aRedraw,
+ nsString& aReason)
{
-#if 0
-ListTag(stdout); printf(": reflowing ");
-nsFrame::ListTag(stdout, childFrame);
-printf("\n");
-#endif
+
+ nsReflowReason reason = aReflowState.reason;
+ PRBool shouldReflow = PR_TRUE;
+
+ // if the reason is incremental and the child is not marked as incremental. Then relow the child
+ // as a resize instead.
+ if (aInfo.isIncremental)
+ reason = eReflowReason_Incremental;
+ else if (reason == eReflowReason_Incremental)
+ reason = eReflowReason_Resize;
+
// subtract out the childs margin and border
const nsStyleSpacing* spacing;
nsresult rv = childFrame->GetStyleData(eStyleStruct_Spacing,
@@ -618,34 +806,31 @@ printf("\n");
nsMargin margin;
spacing->GetMargin(margin);
- nsMargin border;
- spacing->GetBorderPadding(border);
- nsMargin total = margin + border;
- const nsStylePosition* position;
- rv = childFrame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) position);
-
- nsReflowReason reason = aReflowState.reason;
- PRBool shouldReflow = PR_TRUE;
-
- // so if we are incremental and have already reflowed the incremental child or there is an incremental child
- // and its not this one make sure we change the reason to resize.
- if (reason == eReflowReason_Incremental && (nsnull == incrementalChild || incrementalChild != childFrame))
- reason = eReflowReason_Resize;
+ // get the current size of the child
+ nsRect currentRect(0,0,0,0);
+ childFrame->GetRect(currentRect);
// if we don't need a reflow then
// lets see if we are already that size. Yes? then don't even reflow. We are done.
- if (!mSprings[spring].needsReflow) {
- nsRect currentSize;
- childFrame->GetRect(currentSize);
+ if (!aInfo.needsReflow && aInfo.calculatedSize.width != NS_INTRINSICSIZE && aInfo.calculatedSize.height != NS_INTRINSICSIZE) {
- if (currentSize.width > 0 && currentSize.height > 0)
- {
- desiredSize.width = currentSize.width;
- desiredSize.height = currentSize.height;
+ // if the new calculated size has a 0 width or a 0 height
+ if ((currentRect.width == 0 || currentRect.height == 0) && (aInfo.calculatedSize.width == 0 || aInfo.calculatedSize.height == 0)) {
+ shouldReflow = PR_FALSE;
+ desiredSize.width = aInfo.calculatedSize.width - (margin.left + margin.right);
+ desiredSize.height = aInfo.calculatedSize.height - (margin.top + margin.bottom);
+ childFrame->SizeTo(desiredSize.width, desiredSize.height);
+ } else {
+ desiredSize.width = currentRect.width;
+ desiredSize.height = currentRect.height;
- if (currentSize.width == mSprings[spring].calculatedSize.width && currentSize.height == mSprings[spring].calculatedSize.height)
+ // remove the margin. The rect of our child does not include it but our calculated size does.
+ nscoord calcWidth = aInfo.calculatedSize.width - (margin.left + margin.right);
+ nscoord calcHeight = aInfo.calculatedSize.height - (margin.top + margin.bottom);
+
+ // don't reflow if we are already the right size
+ if (currentRect.width == calcWidth && currentRect.height == calcHeight)
shouldReflow = PR_FALSE;
}
}
@@ -653,68 +838,56 @@ printf("\n");
// ok now reflow the child into the springs calculated space
if (shouldReflow) {
+ nsMargin border;
+ spacing->GetBorderPadding(border);
+ nsMargin total = margin + border;
+
+ const nsStylePosition* position;
+ rv = childFrame->GetStyleData(eStyleStruct_Position,
+ (const nsStyleStruct*&) position);
+
desiredSize.width = 0;
desiredSize.height = 0;
+ nsSize size(aInfo.calculatedSize.width, aInfo.calculatedSize.height);
+
+ // only subrtact margin
+ if (size.height != NS_INTRINSICSIZE)
+ size.height -= (margin.top + margin.bottom);
+
+
+ if (size.width != NS_INTRINSICSIZE)
+ size.width -= (margin.left + margin.right);
+
// create a reflow state to tell our child to flow at the given size.
- nsHTMLReflowState reflowState(aPresContext, aReflowState, childFrame, nsSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE));
+ nsHTMLReflowState reflowState(aPresContext, aReflowState, childFrame, nsSize(size.width, NS_INTRINSICSIZE));
reflowState.reason = reason;
+ if (size.height != NS_INTRINSICSIZE)
+ size.height -= (border.top + border.bottom);
+
+ if (size.width != NS_INTRINSICSIZE)
+ size.width -= (border.left + border.right);
+
// tell the child what size they should be
- reflowState.mComputedWidth = mSprings[spring].calculatedSize.width;
- reflowState.mComputedHeight = mSprings[spring].calculatedSize.height;
+ reflowState.mComputedWidth = size.width;
+ reflowState.mComputedHeight = size.height;
- // only subrtact margin and border.
- if (reflowState.mComputedWidth != NS_INTRINSICSIZE)
- reflowState.mComputedWidth -= (total.left + total.right);
-
- if (reflowState.mComputedHeight != NS_INTRINSICSIZE)
- reflowState.mComputedHeight -= (total.top + total.bottom);
-
- // HTML frames do not implement nsIBox so unless they set both their width and height we do not know
- // what there preferred size is. We can assume a preferred width or height of 0 when flexable but when
- // not flexible we are in trouble. Why? Well if the child is fixed we really want its intrinsic size and
- // the only way to get it is to flow with NS_INTRINSIC. So lets do that if we have to.
- if (mSprings[spring].flex == CONSTANT) {
- if (mHorizontal) {
- if (mSprings[spring].prefWidthIntrinsic)
- reflowState.mComputedWidth = NS_INTRINSICSIZE;
- } else {
- if (mSprings[spring].prefHeightIntrinsic)
- reflowState.mComputedHeight = NS_INTRINSICSIZE;
- }
- }
-
- // HTML block don't seem to return the actually size they layed themselves
- // out in if they did not fit. So if the height is 0 indicating no one set it them. Get this
- // fixed in blocks themselves.
- if (mHorizontal) {
- // if we could not get the height of the child because it did not implement nsIBox and
- // it did not provide a height via css and we are trying to lay it out with a height of 0
- if (mSprings[spring].prefHeightIntrinsic && reflowState.mComputedHeight != NS_INTRINSICSIZE) {
- nscoord oldHeight = mSprings[spring].calculatedSize.height;
- mSprings[spring].calculatedSize.height = NS_INTRINSICSIZE;
- FlowChildAt(childFrame, aPresContext, desiredSize, aReflowState, aStatus, spring, incrementalChild);
-
- mSprings[spring].calculatedSize.height = oldHeight;
-
- // remember that when we get the size back it has its margin and borderpadding
- // added to it! So we must remove it before we make the comparison
- desiredSize.width -= (total.left + total.right);
- desiredSize.height -= (total.top + total.bottom);
-
- // see if things are ok
- if (reflowState.mComputedHeight < desiredSize.height)
- reflowState.mComputedHeight = desiredSize.height;
-
- }
-
- }
-
- nsSize* oldMaxElementSize = desiredSize.maxElementSize;
- nsSize maxElementSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
- desiredSize.maxElementSize = &maxElementSize;
+ // nsSize maxElementSize(0, 0);
+ // desiredSize.maxElementSize = &maxElementSize;
+#if DEBUG_REFLOW
+ ListTag(stdout);
+ if (reason == eReflowReason_Incremental && aInfo.isIncremental)
+ printf(": INCREMENTALLY reflowing ");
+ else
+ printf(": reflowing ");
+
+ nsFrame::ListTag(stdout, childFrame);
+ char ch[100];
+ aReason.ToCString(ch,100);
+ printf("because (%s)\n", ch);
+#endif
// do the flow
nsIHTMLReflow* htmlReflow;
@@ -723,28 +896,73 @@ printf("\n");
htmlReflow->WillReflow(aPresContext);
htmlReflow->Reflow(aPresContext, desiredSize, reflowState, aStatus);
+
NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
- if (maxElementSize.width != NS_INTRINSICSIZE && maxElementSize.width > desiredSize.width)
- desiredSize.width = maxElementSize.width;
+ nsFrameState kidState;
+ childFrame->GetFrameState(&kidState);
+
+ // printf("width: %d, height: %d\n", desiredSize.mCombinedArea.width, desiredSize.mCombinedArea.height);
+
+ if (kidState & NS_FRAME_OUTSIDE_CHILDREN) {
+ desiredSize.width = desiredSize.mCombinedArea.width;
+ desiredSize.height = desiredSize.mCombinedArea.height;
+ }
+
+
+// if (maxElementSize.width > desiredSize.width)
+ // desiredSize.width = maxElementSize.width;
+
+ PRBool changedSize = PR_FALSE;
+
+ if (currentRect.width != desiredSize.width || currentRect.height != desiredSize.height)
+ changedSize = PR_TRUE;
+
+ // if the child got bigger then make sure the new size in our min max range
+ if (changedSize) {
+
+ // redraw if we changed size.
+ aRedraw = PR_TRUE;
+
+ if (aInfo.maxSize.width != NS_INTRINSICSIZE && desiredSize.width > aInfo.maxSize.width - (margin.left + margin.right))
+ desiredSize.width = aInfo.maxSize.width - (margin.left + margin.right);
+
+ // if the child was bigger than anticipated and there was a min size set thennn
+ if (aInfo.calculatedSize.width != NS_INTRINSICSIZE && position->mMinWidth.GetUnit() == eStyleUnit_Coord) {
+ nscoord min = position->mMinWidth.GetCoordValue();
+ if (min != 0)
+ desiredSize.width = aInfo.calculatedSize.width - (margin.left + margin.right);
+ }
+
+ if (aInfo.maxSize.height != NS_INTRINSICSIZE && desiredSize.height > aInfo.maxSize.height - (margin.top + margin.bottom))
+ desiredSize.height = aInfo.maxSize.height - (margin.top + margin.bottom);
+
+ // if a min size was set we will always get the desired height
+ if (aInfo.calculatedSize.height != NS_INTRINSICSIZE && position->mMinHeight.GetUnit() == eStyleUnit_Coord) {
+ nscoord min = position->mMinHeight.GetCoordValue();
+ if (min != 0)
+ desiredSize.height = aInfo.calculatedSize.height - (margin.top + margin.bottom);
+ }
+
+ }
// set the rect
- childFrame->SetRect(nsRect(0,0,desiredSize.width, desiredSize.height));
+ childFrame->SizeTo(desiredSize.width, desiredSize.height);
// Stub out desiredSize.maxElementSize so that when go out of
// scope, nothing bad happens!
- desiredSize.maxElementSize = oldMaxElementSize;
+ desiredSize.maxElementSize = nsnull;
// clear out the incremental child, so that we don't flow it incrementally again
- if (reason == eReflowReason_Incremental && incrementalChild == childFrame)
- incrementalChild = nsnull;
+ if (reason == eReflowReason_Incremental && aInfo.isIncremental)
+ aInfo.isIncremental = PR_FALSE;
}
// add the margin back in. The child should add its border automatically
desiredSize.height += (margin.top + margin.bottom);
desiredSize.width += (margin.left + margin.right);
- mSprings[spring].needsReflow = PR_FALSE;
+ aInfo.needsReflow = PR_FALSE;
return NS_OK;
}
@@ -764,7 +982,6 @@ nsBoxFrame::BoundsCheck(const nsBoxInfo& aBoxInfo, nsRect& aRect)
if (aRect.width == NS_INTRINSICSIZE )
aRect.width = aBoxInfo.prefSize.width;
-
// make sure the available size is no bigger than the max size
if (aRect.height > aBoxInfo.maxSize.height)
aRect.height = aBoxInfo.maxSize.height;
@@ -1045,14 +1262,6 @@ nsBoxFrame::GetBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aR
nscoord count = 0;
nsIFrame* childFrame = mFrames.FirstChild();
- /*
- // if we have any children assume we are intrinsic unless a child is not
- if (childFrame != nsnull) {
- aSize.prefHeightIntrinsic = PR_TRUE;
- aSize.prefWidthIntrinsic = PR_TRUE;
- }
- */
-
while (nsnull != childFrame)
{
// if a child needs recalculation then ask it for its size. Otherwise
@@ -1088,30 +1297,28 @@ nsBoxFrame::GetBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aR
nsSize m(margin.left+margin.right,margin.top+margin.bottom);
mSprings[count].minSize += m;
mSprings[count].prefSize += m;
+ if (mSprings[count].maxSize.width != NS_INTRINSICSIZE)
+ mSprings[count].maxSize.width += m.width;
+
+ if (mSprings[count].maxSize.height != NS_INTRINSICSIZE)
+ mSprings[count].maxSize.height += m.height;
spacing->GetBorderPadding(margin);
nsSize b(margin.left+margin.right,margin.top+margin.bottom);
mSprings[count].minSize += b;
mSprings[count].prefSize += b;
+ if (mSprings[count].maxSize.width != NS_INTRINSICSIZE)
+ mSprings[count].maxSize.width += b.width;
+
+ if (mSprings[count].maxSize.height != NS_INTRINSICSIZE)
+ mSprings[count].maxSize.height += b.height;
}
// ok we don't need to calc this guy again
mSprings[count].needsRecalc = PR_FALSE;
}
- /*
- // if a size is not intrinsic then our size is not intrinsic.
- if (!mSprings[count].prefWidthIntrinsic)
- aSize.prefWidthIntrinsic = PR_FALSE;
-
- if (!mSprings[count].prefHeightIntrinsic)
- aSize.prefHeightIntrinsic = PR_FALSE;
- */
-
- // now that we know our child's min, max, pref sizes figure OUR size from them.
- AddSize(mSprings[count].minSize, aSize.minSize, PR_FALSE);
- AddSize(mSprings[count].maxSize, aSize.maxSize, PR_TRUE);
- AddSize(mSprings[count].prefSize, aSize.prefSize, PR_FALSE);
+ AddChildSize(aSize, mSprings[count]);
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(rv == NS_OK,"failed to get next child");
@@ -1135,9 +1342,20 @@ nsBoxFrame::GetBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aR
return rv;
}
+void
+nsBoxFrame::AddChildSize(nsBoxInfo& aInfo, nsBoxInfo& aChildInfo)
+{
+ // now that we know our child's min, max, pref sizes figure OUR size from them.
+ AddSize(aChildInfo.minSize, aInfo.minSize, PR_FALSE);
+ AddSize(aChildInfo.maxSize, aInfo.maxSize, PR_TRUE);
+ AddSize(aChildInfo.prefSize, aInfo.prefSize, PR_FALSE);
+}
+
/**
- * Called with a reflow command. This will dirty all boxes who need to be reflowed.
- * return the last child that is not a box. Part of nsIBox interface.
+ * Boxes work differently that regular HTML elements. Each box knows if it needs to be reflowed or not
+ * So when a box gets an incremental reflow. It runs down all the children and marks them for reflow. If it
+ * Reaches a child that is not a box then it marks that child as incremental so when it is flowed next it
+ * will be flowed incrementally.
*/
NS_IMETHODIMP
nsBoxFrame::Dirty(const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild)
@@ -1163,7 +1381,14 @@ nsBoxFrame::Dirty(const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalC
ibox->Dirty(aReflowState, incrementalChild);
else
incrementalChild = frame;
+
+ // if we found a leaf. Then mark it as being incremental. So when we
+ // flow it we will flow it incrementally
+ if (incrementalChild == childFrame)
+ mSprings[count].isIncremental = PR_TRUE;
+
break;
+
}
rv = childFrame->GetNextSibling(&childFrame);
@@ -1177,6 +1402,41 @@ nsBoxFrame::Dirty(const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalC
return rv;
}
+NS_IMETHODIMP
+nsBoxFrame :: Paint ( nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect,
+ nsFramePaintLayer aWhichLayer)
+{
+ const nsStyleDisplay* disp = (const nsStyleDisplay*)
+ mStyleContext->GetStyleData(eStyleStruct_Display);
+
+ // if we aren't visible then we are done.
+ if (!disp->mVisible)
+ return NS_OK;
+
+ // if we are visible then tell our superclass to paint
+ nsresult r = nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
+ aWhichLayer);
+
+ // paint the draw area
+ /*
+#if DEBUG_REDRAW
+ if (NS_BLOCK_DOCUMENT_ROOT & mFlags) {
+ PRBool result = PR_FALSE;
+ nsRect rect(0,0,0,0);
+ aRenderingContext.GetClipRect(rect, result);
+ if (result) {
+ aRenderingContext.SetColor(NS_RGB(255,0,0));
+ aRenderingContext.DrawRect(rect);
+ }
+ }
+#endif
+*/
+ return r;
+}
+
+
NS_IMETHODIMP nsBoxFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
@@ -1218,6 +1478,19 @@ nsCalculatedBoxInfo::nsCalculatedBoxInfo()
clear();
}
+nsCalculatedBoxInfo::nsCalculatedBoxInfo(const nsBoxInfo& aInfo):nsBoxInfo(aInfo)
+{
+ needsReflow = PR_TRUE;
+ needsRecalc = PR_TRUE;
+ collapsed = PR_FALSE;
+
+ calculatedSize.width = 0;
+ calculatedSize.height = 0;
+
+ sizeValid = PR_FALSE;
+ isIncremental = PR_FALSE;
+}
+
void
nsCalculatedBoxInfo::clear()
{
diff --git a/layout/xul/base/src/nsBoxFrame.h b/layout/xul/base/src/nsBoxFrame.h
index a117eefdc503..236b32f6439c 100644
--- a/layout/xul/base/src/nsBoxFrame.h
+++ b/layout/xul/base/src/nsBoxFrame.h
@@ -42,8 +42,10 @@ public:
PRBool needsReflow;
PRBool needsRecalc;
PRBool collapsed;
+ PRBool isIncremental;
nsCalculatedBoxInfo();
+ nsCalculatedBoxInfo(const nsBoxInfo& aInfo);
virtual void clear();
};
@@ -56,7 +58,7 @@ public:
// nsIBox methods
NS_IMETHOD GetBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize);
- NS_IMETHOD Dirty(const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild);
+ NS_IMETHOD Dirty(const nsHTMLReflowState& aReflowState, nsIFrame*& aIncrementalChild);
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
@@ -73,6 +75,10 @@ public:
nsIAtom* aAttribute,
PRInt32 aHint);
+ NS_IMETHOD Paint ( nsIPresContext& aPresContext,
+ nsIRenderingContext& aRenderingContext,
+ const nsRect& aDirtyRect,
+ nsFramePaintLayer aWhichLayer);
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
@@ -113,47 +119,37 @@ protected:
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus,
- nsRect& availableSize,
- nsIFrame*& incrementalChild);
+ nsRect& availableSize);
virtual nsresult FlowChildAt(nsIFrame* frame,
nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus,
- nscoord spring,
- nsIFrame*& incrementalChild);
+ nsCalculatedBoxInfo& aInfo,
+ PRBool& needsRedraw,
+ nsString& aReason);
virtual nsresult PlaceChildren(nsRect& boxRect);
-
-
+ virtual void ChildResized(nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nsCalculatedBoxInfo& aInfo, PRBool* aResized, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex, nsString& aReason);
+ virtual void LayoutChildrenInRect(nsRect& size);
+ virtual void AddChildSize(nsBoxInfo& aInfo, nsBoxInfo& aChildInfo);
virtual void BoundsCheck(const nsBoxInfo& aBoxInfo, nsRect& aRect);
-
- /*
- virtual void GetDesiredSize(nsIPresContext* aPresContext,
- const nsHTMLReflowState& aReflowState,
- nsHTMLReflowMetrics& aDesiredSize);
- */
+ virtual void InvalidateChildren();
+ virtual void AddSize(const nsSize& a, nsSize& b, PRBool largest);
virtual PRIntn GetSkipSides() const { return 0; }
- virtual void GetInset(nsMargin& margin);
-
- virtual void LayoutChildrenInRect(nsRect& size);
-
- virtual void InvalidateChildren();
-
- virtual void AddSize(const nsSize& a, nsSize& b, PRBool largest);
-
+ virtual void GetInset(nsMargin& margin);
PRBool mHorizontal;
+ nsCalculatedBoxInfo mSprings[100];
+ nscoord mSpringCount;
private:
// XXX for the moment we can only handle 100 children.
// Should use a dynamic array.
- nsCalculatedBoxInfo mSprings[100];
- nscoord mSpringCount;
nsCOMPtr mSpaceManager; // We own this [OWNER].
PRUint32 mFlags;
diff --git a/layout/xul/base/src/nsDeckFrame.cpp b/layout/xul/base/src/nsDeckFrame.cpp
index b35d1b804380..7b6d3f7930f2 100644
--- a/layout/xul/base/src/nsDeckFrame.cpp
+++ b/layout/xul/base/src/nsDeckFrame.cpp
@@ -39,12 +39,8 @@
#include "nsIPresShell.h"
#include "nsStyleChangeList.h"
#include "nsCSSRendering.h"
+#include "nsIViewManager.h"
-/*
-void
-ApplyRenderingChangeToTree(nsIPresContext* aPresContext,
- nsIFrame* aFrame);
-*/
nsresult
NS_NewDeckFrame ( nsIFrame** aNewFrame )
@@ -62,13 +58,6 @@ NS_NewDeckFrame ( nsIFrame** aNewFrame )
} // NS_NewDeckFrame
-/*
-nsDeckFrame::nsDeckFrame()
-{
-}
-*/
-
-
NS_IMETHODIMP
nsDeckFrame::Init(nsIPresContext& aPresContext,
nsIContent* aContent,
@@ -77,8 +66,7 @@ nsDeckFrame::Init(nsIPresContext& aPresContext,
nsIFrame* aPrevInFlow)
{
// Get the element's tag
- nsresult rv = nsHTMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
- mSelectedChanged = PR_TRUE;
+ nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
return rv;
}
@@ -89,46 +77,13 @@ nsDeckFrame::AttributeChanged(nsIPresContext* aPresContext,
nsIAtom* aAttribute,
PRInt32 aHint)
{
- nsresult rv = nsHTMLContainerFrame::AttributeChanged(aPresContext, aChild,
+ nsresult rv = nsBoxFrame::AttributeChanged(aPresContext, aChild,
aAttribute, aHint);
// if the index changed hide the old element and make the now element visible
if (aAttribute == nsHTMLAtoms::value) {
- /*
- nsCOMPtr show ( getter_AddRefs(NS_NewAtom(":-moz-deck-showing")) );
- nsCOMPtr hide ( getter_AddRefs(NS_NewAtom(":-moz-deck-hidden")) );
-
- if (nsnull != mSelected)
- ForceResolveToPseudoElement(*aPresContext,mSelected, hide);
- */
-
- /*
- // reflow
- nsCOMPtr shell;
- aPresContext->GetShell(getter_AddRefs(shell));
-
- nsCOMPtr reflowCmd;
- nsresult rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), this,
- nsIReflowCommand::StyleChanged);
- if (NS_SUCCEEDED(rv))
- shell->AppendReflowCommand(reflowCmd);
- */
-
- /*
- if (nsnull != frame)
- {
- mSelected = frame;
- ForceResolveToPseudoElement(*aPresContext,mSelected, show);
- }
-*/
- // ApplyRenderingChangeToTree(aPresContext, this);
-
- /*
- nsRect rect(0, 0, mRect.width, mRect.height);
- Invalidate(rect, PR_TRUE);
- */
}
@@ -206,209 +161,6 @@ nsDeckFrame::Paint(nsIPresContext& aPresContext,
}
-NS_IMETHODIMP
-nsDeckFrame::Reflow(nsIPresContext& aPresContext,
- nsHTMLReflowMetrics& aDesiredSize,
- const nsHTMLReflowState& aReflowState,
- nsReflowStatus& aStatus)
-{
-
- // if there is incremental we need to tell all nsIBoxes below to blow away the
- // cached values for the children in the reflow list
- nsIFrame* incrementalChild = nsnull;
- if ( aReflowState.reason == eReflowReason_Incremental ) {
- Dirty(aReflowState,incrementalChild);
- }
-
- // get our available size
- nsSize availableSize(aReflowState.mComputedWidth,aReflowState.mComputedHeight);
-
- // if the width or height are intrinsic then lay us our children out at our preferred size
- if (aReflowState.mComputedWidth == NS_INTRINSICSIZE || aReflowState.mComputedHeight == NS_INTRINSICSIZE)
- {
- // get our size
- nsBoxInfo ourSize;
- GetBoxInfo(aPresContext, aReflowState, ourSize);
-
- if (aReflowState.mComputedWidth == NS_INTRINSICSIZE)
- availableSize.width = ourSize.prefSize.width;
-
- if (aReflowState.mComputedHeight == NS_INTRINSICSIZE)
- availableSize.height = ourSize.prefSize.height;
- }
-
- aDesiredSize.width = 0;
- aDesiredSize.height = 0;
-
- // iterate though each child
- PRBool finished = PR_FALSE;
- nsIFrame* changedChild = nsnull;
- int passes = 0;
-
- while(!finished)
- {
- finished = PR_TRUE;
- nscoord count = 0;
- nsIFrame* childFrame = mFrames.FirstChild();
- while (nsnull != childFrame)
- {
- // if we hit the child that cause us to do a second pass
- // then break.
- if (changedChild == childFrame)
- break;
-
- FlowChildAt(childFrame, aPresContext, aDesiredSize, aReflowState, aStatus, availableSize, incrementalChild);
-
- // if the area returned is greater than our size
- if (aDesiredSize.height > availableSize.height || aDesiredSize.width > availableSize.width)
- {
- // note the child that got bigger
- changedChild = childFrame;
-
- // set our size to be the new size
- if (aDesiredSize.width > availableSize.width)
- availableSize.width = aDesiredSize.width;
-
- if (aDesiredSize.height > availableSize.height)
- availableSize.height = aDesiredSize.height;
-
- // indicate we need to start another pass
- finished = PR_FALSE;
- }
-
- // get the next child
- nsresult rv = childFrame->GetNextSibling(&childFrame);
- count++;
- }
-
- // if we get over 10 passes something probably when wrong.
- passes++;
- if (passes > 5)
- NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
- ("DeckFrame reflow bug"));
-
- NS_ASSERTION(passes <= 10,"DeckFrame: Error infinte loop too many passes");
- }
-
- // return the largest dimension
- aDesiredSize.width = availableSize.width;
- aDesiredSize.height = availableSize.height;
-
- // add in our border
- const nsMargin& borderPadding = aReflowState.mComputedBorderPadding;
-
- aDesiredSize.width += borderPadding.left + borderPadding.right;
- aDesiredSize.height += borderPadding.top + borderPadding.bottom;
- aDesiredSize.ascent = aDesiredSize.height;
- aDesiredSize.descent = 0;
-
- return NS_OK;
-}
-
-nsresult
-nsDeckFrame::FlowChildAt(nsIFrame* childFrame,
- nsIPresContext& aPresContext,
- nsHTMLReflowMetrics& desiredSize,
- const nsHTMLReflowState& aReflowState,
- nsReflowStatus& aStatus,
- const nsSize& size,
- nsIFrame*& incrementalChild)
-{
-
- // subtract out the childs margin and border
- const nsStyleSpacing* spacing;
- nsresult rv = childFrame->GetStyleData(eStyleStruct_Spacing,
- (const nsStyleStruct*&) spacing);
-
- nsMargin margin;
- spacing->GetMargin(margin);
- nsMargin border;
- spacing->GetBorderPadding(border);
- nsMargin total = margin + border;
-
- const nsStylePosition* position;
- rv = childFrame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) position);
-
- nsReflowReason reason = aReflowState.reason;
- PRBool shouldReflow = PR_TRUE;
-
- // so if we are incremental and have already reflowed the incremental child or there is an incremental child
- // and its not this one make sure we change the reason to resize.
- if (reason == eReflowReason_Incremental && (nsnull == incrementalChild || incrementalChild != childFrame)) {
- reason = eReflowReason_Resize;
- nsRect currentSize;
- childFrame->GetRect(currentSize);
-
- if (currentSize.width > 0 && currentSize.height > 0)
- {
- desiredSize.width = currentSize.width;
- desiredSize.height = currentSize.height;
-
- if (currentSize.width == size.width && currentSize.height == size.height)
- shouldReflow = PR_FALSE;
- }
- }
-
- // ok now reflow the child into the springs calculated space
- if (shouldReflow) {
-
- desiredSize.width = 0;
- desiredSize.height = 0;
-
- // create a reflow state to tell our child to flow at the given size.
- nsHTMLReflowState reflowState(aPresContext, aReflowState, childFrame, nsSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE));
- reflowState.reason = reason;
-
- reflowState.mComputedWidth = size.width;
- reflowState.mComputedHeight = size.height;
-
- // only subrtact margin and border.
- reflowState.mComputedWidth -= (total.left + total.right);
- reflowState.mComputedHeight -= (total.top + total.bottom);
-
- nsSize maxElementSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
-
- // do the flow
- nsIHTMLReflow* htmlReflow;
-
- rv = childFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow);
- NS_ASSERTION(rv == NS_OK,"failed to get htmlReflow interface.");
-
- htmlReflow->WillReflow(aPresContext);
- htmlReflow->Reflow(aPresContext, desiredSize, reflowState, aStatus);
- NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
-
- // set the rect
- childFrame->SetRect(nsRect(aReflowState.mComputedBorderPadding.left,aReflowState.mComputedBorderPadding.top,desiredSize.width, desiredSize.height));
- }
-
- // add the margin back in. The child should add its border automatically
- desiredSize.height += (margin.top + margin.bottom);
- desiredSize.width += (margin.left + margin.right);
-
- return NS_OK;
-}
-
-
-/*
-NS_IMETHODIMP
-nsDeckFrame::HandleEvent(nsIPresContext& aPresContext,
- nsGUIEvent* aEvent,
- nsEventStatus& aEventStatus)
-{
-
- // send the event to the selected frame
- nsIFrame* selectedFrame = GetSelectedFrame();
-
- // if no selected frame we handle the event
- if (nsnull == selectedFrame)
- return nsHTMLContainerFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
-
- return selectedFrame->HandleEvent(aPresContext, aEvent, aEventStatus);
-}
-*/
-
NS_IMETHODIMP nsDeckFrame::GetFrameForPoint(const nsPoint& aPoint,
nsIFrame** aFrame)
{
@@ -435,48 +187,13 @@ NS_IMETHODIMP nsDeckFrame::GetFrameForPoint(const nsPoint& aPoint,
return NS_OK;
}
-/*
-NS_IMETHODIMP
-nsDeckFrame::SetInitialChildList(nsIPresContext& aPresContext,
- nsIAtom* aListName,
- nsIFrame* aChildList)
-{
- nsresult r = nsHTMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
-
- nsIFrame* frame = GetSelectedFrame();
-
- nsIFrame* childFrame = mFrames.FirstChild();
- while (nsnull != childFrame)
- {
- // if we hit the child that cause us to do a second pass
- // then break.
- if (childFrame != frame)
- {
- mSelected = frame;
- AddStyle(mSelected, gVisibleStyle);
- mSelected->ReResolveStyleContext(&aPresContext, mStyleContext,
- NS_STYLE_HINT_REFLOW,
- nsnull, nsnull);
- } else {
- RemoveStyle(mSelected, gHiddenStyle);
- mSelected->ReResolveStyleContext(&aPresContext, mStyleContext,
- NS_STYLE_HINT_REFLOW,
- nsnull, nsnull);
-
- }
- }
-
- return r;
-}
-*/
-
NS_IMETHODIMP
nsDeckFrame::SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
- nsresult r = nsHTMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
+ nsresult r = nsBoxFrame::SetInitialChildList(aPresContext, aListName, aChildList);
// now that all the children are added. ReResolve our children
// so we hide everything that is hidden in the deck
@@ -487,258 +204,30 @@ nsDeckFrame::SetInitialChildList(nsIPresContext& aPresContext,
}
-NS_IMETHODIMP
-nsDeckFrame::RemoveFrame(nsIPresContext& aPresContext,
- nsIPresShell& aPresShell,
- nsIAtom* aListName,
- nsIFrame* aOldFrame)
+
+void
+nsDeckFrame::AddChildSize(nsBoxInfo& aInfo, nsBoxInfo& aChildInfo)
{
- // remove the child frame
- nsresult rv = nsHTMLContainerFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame);
- mFrames.DestroyFrame(aPresContext, aOldFrame);
- return rv;
-}
+ // largest preferred size
+ if (aInfo.prefSize.width > aChildInfo.prefSize.width)
+ aChildInfo.prefSize.width = aInfo.prefSize.width;
-NS_IMETHODIMP
-nsDeckFrame::InsertFrames(nsIPresContext& aPresContext,
- nsIPresShell& aPresShell,
- nsIAtom* aListName,
- nsIFrame* aPrevFrame,
- nsIFrame* aFrameList)
-{
- mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
- return nsHTMLContainerFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList);
-}
+ if (aInfo.prefSize.height > aChildInfo.prefSize.height)
+ aChildInfo.prefSize.height = aInfo.prefSize.height;
-NS_IMETHODIMP
-nsDeckFrame::AppendFrames(nsIPresContext& aPresContext,
- nsIPresShell& aPresShell,
- nsIAtom* aListName,
- nsIFrame* aFrameList)
-{
- mFrames.AppendFrames(nsnull, aFrameList);
- return nsHTMLContainerFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList);
-}
+ // largest min size
+ if (aInfo.minSize.width > aChildInfo.minSize.width)
+ aChildInfo.minSize.width = aInfo.minSize.width;
-/**
- * Goes though each child asking for its size to determine our size. Returns our deck size minus our border.
- * This method is defined in nsIBox interface.
- */
-NS_IMETHODIMP
-nsDeckFrame::GetBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize)
-{
- nsresult rv;
+ if (aInfo.minSize.height > aChildInfo.minSize.height)
+ aChildInfo.minSize.height = aInfo.minSize.height;
- aSize.clear();
+ // smallest max size
+ if (aInfo.maxSize.width < aChildInfo.maxSize.width)
+ aChildInfo.maxSize.width = aInfo.maxSize.width;
- // run through all the children and get there min, max, and preferred sizes
- // return us the size of the deck
- nscoord count = 0;
- nsIFrame* childFrame = mFrames.FirstChild();
-
- while (nsnull != childFrame)
- {
- nsBoxInfo info;
- // get the size of the child. This is the min, max, preferred, and spring constant
- // it does not include its border.
- rv = GetChildBoxInfo(aPresContext, aReflowState, childFrame, info);
- NS_ASSERTION(rv == NS_OK,"failed to get child box info");
- if (NS_FAILED(rv))
- return rv;
-
- // add in the child's margin and border/padding if there is one.
- const nsStyleSpacing* spacing;
- nsresult rv = childFrame->GetStyleData(eStyleStruct_Spacing,
- (const nsStyleStruct*&) spacing);
-
- NS_ASSERTION(rv == NS_OK,"failed to get spacing info");
- if (NS_FAILED(rv))
- return rv;
-
- nsMargin margin;
- spacing->GetMargin(margin);
- nsSize m(margin.left+margin.right,margin.top+margin.bottom);
- info.minSize += m;
- info.prefSize += m;
-
- spacing->GetBorderPadding(margin);
- nsSize b(margin.left+margin.right,margin.top+margin.bottom);
- info.minSize += b;
- info.prefSize += b;
-
- // largest preferred size
- if (info.prefSize.width > aSize.prefSize.width)
- aSize.prefSize.width = info.prefSize.width;
-
- if (info.prefSize.height > aSize.prefSize.height)
- aSize.prefSize.height = info.prefSize.height;
-
- // largest min size
- if (info.minSize.width > aSize.minSize.width)
- aSize.minSize.width = info.minSize.width;
-
- if (info.minSize.height > aSize.minSize.height)
- aSize.minSize.height = info.minSize.height;
-
- // smallest max size
- if (info.maxSize.width < aSize.maxSize.width)
- aSize.maxSize.width = info.maxSize.width;
-
- if (info.maxSize.height < aSize.maxSize.height)
- aSize.maxSize.height = info.maxSize.height;
-
- rv = childFrame->GetNextSibling(&childFrame);
- NS_ASSERTION(rv == NS_OK,"failed to get next child");
- if (NS_FAILED(rv))
- return rv;
-
- count++;
- }
-
- return rv;
-}
-
-nsresult
-nsDeckFrame::GetChildBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame* aFrame, nsBoxInfo& aSize)
-{
- aSize.clear();
-
- // see if the frame implements IBox interface
- nsCOMPtr ibox = do_QueryInterface(aFrame);
-
- // if it does ask it for its BoxSize and we are done
- if (ibox) {
- ibox->GetBoxInfo(aPresContext, aReflowState, aSize);
- // add in the border, padding, width, min, max
- GetRedefinedMinPrefMax(aFrame, aSize);
- return NS_OK;
- } else {
- GetRedefinedMinPrefMax(aFrame, aSize);
- }
-
-
-
- // set the pref width and height to be intrinsic.
- aSize.prefWidthIntrinsic = PR_TRUE;
- aSize.prefHeightIntrinsic = PR_TRUE;;
-
- return NS_OK;
-}
-
-/**
- * Looks at the given frame and sees if its redefined preferred, min, or max sizes
- * if so it used those instead. Currently it gets its values from css
- */
-void
-nsDeckFrame::GetRedefinedMinPrefMax(nsIFrame* aFrame, nsBoxInfo& aSize)
-{
- // add in the css min, max, pref
- const nsStylePosition* position;
- nsresult rv = aFrame->GetStyleData(eStyleStruct_Position,
- (const nsStyleStruct*&) position);
-
- // see if the width or height was specifically set
- if (position->mWidth.GetUnit() == eStyleUnit_Coord) {
- aSize.prefSize.width = position->mWidth.GetCoordValue();
- aSize.prefWidthIntrinsic = PR_FALSE;
- }
-
- if (position->mHeight.GetUnit() == eStyleUnit_Coord) {
- aSize.prefSize.height = position->mHeight.GetCoordValue();
- aSize.prefHeightIntrinsic = PR_FALSE;
- }
-
- // same for min size. Unfortunately min size is always set to 0. So for now
- // we will assume 0 means not set.
- if (position->mMinWidth.GetUnit() == eStyleUnit_Coord) {
- nscoord min = position->mMinWidth.GetCoordValue();
- if (min != 0)
- aSize.minSize.width = min;
- }
-
- if (position->mMinHeight.GetUnit() == eStyleUnit_Coord) {
- nscoord min = position->mMinHeight.GetCoordValue();
- if (min != 0)
- aSize.minSize.height = min;
- }
-
- // and max
- if (position->mMaxWidth.GetUnit() == eStyleUnit_Coord) {
- nscoord max = position->mMaxWidth.GetCoordValue();
- aSize.maxSize.width = max;
- }
-
- if (position->mMaxHeight.GetUnit() == eStyleUnit_Coord) {
- nscoord max = position->mMaxHeight.GetCoordValue();
- aSize.maxSize.height = max;
- }
-}
-
-/**
- * Called with a reflow command. This will dirty all boxes who need to be reflowed.
- * return the last child that is not a box. Part of nsIBox interface.
- */
-NS_IMETHODIMP
-nsDeckFrame::Dirty(const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild)
-{
- incrementalChild = nsnull;
- nsresult rv = NS_OK;
-
- // Dirty any children that need it.
- nsIFrame* frame;
- aReflowState.reflowCommand->GetNext(frame);
- nscoord count = 0;
- nsIFrame* childFrame = mFrames.FirstChild();
- while (nsnull != childFrame)
- {
- if (childFrame == frame) {
- // clear the spring so it is recalculated on the flow
- nsCOMPtr ibox = do_QueryInterface(childFrame);
- if (ibox)
- ibox->Dirty(aReflowState, incrementalChild);
- else
- incrementalChild = frame;
- break;
- }
-
- rv = childFrame->GetNextSibling(&childFrame);
- NS_ASSERTION(rv == NS_OK,"failed to get next child");
- if (NS_FAILED(rv))
- return rv;
-
- count++;
- }
-
- return rv;
-}
-
-NS_IMETHODIMP nsDeckFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr)
-{
- if (NULL == aInstancePtr) {
- return NS_ERROR_NULL_POINTER;
- }
-
- *aInstancePtr = NULL;
-
- if (aIID.Equals(kIBoxIID)) {
- *aInstancePtr = (void*)(nsIBox*) this;
- NS_ADDREF_THIS();
- return NS_OK;
- }
-
- return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr);
-}
-
-NS_IMETHODIMP_(nsrefcnt)
-nsDeckFrame::AddRef(void)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP_(nsrefcnt)
-nsDeckFrame::Release(void)
-{
- return NS_OK;
+ if (aInfo.maxSize.height < aChildInfo.maxSize.height)
+ aChildInfo.maxSize.height = aInfo.maxSize.height;
}
NS_IMETHODIMP
@@ -830,3 +319,75 @@ nsDeckFrame :: ReResolveStyleContext ( nsIPresContext* aPresContext, nsIStyleCon
} // ReResolveStyleContext
+
+nsresult
+nsDeckFrame::PlaceChildren(nsRect& boxRect)
+{
+ // ------- set the childs positions ---------
+ nscoord x = boxRect.x;
+ nscoord y = boxRect.y;
+
+ nsIFrame* childFrame = mFrames.FirstChild();
+ nscoord count = 0;
+ while (nsnull != childFrame)
+ {
+ nsresult rv;
+
+ // make collapsed children not show up
+ if (mSprings[count].collapsed) {
+
+ childFrame->SetRect(nsRect(0,0,0,0));
+
+ // make the view really small as well
+ nsIView* view = nsnull;
+ childFrame->GetView(&view);
+
+ if (view) {
+ nsCOMPtr vm;
+ view->GetViewManager(*getter_AddRefs(vm));
+ vm->ResizeView(view, 0,0);
+ }
+
+ } else {
+ nsRect rect;
+ childFrame->MoveTo(rect.x, rect.y);
+ }
+
+ rv = childFrame->GetNextSibling(&childFrame);
+ NS_ASSERTION(rv == NS_OK,"failed to get next child");
+ count++;
+ }
+
+ return NS_OK;
+}
+
+void
+nsDeckFrame::ChildResized(nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nsCalculatedBoxInfo& aInfo, PRBool* aResized, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex, nsString& aReason)
+{
+ if (aDesiredSize.width > aRect.width) {
+ aRect.width = aDesiredSize.width;
+ InvalidateChildren();
+ LayoutChildrenInRect(aRect);
+ aReason = "child's width got bigger";
+ aChangedIndex = aIndex;
+ aFinished = PR_FALSE;
+ } else if (aDesiredSize.height > aRect.height) {
+ aRect.height = aDesiredSize.height;
+ InvalidateChildren();
+ LayoutChildrenInRect(aRect);
+ aReason = "child's height got bigger";
+ aChangedIndex = aIndex;
+ aFinished = PR_FALSE;
+ }
+}
+
+void
+nsDeckFrame::LayoutChildrenInRect(nsRect& size)
+{
+ for (int i=0; i shell;
aPresContext->GetShell(getter_AddRefs(shell));
@@ -704,6 +704,10 @@ nsTitledButtonFrame::Reflow(nsIPresContext& aPresContext,
{
mNeedsLayout = PR_TRUE;
nsresult result = nsLeafFrame::Reflow(aPresContext, aMetrics, aReflowState, aStatus);
+
+ // redraw us on a reflow
+ Invalidate(nsRect(0,0,mRect.width, mRect.height), PR_FALSE);
+
return result;
}