Reworked fieldsets to fix numerous bugs.

This commit is contained in:
evaughan%netscape.com 1999-06-01 21:52:11 +00:00
Родитель 6672081973
Коммит 4b0b0ef6f4
7 изменённых файлов: 377 добавлений и 847 удалений

Просмотреть файл

@ -47,6 +47,7 @@
#include "nsStyleConsts.h" #include "nsStyleConsts.h"
#include "nsStyleUtil.h" #include "nsStyleUtil.h"
#include "nsFont.h" #include "nsFont.h"
#include "nsCOMPtr.h"
static NS_DEFINE_IID(kLegendFrameCID, NS_LEGEND_FRAME_CID); static NS_DEFINE_IID(kLegendFrameCID, NS_LEGEND_FRAME_CID);
static NS_DEFINE_IID(kIDOMHTMLFieldSetElementIID, NS_IDOMHTMLFIELDSETELEMENT_IID); static NS_DEFINE_IID(kIDOMHTMLFieldSetElementIID, NS_IDOMHTMLFIELDSETELEMENT_IID);
@ -80,16 +81,11 @@ public:
protected: protected:
virtual PRIntn GetSkipSides() const; virtual PRIntn GetSkipSides() const;
//virtual void GetDesiredSize(nsIPresContext* aPresContext,
// const nsReflowState& aReflowState,
// nsReflowMetrics& aDesiredLayoutSize,
// nsSize& aDesiredWidgetSize);
nsIFrame* mLegendFrame; nsIFrame* mLegendFrame;
nsIFrame* mContentFrame; nsIFrame* mContentFrame;
nsRect mTopBorderGap; nsRect mLegendRect;
PRInt32 mTopBorderOffset; nscoord mLegendSpace;
PRBool mInline;
}; };
nsresult nsresult
@ -110,11 +106,9 @@ NS_NewFieldSetFrame(nsIFrame** aNewFrame)
nsFieldSetFrame::nsFieldSetFrame() nsFieldSetFrame::nsFieldSetFrame()
: nsHTMLContainerFrame() : nsHTMLContainerFrame()
{ {
mContentFrame = nsnull; mContentFrame = nsnull;
mLegendFrame = nsnull; mLegendFrame = nsnull;
mTopBorderGap = nsRect(0,0,0,0); mLegendSpace = 0;
mTopBorderOffset = 0;
mInline = PR_TRUE;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -125,9 +119,8 @@ nsFieldSetFrame::SetInitialChildList(nsIPresContext& aPresContext,
// cache our display type // cache our display type
const nsStyleDisplay* styleDisplay; const nsStyleDisplay* styleDisplay;
GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) styleDisplay); GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) styleDisplay);
mInline = (NS_STYLE_DISPLAY_BLOCK != styleDisplay->mDisplay);
PRUint8 flags = (mInline) ? NS_BLOCK_SHRINK_WRAP : 0; PRUint8 flags = (NS_STYLE_DISPLAY_BLOCK != styleDisplay->mDisplay) ? NS_BLOCK_SHRINK_WRAP : 0;
NS_NewAreaFrame(&mContentFrame, flags); NS_NewAreaFrame(&mContentFrame, flags);
mFrames.SetFrames(mContentFrame); mFrames.SetFrames(mContentFrame);
@ -202,24 +195,77 @@ nsFieldSetFrame::Paint(nsIPresContext& aPresContext,
const nsStyleSpacing* spacing = const nsStyleSpacing* spacing =
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
// XXX nsRect backgroundRect(0, 0, mRect.width, mRect.height); float p2t;
// XXX our parent doesn't account for top and bottom margins yet, if we are inline aPresContext.GetScaledPixelsToTwips(&p2t);
//if (mInline) { nscoord onePixel = NSIntPixelsToTwips(1, p2t);
// nsMargin margin;
// spacing->CalcMarginFor(this, margin); nsMargin border;
// nsRect rect(0, mTopBorderOffset, mRect.width, mRect.height - margin.top - spacing->GetBorder(border);
// margin.bottom - mTopBorderOffset);
// nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this, nscoord yoff = 0;
// aDirtyRect, rect, *color, *spacing, 0, 0);
// nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, // if the border is bigger than the legend. Move the border down
// aDirtyRect, rect, *spacing, mStyleContext, skipSides, &mTopBorderGap); // to be centered on the legend.
//} else { if (border.top < mLegendRect.height)
nsRect rect(0, mTopBorderOffset, mRect.width, mRect.height - mTopBorderOffset); yoff = (mLegendRect.height - border.top)/2;
nsRect rect(0, yoff, mRect.width, mRect.height - yoff);
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this, nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *color, *spacing, 0, 0); aDirtyRect, rect, *color, *spacing, 0, 0);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *spacing, mStyleContext, skipSides, &mTopBorderGap);
//} if (mLegendFrame) {
// we should probably use PaintBorderEdges to do this but for now just use clipping
// to achieve the same effect.
PRBool clipState;
// draw left side
nsRect clipRect(rect);
clipRect.width = mLegendRect.x - rect.x;
clipRect.height = border.top;
aRenderingContext.PushState();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect, clipState);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *spacing, mStyleContext, skipSides);
aRenderingContext.PopState(clipState);
// draw right side
clipRect = rect;
clipRect.x = mLegendRect.x + mLegendRect.width;
clipRect.width -= (mLegendRect.x + mLegendRect.width);
clipRect.height = border.top;
aRenderingContext.PushState();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect, clipState);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *spacing, mStyleContext, skipSides);
aRenderingContext.PopState(clipState);
// draw bottom
clipRect = rect;
clipRect.y += border.top;
clipRect.height = mRect.height - (yoff + border.top);
aRenderingContext.PushState();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect, clipState);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *spacing, mStyleContext, skipSides);
aRenderingContext.PopState(clipState);
} else {
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, nsRect(0,0,mRect.width, mRect.height), *spacing, mStyleContext, skipSides);
}
} }
} }
@ -239,260 +285,156 @@ nsFieldSetFrame::Paint(nsIPresContext& aPresContext,
return NS_OK; return NS_OK;
} }
// XXX a hack until the reflow state does this correctly
// XXX when it gets fixed, leave in the printf statements or add an assertion
static
void FieldSetHack(nsHTMLReflowState& aReflowState, char* aMessage, PRBool aUseMax)
{
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 DESIRED_LEGEND_OFFSET 10
NS_IMETHODIMP NS_IMETHODIMP
nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, nsFieldSetFrame::Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize, nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState, const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus) nsReflowStatus& aStatus)
{ {
// XXX remove the following when the reflow state is fixed
#ifndef bug4534_not_fixed
FieldSetHack((nsHTMLReflowState&)aReflowState, "fieldset", PR_TRUE);
#endif
// availSize could have unconstrained values, don't perform any addition on them // availSize could have unconstrained values, don't perform any addition on them
nsSize availSize(aReflowState.computedWidth, aReflowState.computedHeight); nsSize availSize(aReflowState.computedWidth, aReflowState.computedHeight);
float p2t; // get our border and padding
aPresContext.GetScaledPixelsToTwips(&p2t); const nsMargin &borderPadding = aReflowState.mComputedBorderPadding;
const PRInt32 desiredLegendOffset = NSIntPixelsToTwips(DESIRED_LEGEND_OFFSET, p2t);
const nsStyleSpacing* spacing =
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
//nsMargin margin;
//spacing->CalcMarginFor(this, margin);
nsMargin border;
nsMargin padding;
spacing->CalcBorderFor(this, border);
spacing->CalcPaddingFor(this, padding);
nsMargin borderPadding = border + padding;
// Figure out how big the legend is if there is one.
nsMargin legendMargin(0,0,0,0); nsMargin legendMargin(0,0,0,0);
// if there is a legend frame flow it.
if (mLegendFrame) { if (mLegendFrame) {
nsHTMLReflowState legendReflowState(aPresContext, aReflowState,
mLegendFrame, nsSize(NS_INTRINSICSIZE,NS_INTRINSICSIZE));
// always give the legend as much size as it needs
legendReflowState.computedWidth = NS_INTRINSICSIZE;
legendReflowState.computedHeight = NS_INTRINSICSIZE;
ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, aStatus);
// get the legend's margin
nsIStyleContext* legendSC = nsnull; nsIStyleContext* legendSC = nsnull;
mLegendFrame->GetStyleContext(&legendSC); mLegendFrame->GetStyleContext(&legendSC);
if (legendSC) { if (legendSC) {
const nsStyleSpacing* legendSpacing = const nsStyleSpacing* legendSpacing =
(const nsStyleSpacing*)legendSC->GetStyleData(eStyleStruct_Spacing); (const nsStyleSpacing*)legendSC->GetStyleData(eStyleStruct_Spacing);
legendSpacing->CalcMarginFor(mLegendFrame, legendMargin); legendSpacing->GetMargin(legendMargin);
NS_RELEASE(legendSC); NS_RELEASE(legendSC);
} }
// figure out the legend's rectangle
mLegendRect.width = aDesiredSize.width + legendMargin.left + legendMargin.right;
mLegendRect.height = aDesiredSize.height + legendMargin.top + legendMargin.bottom;
mLegendRect.x = borderPadding.left;
mLegendRect.y = 0;
} }
// reduce available space by border, padding, etc. if we're in a constrained situation mLegendSpace = 0;
nscoord horTaken = borderPadding.left + borderPadding.right + legendMargin.left + legendMargin.right; if (mLegendRect.height > borderPadding.top) {
nscoord verTaken = borderPadding.top + borderPadding.bottom + legendMargin.top + legendMargin.bottom; // center the border on the legend
mLegendSpace = mLegendRect.height - borderPadding.top;
} else {
mLegendRect.y = (borderPadding.top - mLegendRect.height)/2;
}
// if we are contrained then remove the legend from our available height.
if (NS_INTRINSICSIZE != availSize.height) {
if (availSize.height >= mLegendSpace)
availSize.height -= mLegendSpace;
}
// don't get any smaller than the legend
if (NS_INTRINSICSIZE != availSize.width) { if (NS_INTRINSICSIZE != availSize.width) {
availSize.width -= horTaken; if (availSize.width < mLegendRect.width)
availSize.width = PR_MAX(availSize.width,0); availSize.width = mLegendRect.width;
}
if (NS_AUTOHEIGHT != availSize.height) {
// XXX this assumes that the legend is taller than the top border width
availSize.height -= verTaken;
availSize.height = PR_MAX(availSize.height,0);
} }
nsSize maxElementSize(0,0); /*
// get the content's margin
// Try to reflow the legend into the available space. It might not fit nsMargin contentMargin(0,0,0,0);
nsSize legendSize(0,0); nsCOMPtr<nsIStyleContext> contentSC;
if (mLegendFrame) { mContentFrame->GetStyleContext(getter_AddRefs(contentSC));
nsHTMLReflowState legendReflowState(aPresContext, aReflowState, if (contentSC) {
mLegendFrame, availSize); const nsStyleSpacing* spacing =
// XXX remove when reflow state is fixed (const nsStyleSpacing*)contentSC->GetStyleData(eStyleStruct_Spacing);
#ifndef bug4534_not_fixed spacing->GetMargin(contentMargin);
FieldSetHack((nsHTMLReflowState&)legendReflowState, "fieldset's legend", PR_FALSE);
#endif
ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, aStatus);
legendSize.width = aDesiredSize.width;
legendSize.height = aDesiredSize.height;
// The legend didn't fit
if ((NS_INTRINSICSIZE != availSize.width) &&
(availSize.width < aDesiredSize.width + legendMargin.left + legendMargin.right)) {
availSize.width = aDesiredSize.width + horTaken;
}
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;
}
} }
PRBool needAnotherLegendReflow = PR_FALSE; // remove it from our size if we are not intrinsic
if (NS_INTRINSICSIZE != availSize.height)
availSize.height -= (contentMargin.top + contentMargin.bottom);
// Try to reflow the area frame into the available space. It might not fit
if (NS_INTRINSICSIZE != availSize.width)
availSize.width -= (contentMargin.left + contentMargin.right);
*/
// Try to reflow the area frame into the available space.
nsHTMLReflowState contentReflowState(aPresContext, aReflowState, nsHTMLReflowState contentReflowState(aPresContext, aReflowState,
mContentFrame, availSize); mContentFrame, availSize);
// XXX remove when reflow state is fixed
#ifndef bug4534_not_fixed
FieldSetHack(contentReflowState, "fieldset's area", PR_FALSE);
#endif
nscoord contentTopOffset = (legendSize.height > border.top)
? legendSize.height + padding.top
: border.top + padding.top;
ReflowChild(mContentFrame, aPresContext, aDesiredSize, contentReflowState, aStatus); ReflowChild(mContentFrame, aPresContext, aDesiredSize, contentReflowState, aStatus);
//aDesiredSize.width += contentMargin.left + contentMargin.right;
//aDesiredSize.height += contentMargin.top + contentMargin.bottom;
nsSize contentSize(aDesiredSize.width, aDesiredSize.height); // set the rect. make sure we add the margin back in.
nsRect contentRect(borderPadding.left,borderPadding.top + mLegendSpace,aDesiredSize.width ,aDesiredSize.height);
// The content didn't fit PRInt32 align = ((nsLegendFrame*)mLegendFrame)->GetAlign();
if ((NS_UNCONSTRAINEDSIZE != availSize.width) && (availSize.width < aDesiredSize.width)) {
needAnotherLegendReflow = PR_TRUE;
availSize.width = contentSize.width + borderPadding.left + borderPadding.right;
}
if ((NS_UNCONSTRAINEDSIZE != availSize.height) && (availSize.height < aDesiredSize.height)) {
needAnotherLegendReflow = PR_TRUE;
}
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 switch(align) {
if (needAnotherLegendReflow && mLegendFrame) {
nsHTMLReflowState legendReflowState(aPresContext, aReflowState,
mLegendFrame, availSize);
// XXX remove when reflow state is fixed
#ifndef bug4534_not_fixed
FieldSetHack(legendReflowState, "fieldset's legend frame", PR_FALSE);
#endif
ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, aStatus);
legendSize.width = aDesiredSize.width;
legendSize.height = aDesiredSize.height;
}
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 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 (mLegendFrame) {
nscoord legendTopOffset;
if (legendSize.height > border.top) {
legendTopOffset = 0;
} else {
legendTopOffset = (border.top - legendSize.height) / 2;
}
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 + desiredLegendOffset;
break;
case NS_STYLE_TEXT_ALIGN_RIGHT: case NS_STYLE_TEXT_ALIGN_RIGHT:
legendLeftOffset = aDesiredSize.width - border.right - desiredLegendOffset - legendSize.width; mLegendRect.x = contentRect.width - mLegendRect.width + borderPadding.left;
break; 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
// of the spec.
case NS_STYLE_TEXT_ALIGN_CENTER: case NS_STYLE_TEXT_ALIGN_CENTER:
case NS_STYLE_VERTICAL_ALIGN_BOTTOM: mLegendRect.x = contentRect.width/2 - mLegendRect.width/2 + borderPadding.left;
case NS_STYLE_VERTICAL_ALIGN_TOP:
default:
legendLeftOffset = (aDesiredSize.width - legendSize.width) / 2;
break;
}
// reduce by legend margins
legendRect = nsRect(legendLeftOffset + legendMargin.left, legendTopOffset + legendMargin.top,
legendSize.width, legendSize.height);
mLegendFrame->SetRect(legendRect);
// cache values so the border will be painted around the vertical center of the legend
mTopBorderOffset = legendSize.height / 2;
mTopBorderGap = nsRect(legendLeftOffset, legendTopOffset, legendSize.width + legendMargin.left +
legendMargin.right, legendSize.height + legendMargin.top +
legendMargin.bottom);
} }
// Place the content area frame // Place the content area frame.
nsRect contentRect(borderPadding.left, contentTopOffset, contentSize.width, contentSize.height);
mContentFrame->SetRect(contentRect); mContentFrame->SetRect(contentRect);
// Return our size and our result // place the legend
aDesiredSize.height = contentTopOffset + legendSize.height + contentSize.height + borderPadding.bottom; nsRect actualLegendRect(mLegendRect);
actualLegendRect.Deflate(legendMargin);
mLegendFrame->SetRect(actualLegendRect);
// if we are constrained and the child is smaller, use the constrained values // Return our size and our result
if ((NS_AUTOHEIGHT != aReflowState.computedHeight) && (aReflowState.computedHeight > aDesiredSize.height)) { if (aReflowState.computedHeight == NS_INTRINSICSIZE) {
aDesiredSize.height = aReflowState.computedHeight; aDesiredSize.height = mLegendSpace +
borderPadding.top +
aDesiredSize.height +
borderPadding.bottom;
} else {
nscoord min = borderPadding.top + borderPadding.bottom + mLegendRect.height;
aDesiredSize.height = aReflowState.computedHeight + borderPadding.top + borderPadding.bottom;
if (aDesiredSize.height < min)
aDesiredSize.height = min;
} }
if (aReflowState.computedWidth == NS_INTRINSICSIZE) {
aDesiredSize.width = borderPadding.left +
aDesiredSize.width +
borderPadding.right;
} else {
nscoord min = borderPadding.left + borderPadding.right + mLegendRect.width;
aDesiredSize.width = aReflowState.computedWidth + borderPadding.left + borderPadding.right;
if (aDesiredSize.width < min)
aDesiredSize.width = min;
}
aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.ascent = aDesiredSize.height;
aDesiredSize.descent = 0; aDesiredSize.descent = 0;
if (nsnull != aDesiredSize.maxElementSize) { if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = maxElementSize.width; // if the legend it wider use it
aDesiredSize.maxElementSize->height = maxElementSize.height; if (aDesiredSize.maxElementSize->width < mLegendRect.width)
aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); aDesiredSize.maxElementSize->width = mLegendRect.width;
// add in padding.
aDesiredSize.maxElementSize->width += borderPadding.left + borderPadding.right;
// height is border + legend
aDesiredSize.maxElementSize->height += borderPadding.top + borderPadding.bottom + mLegendRect.height;
} }
aStatus = NS_FRAME_COMPLETE; aStatus = NS_FRAME_COMPLETE;

