зеркало из https://github.com/mozilla/pjs.git
Reworked fieldsets to fix numerous bugs.
This commit is contained in:
Родитель
6672081973
Коммит
4b0b0ef6f4
|
@ -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;
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Загрузка…
Ссылка в новой задаче