зеркало из https://github.com/mozilla/gecko-dev.git
Fixed boxes to only invalidate and redraw what has changed.
Made min and max sizes work Made linux not suck!
This commit is contained in:
Родитель
5f74f88c68
Коммит
b1c73fa7c7
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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<nsISpaceManager> mSpaceManager; // We own this [OWNER].
|
||||
PRUint32 mFlags;
|
||||
|
||||
|
|
|
@ -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<nsIAtom> show ( getter_AddRefs(NS_NewAtom(":-moz-deck-showing")) );
|
||||
nsCOMPtr<nsIAtom> hide ( getter_AddRefs(NS_NewAtom(":-moz-deck-hidden")) );
|
||||
|
||||
if (nsnull != mSelected)
|
||||
ForceResolveToPseudoElement(*aPresContext,mSelected, hide);
|
||||
*/
|
||||
|
||||
/*
|
||||
// reflow
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
aPresContext->GetShell(getter_AddRefs(shell));
|
||||
|
||||
nsCOMPtr<nsIReflowCommand> 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<nsIBox> 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<nsIBox> 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<nsIViewManager> 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<mSpringCount; i++) {
|
||||
mSprings[i].calculatedSize.width = size.width;
|
||||
mSprings[i].calculatedSize.height = size.height;
|
||||
mSprings[i].sizeValid = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,22 +28,15 @@
|
|||
#ifndef nsDeckFrame_h___
|
||||
#define nsDeckFrame_h___
|
||||
|
||||
#include "nsHTMLContainerFrame.h"
|
||||
#include "nsIBox.h"
|
||||
#include "nsBoxFrame.h"
|
||||
|
||||
class nsDeckFrame : public nsHTMLContainerFrame, public nsIBox
|
||||
class nsDeckFrame : public nsBoxFrame
|
||||
{
|
||||
public:
|
||||
|
||||
friend nsresult NS_NewDeckFrame(nsIFrame** aNewFrame);
|
||||
|
||||
NS_IMETHOD GetBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize);
|
||||
NS_IMETHOD Dirty(const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild);
|
||||
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
|
||||
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void);
|
||||
NS_IMETHOD_(nsrefcnt) Release(void);
|
||||
|
||||
|
||||
NS_IMETHOD ReResolveStyleContext ( nsIPresContext* aPresContext,
|
||||
nsIStyleContext* aParentContext,
|
||||
|
@ -63,42 +56,17 @@ public:
|
|||
nsIAtom* aAttribute,
|
||||
PRInt32 aHint);
|
||||
|
||||
|
||||
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
NS_IMETHOD Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect,
|
||||
nsFramePaintLayer aWhichLayer);
|
||||
|
||||
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList);
|
||||
|
||||
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList);
|
||||
|
||||
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame);
|
||||
|
||||
|
||||
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aChildList);
|
||||
|
||||
/*
|
||||
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus& aEventStatus);
|
||||
*/
|
||||
|
||||
NS_IMETHOD GetFrameForPoint(const nsPoint& aPoint,
|
||||
nsIFrame** aFrame);
|
||||
|
||||
|
@ -107,21 +75,16 @@ public:
|
|||
protected:
|
||||
|
||||
virtual nsIFrame* GetSelectedFrame();
|
||||
virtual nsresult GetChildBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame* aFrame, nsBoxInfo& aSize);
|
||||
virtual void GetRedefinedMinPrefMax(nsIFrame* aFrame, nsBoxInfo& aSize);
|
||||
virtual nsresult FlowChildAt(nsIFrame* frame,
|
||||
nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
const nsSize& size,
|
||||
nsIFrame*& incrementalChild);
|
||||
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);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
nsIFrame* mSelected;
|
||||
PRBool mSelectedChanged;
|
||||
|
||||
}; // class nsDeckFrame
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ nsTitledButtonFrame::AttributeChanged(nsIPresContext* aPresContext,
|
|||
mNeedsLayout = PR_TRUE;
|
||||
UpdateAttributes(*aPresContext);
|
||||
|
||||
#if 0
|
||||
#if 1 // added back in because boxes now handle only redraw what is reflowed.
|
||||
// reflow
|
||||
nsCOMPtr<nsIPresShell> 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;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче