diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index d39f5853c56..aab2aa97287 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -360,14 +360,16 @@ NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsIPresContext& aPresConte } PRInt32 rowHeight = 0; - nsSize calcSize; + nsSize desiredSize; + nsSize minSize; PRBool widthExplicit, heightExplicit; nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, nsnull, maxWidth, PR_TRUE, nsHTMLAtoms::size, 1); // XXX fix CalculateSize to return PRUint32 - PRUint32 numRows = (PRUint32)nsFormControlHelper::CalculateSize(&aPresContext, this, styleSize, textSpec, - calcSize, widthExplicit, heightExplicit, rowHeight, - aReflowState.rendContext); + PRUint32 numRows = + (PRUint32)nsFormControlHelper::CalculateSize(&aPresContext, aReflowState.rendContext, this, + styleSize, textSpec, desiredSize, minSize, + widthExplicit, heightExplicit, rowHeight); float sp2t; float p2t; @@ -380,23 +382,12 @@ NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsIPresContext& aPresConte nscoord scrollbarHeight = 0; nsListControlFrame::GetScrollBarDimensions(aPresContext, scrollbarWidth, scrollbarHeight); - nscoord extra = calcSize.height - (rowHeight * numRows); + nscoord extra = desiredSize.height - (rowHeight * numRows); numRows = (numOptions > 20 ? 20 : numOptions); - calcSize.height = (numRows * rowHeight) + extra; - if (numRows < 21) { - //calcSize.width += scrollbarWidth; - } - - /*aDesiredSize.width = calcSize.width; - // account for vertical scrollbar, if present - if (!widthExplicit && (numRows < (PRInt32)numOptions)) { - aDesiredSize.width += scrollbarWidth; - } -*/ + desiredSize.height = (numRows * rowHeight) + extra; aDesiredSize.descent = 0; - nsMargin border; const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); mySpacing->CalcBorderFor(this, border); @@ -416,21 +407,22 @@ NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsIPresContext& aPresConte sis.mFont = &font; context->GetSystemAttribute(eSystemAttr_Font_Tooltips, &sis); - nscoord adjustment = NSIntPixelsToTwips(14, p2t); + nscoord horKludgeAdjustment = NSIntPixelsToTwips(14, p2t); + nscoord horAdjustment = scrollbarScaledWidth + border.left + border.right + horKludgeAdjustment; - aDesiredSize.width = calcSize.width + scrollbarScaledWidth + border.left + border.right + adjustment; - aDesiredSize.height = rowHeight + onePixel; - aDesiredSize.height = rowHeight + onePixel; + aDesiredSize.width = desiredSize.width + horAdjustment; + + nscoord verKludgeAdjustment = onePixel; + nscoord verAdjustment = border.top + border.bottom + verKludgeAdjustment; + + aDesiredSize.height = rowHeight + verAdjustment; mButtonRect.SetRect(aDesiredSize.width-scrollbarScaledWidth-border.right, border.top, scrollbarScaledWidth, aDesiredSize.height); - desiredSize = aDesiredSize; - aDesiredSize.height += border.top + border.bottom; - if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.maxElementSize->width = aDesiredSize.width; - aDesiredSize.maxElementSize->height = aDesiredSize.height; + aDesiredSize.maxElementSize->width = minSize.width + verAdjustment; + aDesiredSize.maxElementSize->height = minSize.height + horAdjustment; } diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp index d4832bc6524..733c20ade43 100644 --- a/layout/forms/nsFieldSetFrame.cpp +++ b/layout/forms/nsFieldSetFrame.cpp @@ -79,7 +79,6 @@ public: protected: - void SetMaxElementSize(nsSize& maxSize, nsSize* aSize); virtual PRIntn GetSkipSides() const; //virtual void GetDesiredSize(nsIPresContext* aPresContext, // const nsReflowState& aReflowState, @@ -228,27 +227,55 @@ nsFieldSetFrame::Paint(nsIPresContext& aPresContext, return NS_OK; } -void -nsFieldSetFrame::SetMaxElementSize(nsSize& maxSize, nsSize* aSize) +// XXX a hack until the reflow state does this correctly +// XXX when it gets fixed, leave in the printf statements or add an assertion +void FieldSetHack(nsHTMLReflowState& aReflowState, char* aMessage, PRBool aUseMax) { - if (aSize) { - maxSize.width = (maxSize.width >= aSize->width) ? maxSize.width : aSize->width; - maxSize.height = (maxSize.height >= aSize->width) ? maxSize.height : aSize->height; + if (aReflowState.computedWidth == 0) { + aReflowState.computedWidth = aReflowState.availableWidth; + } + if ((aReflowState.computedWidth != NS_INTRINSICSIZE) && + (aReflowState.availableWidth > 0)) { +// printf("BUG - %s has a computed width = %d, available width = %d \n", +// aMessage, aReflowState.computedWidth, aReflowState.availableWidth); + if (aUseMax) { + aReflowState.computedWidth = PR_MAX(aReflowState.computedWidth,aReflowState.availableWidth); + } else { + aReflowState.computedWidth = PR_MIN(aReflowState.computedWidth,aReflowState.availableWidth); + } + } + if (aReflowState.computedHeight == 0) { + aReflowState.computedHeight = aReflowState.availableHeight; + } + if ((aReflowState.computedHeight != NS_INTRINSICSIZE) && + (aReflowState.availableHeight > 0)) { +// printf("BUG - %s has a computed height = %d, available height = %d \n", +// aMessage, aReflowState.computedHeight, aReflowState.availableHeight); + if (aUseMax) { + aReflowState.computedHeight = PR_MAX(aReflowState.computedHeight,aReflowState.availableHeight); + } else { + aReflowState.computedHeight = PR_MIN(aReflowState.computedHeight,aReflowState.availableHeight); + } } } + // XXX currently only supports legend align=left,center,right -#define MIN_TOP_BORDER 10 +#define DESIRED_LEGEND_OFFSET 10 NS_IMETHODIMP -nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, - nsHTMLReflowMetrics& aDesiredSize, +nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) + nsReflowStatus& aStatus) { - nsSize availSize(aReflowState.availableWidth, aReflowState.availableWidth); + // XXX remove the following when the reflow state is fixed + FieldSetHack((nsHTMLReflowState&)aReflowState, "fieldset", PR_TRUE); + // availSize could have unconstrained values, don't perform any addition on them + nsSize availSize(aReflowState.computedWidth, aReflowState.computedHeight); + float p2t; aPresContext.GetScaledPixelsToTwips(&p2t); - const PRInt32 minTopBorder = NSIntPixelsToTwips(MIN_TOP_BORDER, p2t); + const PRInt32 desiredLegendOffset = NSIntPixelsToTwips(DESIRED_LEGEND_OFFSET, p2t); const nsStyleSpacing* spacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); @@ -275,25 +302,18 @@ nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, } // reduce available space by border, padding, etc. if we're in a constrained situation - nscoord horTaken = borderPadding.left + borderPadding.right + (2 * minTopBorder) + - legendMargin.left + legendMargin.right; + nscoord horTaken = borderPadding.left + borderPadding.right + legendMargin.left + legendMargin.right; nscoord verTaken = padding.top + borderPadding.bottom + legendMargin.top + legendMargin.bottom; - if (aReflowState.HaveFixedContentWidth()) { - availSize.width = aReflowState.computedWidth; + + if (NS_INTRINSICSIZE != availSize.width) { + availSize.width -= horTaken; + availSize.width = PR_MAX(availSize.width,0); } - else { - if (NS_UNCONSTRAINEDSIZE != availSize.width) - availSize.width -= horTaken; - } - if (NS_UNCONSTRAINEDSIZE != availSize.height) { + if (NS_AUTOHEIGHT != availSize.height) { // XXX this assumes that the legend is taller than the top border width availSize.height -= verTaken; - if (mInline) { // XXX parents don't account for inline top, bottom margins yet - availSize.height -= margin.top; - } + availSize.height = PR_MAX(availSize.height,0); } - if (availSize.height < 0) - availSize.height = 1; nsSize maxElementSize(0,0); @@ -302,37 +322,45 @@ nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, if (mLegendFrame) { nsHTMLReflowState legendReflowState(aPresContext, mLegendFrame, aReflowState, availSize); + // XXX remove when reflow state is fixed + FieldSetHack((nsHTMLReflowState&)legendReflowState, "fieldset's legend", PR_FALSE); ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, aStatus); legendSize.width = aDesiredSize.width; legendSize.height = aDesiredSize.height; // The legend didn't fit - if ((NS_UNCONSTRAINEDSIZE != availSize.width) && + if ((NS_INTRINSICSIZE != availSize.width) && (availSize.width < aDesiredSize.width + legendMargin.left + legendMargin.right)) { availSize.width = aDesiredSize.width + horTaken; } - if ((NS_UNCONSTRAINEDSIZE != availSize.height) && (availSize.height < aDesiredSize.height)) { - availSize.height = 0; - } else if (NS_UNCONSTRAINEDSIZE != availSize.height) { - availSize.height -= aDesiredSize.height; + if (NS_AUTOHEIGHT != availSize.height) { + if (availSize.height < aDesiredSize.height) { + availSize.height = 0; + } else { + availSize.height -= aDesiredSize.height; + } + } + if (aDesiredSize.maxElementSize) { + maxElementSize.width = aDesiredSize.maxElementSize->width; + maxElementSize.height = aDesiredSize.maxElementSize->height; } - SetMaxElementSize(maxElementSize, aDesiredSize.maxElementSize); } PRBool needAnotherLegendReflow = PR_FALSE; - // Try to reflow the content frame into the available space. It might not fit - nsSize contentSize(0,0); + // Try to reflow the area frame into the available space. It might not fit nsHTMLReflowState contentReflowState(aPresContext, mContentFrame, aReflowState, availSize); + // XXX remove when reflow state is fixed + FieldSetHack(contentReflowState, "fieldset's area", PR_FALSE); + nscoord contentTopOffset = (legendSize.height > border.top) - ? legendSize.height + padding.top - : border.top + padding.top; + ? legendSize.height + padding.top + : border.top + padding.top; ReflowChild(mContentFrame, aPresContext, aDesiredSize, contentReflowState, aStatus); - contentSize.width = aDesiredSize.width; - contentSize.height = aDesiredSize.height; + nsSize contentSize(aDesiredSize.width, aDesiredSize.height); // The content didn't fit if ((NS_UNCONSTRAINEDSIZE != availSize.width) && (availSize.width < aDesiredSize.width)) { @@ -342,51 +370,67 @@ nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, if ((NS_UNCONSTRAINEDSIZE != availSize.height) && (availSize.height < aDesiredSize.height)) { needAnotherLegendReflow = PR_TRUE; } - SetMaxElementSize(maxElementSize, aDesiredSize.maxElementSize); + if (aDesiredSize.maxElementSize) { + aDesiredSize.maxElementSize->width = PR_MAX(aDesiredSize.maxElementSize->width,maxElementSize.width); + maxElementSize.height += aDesiredSize.maxElementSize->height; + } // need to reflow the legend a 2nd time if (needAnotherLegendReflow && mLegendFrame) { nsHTMLReflowState legendReflowState(aPresContext, mLegendFrame, aReflowState, availSize); + // XXX remove when reflow state is fixed + FieldSetHack(legendReflowState, "fieldset's legend frame", PR_FALSE); ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, aStatus); legendSize.width = aDesiredSize.width; legendSize.height = aDesiredSize.height; } - nscoord legendWidth = legendSize.width + border.left + border.right + (2 * minTopBorder); + nscoord legendWidth = legendSize.width + border.left + border.right; nscoord contentWidth = contentSize.width + borderPadding.left + borderPadding.right; + PRBool legendOffsetFits = PR_TRUE; // can the legend be offset by the 10 pixels + aDesiredSize.width = (legendWidth > contentWidth) ? legendWidth : contentWidth; - if (aReflowState.HaveFixedContentWidth() && (aReflowState.computedWidth > aDesiredSize.width)) { - aDesiredSize.width = aReflowState.computedWidth; + + // if we are constrained and the child is smaller, use the constrained values + //if ((NS_INTRINSICSIZE != aReflowState.computedWidth) && + // (aReflowState.computedWidth > aDesiredSize.width)) { + // aDesiredSize.width = aReflowState.computedWidth; + //} + + if ((NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) && + ( (legendWidth + (2 * desiredLegendOffset)) > aDesiredSize.width) ) { + legendOffsetFits = PR_FALSE; } // Place the legend nsRect legendRect(0, 0, 0, 0); contentTopOffset = border.top + padding.top; - if (mInline) // XXX parents don't handle inline top, bottom margins - contentTopOffset += margin.top; if (mLegendFrame) { nscoord legendTopOffset; if (legendSize.height > border.top) { - legendTopOffset = (mInline) ? margin.top : 0; // XXX parents don't ....... + legendTopOffset = 0; } else { legendTopOffset = (border.top - legendSize.height) / 2; - if (mInline) // XXX parents don't ...... - legendTopOffset += margin.top; } contentTopOffset = legendTopOffset + legendSize.height + padding.top; nscoord legendLeftOffset = 0; PRInt32 align = ((nsLegendFrame*)mLegendFrame)->GetAlign(); + // if there isn't room for the 10 pixel left/right offset, align center + if (!legendOffsetFits) { + align = NS_STYLE_TEXT_ALIGN_CENTER; + } + switch(align) { case NS_STYLE_TEXT_ALIGN_LEFT: - legendLeftOffset = border.left + minTopBorder; + legendLeftOffset = border.left + desiredLegendOffset; break; case NS_STYLE_TEXT_ALIGN_RIGHT: - legendLeftOffset = aDesiredSize.width - border.right - minTopBorder - legendSize.width; + legendLeftOffset = aDesiredSize.width - border.right - desiredLegendOffset - legendSize.width; break; // XXX The spec specifies center and top but we are following IE4's lead and making left // be the upper left and right be the upper right. IE4 introduced center which is not part @@ -406,30 +450,28 @@ nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, // cache values so the border will be painted around the vertical center of the legend mTopBorderOffset = legendSize.height / 2; - if (mInline) // XXX parents don't yet ..... - mTopBorderOffset += margin.top; mTopBorderGap = nsRect(legendLeftOffset, legendTopOffset, legendSize.width + legendMargin.left + legendMargin.right, legendSize.height + legendMargin.top + legendMargin.bottom); } - // Place the content frame + // Place the content area frame nsRect contentRect(borderPadding.left, contentTopOffset, contentSize.width, contentSize.height); mContentFrame->SetRect(contentRect); // Return our size and our result - aDesiredSize.height = contentTopOffset + contentSize.height + borderPadding.bottom; - if (mInline) // XXX parents don't yet ...... - aDesiredSize.height += margin.bottom; - if (aReflowState.HaveFixedContentHeight() && (aReflowState.computedHeight > aDesiredSize.height)) { - aDesiredSize.height = aReflowState.computedHeight; - } + aDesiredSize.height = contentTopOffset + legendSize.height + contentSize.height + borderPadding.bottom; + + // if we are constrained and the child is smaller, use the constrained values + //if ((NS_AUTOHEIGHT != aReflowState.computedHeight) && (aReflowState.computedHeight > aDesiredSize.height)) { + // aDesiredSize.height = aReflowState.computedHeight; + //} aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); aDesiredSize.maxElementSize->width = maxElementSize.width; aDesiredSize.maxElementSize->height = maxElementSize.height; + aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); } aStatus = NS_FRAME_COMPLETE; diff --git a/layout/forms/nsFormControlFrame.cpp b/layout/forms/nsFormControlFrame.cpp index 77aaa107484..3aa6d3aa4aa 100644 --- a/layout/forms/nsFormControlFrame.cpp +++ b/layout/forms/nsFormControlFrame.cpp @@ -322,9 +322,7 @@ nsFormControlFrame::Reflow(nsIPresContext& aPresContext, aDesiredSize.descent = 0; if (nsnull != aDesiredSize.maxElementSize) { -//XXX aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); - aDesiredSize.maxElementSize->width = aDesiredSize.width; - aDesiredSize.maxElementSize->height = aDesiredSize.height; + //XXX aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); } aStatus = NS_FRAME_COMPLETE; diff --git a/layout/forms/nsFormControlFrame.h b/layout/forms/nsFormControlFrame.h index f5498ef817d..68efc165723 100644 --- a/layout/forms/nsFormControlFrame.h +++ b/layout/forms/nsFormControlFrame.h @@ -40,7 +40,7 @@ class nsFormFrame; // using GFX calls, rather than creating a widget. Undefining it // causes widgets to be used for form elements. @see RequiresWidget method // to see which widgets will obey this directive. -#define NS_GFX_RENDER_FORM_ELEMENTS +//#define NS_GFX_RENDER_FORM_ELEMENTS /** * nsFormControlFrame is the base class for frames of form controls. It diff --git a/layout/forms/nsFormControlHelper.cpp b/layout/forms/nsFormControlHelper.cpp index f59759c15ac..501a1dbf99c 100644 --- a/layout/forms/nsFormControlHelper.cpp +++ b/layout/forms/nsFormControlHelper.cpp @@ -174,19 +174,25 @@ nsFormControlHelper::GetTextSize(nsIPresContext& aPresContext, nsIFormControlFra } PRInt32 -nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, nsIFormControlFrame* aFrame, - const nsSize& aCSSSize, nsInputDimensionSpec& aSpec, - nsSize& aBounds, PRBool& aWidthExplicit, - PRBool& aHeightExplicit, nscoord& aRowHeight, - nsIRenderingContext *aRendContext) +nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, + nsIRenderingContext* aRendContext, + nsIFormControlFrame* aFrame, + const nsSize& aCSSSize, + nsInputDimensionSpec& aSpec, + nsSize& aDesiredSize, + nsSize& aMinSize, + PRBool& aWidthExplicit, + PRBool& aHeightExplicit, + nscoord& aRowHeight) { - nscoord charWidth = 0; + nscoord charWidth = 0; + nscoord charHeight = 0; PRInt32 numRows = ATTR_NOTSET; aWidthExplicit = PR_FALSE; aHeightExplicit = PR_FALSE; - aBounds.width = CSS_NOTSET; - aBounds.height = CSS_NOTSET; + aDesiredSize.width = CSS_NOTSET; + aDesiredSize.height = CSS_NOTSET; nsSize textSize(0,0); nsIContent* iContent = nsnull; @@ -213,45 +219,63 @@ nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, nsIFormControl float p2t; aPresContext->GetScaledPixelsToTwips(&p2t); - // determine the width - nscoord adjSize; +#if 0 + // determine if it is percentage based width, height + PRBool percentageWidth = PR_FALSE; + PRBool percentageHeight = PR_FALSE; + + const nsStylePosition* pos; + nsIFrame* iFrame = nsnull; + nsresult rv = aFrame->QueryInterface(kIFrameIID, (void**)&iFrame); + if ((NS_OK == rv) && (nsnull != iFrame)) { + iFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)pos); + if (eStyleUnit_Percent == pos->mWidth.GetUnit()) { + percentageWidth = PR_TRUE; + } + if (eStyleUnit_Percent == pos->mWidth.GetUnit()) { + percentageHeight = PR_TRUE; + } + } +#endif + // determine the width, char height, row height if (NS_CONTENT_ATTR_HAS_VALUE == colStatus) { // col attr will provide width PRInt32 col = ((colAttr.GetUnit() == eHTMLUnit_Pixel) ? colAttr.GetPixelValue() : colAttr.GetIntValue()); if (aSpec.mColSizeAttrInPixels) { - col = (col <= 0) ? 15 : col; - aBounds.width = NSIntPixelsToTwips(col, p2t); - } - else { - col = (col <= 0) ? 1 : col; - charWidth = GetTextSize(*aPresContext, aFrame, col, aBounds, aRendContext); - aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET + // need to set charWidth and aDesiredSize.height + charWidth = GetTextSize(*aPresContext, aFrame, 1, aDesiredSize, aRendContext); + col = (col <= 0) ? 15 : col; // XXX why a default of 15 pixels, why hide it + aDesiredSize.width = NSIntPixelsToTwips(col, p2t); + } else { + col = (col <= 0) ? 1 : col; // XXX why a default of 1 char, why hide it + charWidth = GetTextSize(*aPresContext, aFrame, col, aDesiredSize, aRendContext); } if (aSpec.mColSizeAttrInPixels) { aWidthExplicit = PR_TRUE; } - } - else { + aMinSize.width = aDesiredSize.width; + } else { + // set aDesiredSize for height calculation below. CSS may override width + if (NS_CONTENT_ATTR_HAS_VALUE == valStatus) { // use width of initial value + charWidth = GetTextSize(*aPresContext, aFrame, valAttr, aDesiredSize, aRendContext); + } else if (aSpec.mColDefaultValue) { // use default value + charWidth = GetTextSize(*aPresContext, aFrame, *aSpec.mColDefaultValue, aDesiredSize, aRendContext); + } else if (aSpec.mColDefaultSizeInPixels) { // use default width in pixels + charWidth = GetTextSize(*aPresContext, aFrame, 1, aDesiredSize, aRendContext); + aDesiredSize.width = aSpec.mColDefaultSize; + } else { // use default width in num characters + charWidth = GetTextSize(*aPresContext, aFrame, aSpec.mColDefaultSize, aDesiredSize, aRendContext); + } + aMinSize.width = aDesiredSize.width; if (CSS_NOTSET != aCSSSize.width) { // css provides width - aBounds.width = (aCSSSize.width > 0) ? aCSSSize.width : 1; - aWidthExplicit = PR_TRUE; - } - else { - if (NS_CONTENT_ATTR_HAS_VALUE == valStatus) { // use width of initial value - charWidth = GetTextSize(*aPresContext, aFrame, valAttr, aBounds, aRendContext); + NS_ASSERTION(aCSSSize.width > 0, "form control's computed width is <= 0"); + if (NS_INTRINSICSIZE != aCSSSize.width) { + aDesiredSize.width = PR_MAX(aDesiredSize.width,aCSSSize.width); + aWidthExplicit = PR_TRUE; } - else if (aSpec.mColDefaultValue) { // use default value - charWidth = GetTextSize(*aPresContext, aFrame, *aSpec.mColDefaultValue, aBounds, aRendContext); - } - else if (aSpec.mColDefaultSizeInPixels) { // use default width in pixels - charWidth = GetTextSize(*aPresContext, aFrame, 1, aBounds, aRendContext); - aBounds.width = aSpec.mColDefaultSize; - } - else { // use default width in num characters - charWidth = GetTextSize(*aPresContext, aFrame, aSpec.mColDefaultSize, aBounds, aRendContext); - } - aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET } } + aRowHeight = aDesiredSize.height; + aMinSize.height = aDesiredSize.height; // determine the height nsHTMLValue rowAttr; @@ -260,52 +284,40 @@ nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, nsIFormControl rowStatus = hContent->GetHTMLAttribute(aSpec.mRowSizeAttr, rowAttr); } if (NS_CONTENT_ATTR_HAS_VALUE == rowStatus) { // row attr will provide height - PRInt32 rowAttrInt = ((rowAttr.GetUnit() == eHTMLUnit_Pixel) ? rowAttr.GetPixelValue() : rowAttr.GetIntValue()); - adjSize = (rowAttrInt > 0) ? rowAttrInt : 1; - if (0 == charWidth) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); - aBounds.height = textSize.height * adjSize; - aRowHeight = textSize.height; - numRows = adjSize; + PRInt32 rowAttrInt = ((rowAttr.GetUnit() == eHTMLUnit_Pixel) + ? rowAttr.GetPixelValue() : rowAttr.GetIntValue()); + numRows = (rowAttrInt > 0) ? rowAttrInt : 1; + aDesiredSize.height = aDesiredSize.height * numRows; + } else { + aDesiredSize.height = aDesiredSize.height * aSpec.mRowDefaultSize; + if (CSS_NOTSET != aCSSSize.height) { // css provides height + NS_ASSERTION(aCSSSize.height > 0, "form control's computed height is <= 0"); + if (NS_INTRINSICSIZE != aCSSSize.height) { + aDesiredSize.height = PR_MAX(aDesiredSize.height,aCSSSize.height); + aHeightExplicit = PR_TRUE; + } } - else { - aBounds.height = aBounds.height * adjSize; - } - } - else if (CSS_NOTSET != aCSSSize.height) { // css provides height - aBounds.height = (aCSSSize.height > 0) ? aCSSSize.height : 1; - aHeightExplicit = PR_TRUE; - } - else { // use default height in num lines - if (0 == charWidth) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); - aBounds.height = textSize.height * aSpec.mRowDefaultSize; - aRowHeight = textSize.height; - } - else { - aBounds.height = aBounds.height * aSpec.mRowDefaultSize; - } - } - - if ((0 == charWidth) || (0 == textSize.width)) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); - aRowHeight = textSize.height; } // add inside padding if necessary if (!aWidthExplicit) { - aBounds.width += (2 * aFrame->GetHorizontalInsidePadding(*aPresContext, p2t, aBounds.width, charWidth)); + PRInt32 hPadding = (2 * aFrame->GetHorizontalInsidePadding(*aPresContext, p2t, aDesiredSize.width, charWidth)); + aDesiredSize.width += hPadding; + aMinSize.width += hPadding; } if (!aHeightExplicit) { - aBounds.height += (2 * aFrame->GetVerticalInsidePadding(p2t, textSize.height)); + PRInt32 vPadding = (2 * aFrame->GetVerticalInsidePadding(p2t, aRowHeight)); + aDesiredSize.height += vPadding; + aMinSize.height += vPadding; } NS_RELEASE(hContent); if (ATTR_NOTSET == numRows) { - numRows = aBounds.height / aRowHeight; + numRows = aDesiredSize.height / aRowHeight; } NS_RELEASE(iContent); + return numRows; } diff --git a/layout/forms/nsFormControlHelper.h b/layout/forms/nsFormControlHelper.h index 680aacef7e4..8428a8523ff 100644 --- a/layout/forms/nsFormControlHelper.h +++ b/layout/forms/nsFormControlHelper.h @@ -90,13 +90,16 @@ class nsFormControlHelper public: - static nscoord CalculateSize (nsIPresContext* aPresContext, nsIFormControlFrame* aFrame, - const nsSize& aCSSSize, nsInputDimensionSpec& aDimensionSpec, - nsSize& aBounds, PRBool& aWidthExplicit, - PRBool& aHeightExplicit, nscoord& aRowSize, - nsIRenderingContext *aRendContext); - - + static nscoord CalculateSize (nsIPresContext* aPresContext, + nsIRenderingContext* aRendContext, + nsIFormControlFrame* aFrame, + const nsSize& aCSSSize, + nsInputDimensionSpec& aDimensionSpec, + nsSize& aDesiredSize, + nsSize& aMinSize, + PRBool& aWidthExplicit, + PRBool& aHeightExplicit, + nscoord& aRowSize); static nscoord GetTextSize(nsIPresContext& aContext, nsIFormControlFrame* aFrame, const nsString& aString, nsSize& aSize, diff --git a/layout/forms/nsHTMLButtonControlFrame.cpp b/layout/forms/nsHTMLButtonControlFrame.cpp index a8e7ae752d0..a282940bf84 100644 --- a/layout/forms/nsHTMLButtonControlFrame.cpp +++ b/layout/forms/nsHTMLButtonControlFrame.cpp @@ -603,12 +603,40 @@ nsHTMLButtonControlFrame::Paint(nsIPresContext& aPresContext, return result; } +// XXX a hack until the reflow state does this correctly +// XXX when it gets fixed, leave in the printf statements or add an assertion +void ButtonHack(nsHTMLReflowState& aReflowState, char* aMessage) +{ + if (aReflowState.computedWidth == 0) { + aReflowState.computedWidth = aReflowState.availableWidth; + } + if ((aReflowState.computedWidth != NS_INTRINSICSIZE) && + (aReflowState.computedWidth > aReflowState.availableWidth) && + (aReflowState.availableWidth > 0)) { +// printf("BUG - %s has a computed width = %d, available width = %d \n", +// aMessage, aReflowState.computedWidth, aReflowState.availableWidth); + aReflowState.computedWidth = aReflowState.availableWidth; + } + if (aReflowState.computedHeight == 0) { + aReflowState.computedHeight = aReflowState.availableHeight; + } + if ((aReflowState.computedHeight != NS_INTRINSICSIZE) && + (aReflowState.computedHeight > aReflowState.availableHeight) && + (aReflowState.availableHeight > 0)) { +// printf("BUG - %s has a computed height = %d, available height = %d \n", +// aMessage, aReflowState.computedHeight, aReflowState.availableHeight); + aReflowState.computedHeight = aReflowState.availableHeight; + } +} + NS_IMETHODIMP nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + // XXX remove the following when the reflow state is fixed + ButtonHack((nsHTMLReflowState&)aReflowState, "html4 button"); if (!mDidInit) { // create our view, we need a view to grab the mouse nsIView* view; @@ -640,8 +668,26 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, // reflow the child nsIFrame* firstKid = mFrames.FirstChild(); - nsSize availSize(aReflowState.availableWidth, aReflowState.availableHeight); + nsSize availSize(aReflowState.computedWidth, aReflowState.computedHeight); + + // get border and padding + const nsStyleSpacing* spacing = + (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); + nsMargin borderPadding; + spacing->CalcBorderPaddingFor(this, borderPadding); + + if (NS_INTRINSICSIZE != availSize.width) { + availSize.width -= borderPadding.left + borderPadding.right; + availSize.width = PR_MAX(availSize.width,0); + } + if (NS_AUTOHEIGHT != availSize.height) { + availSize.height -= borderPadding.top + borderPadding.bottom; + availSize.height = PR_MAX(availSize.height,0); + } + nsHTMLReflowState reflowState(aPresContext, firstKid, aReflowState, availSize); + // XXX remove the following when the reflow state is fixed + ButtonHack(reflowState, "html4 button's area"); // XXX Proper handling of incremental reflow... if (eReflowReason_Incremental == aReflowState.reason) { @@ -663,12 +709,6 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, aStatus); - // get border and padding - const nsStyleSpacing* spacing = - (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); - nsMargin borderPadding; - spacing->CalcBorderPaddingFor(this, borderPadding); - // Place the child nsRect rect = nsRect(borderPadding.left, borderPadding.top, aDesiredSize.width, aDesiredSize.height); firstKid->SetRect(rect); @@ -677,18 +717,18 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, aDesiredSize.width += borderPadding.left + borderPadding.right; aDesiredSize.height += borderPadding.top + borderPadding.bottom; - // adjust our max element size, if necessary + //adjust our max element size, if necessary if (aDesiredSize.maxElementSize) { aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); } // if we are constrained and the child is smaller, use the constrained values - if (aReflowState.HaveFixedContentWidth() && (aDesiredSize.width < aReflowState.computedWidth)) { - aDesiredSize.width = aReflowState.computedWidth; - } - if (aReflowState.HaveFixedContentHeight() && (aDesiredSize.height < aReflowState.computedHeight)) { - aDesiredSize.height = aReflowState.computedHeight; - } + //if (aReflowState.HaveFixedContentWidth() && (aDesiredSize.width < aReflowState.computedWidth)) { + // aDesiredSize.width = aReflowState.computedWidth; + //} + //if (aReflowState.HaveFixedContentHeight() && (aDesiredSize.height < aReflowState.computedHeight)) { + // aDesiredSize.height = aReflowState.computedHeight; + //} aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; diff --git a/layout/forms/nsLegendFrame.cpp b/layout/forms/nsLegendFrame.cpp index a8893542509..aa4b1463cfd 100644 --- a/layout/forms/nsLegendFrame.cpp +++ b/layout/forms/nsLegendFrame.cpp @@ -120,19 +120,41 @@ nsLegendFrame::Paint(nsIPresContext& aPresContext, return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); } +// XXX a hack until the reflow state does this correctly +// XXX when it gets fixed, leave in the printf statements or add an assertion +void LegendHack(nsHTMLReflowState& aReflowState, char* aMessage) +{ + if (aReflowState.computedWidth == 0) { + aReflowState.computedWidth = aReflowState.availableWidth; + } + if ((aReflowState.computedWidth != NS_INTRINSICSIZE) && + (aReflowState.computedWidth > aReflowState.availableWidth) && + (aReflowState.availableWidth > 0)) { +// printf("BUG - %s has a computed width = %d, available width = %d \n", +// aMessage, aReflowState.computedWidth, aReflowState.availableWidth); + aReflowState.computedWidth = aReflowState.availableWidth; + } + if (aReflowState.computedHeight == 0) { + aReflowState.computedHeight = aReflowState.availableHeight; + } + if ((aReflowState.computedHeight != NS_INTRINSICSIZE) && + (aReflowState.computedHeight > aReflowState.availableHeight) && + (aReflowState.availableHeight > 0)) { +// printf("BUG - %s has a computed height = %d, available height = %d \n", +// aMessage, aReflowState.computedHeight, aReflowState.availableHeight); + aReflowState.computedHeight = aReflowState.availableHeight; + } +} + NS_IMETHODIMP nsLegendFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - nsSize availSize(aReflowState.availableWidth, aReflowState.availableHeight); - - // reflow the child - nsIFrame* firstKid = mFrames.FirstChild(); - nsHTMLReflowState reflowState(aPresContext, firstKid, aReflowState, - availSize); - ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, aStatus); + //XXX remove when reflow state is fixed + LegendHack((nsHTMLReflowState&)aReflowState, "legend"); + nsSize availSize(aReflowState.computedWidth, aReflowState.computedHeight); // get border and padding const nsStyleSpacing* spacing = @@ -140,6 +162,24 @@ nsLegendFrame::Reflow(nsIPresContext& aPresContext, nsMargin borderPadding; spacing->CalcBorderPaddingFor(this, borderPadding); + if (NS_INTRINSICSIZE != availSize.width) { + availSize.width -= borderPadding.left + borderPadding.top; + availSize.width = PR_MAX(availSize.width,0); + } + if (NS_AUTOHEIGHT != availSize.height) { + availSize.height -= borderPadding.top + borderPadding.bottom; + availSize.height = PR_MAX(availSize.height,0); + } + + // reflow the child + nsIFrame* firstKid = mFrames.FirstChild(); + nsHTMLReflowState reflowState(aPresContext, firstKid, aReflowState, + availSize); + //XXX remove when reflow state is fixed + LegendHack(reflowState, "legend's area"); + ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, aStatus); + + // Place the child nsRect rect = nsRect(borderPadding.left, borderPadding.top, aDesiredSize.width, aDesiredSize.height); firstKid->SetRect(rect); diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index 4a5159c4b73..4dd90ca3be8 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -243,6 +243,8 @@ nsListControlFrame::PaintChildren(nsIPresContext& aPresContext, } //---------------------------------------------------------------------- +// XXX this needs to properly deal with max element size. percentage based unconstrained widths cannot +// be allowed to return large max element sizes or tables will get too large. NS_IMETHODIMP nsListControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -890,6 +892,7 @@ nsListControlFrame::GetHorizontalInsidePadding(nsIPresContext& aPresContext, //---------------------------------------------------------------------- + void nsListControlFrame::GetDesiredSize(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, @@ -933,14 +936,15 @@ nsListControlFrame::GetDesiredSize(nsIPresContext* aPresContext, } PRInt32 rowHeight = 0; - nsSize calcSize; + nsSize desiredSize; + nsSize minSize; PRBool widthExplicit, heightExplicit; nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, nsnull, maxWidth, PR_TRUE, nsHTMLAtoms::size, 1); // XXX fix CalculateSize to return PRUint32 - mNumRows = (PRUint32)nsFormControlHelper::CalculateSize(aPresContext, this, styleSize, textSpec, - calcSize, widthExplicit, heightExplicit, rowHeight, - aReflowState.rendContext); + mNumRows = (PRUint32)nsFormControlHelper::CalculateSize (aPresContext, aReflowState.rendContext, this, styleSize, + textSpec, desiredSize, minSize, widthExplicit, + heightExplicit, rowHeight); float sp2t; float p2t; @@ -954,16 +958,16 @@ nsListControlFrame::GetDesiredSize(nsIPresContext* aPresContext, if (mInDropDownMode) { //PRUint32 numOptions; //options->GetLength(&numOptions); - nscoord extra = calcSize.height - (rowHeight * mNumRows); + nscoord extra = desiredSize.height - (rowHeight * mNumRows); mNumRows = (numOptions > 20 ? 20 : numOptions); - calcSize.height = (mNumRows * rowHeight) + extra; + desiredSize.height = (mNumRows * rowHeight) + extra; if (mNumRows < 21) { //calcSize.width += scrollbarWidth; } } - aDesiredLayoutSize.width = calcSize.width; + aDesiredLayoutSize.width = desiredSize.width; // account for vertical scrollbar, if present //if (!widthExplicit && ((mNumRows < numOptions) || mIsComboBox)) { //if (!widthExplicit && (mNumRows < (PRInt32)numOptions)) { @@ -974,10 +978,13 @@ nsListControlFrame::GetDesiredSize(nsIPresContext* aPresContext, //aDesiredLayoutSize.height = (mIsComboBox) // ? rowHeight + (2 * GetVerticalInsidePadding(p2t, rowHeight)) // : calcSize.height; - aDesiredLayoutSize.height = calcSize.height; + aDesiredLayoutSize.height = desiredSize.height; aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; aDesiredLayoutSize.descent = 0; + // XXX When this code is working, max element size needs to be set properly from CalculateSize + // above. look at some of the other form control to see how to do it. + aDesiredWidgetSize.width = maxWidth; aDesiredWidgetSize.height = rowHeight; //if (mIsComboBox) { // add in pull down size diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index b677328492f..79cd8bfba9c 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -226,6 +226,7 @@ nsTextControlFrame::EnterPressed(nsIPresContext& aPresContext) } } +#define DEFAULT_PIXEL_WIDTH 20 void nsTextControlFrame::GetDesiredSize(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, @@ -239,7 +240,8 @@ nsTextControlFrame::GetDesiredSize(nsIPresContext* aPresContext, nsSize styleSize; GetStyleSize(*aPresContext, aReflowState, styleSize); - nsSize size; + nsSize desiredSize; + nsSize minSize; PRBool widthExplicit, heightExplicit; PRInt32 ignore; @@ -248,22 +250,20 @@ nsTextControlFrame::GetDesiredSize(nsIPresContext* aPresContext, if ((NS_FORM_INPUT_TEXT == type) || (NS_FORM_INPUT_PASSWORD == type)) { PRInt32 width; if (NS_CONTENT_ATTR_HAS_VALUE != GetSizeFromContent(&width)) { - width = 20; + width = DEFAULT_PIXEL_WIDTH; } //if (eCompatibility_NavQuirks == mode) { // width += 1; //} nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, nsnull, width, PR_FALSE, nsnull, 1); - nsFormControlHelper::CalculateSize(aPresContext, this, styleSize, textSpec, size, - widthExplicit, heightExplicit, ignore, - aReflowState.rendContext); + nsFormControlHelper::CalculateSize(aPresContext, aReflowState.rendContext, this, styleSize, + textSpec, desiredSize, minSize, widthExplicit, heightExplicit, ignore); } else { - nsInputDimensionSpec areaSpec(nsHTMLAtoms::cols, PR_FALSE, nsnull, nsnull, 20, + nsInputDimensionSpec areaSpec(nsHTMLAtoms::cols, PR_FALSE, nsnull, nsnull, DEFAULT_PIXEL_WIDTH, PR_FALSE, nsHTMLAtoms::rows, 1); - nsFormControlHelper::CalculateSize(aPresContext, this, styleSize, areaSpec, size, - widthExplicit, heightExplicit, ignore, - aReflowState.rendContext); + nsFormControlHelper::CalculateSize(aPresContext, aReflowState.rendContext, this, styleSize, + areaSpec, desiredSize, minSize, widthExplicit, heightExplicit, ignore); } if (NS_FORM_TEXTAREA == type) { @@ -287,20 +287,28 @@ nsTextControlFrame::GetDesiredSize(nsIPresContext* aPresContext, } if (!heightExplicit) { - size.height += scrollbarHeight; + desiredSize.height += scrollbarHeight; + minSize.height += scrollbarHeight; } if (!widthExplicit) { - size.width += scrollbarWidth; + desiredSize.width += scrollbarWidth; + minSize.width += scrollbarWidth; } } - - aDesiredLayoutSize.width = size.width; - aDesiredLayoutSize.height = size.height; + aDesiredLayoutSize.width = desiredSize.width; + aDesiredLayoutSize.height = desiredSize.height; aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; aDesiredLayoutSize.descent = 0; + + if (aDesiredLayoutSize.maxElementSize) { + aDesiredLayoutSize.maxElementSize->width = minSize.width; + aDesiredLayoutSize.maxElementSize->height = minSize.width; + } + aDesiredWidgetSize.width = aDesiredLayoutSize.width; aDesiredWidgetSize.height = aDesiredLayoutSize.height; + } nsWidgetInitData* diff --git a/layout/generic/nsAreaFrame.cpp b/layout/generic/nsAreaFrame.cpp index bd31c5fabb4..36329806445 100644 --- a/layout/generic/nsAreaFrame.cpp +++ b/layout/generic/nsAreaFrame.cpp @@ -449,7 +449,7 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, aReflowState.reflowCommand->GetNext(nextFrame, PR_FALSE); // See if it's one of our absolutely positioned child frames - if (mAbsoluteFrames.ContainsFrame(nextFrame)) { + if (nextFrame && mAbsoluteFrames.ContainsFrame(nextFrame)) { // Remove the next frame from the reflow path aReflowState.reflowCommand->GetNext(nextFrame, PR_TRUE); diff --git a/layout/html/base/src/nsAreaFrame.cpp b/layout/html/base/src/nsAreaFrame.cpp index bd31c5fabb4..36329806445 100644 --- a/layout/html/base/src/nsAreaFrame.cpp +++ b/layout/html/base/src/nsAreaFrame.cpp @@ -449,7 +449,7 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, aReflowState.reflowCommand->GetNext(nextFrame, PR_FALSE); // See if it's one of our absolutely positioned child frames - if (mAbsoluteFrames.ContainsFrame(nextFrame)) { + if (nextFrame && mAbsoluteFrames.ContainsFrame(nextFrame)) { // Remove the next frame from the reflow path aReflowState.reflowCommand->GetNext(nextFrame, PR_TRUE); diff --git a/layout/html/forms/src/nsButtonControlFrame.cpp b/layout/html/forms/src/nsButtonControlFrame.cpp index 44be184cf99..515a3700bcc 100644 --- a/layout/html/forms/src/nsButtonControlFrame.cpp +++ b/layout/html/forms/src/nsButtonControlFrame.cpp @@ -301,8 +301,6 @@ nsButtonControlFrame::Reflow(nsIPresContext& aPresContext, AddBordersAndPadding(&aPresContext, aReflowState, aDesiredSize, bp); if (nsnull != aDesiredSize.maxElementSize) { aDesiredSize.AddBorderPaddingToMaxElementSize(bp); - aDesiredSize.maxElementSize->width = aDesiredSize.width; - aDesiredSize.maxElementSize->height = aDesiredSize.height; } aStatus = NS_FRAME_COMPLETE; return NS_OK; @@ -313,56 +311,64 @@ nsButtonControlFrame::Reflow(nsIPresContext& aPresContext, } void -nsButtonControlFrame::GetDesiredSize(nsIPresContext* aPresContext, - const nsHTMLReflowState& aReflowState, - nsHTMLReflowMetrics& aDesiredLayoutSize, - nsSize& aDesiredWidgetSize) +nsButtonControlFrame::GetDesiredSize(nsIPresContext* aPresContext, + const nsHTMLReflowState& aReflowState, + nsHTMLReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize) { PRInt32 type; GetType(&type); if (NS_FORM_INPUT_HIDDEN == type) { // there is no physical rep - aDesiredLayoutSize.width = 0; - aDesiredLayoutSize.height = 0; - aDesiredLayoutSize.ascent = 0; + aDesiredLayoutSize.width = 0; + aDesiredLayoutSize.height = 0; + aDesiredLayoutSize.ascent = 0; aDesiredLayoutSize.descent = 0; } else { #ifdef NS_GFX_RENDER_FORM_ELEMENTS - nsCOMPtr outlineStyle( dont_QueryInterface(mStyleContext) ); - nsCOMPtr sbAtom ( dont_QueryInterface(NS_NewAtom(":button-outline")) ); - aPresContext->ProbePseudoStyleContextFor(mContent, sbAtom, mStyleContext, PR_FALSE, getter_AddRefs(outlineStyle)); + nsCOMPtr outlineStyle( dont_QueryInterface(mStyleContext) ); + nsCOMPtr sbAtom ( dont_QueryInterface(NS_NewAtom(":button-outline")) ); + aPresContext->ProbePseudoStyleContextFor(mContent, sbAtom, mStyleContext, PR_FALSE, getter_AddRefs(outlineStyle)); - const nsStyleSpacing* outline = (const nsStyleSpacing*)outlineStyle->GetStyleData(eStyleStruct_Spacing); - - nsMargin outlineBorder; - outline->CalcBorderFor(this, outlineBorder); + const nsStyleSpacing* outline = (const nsStyleSpacing*)outlineStyle->GetStyleData(eStyleStruct_Spacing); + nsMargin outlineBorder; + outline->CalcBorderFor(this, outlineBorder); #endif nsSize styleSize; GetStyleSize(*aPresContext, aReflowState, styleSize); - // a browse button shares is style context with its parent nsInputFile + // a browse button shares its style context with its parent nsInputFile // it uses everything from it except width if (NS_FORM_BROWSE == type) { styleSize.width = CSS_NOTSET; } - nsSize size; + nsSize desiredSize; + nsSize minSize; PRBool widthExplicit, heightExplicit; PRInt32 ignore; nsAutoString defaultLabel; GetDefaultLabel(defaultLabel); nsInputDimensionSpec spec(nsHTMLAtoms::size, PR_TRUE, nsHTMLAtoms::value, &defaultLabel, 1, PR_FALSE, nsnull, 1); - nsFormControlHelper::CalculateSize(aPresContext, this, styleSize, spec, size, - widthExplicit, heightExplicit, ignore, - aReflowState.rendContext); - #ifdef NS_GFX_RENDER_FORM_ELEMENTS - aDesiredLayoutSize.width = size.width + outlineBorder.left + outlineBorder.right; - aDesiredLayoutSize.height= size.height + outlineBorder.top + outlineBorder.bottom; -#else - aDesiredLayoutSize.width = size.width; - aDesiredLayoutSize.height= size.height; + nsFormControlHelper::CalculateSize(aPresContext, aReflowState.rendContext, this, styleSize, + spec, desiredSize, minSize, widthExplicit, heightExplicit, ignore); + + // set desired size, max element size + aDesiredLayoutSize.width = desiredSize.width; + aDesiredLayoutSize.height= desiredSize.height; + if (aDesiredLayoutSize.maxElementSize) { + aDesiredLayoutSize.maxElementSize->width = minSize.width; + aDesiredLayoutSize.maxElementSize->height = minSize.height; + } +#ifdef NS_GFX_RENDER_FORM_ELEMENTS + nscoord horOutline = outlineBorder.left + outlineBorder.right; + nscoord verOutline = outlineBorder.top + outlineBorder.bottom; + aDesiredLayoutSize.width += horOutline; + aDesiredLayoutSize.height += verOutline; + if (aDesiredLayoutSize.maxElementSize) { + aDesiredLayoutSize.maxElementSize->width += horOutline; + aDesiredLayoutSize.maxElementSize->height += verOutline; + } #endif - aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; - aDesiredLayoutSize.descent = 0; } aDesiredWidgetSize.width = aDesiredLayoutSize.width; diff --git a/layout/html/forms/src/nsComboboxControlFrame.cpp b/layout/html/forms/src/nsComboboxControlFrame.cpp index d39f5853c56..aab2aa97287 100644 --- a/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -360,14 +360,16 @@ NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsIPresContext& aPresConte } PRInt32 rowHeight = 0; - nsSize calcSize; + nsSize desiredSize; + nsSize minSize; PRBool widthExplicit, heightExplicit; nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, nsnull, maxWidth, PR_TRUE, nsHTMLAtoms::size, 1); // XXX fix CalculateSize to return PRUint32 - PRUint32 numRows = (PRUint32)nsFormControlHelper::CalculateSize(&aPresContext, this, styleSize, textSpec, - calcSize, widthExplicit, heightExplicit, rowHeight, - aReflowState.rendContext); + PRUint32 numRows = + (PRUint32)nsFormControlHelper::CalculateSize(&aPresContext, aReflowState.rendContext, this, + styleSize, textSpec, desiredSize, minSize, + widthExplicit, heightExplicit, rowHeight); float sp2t; float p2t; @@ -380,23 +382,12 @@ NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsIPresContext& aPresConte nscoord scrollbarHeight = 0; nsListControlFrame::GetScrollBarDimensions(aPresContext, scrollbarWidth, scrollbarHeight); - nscoord extra = calcSize.height - (rowHeight * numRows); + nscoord extra = desiredSize.height - (rowHeight * numRows); numRows = (numOptions > 20 ? 20 : numOptions); - calcSize.height = (numRows * rowHeight) + extra; - if (numRows < 21) { - //calcSize.width += scrollbarWidth; - } - - /*aDesiredSize.width = calcSize.width; - // account for vertical scrollbar, if present - if (!widthExplicit && (numRows < (PRInt32)numOptions)) { - aDesiredSize.width += scrollbarWidth; - } -*/ + desiredSize.height = (numRows * rowHeight) + extra; aDesiredSize.descent = 0; - nsMargin border; const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); mySpacing->CalcBorderFor(this, border); @@ -416,21 +407,22 @@ NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsIPresContext& aPresConte sis.mFont = &font; context->GetSystemAttribute(eSystemAttr_Font_Tooltips, &sis); - nscoord adjustment = NSIntPixelsToTwips(14, p2t); + nscoord horKludgeAdjustment = NSIntPixelsToTwips(14, p2t); + nscoord horAdjustment = scrollbarScaledWidth + border.left + border.right + horKludgeAdjustment; - aDesiredSize.width = calcSize.width + scrollbarScaledWidth + border.left + border.right + adjustment; - aDesiredSize.height = rowHeight + onePixel; - aDesiredSize.height = rowHeight + onePixel; + aDesiredSize.width = desiredSize.width + horAdjustment; + + nscoord verKludgeAdjustment = onePixel; + nscoord verAdjustment = border.top + border.bottom + verKludgeAdjustment; + + aDesiredSize.height = rowHeight + verAdjustment; mButtonRect.SetRect(aDesiredSize.width-scrollbarScaledWidth-border.right, border.top, scrollbarScaledWidth, aDesiredSize.height); - desiredSize = aDesiredSize; - aDesiredSize.height += border.top + border.bottom; - if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.maxElementSize->width = aDesiredSize.width; - aDesiredSize.maxElementSize->height = aDesiredSize.height; + aDesiredSize.maxElementSize->width = minSize.width + verAdjustment; + aDesiredSize.maxElementSize->height = minSize.height + horAdjustment; } diff --git a/layout/html/forms/src/nsFieldSetFrame.cpp b/layout/html/forms/src/nsFieldSetFrame.cpp index d4832bc6524..733c20ade43 100644 --- a/layout/html/forms/src/nsFieldSetFrame.cpp +++ b/layout/html/forms/src/nsFieldSetFrame.cpp @@ -79,7 +79,6 @@ public: protected: - void SetMaxElementSize(nsSize& maxSize, nsSize* aSize); virtual PRIntn GetSkipSides() const; //virtual void GetDesiredSize(nsIPresContext* aPresContext, // const nsReflowState& aReflowState, @@ -228,27 +227,55 @@ nsFieldSetFrame::Paint(nsIPresContext& aPresContext, return NS_OK; } -void -nsFieldSetFrame::SetMaxElementSize(nsSize& maxSize, nsSize* aSize) +// XXX a hack until the reflow state does this correctly +// XXX when it gets fixed, leave in the printf statements or add an assertion +void FieldSetHack(nsHTMLReflowState& aReflowState, char* aMessage, PRBool aUseMax) { - if (aSize) { - maxSize.width = (maxSize.width >= aSize->width) ? maxSize.width : aSize->width; - maxSize.height = (maxSize.height >= aSize->width) ? maxSize.height : aSize->height; + if (aReflowState.computedWidth == 0) { + aReflowState.computedWidth = aReflowState.availableWidth; + } + if ((aReflowState.computedWidth != NS_INTRINSICSIZE) && + (aReflowState.availableWidth > 0)) { +// printf("BUG - %s has a computed width = %d, available width = %d \n", +// aMessage, aReflowState.computedWidth, aReflowState.availableWidth); + if (aUseMax) { + aReflowState.computedWidth = PR_MAX(aReflowState.computedWidth,aReflowState.availableWidth); + } else { + aReflowState.computedWidth = PR_MIN(aReflowState.computedWidth,aReflowState.availableWidth); + } + } + if (aReflowState.computedHeight == 0) { + aReflowState.computedHeight = aReflowState.availableHeight; + } + if ((aReflowState.computedHeight != NS_INTRINSICSIZE) && + (aReflowState.availableHeight > 0)) { +// printf("BUG - %s has a computed height = %d, available height = %d \n", +// aMessage, aReflowState.computedHeight, aReflowState.availableHeight); + if (aUseMax) { + aReflowState.computedHeight = PR_MAX(aReflowState.computedHeight,aReflowState.availableHeight); + } else { + aReflowState.computedHeight = PR_MIN(aReflowState.computedHeight,aReflowState.availableHeight); + } } } + // XXX currently only supports legend align=left,center,right -#define MIN_TOP_BORDER 10 +#define DESIRED_LEGEND_OFFSET 10 NS_IMETHODIMP -nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, - nsHTMLReflowMetrics& aDesiredSize, +nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) + nsReflowStatus& aStatus) { - nsSize availSize(aReflowState.availableWidth, aReflowState.availableWidth); + // XXX remove the following when the reflow state is fixed + FieldSetHack((nsHTMLReflowState&)aReflowState, "fieldset", PR_TRUE); + // availSize could have unconstrained values, don't perform any addition on them + nsSize availSize(aReflowState.computedWidth, aReflowState.computedHeight); + float p2t; aPresContext.GetScaledPixelsToTwips(&p2t); - const PRInt32 minTopBorder = NSIntPixelsToTwips(MIN_TOP_BORDER, p2t); + const PRInt32 desiredLegendOffset = NSIntPixelsToTwips(DESIRED_LEGEND_OFFSET, p2t); const nsStyleSpacing* spacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); @@ -275,25 +302,18 @@ nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, } // reduce available space by border, padding, etc. if we're in a constrained situation - nscoord horTaken = borderPadding.left + borderPadding.right + (2 * minTopBorder) + - legendMargin.left + legendMargin.right; + nscoord horTaken = borderPadding.left + borderPadding.right + legendMargin.left + legendMargin.right; nscoord verTaken = padding.top + borderPadding.bottom + legendMargin.top + legendMargin.bottom; - if (aReflowState.HaveFixedContentWidth()) { - availSize.width = aReflowState.computedWidth; + + if (NS_INTRINSICSIZE != availSize.width) { + availSize.width -= horTaken; + availSize.width = PR_MAX(availSize.width,0); } - else { - if (NS_UNCONSTRAINEDSIZE != availSize.width) - availSize.width -= horTaken; - } - if (NS_UNCONSTRAINEDSIZE != availSize.height) { + if (NS_AUTOHEIGHT != availSize.height) { // XXX this assumes that the legend is taller than the top border width availSize.height -= verTaken; - if (mInline) { // XXX parents don't account for inline top, bottom margins yet - availSize.height -= margin.top; - } + availSize.height = PR_MAX(availSize.height,0); } - if (availSize.height < 0) - availSize.height = 1; nsSize maxElementSize(0,0); @@ -302,37 +322,45 @@ nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, if (mLegendFrame) { nsHTMLReflowState legendReflowState(aPresContext, mLegendFrame, aReflowState, availSize); + // XXX remove when reflow state is fixed + FieldSetHack((nsHTMLReflowState&)legendReflowState, "fieldset's legend", PR_FALSE); ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, aStatus); legendSize.width = aDesiredSize.width; legendSize.height = aDesiredSize.height; // The legend didn't fit - if ((NS_UNCONSTRAINEDSIZE != availSize.width) && + if ((NS_INTRINSICSIZE != availSize.width) && (availSize.width < aDesiredSize.width + legendMargin.left + legendMargin.right)) { availSize.width = aDesiredSize.width + horTaken; } - if ((NS_UNCONSTRAINEDSIZE != availSize.height) && (availSize.height < aDesiredSize.height)) { - availSize.height = 0; - } else if (NS_UNCONSTRAINEDSIZE != availSize.height) { - availSize.height -= aDesiredSize.height; + if (NS_AUTOHEIGHT != availSize.height) { + if (availSize.height < aDesiredSize.height) { + availSize.height = 0; + } else { + availSize.height -= aDesiredSize.height; + } + } + if (aDesiredSize.maxElementSize) { + maxElementSize.width = aDesiredSize.maxElementSize->width; + maxElementSize.height = aDesiredSize.maxElementSize->height; } - SetMaxElementSize(maxElementSize, aDesiredSize.maxElementSize); } PRBool needAnotherLegendReflow = PR_FALSE; - // Try to reflow the content frame into the available space. It might not fit - nsSize contentSize(0,0); + // Try to reflow the area frame into the available space. It might not fit nsHTMLReflowState contentReflowState(aPresContext, mContentFrame, aReflowState, availSize); + // XXX remove when reflow state is fixed + FieldSetHack(contentReflowState, "fieldset's area", PR_FALSE); + nscoord contentTopOffset = (legendSize.height > border.top) - ? legendSize.height + padding.top - : border.top + padding.top; + ? legendSize.height + padding.top + : border.top + padding.top; ReflowChild(mContentFrame, aPresContext, aDesiredSize, contentReflowState, aStatus); - contentSize.width = aDesiredSize.width; - contentSize.height = aDesiredSize.height; + nsSize contentSize(aDesiredSize.width, aDesiredSize.height); // The content didn't fit if ((NS_UNCONSTRAINEDSIZE != availSize.width) && (availSize.width < aDesiredSize.width)) { @@ -342,51 +370,67 @@ nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, if ((NS_UNCONSTRAINEDSIZE != availSize.height) && (availSize.height < aDesiredSize.height)) { needAnotherLegendReflow = PR_TRUE; } - SetMaxElementSize(maxElementSize, aDesiredSize.maxElementSize); + if (aDesiredSize.maxElementSize) { + aDesiredSize.maxElementSize->width = PR_MAX(aDesiredSize.maxElementSize->width,maxElementSize.width); + maxElementSize.height += aDesiredSize.maxElementSize->height; + } // need to reflow the legend a 2nd time if (needAnotherLegendReflow && mLegendFrame) { nsHTMLReflowState legendReflowState(aPresContext, mLegendFrame, aReflowState, availSize); + // XXX remove when reflow state is fixed + FieldSetHack(legendReflowState, "fieldset's legend frame", PR_FALSE); ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, aStatus); legendSize.width = aDesiredSize.width; legendSize.height = aDesiredSize.height; } - nscoord legendWidth = legendSize.width + border.left + border.right + (2 * minTopBorder); + nscoord legendWidth = legendSize.width + border.left + border.right; nscoord contentWidth = contentSize.width + borderPadding.left + borderPadding.right; + PRBool legendOffsetFits = PR_TRUE; // can the legend be offset by the 10 pixels + aDesiredSize.width = (legendWidth > contentWidth) ? legendWidth : contentWidth; - if (aReflowState.HaveFixedContentWidth() && (aReflowState.computedWidth > aDesiredSize.width)) { - aDesiredSize.width = aReflowState.computedWidth; + + // if we are constrained and the child is smaller, use the constrained values + //if ((NS_INTRINSICSIZE != aReflowState.computedWidth) && + // (aReflowState.computedWidth > aDesiredSize.width)) { + // aDesiredSize.width = aReflowState.computedWidth; + //} + + if ((NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) && + ( (legendWidth + (2 * desiredLegendOffset)) > aDesiredSize.width) ) { + legendOffsetFits = PR_FALSE; } // Place the legend nsRect legendRect(0, 0, 0, 0); contentTopOffset = border.top + padding.top; - if (mInline) // XXX parents don't handle inline top, bottom margins - contentTopOffset += margin.top; if (mLegendFrame) { nscoord legendTopOffset; if (legendSize.height > border.top) { - legendTopOffset = (mInline) ? margin.top : 0; // XXX parents don't ....... + legendTopOffset = 0; } else { legendTopOffset = (border.top - legendSize.height) / 2; - if (mInline) // XXX parents don't ...... - legendTopOffset += margin.top; } contentTopOffset = legendTopOffset + legendSize.height + padding.top; nscoord legendLeftOffset = 0; PRInt32 align = ((nsLegendFrame*)mLegendFrame)->GetAlign(); + // if there isn't room for the 10 pixel left/right offset, align center + if (!legendOffsetFits) { + align = NS_STYLE_TEXT_ALIGN_CENTER; + } + switch(align) { case NS_STYLE_TEXT_ALIGN_LEFT: - legendLeftOffset = border.left + minTopBorder; + legendLeftOffset = border.left + desiredLegendOffset; break; case NS_STYLE_TEXT_ALIGN_RIGHT: - legendLeftOffset = aDesiredSize.width - border.right - minTopBorder - legendSize.width; + legendLeftOffset = aDesiredSize.width - border.right - desiredLegendOffset - legendSize.width; break; // XXX The spec specifies center and top but we are following IE4's lead and making left // be the upper left and right be the upper right. IE4 introduced center which is not part @@ -406,30 +450,28 @@ nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, // cache values so the border will be painted around the vertical center of the legend mTopBorderOffset = legendSize.height / 2; - if (mInline) // XXX parents don't yet ..... - mTopBorderOffset += margin.top; mTopBorderGap = nsRect(legendLeftOffset, legendTopOffset, legendSize.width + legendMargin.left + legendMargin.right, legendSize.height + legendMargin.top + legendMargin.bottom); } - // Place the content frame + // Place the content area frame nsRect contentRect(borderPadding.left, contentTopOffset, contentSize.width, contentSize.height); mContentFrame->SetRect(contentRect); // Return our size and our result - aDesiredSize.height = contentTopOffset + contentSize.height + borderPadding.bottom; - if (mInline) // XXX parents don't yet ...... - aDesiredSize.height += margin.bottom; - if (aReflowState.HaveFixedContentHeight() && (aReflowState.computedHeight > aDesiredSize.height)) { - aDesiredSize.height = aReflowState.computedHeight; - } + aDesiredSize.height = contentTopOffset + legendSize.height + contentSize.height + borderPadding.bottom; + + // if we are constrained and the child is smaller, use the constrained values + //if ((NS_AUTOHEIGHT != aReflowState.computedHeight) && (aReflowState.computedHeight > aDesiredSize.height)) { + // aDesiredSize.height = aReflowState.computedHeight; + //} aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); aDesiredSize.maxElementSize->width = maxElementSize.width; aDesiredSize.maxElementSize->height = maxElementSize.height; + aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); } aStatus = NS_FRAME_COMPLETE; diff --git a/layout/html/forms/src/nsFormControlFrame.cpp b/layout/html/forms/src/nsFormControlFrame.cpp index 77aaa107484..3aa6d3aa4aa 100644 --- a/layout/html/forms/src/nsFormControlFrame.cpp +++ b/layout/html/forms/src/nsFormControlFrame.cpp @@ -322,9 +322,7 @@ nsFormControlFrame::Reflow(nsIPresContext& aPresContext, aDesiredSize.descent = 0; if (nsnull != aDesiredSize.maxElementSize) { -//XXX aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); - aDesiredSize.maxElementSize->width = aDesiredSize.width; - aDesiredSize.maxElementSize->height = aDesiredSize.height; + //XXX aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); } aStatus = NS_FRAME_COMPLETE; diff --git a/layout/html/forms/src/nsFormControlFrame.h b/layout/html/forms/src/nsFormControlFrame.h index f5498ef817d..68efc165723 100644 --- a/layout/html/forms/src/nsFormControlFrame.h +++ b/layout/html/forms/src/nsFormControlFrame.h @@ -40,7 +40,7 @@ class nsFormFrame; // using GFX calls, rather than creating a widget. Undefining it // causes widgets to be used for form elements. @see RequiresWidget method // to see which widgets will obey this directive. -#define NS_GFX_RENDER_FORM_ELEMENTS +//#define NS_GFX_RENDER_FORM_ELEMENTS /** * nsFormControlFrame is the base class for frames of form controls. It diff --git a/layout/html/forms/src/nsFormControlHelper.cpp b/layout/html/forms/src/nsFormControlHelper.cpp index f59759c15ac..501a1dbf99c 100644 --- a/layout/html/forms/src/nsFormControlHelper.cpp +++ b/layout/html/forms/src/nsFormControlHelper.cpp @@ -174,19 +174,25 @@ nsFormControlHelper::GetTextSize(nsIPresContext& aPresContext, nsIFormControlFra } PRInt32 -nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, nsIFormControlFrame* aFrame, - const nsSize& aCSSSize, nsInputDimensionSpec& aSpec, - nsSize& aBounds, PRBool& aWidthExplicit, - PRBool& aHeightExplicit, nscoord& aRowHeight, - nsIRenderingContext *aRendContext) +nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, + nsIRenderingContext* aRendContext, + nsIFormControlFrame* aFrame, + const nsSize& aCSSSize, + nsInputDimensionSpec& aSpec, + nsSize& aDesiredSize, + nsSize& aMinSize, + PRBool& aWidthExplicit, + PRBool& aHeightExplicit, + nscoord& aRowHeight) { - nscoord charWidth = 0; + nscoord charWidth = 0; + nscoord charHeight = 0; PRInt32 numRows = ATTR_NOTSET; aWidthExplicit = PR_FALSE; aHeightExplicit = PR_FALSE; - aBounds.width = CSS_NOTSET; - aBounds.height = CSS_NOTSET; + aDesiredSize.width = CSS_NOTSET; + aDesiredSize.height = CSS_NOTSET; nsSize textSize(0,0); nsIContent* iContent = nsnull; @@ -213,45 +219,63 @@ nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, nsIFormControl float p2t; aPresContext->GetScaledPixelsToTwips(&p2t); - // determine the width - nscoord adjSize; +#if 0 + // determine if it is percentage based width, height + PRBool percentageWidth = PR_FALSE; + PRBool percentageHeight = PR_FALSE; + + const nsStylePosition* pos; + nsIFrame* iFrame = nsnull; + nsresult rv = aFrame->QueryInterface(kIFrameIID, (void**)&iFrame); + if ((NS_OK == rv) && (nsnull != iFrame)) { + iFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)pos); + if (eStyleUnit_Percent == pos->mWidth.GetUnit()) { + percentageWidth = PR_TRUE; + } + if (eStyleUnit_Percent == pos->mWidth.GetUnit()) { + percentageHeight = PR_TRUE; + } + } +#endif + // determine the width, char height, row height if (NS_CONTENT_ATTR_HAS_VALUE == colStatus) { // col attr will provide width PRInt32 col = ((colAttr.GetUnit() == eHTMLUnit_Pixel) ? colAttr.GetPixelValue() : colAttr.GetIntValue()); if (aSpec.mColSizeAttrInPixels) { - col = (col <= 0) ? 15 : col; - aBounds.width = NSIntPixelsToTwips(col, p2t); - } - else { - col = (col <= 0) ? 1 : col; - charWidth = GetTextSize(*aPresContext, aFrame, col, aBounds, aRendContext); - aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET + // need to set charWidth and aDesiredSize.height + charWidth = GetTextSize(*aPresContext, aFrame, 1, aDesiredSize, aRendContext); + col = (col <= 0) ? 15 : col; // XXX why a default of 15 pixels, why hide it + aDesiredSize.width = NSIntPixelsToTwips(col, p2t); + } else { + col = (col <= 0) ? 1 : col; // XXX why a default of 1 char, why hide it + charWidth = GetTextSize(*aPresContext, aFrame, col, aDesiredSize, aRendContext); } if (aSpec.mColSizeAttrInPixels) { aWidthExplicit = PR_TRUE; } - } - else { + aMinSize.width = aDesiredSize.width; + } else { + // set aDesiredSize for height calculation below. CSS may override width + if (NS_CONTENT_ATTR_HAS_VALUE == valStatus) { // use width of initial value + charWidth = GetTextSize(*aPresContext, aFrame, valAttr, aDesiredSize, aRendContext); + } else if (aSpec.mColDefaultValue) { // use default value + charWidth = GetTextSize(*aPresContext, aFrame, *aSpec.mColDefaultValue, aDesiredSize, aRendContext); + } else if (aSpec.mColDefaultSizeInPixels) { // use default width in pixels + charWidth = GetTextSize(*aPresContext, aFrame, 1, aDesiredSize, aRendContext); + aDesiredSize.width = aSpec.mColDefaultSize; + } else { // use default width in num characters + charWidth = GetTextSize(*aPresContext, aFrame, aSpec.mColDefaultSize, aDesiredSize, aRendContext); + } + aMinSize.width = aDesiredSize.width; if (CSS_NOTSET != aCSSSize.width) { // css provides width - aBounds.width = (aCSSSize.width > 0) ? aCSSSize.width : 1; - aWidthExplicit = PR_TRUE; - } - else { - if (NS_CONTENT_ATTR_HAS_VALUE == valStatus) { // use width of initial value - charWidth = GetTextSize(*aPresContext, aFrame, valAttr, aBounds, aRendContext); + NS_ASSERTION(aCSSSize.width > 0, "form control's computed width is <= 0"); + if (NS_INTRINSICSIZE != aCSSSize.width) { + aDesiredSize.width = PR_MAX(aDesiredSize.width,aCSSSize.width); + aWidthExplicit = PR_TRUE; } - else if (aSpec.mColDefaultValue) { // use default value - charWidth = GetTextSize(*aPresContext, aFrame, *aSpec.mColDefaultValue, aBounds, aRendContext); - } - else if (aSpec.mColDefaultSizeInPixels) { // use default width in pixels - charWidth = GetTextSize(*aPresContext, aFrame, 1, aBounds, aRendContext); - aBounds.width = aSpec.mColDefaultSize; - } - else { // use default width in num characters - charWidth = GetTextSize(*aPresContext, aFrame, aSpec.mColDefaultSize, aBounds, aRendContext); - } - aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET } } + aRowHeight = aDesiredSize.height; + aMinSize.height = aDesiredSize.height; // determine the height nsHTMLValue rowAttr; @@ -260,52 +284,40 @@ nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, nsIFormControl rowStatus = hContent->GetHTMLAttribute(aSpec.mRowSizeAttr, rowAttr); } if (NS_CONTENT_ATTR_HAS_VALUE == rowStatus) { // row attr will provide height - PRInt32 rowAttrInt = ((rowAttr.GetUnit() == eHTMLUnit_Pixel) ? rowAttr.GetPixelValue() : rowAttr.GetIntValue()); - adjSize = (rowAttrInt > 0) ? rowAttrInt : 1; - if (0 == charWidth) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); - aBounds.height = textSize.height * adjSize; - aRowHeight = textSize.height; - numRows = adjSize; + PRInt32 rowAttrInt = ((rowAttr.GetUnit() == eHTMLUnit_Pixel) + ? rowAttr.GetPixelValue() : rowAttr.GetIntValue()); + numRows = (rowAttrInt > 0) ? rowAttrInt : 1; + aDesiredSize.height = aDesiredSize.height * numRows; + } else { + aDesiredSize.height = aDesiredSize.height * aSpec.mRowDefaultSize; + if (CSS_NOTSET != aCSSSize.height) { // css provides height + NS_ASSERTION(aCSSSize.height > 0, "form control's computed height is <= 0"); + if (NS_INTRINSICSIZE != aCSSSize.height) { + aDesiredSize.height = PR_MAX(aDesiredSize.height,aCSSSize.height); + aHeightExplicit = PR_TRUE; + } } - else { - aBounds.height = aBounds.height * adjSize; - } - } - else if (CSS_NOTSET != aCSSSize.height) { // css provides height - aBounds.height = (aCSSSize.height > 0) ? aCSSSize.height : 1; - aHeightExplicit = PR_TRUE; - } - else { // use default height in num lines - if (0 == charWidth) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); - aBounds.height = textSize.height * aSpec.mRowDefaultSize; - aRowHeight = textSize.height; - } - else { - aBounds.height = aBounds.height * aSpec.mRowDefaultSize; - } - } - - if ((0 == charWidth) || (0 == textSize.width)) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize, aRendContext); - aRowHeight = textSize.height; } // add inside padding if necessary if (!aWidthExplicit) { - aBounds.width += (2 * aFrame->GetHorizontalInsidePadding(*aPresContext, p2t, aBounds.width, charWidth)); + PRInt32 hPadding = (2 * aFrame->GetHorizontalInsidePadding(*aPresContext, p2t, aDesiredSize.width, charWidth)); + aDesiredSize.width += hPadding; + aMinSize.width += hPadding; } if (!aHeightExplicit) { - aBounds.height += (2 * aFrame->GetVerticalInsidePadding(p2t, textSize.height)); + PRInt32 vPadding = (2 * aFrame->GetVerticalInsidePadding(p2t, aRowHeight)); + aDesiredSize.height += vPadding; + aMinSize.height += vPadding; } NS_RELEASE(hContent); if (ATTR_NOTSET == numRows) { - numRows = aBounds.height / aRowHeight; + numRows = aDesiredSize.height / aRowHeight; } NS_RELEASE(iContent); + return numRows; } diff --git a/layout/html/forms/src/nsFormControlHelper.h b/layout/html/forms/src/nsFormControlHelper.h index 680aacef7e4..8428a8523ff 100644 --- a/layout/html/forms/src/nsFormControlHelper.h +++ b/layout/html/forms/src/nsFormControlHelper.h @@ -90,13 +90,16 @@ class nsFormControlHelper public: - static nscoord CalculateSize (nsIPresContext* aPresContext, nsIFormControlFrame* aFrame, - const nsSize& aCSSSize, nsInputDimensionSpec& aDimensionSpec, - nsSize& aBounds, PRBool& aWidthExplicit, - PRBool& aHeightExplicit, nscoord& aRowSize, - nsIRenderingContext *aRendContext); - - + static nscoord CalculateSize (nsIPresContext* aPresContext, + nsIRenderingContext* aRendContext, + nsIFormControlFrame* aFrame, + const nsSize& aCSSSize, + nsInputDimensionSpec& aDimensionSpec, + nsSize& aDesiredSize, + nsSize& aMinSize, + PRBool& aWidthExplicit, + PRBool& aHeightExplicit, + nscoord& aRowSize); static nscoord GetTextSize(nsIPresContext& aContext, nsIFormControlFrame* aFrame, const nsString& aString, nsSize& aSize, diff --git a/layout/html/forms/src/nsHTMLButtonControlFrame.cpp b/layout/html/forms/src/nsHTMLButtonControlFrame.cpp index a8e7ae752d0..a282940bf84 100644 --- a/layout/html/forms/src/nsHTMLButtonControlFrame.cpp +++ b/layout/html/forms/src/nsHTMLButtonControlFrame.cpp @@ -603,12 +603,40 @@ nsHTMLButtonControlFrame::Paint(nsIPresContext& aPresContext, return result; } +// XXX a hack until the reflow state does this correctly +// XXX when it gets fixed, leave in the printf statements or add an assertion +void ButtonHack(nsHTMLReflowState& aReflowState, char* aMessage) +{ + if (aReflowState.computedWidth == 0) { + aReflowState.computedWidth = aReflowState.availableWidth; + } + if ((aReflowState.computedWidth != NS_INTRINSICSIZE) && + (aReflowState.computedWidth > aReflowState.availableWidth) && + (aReflowState.availableWidth > 0)) { +// printf("BUG - %s has a computed width = %d, available width = %d \n", +// aMessage, aReflowState.computedWidth, aReflowState.availableWidth); + aReflowState.computedWidth = aReflowState.availableWidth; + } + if (aReflowState.computedHeight == 0) { + aReflowState.computedHeight = aReflowState.availableHeight; + } + if ((aReflowState.computedHeight != NS_INTRINSICSIZE) && + (aReflowState.computedHeight > aReflowState.availableHeight) && + (aReflowState.availableHeight > 0)) { +// printf("BUG - %s has a computed height = %d, available height = %d \n", +// aMessage, aReflowState.computedHeight, aReflowState.availableHeight); + aReflowState.computedHeight = aReflowState.availableHeight; + } +} + NS_IMETHODIMP nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + // XXX remove the following when the reflow state is fixed + ButtonHack((nsHTMLReflowState&)aReflowState, "html4 button"); if (!mDidInit) { // create our view, we need a view to grab the mouse nsIView* view; @@ -640,8 +668,26 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, // reflow the child nsIFrame* firstKid = mFrames.FirstChild(); - nsSize availSize(aReflowState.availableWidth, aReflowState.availableHeight); + nsSize availSize(aReflowState.computedWidth, aReflowState.computedHeight); + + // get border and padding + const nsStyleSpacing* spacing = + (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); + nsMargin borderPadding; + spacing->CalcBorderPaddingFor(this, borderPadding); + + if (NS_INTRINSICSIZE != availSize.width) { + availSize.width -= borderPadding.left + borderPadding.right; + availSize.width = PR_MAX(availSize.width,0); + } + if (NS_AUTOHEIGHT != availSize.height) { + availSize.height -= borderPadding.top + borderPadding.bottom; + availSize.height = PR_MAX(availSize.height,0); + } + nsHTMLReflowState reflowState(aPresContext, firstKid, aReflowState, availSize); + // XXX remove the following when the reflow state is fixed + ButtonHack(reflowState, "html4 button's area"); // XXX Proper handling of incremental reflow... if (eReflowReason_Incremental == aReflowState.reason) { @@ -663,12 +709,6 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, aStatus); - // get border and padding - const nsStyleSpacing* spacing = - (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); - nsMargin borderPadding; - spacing->CalcBorderPaddingFor(this, borderPadding); - // Place the child nsRect rect = nsRect(borderPadding.left, borderPadding.top, aDesiredSize.width, aDesiredSize.height); firstKid->SetRect(rect); @@ -677,18 +717,18 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, aDesiredSize.width += borderPadding.left + borderPadding.right; aDesiredSize.height += borderPadding.top + borderPadding.bottom; - // adjust our max element size, if necessary + //adjust our max element size, if necessary if (aDesiredSize.maxElementSize) { aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); } // if we are constrained and the child is smaller, use the constrained values - if (aReflowState.HaveFixedContentWidth() && (aDesiredSize.width < aReflowState.computedWidth)) { - aDesiredSize.width = aReflowState.computedWidth; - } - if (aReflowState.HaveFixedContentHeight() && (aDesiredSize.height < aReflowState.computedHeight)) { - aDesiredSize.height = aReflowState.computedHeight; - } + //if (aReflowState.HaveFixedContentWidth() && (aDesiredSize.width < aReflowState.computedWidth)) { + // aDesiredSize.width = aReflowState.computedWidth; + //} + //if (aReflowState.HaveFixedContentHeight() && (aDesiredSize.height < aReflowState.computedHeight)) { + // aDesiredSize.height = aReflowState.computedHeight; + //} aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; diff --git a/layout/html/forms/src/nsLabelFrame.cpp b/layout/html/forms/src/nsLabelFrame.cpp index 367c6e11ad1..48483c34375 100644 --- a/layout/html/forms/src/nsLabelFrame.cpp +++ b/layout/html/forms/src/nsLabelFrame.cpp @@ -383,12 +383,40 @@ nsLabelFrame::Paint(nsIPresContext& aPresContext, return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); } -NS_IMETHODIMP -nsLabelFrame::Reflow(nsIPresContext& aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) +// XXX a hack until the reflow state does this correctly +// XXX when it gets fixed, leave in the printf statements or add an assertion +void LabelHack(nsHTMLReflowState& aReflowState, char* aMessage) { + if (aReflowState.computedWidth == 0) { + aReflowState.computedWidth = aReflowState.availableWidth; + } + if ((aReflowState.computedWidth != NS_INTRINSICSIZE) && + (aReflowState.computedWidth > aReflowState.availableWidth) && + (aReflowState.availableWidth > 0)) { +// printf("BUG - %s has a computed width = %d, available width = %d \n", +// aMessage, aReflowState.computedWidth, aReflowState.availableWidth); + aReflowState.computedWidth = aReflowState.availableWidth; + } + if (aReflowState.computedHeight == 0) { + aReflowState.computedHeight = aReflowState.availableHeight; + } + if ((aReflowState.computedHeight != NS_INTRINSICSIZE) && + (aReflowState.computedHeight > aReflowState.availableHeight) && + (aReflowState.availableHeight > 0)) { +// printf("BUG - %s has a computed height = %d, available height = %d \n", +// aMessage, aReflowState.computedHeight, aReflowState.availableHeight); + aReflowState.computedHeight = aReflowState.availableHeight; + } +} + +NS_IMETHODIMP +nsLabelFrame::Reflow(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + // XXX remove the following when the reflow state is fixed + LabelHack((nsHTMLReflowState&)aReflowState, "BUG - label"); if (!mDidInit) { // create our view, we need a view to grab the mouse nsIView* view; @@ -424,12 +452,7 @@ nsLabelFrame::Reflow(nsIPresContext& aPresContext, } } - nsSize availSize(aReflowState.availableWidth, aReflowState.availableHeight); - - // reflow the child - nsIFrame* firstKid = mFrames.FirstChild(); - nsHTMLReflowState reflowState(aPresContext, firstKid, aReflowState, availSize); - ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, aStatus); + nsSize availSize(aReflowState.computedWidth, aReflowState.computedHeight); // get border and padding const nsStyleSpacing* spacing = @@ -437,6 +460,22 @@ nsLabelFrame::Reflow(nsIPresContext& aPresContext, nsMargin borderPadding; spacing->CalcBorderPaddingFor(this, borderPadding); + if (NS_INTRINSICSIZE != availSize.width) { + availSize.width -= borderPadding.left + borderPadding.right; + availSize.width = PR_MAX(availSize.width,0); + } + if (NS_AUTOHEIGHT != availSize.height) { + availSize.height -= borderPadding.top + borderPadding.bottom; + availSize.height = PR_MAX(availSize.height,0); + } + + // reflow the child + nsIFrame* firstKid = mFrames.FirstChild(); + nsHTMLReflowState reflowState(aPresContext, firstKid, aReflowState, availSize); + // XXX remove when reflow state is fixed + LabelHack(reflowState, "label's area"); + ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, aStatus); + // Place the child nsRect rect = nsRect(borderPadding.left, borderPadding.top, aDesiredSize.width, aDesiredSize.height); firstKid->SetRect(rect); @@ -451,12 +490,12 @@ nsLabelFrame::Reflow(nsIPresContext& aPresContext, } // if we are constrained and the child is smaller, use the constrained values - if (aReflowState.HaveFixedContentWidth() && (aDesiredSize.width < aReflowState.computedWidth)) { - aDesiredSize.width = aReflowState.computedWidth; - } - if (aReflowState.HaveFixedContentHeight() && (aDesiredSize.height < aReflowState.computedHeight)) { - aDesiredSize.height = aReflowState.computedHeight; - } + //if (aReflowState.HaveFixedContentWidth() && (aDesiredSize.width < aReflowState.computedWidth)) { + // aDesiredSize.width = aReflowState.computedWidth; + //} + //if (aReflowState.HaveFixedContentHeight() && (aDesiredSize.height < aReflowState.computedHeight)) { + // aDesiredSize.height = aReflowState.computedHeight; + //} aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; diff --git a/layout/html/forms/src/nsLegendFrame.cpp b/layout/html/forms/src/nsLegendFrame.cpp index a8893542509..aa4b1463cfd 100644 --- a/layout/html/forms/src/nsLegendFrame.cpp +++ b/layout/html/forms/src/nsLegendFrame.cpp @@ -120,19 +120,41 @@ nsLegendFrame::Paint(nsIPresContext& aPresContext, return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); } +// XXX a hack until the reflow state does this correctly +// XXX when it gets fixed, leave in the printf statements or add an assertion +void LegendHack(nsHTMLReflowState& aReflowState, char* aMessage) +{ + if (aReflowState.computedWidth == 0) { + aReflowState.computedWidth = aReflowState.availableWidth; + } + if ((aReflowState.computedWidth != NS_INTRINSICSIZE) && + (aReflowState.computedWidth > aReflowState.availableWidth) && + (aReflowState.availableWidth > 0)) { +// printf("BUG - %s has a computed width = %d, available width = %d \n", +// aMessage, aReflowState.computedWidth, aReflowState.availableWidth); + aReflowState.computedWidth = aReflowState.availableWidth; + } + if (aReflowState.computedHeight == 0) { + aReflowState.computedHeight = aReflowState.availableHeight; + } + if ((aReflowState.computedHeight != NS_INTRINSICSIZE) && + (aReflowState.computedHeight > aReflowState.availableHeight) && + (aReflowState.availableHeight > 0)) { +// printf("BUG - %s has a computed height = %d, available height = %d \n", +// aMessage, aReflowState.computedHeight, aReflowState.availableHeight); + aReflowState.computedHeight = aReflowState.availableHeight; + } +} + NS_IMETHODIMP nsLegendFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - nsSize availSize(aReflowState.availableWidth, aReflowState.availableHeight); - - // reflow the child - nsIFrame* firstKid = mFrames.FirstChild(); - nsHTMLReflowState reflowState(aPresContext, firstKid, aReflowState, - availSize); - ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, aStatus); + //XXX remove when reflow state is fixed + LegendHack((nsHTMLReflowState&)aReflowState, "legend"); + nsSize availSize(aReflowState.computedWidth, aReflowState.computedHeight); // get border and padding const nsStyleSpacing* spacing = @@ -140,6 +162,24 @@ nsLegendFrame::Reflow(nsIPresContext& aPresContext, nsMargin borderPadding; spacing->CalcBorderPaddingFor(this, borderPadding); + if (NS_INTRINSICSIZE != availSize.width) { + availSize.width -= borderPadding.left + borderPadding.top; + availSize.width = PR_MAX(availSize.width,0); + } + if (NS_AUTOHEIGHT != availSize.height) { + availSize.height -= borderPadding.top + borderPadding.bottom; + availSize.height = PR_MAX(availSize.height,0); + } + + // reflow the child + nsIFrame* firstKid = mFrames.FirstChild(); + nsHTMLReflowState reflowState(aPresContext, firstKid, aReflowState, + availSize); + //XXX remove when reflow state is fixed + LegendHack(reflowState, "legend's area"); + ReflowChild(firstKid, aPresContext, aDesiredSize, reflowState, aStatus); + + // Place the child nsRect rect = nsRect(borderPadding.left, borderPadding.top, aDesiredSize.width, aDesiredSize.height); firstKid->SetRect(rect); diff --git a/layout/html/forms/src/nsListControlFrame.cpp b/layout/html/forms/src/nsListControlFrame.cpp index 4a5159c4b73..4dd90ca3be8 100644 --- a/layout/html/forms/src/nsListControlFrame.cpp +++ b/layout/html/forms/src/nsListControlFrame.cpp @@ -243,6 +243,8 @@ nsListControlFrame::PaintChildren(nsIPresContext& aPresContext, } //---------------------------------------------------------------------- +// XXX this needs to properly deal with max element size. percentage based unconstrained widths cannot +// be allowed to return large max element sizes or tables will get too large. NS_IMETHODIMP nsListControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -890,6 +892,7 @@ nsListControlFrame::GetHorizontalInsidePadding(nsIPresContext& aPresContext, //---------------------------------------------------------------------- + void nsListControlFrame::GetDesiredSize(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, @@ -933,14 +936,15 @@ nsListControlFrame::GetDesiredSize(nsIPresContext* aPresContext, } PRInt32 rowHeight = 0; - nsSize calcSize; + nsSize desiredSize; + nsSize minSize; PRBool widthExplicit, heightExplicit; nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, nsnull, maxWidth, PR_TRUE, nsHTMLAtoms::size, 1); // XXX fix CalculateSize to return PRUint32 - mNumRows = (PRUint32)nsFormControlHelper::CalculateSize(aPresContext, this, styleSize, textSpec, - calcSize, widthExplicit, heightExplicit, rowHeight, - aReflowState.rendContext); + mNumRows = (PRUint32)nsFormControlHelper::CalculateSize (aPresContext, aReflowState.rendContext, this, styleSize, + textSpec, desiredSize, minSize, widthExplicit, + heightExplicit, rowHeight); float sp2t; float p2t; @@ -954,16 +958,16 @@ nsListControlFrame::GetDesiredSize(nsIPresContext* aPresContext, if (mInDropDownMode) { //PRUint32 numOptions; //options->GetLength(&numOptions); - nscoord extra = calcSize.height - (rowHeight * mNumRows); + nscoord extra = desiredSize.height - (rowHeight * mNumRows); mNumRows = (numOptions > 20 ? 20 : numOptions); - calcSize.height = (mNumRows * rowHeight) + extra; + desiredSize.height = (mNumRows * rowHeight) + extra; if (mNumRows < 21) { //calcSize.width += scrollbarWidth; } } - aDesiredLayoutSize.width = calcSize.width; + aDesiredLayoutSize.width = desiredSize.width; // account for vertical scrollbar, if present //if (!widthExplicit && ((mNumRows < numOptions) || mIsComboBox)) { //if (!widthExplicit && (mNumRows < (PRInt32)numOptions)) { @@ -974,10 +978,13 @@ nsListControlFrame::GetDesiredSize(nsIPresContext* aPresContext, //aDesiredLayoutSize.height = (mIsComboBox) // ? rowHeight + (2 * GetVerticalInsidePadding(p2t, rowHeight)) // : calcSize.height; - aDesiredLayoutSize.height = calcSize.height; + aDesiredLayoutSize.height = desiredSize.height; aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; aDesiredLayoutSize.descent = 0; + // XXX When this code is working, max element size needs to be set properly from CalculateSize + // above. look at some of the other form control to see how to do it. + aDesiredWidgetSize.width = maxWidth; aDesiredWidgetSize.height = rowHeight; //if (mIsComboBox) { // add in pull down size diff --git a/layout/html/forms/src/nsSelectControlFrame.cpp b/layout/html/forms/src/nsSelectControlFrame.cpp index 3dd3fa5f896..f9381195a11 100644 --- a/layout/html/forms/src/nsSelectControlFrame.cpp +++ b/layout/html/forms/src/nsSelectControlFrame.cpp @@ -292,10 +292,10 @@ nsSelectControlFrame::GetCID() } void -nsSelectControlFrame::GetDesiredSize(nsIPresContext* aPresContext, +nsSelectControlFrame::GetDesiredSize(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, - nsHTMLReflowMetrics& aDesiredLayoutSize, - nsSize& aDesiredWidgetSize) + nsHTMLReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize) { nsIDOMHTMLSelectElement* select = GetSelect(); if (!select) { @@ -334,14 +334,16 @@ nsSelectControlFrame::GetDesiredSize(nsIPresContext* aPresContext, } PRInt32 rowHeight = 0; - nsSize calcSize; + nsSize desiredSize; + nsSize minSize; PRBool widthExplicit, heightExplicit; nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, nsnull, maxWidth, PR_TRUE, nsHTMLAtoms::size, 1); // XXX fix CalculateSize to return PRUint32 - mNumRows = (PRUint32)nsFormControlHelper::CalculateSize(aPresContext, this, styleSize, textSpec, - calcSize, widthExplicit, heightExplicit, rowHeight, - aReflowState.rendContext); + mNumRows = + (PRUint32)nsFormControlHelper::CalculateSize(aPresContext, aReflowState.rendContext, this, styleSize, + textSpec, desiredSize, minSize, widthExplicit, + heightExplicit, rowHeight); // here it is determined whether we are a combo box PRInt32 sizeAttr; @@ -374,16 +376,28 @@ nsSelectControlFrame::GetDesiredSize(nsIPresContext* aPresContext, scrollbarHeight = scrollbarWidth; } - aDesiredLayoutSize.width = calcSize.width; + aDesiredLayoutSize.width = desiredSize.width; // account for vertical scrollbar, if present if (!widthExplicit && ((mNumRows < numOptions) || mIsComboBox)) { aDesiredLayoutSize.width += scrollbarWidth; } + if (aDesiredLayoutSize.maxElementSize) { + aDesiredLayoutSize.maxElementSize->width = minSize.width; + if (!widthExplicit && ((mNumRows < numOptions) || mIsComboBox)) { + aDesiredLayoutSize.maxElementSize->width += scrollbarWidth; + } + } // XXX put this in widget library, combo boxes are fixed height (visible part) aDesiredLayoutSize.height = (mIsComboBox) ? rowHeight + (2 * GetVerticalInsidePadding(p2t, rowHeight)) - : calcSize.height; + : desiredSize.height; + if (aDesiredLayoutSize.maxElementSize) { + aDesiredLayoutSize.maxElementSize->height = (mIsComboBox) + ? rowHeight + (2 * GetVerticalInsidePadding(p2t, rowHeight)) + : minSize.height; + } + aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; aDesiredLayoutSize.descent = 0; @@ -399,6 +413,9 @@ nsSelectControlFrame::GetDesiredSize(nsIPresContext* aPresContext, nscoord ignore; GetWidgetSize(*aPresContext, ignore, aDesiredLayoutSize.height); aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; + if (aDesiredLayoutSize.maxElementSize) { + aDesiredLayoutSize.maxElementSize->height = aDesiredLayoutSize.height; + } } NS_RELEASE(select); diff --git a/layout/html/forms/src/nsTextControlFrame.cpp b/layout/html/forms/src/nsTextControlFrame.cpp index b677328492f..79cd8bfba9c 100644 --- a/layout/html/forms/src/nsTextControlFrame.cpp +++ b/layout/html/forms/src/nsTextControlFrame.cpp @@ -226,6 +226,7 @@ nsTextControlFrame::EnterPressed(nsIPresContext& aPresContext) } } +#define DEFAULT_PIXEL_WIDTH 20 void nsTextControlFrame::GetDesiredSize(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, @@ -239,7 +240,8 @@ nsTextControlFrame::GetDesiredSize(nsIPresContext* aPresContext, nsSize styleSize; GetStyleSize(*aPresContext, aReflowState, styleSize); - nsSize size; + nsSize desiredSize; + nsSize minSize; PRBool widthExplicit, heightExplicit; PRInt32 ignore; @@ -248,22 +250,20 @@ nsTextControlFrame::GetDesiredSize(nsIPresContext* aPresContext, if ((NS_FORM_INPUT_TEXT == type) || (NS_FORM_INPUT_PASSWORD == type)) { PRInt32 width; if (NS_CONTENT_ATTR_HAS_VALUE != GetSizeFromContent(&width)) { - width = 20; + width = DEFAULT_PIXEL_WIDTH; } //if (eCompatibility_NavQuirks == mode) { // width += 1; //} nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, nsnull, width, PR_FALSE, nsnull, 1); - nsFormControlHelper::CalculateSize(aPresContext, this, styleSize, textSpec, size, - widthExplicit, heightExplicit, ignore, - aReflowState.rendContext); + nsFormControlHelper::CalculateSize(aPresContext, aReflowState.rendContext, this, styleSize, + textSpec, desiredSize, minSize, widthExplicit, heightExplicit, ignore); } else { - nsInputDimensionSpec areaSpec(nsHTMLAtoms::cols, PR_FALSE, nsnull, nsnull, 20, + nsInputDimensionSpec areaSpec(nsHTMLAtoms::cols, PR_FALSE, nsnull, nsnull, DEFAULT_PIXEL_WIDTH, PR_FALSE, nsHTMLAtoms::rows, 1); - nsFormControlHelper::CalculateSize(aPresContext, this, styleSize, areaSpec, size, - widthExplicit, heightExplicit, ignore, - aReflowState.rendContext); + nsFormControlHelper::CalculateSize(aPresContext, aReflowState.rendContext, this, styleSize, + areaSpec, desiredSize, minSize, widthExplicit, heightExplicit, ignore); } if (NS_FORM_TEXTAREA == type) { @@ -287,20 +287,28 @@ nsTextControlFrame::GetDesiredSize(nsIPresContext* aPresContext, } if (!heightExplicit) { - size.height += scrollbarHeight; + desiredSize.height += scrollbarHeight; + minSize.height += scrollbarHeight; } if (!widthExplicit) { - size.width += scrollbarWidth; + desiredSize.width += scrollbarWidth; + minSize.width += scrollbarWidth; } } - - aDesiredLayoutSize.width = size.width; - aDesiredLayoutSize.height = size.height; + aDesiredLayoutSize.width = desiredSize.width; + aDesiredLayoutSize.height = desiredSize.height; aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; aDesiredLayoutSize.descent = 0; + + if (aDesiredLayoutSize.maxElementSize) { + aDesiredLayoutSize.maxElementSize->width = minSize.width; + aDesiredLayoutSize.maxElementSize->height = minSize.width; + } + aDesiredWidgetSize.width = aDesiredLayoutSize.width; aDesiredWidgetSize.height = aDesiredLayoutSize.height; + } nsWidgetInitData*