Просмотреть файл

@ -18,14 +18,11 @@
// YY need to pass isMultiple before create called // YY need to pass isMultiple before create called
//#include "nsFormControlFrame.h"
#include "nsLegendFrame.h" #include "nsLegendFrame.h"
#include "nsIDOMNode.h" #include "nsIDOMNode.h"
#include "nsIDOMHTMLLegendElement.h" #include "nsIDOMHTMLLegendElement.h"
#include "nsCSSRendering.h" #include "nsCSSRendering.h"
//#include "nsIDOMHTMLCollection.h"
#include "nsIContent.h" #include "nsIContent.h"
//#include "prtypes.h"
#include "nsIFrame.h" #include "nsIFrame.h"
#include "nsISupports.h" #include "nsISupports.h"
#include "nsIAtom.h" #include "nsIAtom.h"
@ -33,14 +30,7 @@
#include "nsIHTMLContent.h" #include "nsIHTMLContent.h"
#include "nsHTMLIIDs.h" #include "nsHTMLIIDs.h"
#include "nsHTMLParts.h" #include "nsHTMLParts.h"
//#include "nsIRadioButton.h"
//#include "nsWidgetsCID.h"
//#include "nsSize.h"
#include "nsHTMLAtoms.h" #include "nsHTMLAtoms.h"
//#include "nsIView.h"
//#include "nsIListWidget.h"
//#include "nsIComboBox.h"
//#include "nsIListBox.h"
#include "nsIStyleContext.h" #include "nsIStyleContext.h"
#include "nsStyleConsts.h" #include "nsStyleConsts.h"
#include "nsStyleUtil.h" #include "nsStyleUtil.h"
@ -65,9 +55,8 @@ NS_NewLegendFrame(nsIFrame** aNewFrame)
} }
nsLegendFrame::nsLegendFrame() nsLegendFrame::nsLegendFrame()
: nsHTMLContainerFrame() : nsAreaFrame()
{ {
mInline = PR_FALSE;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -84,137 +73,9 @@ nsLegendFrame::QueryInterface(REFNSIID aIID, void** aInstancePtrResult)
return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtrResult); return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtrResult);
} }
NS_IMETHODIMP
nsLegendFrame::SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
// cache our display type
const nsStyleDisplay* styleDisplay;
GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) styleDisplay);
mInline = (NS_STYLE_DISPLAY_BLOCK != styleDisplay->mDisplay);
PRUint8 flags = (mInline) ? NS_BLOCK_SHRINK_WRAP : 0;
nsIFrame* areaFrame;
NS_NewAreaFrame(&areaFrame, flags);
mFrames.SetFrames(areaFrame);
// Resolve style and initialize the frame
nsIStyleContext* styleContext;
aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::legendContentPseudo,
mStyleContext, PR_FALSE,
&styleContext);
mFrames.FirstChild()->Init(aPresContext, mContent, this, styleContext, nsnull);
NS_RELEASE(styleContext);
// Set the parent for each of the child frames
for (nsIFrame* frame = aChildList; nsnull != frame; frame->GetNextSibling(&frame)) {
frame->SetParent(mFrames.FirstChild());
}
// Queue up the frames for the inline frame
return mFrames.FirstChild()->SetInitialChildList(aPresContext, nsnull, aChildList);
}
NS_IMETHODIMP
nsLegendFrame::Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
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
static
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)
{
//XXX remove when reflow state is fixed
LegendHack((nsHTMLReflowState&)aReflowState, "legend");
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.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, aReflowState, firstKid,
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);
// add in our border and padding to the size of the child
aDesiredSize.width += borderPadding.left + borderPadding.right;
if (aReflowState.HaveFixedContentWidth() && (aReflowState.computedWidth > aDesiredSize.width)) {
aDesiredSize.width = aReflowState.computedWidth;
}
aDesiredSize.height += borderPadding.top + borderPadding.bottom;
if (aReflowState.HaveFixedContentHeight() && (aReflowState.computedHeight > aDesiredSize.height)) {
aDesiredSize.height = aReflowState.computedHeight;
}
// adjust our max element size, if necessary
if (aDesiredSize.maxElementSize) {
aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding);
}
aDesiredSize.ascent = aDesiredSize.height;
aDesiredSize.descent = 0;
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
PRInt32 nsLegendFrame::GetAlign() PRInt32 nsLegendFrame::GetAlign()
{ {
PRInt32 intValue = NS_STYLE_TEXT_ALIGN_CENTER; PRInt32 intValue = NS_STYLE_TEXT_ALIGN_LEFT;
nsIHTMLContent* content = nsnull; nsIHTMLContent* content = nsnull;
mContent->QueryInterface(kIHTMLContentIID, (void**) &content); mContent->QueryInterface(kIHTMLContentIID, (void**) &content);
if (nsnull != content) { if (nsnull != content) {
@ -229,18 +90,6 @@ PRInt32 nsLegendFrame::GetAlign()
return intValue; return intValue;
} }
PRIntn
nsLegendFrame::GetSkipSides() const
{
return 0;
}
PRBool
nsLegendFrame::IsInline()
{
return mInline;
}
NS_IMETHODIMP NS_IMETHODIMP
nsLegendFrame::GetFrameName(nsString& aResult) const nsLegendFrame::GetFrameName(nsString& aResult) const
{ {

Просмотреть файл

@ -19,7 +19,7 @@
#ifndef nsLegendFrame_h___ #ifndef nsLegendFrame_h___
#define nsLegendFrame_h___ #define nsLegendFrame_h___
#include "nsHTMLContainerFrame.h" #include "nsAreaFrame.h"
class nsIContent; class nsIContent;
class nsIFrame; class nsIFrame;
class nsIPresContext; class nsIPresContext;
@ -30,42 +30,16 @@ struct nsRect;
#define NS_LEGEND_FRAME_CID \ #define NS_LEGEND_FRAME_CID \
{ 0x73805d40, 0x5a24, 0x11d2, { 0x80, 0x46, 0x0, 0x60, 0x8, 0x15, 0xa7, 0x91 } } { 0x73805d40, 0x5a24, 0x11d2, { 0x80, 0x46, 0x0, 0x60, 0x8, 0x15, 0xa7, 0x91 } }
class nsLegendFrame : public nsHTMLContainerFrame { class nsLegendFrame : public nsAreaFrame {
public: public:
nsLegendFrame(); nsLegendFrame();
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_METHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD GetFrameName(nsString& aResult) const; NS_IMETHOD GetFrameName(nsString& aResult) const;
PRInt32 GetAlign(); PRInt32 GetAlign();
PRBool IsInline();
protected:
PRIntn GetSkipSides() const;
PRBool mInline;
//virtual void GetDesiredSize(nsIPresContext* aPresContext,
// const nsReflowState& aReflowState,
// nsReflowMetrics& aDesiredLayoutSize,
// nsSize& aDesiredWidgetSize);
}; };

Просмотреть файл

@ -47,6 +47,7 @@
#include "nsStyleConsts.h" #include "nsStyleConsts.h"
#include "nsStyleUtil.h" #include "nsStyleUtil.h"
#include "nsFont.h" #include "nsFont.h"
#include "nsCOMPtr.h"
static NS_DEFINE_IID(kLegendFrameCID, NS_LEGEND_FRAME_CID); static NS_DEFINE_IID(kLegendFrameCID, NS_LEGEND_FRAME_CID);
static NS_DEFINE_IID(kIDOMHTMLFieldSetElementIID, NS_IDOMHTMLFIELDSETELEMENT_IID); static NS_DEFINE_IID(kIDOMHTMLFieldSetElementIID, NS_IDOMHTMLFIELDSETELEMENT_IID);
@ -80,16 +81,11 @@ public:
protected: protected:
virtual PRIntn GetSkipSides() const; virtual PRIntn GetSkipSides() const;
//virtual void GetDesiredSize(nsIPresContext* aPresContext,
// const nsReflowState& aReflowState,
// nsReflowMetrics& aDesiredLayoutSize,
// nsSize& aDesiredWidgetSize);
nsIFrame* mLegendFrame; nsIFrame* mLegendFrame;
nsIFrame* mContentFrame; nsIFrame* mContentFrame;
nsRect mTopBorderGap; nsRect mLegendRect;
PRInt32 mTopBorderOffset; nscoord mLegendSpace;
PRBool mInline;
}; };
nsresult nsresult
@ -110,11 +106,9 @@ NS_NewFieldSetFrame(nsIFrame** aNewFrame)
nsFieldSetFrame::nsFieldSetFrame() nsFieldSetFrame::nsFieldSetFrame()
: nsHTMLContainerFrame() : nsHTMLContainerFrame()
{ {
mContentFrame = nsnull; mContentFrame = nsnull;
mLegendFrame = nsnull; mLegendFrame = nsnull;
mTopBorderGap = nsRect(0,0,0,0); mLegendSpace = 0;
mTopBorderOffset = 0;
mInline = PR_TRUE;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -125,9 +119,8 @@ nsFieldSetFrame::SetInitialChildList(nsIPresContext& aPresContext,
// cache our display type // cache our display type
const nsStyleDisplay* styleDisplay; const nsStyleDisplay* styleDisplay;
GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) styleDisplay); GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) styleDisplay);
mInline = (NS_STYLE_DISPLAY_BLOCK != styleDisplay->mDisplay);
PRUint8 flags = (mInline) ? NS_BLOCK_SHRINK_WRAP : 0; PRUint8 flags = (NS_STYLE_DISPLAY_BLOCK != styleDisplay->mDisplay) ? NS_BLOCK_SHRINK_WRAP : 0;
NS_NewAreaFrame(&mContentFrame, flags); NS_NewAreaFrame(&mContentFrame, flags);
mFrames.SetFrames(mContentFrame); mFrames.SetFrames(mContentFrame);
@ -202,24 +195,77 @@ nsFieldSetFrame::Paint(nsIPresContext& aPresContext,
const nsStyleSpacing* spacing = const nsStyleSpacing* spacing =
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
// XXX nsRect backgroundRect(0, 0, mRect.width, mRect.height); float p2t;
// XXX our parent doesn't account for top and bottom margins yet, if we are inline aPresContext.GetScaledPixelsToTwips(&p2t);
//if (mInline) { nscoord onePixel = NSIntPixelsToTwips(1, p2t);
// nsMargin margin;
// spacing->CalcMarginFor(this, margin); nsMargin border;
// nsRect rect(0, mTopBorderOffset, mRect.width, mRect.height - margin.top - spacing->GetBorder(border);
// margin.bottom - mTopBorderOffset);
// nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this, nscoord yoff = 0;
// aDirtyRect, rect, *color, *spacing, 0, 0);
// nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, // if the border is bigger than the legend. Move the border down
// aDirtyRect, rect, *spacing, mStyleContext, skipSides, &mTopBorderGap); // to be centered on the legend.
//} else { if (border.top < mLegendRect.height)
nsRect rect(0, mTopBorderOffset, mRect.width, mRect.height - mTopBorderOffset); yoff = (mLegendRect.height - border.top)/2;
nsRect rect(0, yoff, mRect.width, mRect.height - yoff);
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this, nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *color, *spacing, 0, 0); aDirtyRect, rect, *color, *spacing, 0, 0);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *spacing, mStyleContext, skipSides, &mTopBorderGap);
//} if (mLegendFrame) {
// we should probably use PaintBorderEdges to do this but for now just use clipping
// to achieve the same effect.
PRBool clipState;
// draw left side
nsRect clipRect(rect);
clipRect.width = mLegendRect.x - rect.x;
clipRect.height = border.top;
aRenderingContext.PushState();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect, clipState);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *spacing, mStyleContext, skipSides);
aRenderingContext.PopState(clipState);
// draw right side
clipRect = rect;
clipRect.x = mLegendRect.x + mLegendRect.width;
clipRect.width -= (mLegendRect.x + mLegendRect.width);
clipRect.height = border.top;
aRenderingContext.PushState();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect, clipState);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *spacing, mStyleContext, skipSides);
aRenderingContext.PopState(clipState);
// draw bottom
clipRect = rect;
clipRect.y += border.top;
clipRect.height = mRect.height - (yoff + border.top);
aRenderingContext.PushState();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect, clipState);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *spacing, mStyleContext, skipSides);
aRenderingContext.PopState(clipState);
} else {
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, nsRect(0,0,mRect.width, mRect.height), *spacing, mStyleContext, skipSides);
}
} }
} }
@ -239,260 +285,156 @@ nsFieldSetFrame::Paint(nsIPresContext& aPresContext,
return NS_OK; return NS_OK;
} }
// XXX a hack until the reflow state does this correctly
// XXX when it gets fixed, leave in the printf statements or add an assertion
static
void FieldSetHack(nsHTMLReflowState& aReflowState, char* aMessage, PRBool aUseMax)
{
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 DESIRED_LEGEND_OFFSET 10
NS_IMETHODIMP NS_IMETHODIMP
nsFieldSetFrame::Reflow(nsIPresContext& aPresContext, nsFieldSetFrame::Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize, nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState, const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus) nsReflowStatus& aStatus)
{ {
// XXX remove the following when the reflow state is fixed
#ifndef bug4534_not_fixed
FieldSetHack((nsHTMLReflowState&)aReflowState, "fieldset", PR_TRUE);
#endif
// availSize could have unconstrained values, don't perform any addition on them // availSize could have unconstrained values, don't perform any addition on them
nsSize availSize(aReflowState.computedWidth, aReflowState.computedHeight); nsSize availSize(aReflowState.computedWidth, aReflowState.computedHeight);
float p2t; // get our border and padding
aPresContext.GetScaledPixelsToTwips(&p2t); const nsMargin &borderPadding = aReflowState.mComputedBorderPadding;
const PRInt32 desiredLegendOffset = NSIntPixelsToTwips(DESIRED_LEGEND_OFFSET, p2t);
const nsStyleSpacing* spacing =
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
//nsMargin margin;
//spacing->CalcMarginFor(this, margin);
nsMargin border;
nsMargin padding;
spacing->CalcBorderFor(this, border);
spacing->CalcPaddingFor(this, padding);
nsMargin borderPadding = border + padding;
// Figure out how big the legend is if there is one.
nsMargin legendMargin(0,0,0,0); nsMargin legendMargin(0,0,0,0);
// if there is a legend frame flow it.
if (mLegendFrame) { if (mLegendFrame) {
nsHTMLReflowState legendReflowState(aPresContext, aReflowState,
mLegendFrame, nsSize(NS_INTRINSICSIZE,NS_INTRINSICSIZE));
// always give the legend as much size as it needs
legendReflowState.computedWidth = NS_INTRINSICSIZE;
legendReflowState.computedHeight = NS_INTRINSICSIZE;
ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, aStatus);
// get the legend's margin
nsIStyleContext* legendSC = nsnull; nsIStyleContext* legendSC = nsnull;
mLegendFrame->GetStyleContext(&legendSC); mLegendFrame->GetStyleContext(&legendSC);
if (legendSC) { if (legendSC) {
const nsStyleSpacing* legendSpacing = const nsStyleSpacing* legendSpacing =
(const nsStyleSpacing*)legendSC->GetStyleData(eStyleStruct_Spacing); (const nsStyleSpacing*)legendSC->GetStyleData(eStyleStruct_Spacing);
legendSpacing->CalcMarginFor(mLegendFrame, legendMargin); legendSpacing->GetMargin(legendMargin);
NS_RELEASE(legendSC); NS_RELEASE(legendSC);
} }
// figure out the legend's rectangle
mLegendRect.width = aDesiredSize.width + legendMargin.left + legendMargin.right;
mLegendRect.height = aDesiredSize.height + legendMargin.top + legendMargin.bottom;
mLegendRect.x = borderPadding.left;
mLegendRect.y = 0;
} }
// reduce available space by border, padding, etc. if we're in a constrained situation mLegendSpace = 0;
nscoord horTaken = borderPadding.left + borderPadding.right + legendMargin.left + legendMargin.right; if (mLegendRect.height > borderPadding.top) {
nscoord verTaken = borderPadding.top + borderPadding.bottom + legendMargin.top + legendMargin.bottom; // center the border on the legend
mLegendSpace = mLegendRect.height - borderPadding.top;
} else {
mLegendRect.y = (borderPadding.top - mLegendRect.height)/2;
}
// if we are contrained then remove the legend from our available height.
if (NS_INTRINSICSIZE != availSize.height) {
if (availSize.height >= mLegendSpace)
availSize.height -= mLegendSpace;
}
// don't get any smaller than the legend
if (NS_INTRINSICSIZE != availSize.width) { if (NS_INTRINSICSIZE != availSize.width) {
availSize.width -= horTaken; if (availSize.width < mLegendRect.width)
availSize.width = PR_MAX(availSize.width,0); availSize.width = mLegendRect.width;
}
if (NS_AUTOHEIGHT != availSize.height) {
// XXX this assumes that the legend is taller than the top border width
availSize.height -= verTaken;
availSize.height = PR_MAX(availSize.height,0);
} }
nsSize maxElementSize(0,0); /*
// get the content's margin
// Try to reflow the legend into the available space. It might not fit nsMargin contentMargin(0,0,0,0);
nsSize legendSize(0,0); nsCOMPtr<nsIStyleContext> contentSC;
if (mLegendFrame) { mContentFrame->GetStyleContext(getter_AddRefs(contentSC));
nsHTMLReflowState legendReflowState(aPresContext, aReflowState, if (contentSC) {
mLegendFrame, availSize); const nsStyleSpacing* spacing =
// XXX remove when reflow state is fixed (const nsStyleSpacing*)contentSC->GetStyleData(eStyleStruct_Spacing);
#ifndef bug4534_not_fixed spacing->GetMargin(contentMargin);
FieldSetHack((nsHTMLReflowState&)legendReflowState, "fieldset's legend", PR_FALSE);
#endif
ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, aStatus);
legendSize.width = aDesiredSize.width;
legendSize.height = aDesiredSize.height;
// The legend didn't fit
if ((NS_INTRINSICSIZE != availSize.width) &&
(availSize.width < aDesiredSize.width + legendMargin.left + legendMargin.right)) {
availSize.width = aDesiredSize.width + horTaken;
}
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;
}
} }
PRBool needAnotherLegendReflow = PR_FALSE; // remove it from our size if we are not intrinsic
if (NS_INTRINSICSIZE != availSize.height)
availSize.height -= (contentMargin.top + contentMargin.bottom);
// Try to reflow the area frame into the available space. It might not fit
if (NS_INTRINSICSIZE != availSize.width)
availSize.width -= (contentMargin.left + contentMargin.right);
*/
// Try to reflow the area frame into the available space.
nsHTMLReflowState contentReflowState(aPresContext, aReflowState, nsHTMLReflowState contentReflowState(aPresContext, aReflowState,
mContentFrame, availSize); mContentFrame, availSize);
// XXX remove when reflow state is fixed
#ifndef bug4534_not_fixed
FieldSetHack(contentReflowState, "fieldset's area", PR_FALSE);
#endif
nscoord contentTopOffset = (legendSize.height > border.top)
? legendSize.height + padding.top
: border.top + padding.top;
ReflowChild(mContentFrame, aPresContext, aDesiredSize, contentReflowState, aStatus); ReflowChild(mContentFrame, aPresContext, aDesiredSize, contentReflowState, aStatus);
//aDesiredSize.width += contentMargin.left + contentMargin.right;
//aDesiredSize.height += contentMargin.top + contentMargin.bottom;
nsSize contentSize(aDesiredSize.width, aDesiredSize.height); // set the rect. make sure we add the margin back in.
nsRect contentRect(borderPadding.left,borderPadding.top + mLegendSpace,aDesiredSize.width ,aDesiredSize.height);
// The content didn't fit PRInt32 align = ((nsLegendFrame*)mLegendFrame)->GetAlign();
if ((NS_UNCONSTRAINEDSIZE != availSize.width) && (availSize.width < aDesiredSize.width)) {
needAnotherLegendReflow = PR_TRUE;
availSize.width = contentSize.width + borderPadding.left + borderPadding.right;
}
if ((NS_UNCONSTRAINEDSIZE != availSize.height) && (availSize.height < aDesiredSize.height)) {
needAnotherLegendReflow = PR_TRUE;
}
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 switch(align) {
if (needAnotherLegendReflow && mLegendFrame) {
nsHTMLReflowState legendReflowState(aPresContext, aReflowState,
mLegendFrame, availSize);
// XXX remove when reflow state is fixed
#ifndef bug4534_not_fixed
FieldSetHack(legendReflowState, "fieldset's legend frame", PR_FALSE);
#endif
ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, aStatus);
legendSize.width = aDesiredSize.width;
legendSize.height = aDesiredSize.height;
}
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 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 (mLegendFrame) {
nscoord legendTopOffset;
if (legendSize.height > border.top) {
legendTopOffset = 0;
} else {
legendTopOffset = (border.top - legendSize.height) / 2;
}
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 + desiredLegendOffset;
break;
case NS_STYLE_TEXT_ALIGN_RIGHT: case NS_STYLE_TEXT_ALIGN_RIGHT:
legendLeftOffset = aDesiredSize.width - border.right - desiredLegendOffset - legendSize.width; mLegendRect.x = contentRect.width - mLegendRect.width + borderPadding.left;
break; 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
// of the spec.
case NS_STYLE_TEXT_ALIGN_CENTER: case NS_STYLE_TEXT_ALIGN_CENTER:
case NS_STYLE_VERTICAL_ALIGN_BOTTOM: mLegendRect.x = contentRect.width/2 - mLegendRect.width/2 + borderPadding.left;
case NS_STYLE_VERTICAL_ALIGN_TOP:
default:
legendLeftOffset = (aDesiredSize.width - legendSize.width) / 2;
break;
}
// reduce by legend margins
legendRect = nsRect(legendLeftOffset + legendMargin.left, legendTopOffset + legendMargin.top,
legendSize.width, legendSize.height);
mLegendFrame->SetRect(legendRect);
// cache values so the border will be painted around the vertical center of the legend
mTopBorderOffset = legendSize.height / 2;
mTopBorderGap = nsRect(legendLeftOffset, legendTopOffset, legendSize.width + legendMargin.left +
legendMargin.right, legendSize.height + legendMargin.top +
legendMargin.bottom);
} }
// Place the content area frame // Place the content area frame.
nsRect contentRect(borderPadding.left, contentTopOffset, contentSize.width, contentSize.height);
mContentFrame->SetRect(contentRect); mContentFrame->SetRect(contentRect);
// Return our size and our result // place the legend
aDesiredSize.height = contentTopOffset + legendSize.height + contentSize.height + borderPadding.bottom; nsRect actualLegendRect(mLegendRect);
actualLegendRect.Deflate(legendMargin);
mLegendFrame->SetRect(actualLegendRect);
// if we are constrained and the child is smaller, use the constrained values // Return our size and our result
if ((NS_AUTOHEIGHT != aReflowState.computedHeight) && (aReflowState.computedHeight > aDesiredSize.height)) { if (aReflowState.computedHeight == NS_INTRINSICSIZE) {
aDesiredSize.height = aReflowState.computedHeight; aDesiredSize.height = mLegendSpace +
borderPadding.top +
aDesiredSize.height +
borderPadding.bottom;
} else {
nscoord min = borderPadding.top + borderPadding.bottom + mLegendRect.height;
aDesiredSize.height = aReflowState.computedHeight + borderPadding.top + borderPadding.bottom;
if (aDesiredSize.height < min)
aDesiredSize.height = min;
} }
if (aReflowState.computedWidth == NS_INTRINSICSIZE) {
aDesiredSize.width = borderPadding.left +
aDesiredSize.width +
borderPadding.right;
} else {
nscoord min = borderPadding.left + borderPadding.right + mLegendRect.width;
aDesiredSize.width = aReflowState.computedWidth + borderPadding.left + borderPadding.right;
if (aDesiredSize.width < min)
aDesiredSize.width = min;
}
aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.ascent = aDesiredSize.height;
aDesiredSize.descent = 0; aDesiredSize.descent = 0;
if (nsnull != aDesiredSize.maxElementSize) { if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = maxElementSize.width; // if the legend it wider use it
aDesiredSize.maxElementSize->height = maxElementSize.height; if (aDesiredSize.maxElementSize->width < mLegendRect.width)
aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding); aDesiredSize.maxElementSize->width = mLegendRect.width;
// add in padding.
aDesiredSize.maxElementSize->width += borderPadding.left + borderPadding.right;
// height is border + legend
aDesiredSize.maxElementSize->height += borderPadding.top + borderPadding.bottom + mLegendRect.height;
} }
aStatus = NS_FRAME_COMPLETE; aStatus = NS_FRAME_COMPLETE;

Просмотреть файл

@ -18,14 +18,11 @@
// YY need to pass isMultiple before create called // YY need to pass isMultiple before create called
//#include "nsFormControlFrame.h"
#include "nsLegendFrame.h" #include "nsLegendFrame.h"
#include "nsIDOMNode.h" #include "nsIDOMNode.h"
#include "nsIDOMHTMLLegendElement.h" #include "nsIDOMHTMLLegendElement.h"
#include "nsCSSRendering.h" #include "nsCSSRendering.h"
//#include "nsIDOMHTMLCollection.h"
#include "nsIContent.h" #include "nsIContent.h"
//#include "prtypes.h"
#include "nsIFrame.h" #include "nsIFrame.h"
#include "nsISupports.h" #include "nsISupports.h"
#include "nsIAtom.h" #include "nsIAtom.h"
@ -33,14 +30,7 @@
#include "nsIHTMLContent.h" #include "nsIHTMLContent.h"
#include "nsHTMLIIDs.h" #include "nsHTMLIIDs.h"
#include "nsHTMLParts.h" #include "nsHTMLParts.h"
//#include "nsIRadioButton.h"
//#include "nsWidgetsCID.h"
//#include "nsSize.h"
#include "nsHTMLAtoms.h" #include "nsHTMLAtoms.h"
//#include "nsIView.h"
//#include "nsIListWidget.h"
//#include "nsIComboBox.h"
//#include "nsIListBox.h"
#include "nsIStyleContext.h" #include "nsIStyleContext.h"
#include "nsStyleConsts.h" #include "nsStyleConsts.h"
#include "nsStyleUtil.h" #include "nsStyleUtil.h"
@ -65,9 +55,8 @@ NS_NewLegendFrame(nsIFrame** aNewFrame)
} }
nsLegendFrame::nsLegendFrame() nsLegendFrame::nsLegendFrame()
: nsHTMLContainerFrame() : nsAreaFrame()
{ {
mInline = PR_FALSE;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -84,137 +73,9 @@ nsLegendFrame::QueryInterface(REFNSIID aIID, void** aInstancePtrResult)
return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtrResult); return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtrResult);
} }
NS_IMETHODIMP
nsLegendFrame::SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
// cache our display type
const nsStyleDisplay* styleDisplay;
GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) styleDisplay);
mInline = (NS_STYLE_DISPLAY_BLOCK != styleDisplay->mDisplay);
PRUint8 flags = (mInline) ? NS_BLOCK_SHRINK_WRAP : 0;
nsIFrame* areaFrame;
NS_NewAreaFrame(&areaFrame, flags);
mFrames.SetFrames(areaFrame);
// Resolve style and initialize the frame
nsIStyleContext* styleContext;
aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::legendContentPseudo,
mStyleContext, PR_FALSE,
&styleContext);
mFrames.FirstChild()->Init(aPresContext, mContent, this, styleContext, nsnull);
NS_RELEASE(styleContext);
// Set the parent for each of the child frames
for (nsIFrame* frame = aChildList; nsnull != frame; frame->GetNextSibling(&frame)) {
frame->SetParent(mFrames.FirstChild());
}
// Queue up the frames for the inline frame
return mFrames.FirstChild()->SetInitialChildList(aPresContext, nsnull, aChildList);
}
NS_IMETHODIMP
nsLegendFrame::Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
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
static
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)
{
//XXX remove when reflow state is fixed
LegendHack((nsHTMLReflowState&)aReflowState, "legend");
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.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, aReflowState, firstKid,
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);
// add in our border and padding to the size of the child
aDesiredSize.width += borderPadding.left + borderPadding.right;
if (aReflowState.HaveFixedContentWidth() && (aReflowState.computedWidth > aDesiredSize.width)) {
aDesiredSize.width = aReflowState.computedWidth;
}
aDesiredSize.height += borderPadding.top + borderPadding.bottom;
if (aReflowState.HaveFixedContentHeight() && (aReflowState.computedHeight > aDesiredSize.height)) {
aDesiredSize.height = aReflowState.computedHeight;
}
// adjust our max element size, if necessary
if (aDesiredSize.maxElementSize) {
aDesiredSize.AddBorderPaddingToMaxElementSize(borderPadding);
}
aDesiredSize.ascent = aDesiredSize.height;
aDesiredSize.descent = 0;
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
PRInt32 nsLegendFrame::GetAlign() PRInt32 nsLegendFrame::GetAlign()
{ {
PRInt32 intValue = NS_STYLE_TEXT_ALIGN_CENTER; PRInt32 intValue = NS_STYLE_TEXT_ALIGN_LEFT;
nsIHTMLContent* content = nsnull; nsIHTMLContent* content = nsnull;
mContent->QueryInterface(kIHTMLContentIID, (void**) &content); mContent->QueryInterface(kIHTMLContentIID, (void**) &content);
if (nsnull != content) { if (nsnull != content) {
@ -229,18 +90,6 @@ PRInt32 nsLegendFrame::GetAlign()
return intValue; return intValue;
} }
PRIntn
nsLegendFrame::GetSkipSides() const
{
return 0;
}
PRBool
nsLegendFrame::IsInline()
{
return mInline;
}
NS_IMETHODIMP NS_IMETHODIMP
nsLegendFrame::GetFrameName(nsString& aResult) const nsLegendFrame::GetFrameName(nsString& aResult) const
{ {

Просмотреть файл

@ -19,7 +19,7 @@
#ifndef nsLegendFrame_h___ #ifndef nsLegendFrame_h___
#define nsLegendFrame_h___ #define nsLegendFrame_h___
#include "nsHTMLContainerFrame.h" #include "nsAreaFrame.h"
class nsIContent; class nsIContent;
class nsIFrame; class nsIFrame;
class nsIPresContext; class nsIPresContext;
@ -30,42 +30,16 @@ struct nsRect;
#define NS_LEGEND_FRAME_CID \ #define NS_LEGEND_FRAME_CID \
{ 0x73805d40, 0x5a24, 0x11d2, { 0x80, 0x46, 0x0, 0x60, 0x8, 0x15, 0xa7, 0x91 } } { 0x73805d40, 0x5a24, 0x11d2, { 0x80, 0x46, 0x0, 0x60, 0x8, 0x15, 0xa7, 0x91 } }
class nsLegendFrame : public nsHTMLContainerFrame { class nsLegendFrame : public nsAreaFrame {
public: public:
nsLegendFrame(); nsLegendFrame();
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_METHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD GetFrameName(nsString& aResult) const; NS_IMETHOD GetFrameName(nsString& aResult) const;
PRInt32 GetAlign(); PRInt32 GetAlign();
PRBool IsInline();
protected:
PRIntn GetSkipSides() const;
PRBool mInline;
//virtual void GetDesiredSize(nsIPresContext* aPresContext,
// const nsReflowState& aReflowState,
// nsReflowMetrics& aDesiredLayoutSize,
// nsSize& aDesiredWidgetSize);
}; };

Просмотреть файл

@ -667,13 +667,13 @@ nsBoxFrame::BoundsCheck(const nsBoxInfo& aBoxInfo, nsRect& aRect)
if (aRect.width == NS_INTRINSICSIZE ) if (aRect.width == NS_INTRINSICSIZE )
aRect.width = aBoxInfo.prefSize.width; aRect.width = aBoxInfo.prefSize.width;
/*
// make sure the available size is no bigger than the max size // make sure the available size is no bigger than the max size
if (aRect.height > aBoxInfo.maxSize.height) if (aRect.height > aBoxInfo.maxSize.height)
aRect.height = aBoxInfo.maxSize.height; aRect.height = aBoxInfo.maxSize.height;
if (aRect.width > aBoxInfo.maxSize.width) if (aRect.width > aBoxInfo.maxSize.width)
aRect.width = aBoxInfo.maxSize.width); aRect.width = aBoxInfo.maxSize.width;
// make sure the available size is at least as big as the min size // make sure the available size is at least as big as the min size
if (aRect.height < aBoxInfo.minSize.height) if (aRect.height < aBoxInfo.minSize.height)
@ -681,7 +681,7 @@ nsBoxFrame::BoundsCheck(const nsBoxInfo& aBoxInfo, nsRect& aRect)
if (aRect.width < aBoxInfo.minSize.width) if (aRect.width < aBoxInfo.minSize.width)
aRect.width = aBoxInfo.minSize.width; aRect.width = aBoxInfo.minSize.width;
*/
} }
/** /**