michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsFieldSetFrame.h" michael@0: michael@0: #include "nsCSSAnonBoxes.h" michael@0: #include "nsLegendFrame.h" michael@0: #include "nsCSSRendering.h" michael@0: #include michael@0: #include "nsIFrame.h" michael@0: #include "nsPresContext.h" michael@0: #include "RestyleManager.h" michael@0: #include "nsGkAtoms.h" michael@0: #include "nsStyleConsts.h" michael@0: #include "nsDisplayList.h" michael@0: #include "nsRenderingContext.h" michael@0: #include "nsIScrollableFrame.h" michael@0: #include "mozilla/Likely.h" michael@0: #include "mozilla/Maybe.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::layout; michael@0: michael@0: nsIFrame* michael@0: NS_NewFieldSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) michael@0: { michael@0: return new (aPresShell) nsFieldSetFrame(aContext); michael@0: } michael@0: michael@0: NS_IMPL_FRAMEARENA_HELPERS(nsFieldSetFrame) michael@0: michael@0: nsFieldSetFrame::nsFieldSetFrame(nsStyleContext* aContext) michael@0: : nsContainerFrame(aContext) michael@0: { michael@0: mLegendSpace = 0; michael@0: } michael@0: michael@0: nsIAtom* michael@0: nsFieldSetFrame::GetType() const michael@0: { michael@0: return nsGkAtoms::fieldSetFrame; michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: nsresult michael@0: nsFieldSetFrame::SetInitialChildList(ChildListID aListID, michael@0: nsFrameList& aChildList) michael@0: { michael@0: nsresult rv = nsContainerFrame::SetInitialChildList(kPrincipalList, aChildList); michael@0: MOZ_ASSERT(GetInner()); michael@0: return rv; michael@0: } michael@0: #endif michael@0: michael@0: nsRect michael@0: nsFieldSetFrame::VisualBorderRectRelativeToSelf() const michael@0: { michael@0: nscoord topBorder = StyleBorder()->GetComputedBorderWidth(NS_SIDE_TOP); michael@0: nsRect r(nsPoint(0,0), GetSize()); michael@0: if (topBorder < mLegendRect.height) { michael@0: nscoord yoff = (mLegendRect.height - topBorder) / 2; michael@0: r.y += yoff; michael@0: r.height -= yoff; michael@0: } michael@0: return r; michael@0: } michael@0: michael@0: nsIFrame* michael@0: nsFieldSetFrame::GetInner() const michael@0: { michael@0: nsIFrame* last = mFrames.LastChild(); michael@0: if (last && michael@0: last->StyleContext()->GetPseudo() == nsCSSAnonBoxes::fieldsetContent) { michael@0: return last; michael@0: } michael@0: MOZ_ASSERT(mFrames.LastChild() == mFrames.FirstChild()); michael@0: return nullptr; michael@0: } michael@0: michael@0: nsIFrame* michael@0: nsFieldSetFrame::GetLegend() const michael@0: { michael@0: if (mFrames.FirstChild() == GetInner()) { michael@0: MOZ_ASSERT(mFrames.LastChild() == mFrames.FirstChild()); michael@0: return nullptr; michael@0: } michael@0: MOZ_ASSERT(mFrames.FirstChild() && michael@0: mFrames.FirstChild()->GetContentInsertionFrame()->GetType() == michael@0: nsGkAtoms::legendFrame); michael@0: return mFrames.FirstChild(); michael@0: } michael@0: michael@0: class nsDisplayFieldSetBorderBackground : public nsDisplayItem { michael@0: public: michael@0: nsDisplayFieldSetBorderBackground(nsDisplayListBuilder* aBuilder, michael@0: nsFieldSetFrame* aFrame) michael@0: : nsDisplayItem(aBuilder, aFrame) { michael@0: MOZ_COUNT_CTOR(nsDisplayFieldSetBorderBackground); michael@0: } michael@0: #ifdef NS_BUILD_REFCNT_LOGGING michael@0: virtual ~nsDisplayFieldSetBorderBackground() { michael@0: MOZ_COUNT_DTOR(nsDisplayFieldSetBorderBackground); michael@0: } michael@0: #endif michael@0: michael@0: virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, michael@0: HitTestState* aState, michael@0: nsTArray *aOutFrames) MOZ_OVERRIDE; michael@0: virtual void Paint(nsDisplayListBuilder* aBuilder, michael@0: nsRenderingContext* aCtx) MOZ_OVERRIDE; michael@0: virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, michael@0: const nsDisplayItemGeometry* aGeometry, michael@0: nsRegion *aInvalidRegion) MOZ_OVERRIDE; michael@0: NS_DISPLAY_DECL_NAME("FieldSetBorderBackground", TYPE_FIELDSET_BORDER_BACKGROUND) michael@0: }; michael@0: michael@0: void nsDisplayFieldSetBorderBackground::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, michael@0: HitTestState* aState, nsTArray *aOutFrames) michael@0: { michael@0: // aPt is guaranteed to be in this item's bounds. We do the hit test based on the michael@0: // frame bounds even though our background doesn't cover the whole frame. michael@0: // It's not clear whether this is correct. michael@0: aOutFrames->AppendElement(mFrame); michael@0: } michael@0: michael@0: void michael@0: nsDisplayFieldSetBorderBackground::Paint(nsDisplayListBuilder* aBuilder, michael@0: nsRenderingContext* aCtx) michael@0: { michael@0: static_cast(mFrame)-> michael@0: PaintBorderBackground(*aCtx, ToReferenceFrame(), michael@0: mVisibleRect, aBuilder->GetBackgroundPaintFlags()); michael@0: } michael@0: michael@0: void michael@0: nsDisplayFieldSetBorderBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, michael@0: const nsDisplayItemGeometry* aGeometry, michael@0: nsRegion *aInvalidRegion) michael@0: { michael@0: AddInvalidRegionForSyncDecodeBackgroundImages(aBuilder, aGeometry, aInvalidRegion); michael@0: michael@0: nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion); michael@0: } michael@0: michael@0: void michael@0: nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, michael@0: const nsRect& aDirtyRect, michael@0: const nsDisplayListSet& aLists) { michael@0: // Paint our background and border in a special way. michael@0: // REVIEW: We don't really need to check frame emptiness here; if it's empty, michael@0: // the background/border display item won't do anything, and if it isn't empty, michael@0: // we need to paint the outline michael@0: if (!(GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) && michael@0: IsVisibleForPainting(aBuilder)) { michael@0: if (StyleBorder()->mBoxShadow) { michael@0: aLists.BorderBackground()->AppendNewToTop(new (aBuilder) michael@0: nsDisplayBoxShadowOuter(aBuilder, this)); michael@0: } michael@0: michael@0: // don't bother checking to see if we really have a border or background. michael@0: // we usually will have a border. michael@0: aLists.BorderBackground()->AppendNewToTop(new (aBuilder) michael@0: nsDisplayFieldSetBorderBackground(aBuilder, this)); michael@0: michael@0: DisplayOutlineUnconditional(aBuilder, aLists); michael@0: michael@0: DO_GLOBAL_REFLOW_COUNT_DSP("nsFieldSetFrame"); michael@0: } michael@0: michael@0: if (GetPrevInFlow()) { michael@0: DisplayOverflowContainers(aBuilder, aDirtyRect, aLists); michael@0: } michael@0: michael@0: nsDisplayListCollection contentDisplayItems; michael@0: if (nsIFrame* inner = GetInner()) { michael@0: // Collect the inner frame's display items into their own collection. michael@0: // We need to be calling BuildDisplayList on it before the legend in michael@0: // case it contains out-of-flow frames whose placeholders are in the michael@0: // legend. However, we want the inner frame's display items to be michael@0: // after the legend's display items in z-order, so we need to save them michael@0: // and append them later. michael@0: BuildDisplayListForChild(aBuilder, inner, aDirtyRect, contentDisplayItems); michael@0: } michael@0: if (nsIFrame* legend = GetLegend()) { michael@0: // The legend's background goes on our BlockBorderBackgrounds list because michael@0: // it's a block child. michael@0: nsDisplayListSet set(aLists, aLists.BlockBorderBackgrounds()); michael@0: BuildDisplayListForChild(aBuilder, legend, aDirtyRect, set); michael@0: } michael@0: // Put the inner frame's display items on the master list. Note that this michael@0: // moves its border/background display items to our BorderBackground() list, michael@0: // which isn't really correct, but it's OK because the inner frame is michael@0: // anonymous and can't have its own border and background. michael@0: contentDisplayItems.MoveTo(aLists); michael@0: } michael@0: michael@0: void michael@0: nsFieldSetFrame::PaintBorderBackground(nsRenderingContext& aRenderingContext, michael@0: nsPoint aPt, const nsRect& aDirtyRect, uint32_t aBGFlags) michael@0: { michael@0: // if the border is smaller than the legend. Move the border down michael@0: // to be centered on the legend. michael@0: // FIXME: This means border-radius clamping is incorrect; we should michael@0: // override nsIFrame::GetBorderRadii. michael@0: nsRect rect = VisualBorderRectRelativeToSelf(); michael@0: nscoord yoff = rect.y; michael@0: rect += aPt; michael@0: nsPresContext* presContext = PresContext(); michael@0: michael@0: nsCSSRendering::PaintBackground(presContext, aRenderingContext, this, michael@0: aDirtyRect, rect, aBGFlags); michael@0: michael@0: nsCSSRendering::PaintBoxShadowInner(presContext, aRenderingContext, michael@0: this, rect, aDirtyRect); michael@0: michael@0: if (nsIFrame* legend = GetLegend()) { michael@0: nscoord topBorder = StyleBorder()->GetComputedBorderWidth(NS_SIDE_TOP); michael@0: michael@0: // Use the rect of the legend frame, not mLegendRect, so we draw our michael@0: // border under the legend's left and right margins. michael@0: nsRect legendRect = legend->GetRect() + aPt; michael@0: michael@0: // we should probably use PaintBorderEdges to do this but for now just use clipping michael@0: // to achieve the same effect. michael@0: michael@0: // draw left side michael@0: nsRect clipRect(rect); michael@0: clipRect.width = legendRect.x - rect.x; michael@0: clipRect.height = topBorder; michael@0: michael@0: aRenderingContext.PushState(); michael@0: aRenderingContext.IntersectClip(clipRect); michael@0: nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, michael@0: aDirtyRect, rect, mStyleContext); michael@0: michael@0: aRenderingContext.PopState(); michael@0: michael@0: michael@0: // draw right side michael@0: clipRect = rect; michael@0: clipRect.x = legendRect.XMost(); michael@0: clipRect.width = rect.XMost() - legendRect.XMost(); michael@0: clipRect.height = topBorder; michael@0: michael@0: aRenderingContext.PushState(); michael@0: aRenderingContext.IntersectClip(clipRect); michael@0: nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, michael@0: aDirtyRect, rect, mStyleContext); michael@0: michael@0: aRenderingContext.PopState(); michael@0: michael@0: michael@0: // draw bottom michael@0: clipRect = rect; michael@0: clipRect.y += topBorder; michael@0: clipRect.height = mRect.height - (yoff + topBorder); michael@0: michael@0: aRenderingContext.PushState(); michael@0: aRenderingContext.IntersectClip(clipRect); michael@0: nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, michael@0: aDirtyRect, rect, mStyleContext); michael@0: michael@0: aRenderingContext.PopState(); michael@0: } else { michael@0: michael@0: nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, michael@0: aDirtyRect, michael@0: nsRect(aPt, mRect.Size()), michael@0: mStyleContext); michael@0: } michael@0: } michael@0: michael@0: nscoord michael@0: nsFieldSetFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext, michael@0: nsLayoutUtils::IntrinsicWidthType aType) michael@0: { michael@0: nscoord legendWidth = 0; michael@0: nscoord contentWidth = 0; michael@0: if (nsIFrame* legend = GetLegend()) { michael@0: legendWidth = michael@0: nsLayoutUtils::IntrinsicForContainer(aRenderingContext, legend, aType); michael@0: } michael@0: michael@0: if (nsIFrame* inner = GetInner()) { michael@0: // Ignore padding on the inner, since the padding will be applied to the michael@0: // outer instead, and the padding computed for the inner is wrong michael@0: // for percentage padding. michael@0: contentWidth = michael@0: nsLayoutUtils::IntrinsicForContainer(aRenderingContext, inner, aType, michael@0: nsLayoutUtils::IGNORE_PADDING); michael@0: } michael@0: michael@0: return std::max(legendWidth, contentWidth); michael@0: } michael@0: michael@0: michael@0: nscoord michael@0: nsFieldSetFrame::GetMinWidth(nsRenderingContext* aRenderingContext) michael@0: { michael@0: nscoord result = 0; michael@0: DISPLAY_MIN_WIDTH(this, result); michael@0: michael@0: result = GetIntrinsicWidth(aRenderingContext, nsLayoutUtils::MIN_WIDTH); michael@0: return result; michael@0: } michael@0: michael@0: nscoord michael@0: nsFieldSetFrame::GetPrefWidth(nsRenderingContext* aRenderingContext) michael@0: { michael@0: nscoord result = 0; michael@0: DISPLAY_PREF_WIDTH(this, result); michael@0: michael@0: result = GetIntrinsicWidth(aRenderingContext, nsLayoutUtils::PREF_WIDTH); michael@0: return result; michael@0: } michael@0: michael@0: /* virtual */ nsSize michael@0: nsFieldSetFrame::ComputeSize(nsRenderingContext *aRenderingContext, michael@0: nsSize aCBSize, nscoord aAvailableWidth, michael@0: nsSize aMargin, nsSize aBorder, nsSize aPadding, michael@0: uint32_t aFlags) michael@0: { michael@0: nsSize result = michael@0: nsContainerFrame::ComputeSize(aRenderingContext, aCBSize, aAvailableWidth, michael@0: aMargin, aBorder, aPadding, aFlags); michael@0: michael@0: // Fieldsets never shrink below their min width. michael@0: michael@0: // If we're a container for font size inflation, then shrink michael@0: // wrapping inside of us should not apply font size inflation. michael@0: AutoMaybeDisableFontInflation an(this); michael@0: michael@0: nscoord minWidth = GetMinWidth(aRenderingContext); michael@0: if (minWidth > result.width) michael@0: result.width = minWidth; michael@0: michael@0: return result; michael@0: } michael@0: michael@0: nsresult michael@0: nsFieldSetFrame::Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) michael@0: { michael@0: DO_GLOBAL_REFLOW_COUNT("nsFieldSetFrame"); michael@0: DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); michael@0: michael@0: NS_PRECONDITION(aReflowState.ComputedWidth() != NS_INTRINSICSIZE, michael@0: "Should have a precomputed width!"); michael@0: michael@0: // Initialize OUT parameter michael@0: aStatus = NS_FRAME_COMPLETE; michael@0: michael@0: nsOverflowAreas ocBounds; michael@0: nsReflowStatus ocStatus = NS_FRAME_COMPLETE; michael@0: if (GetPrevInFlow()) { michael@0: ReflowOverflowContainerChildren(aPresContext, aReflowState, ocBounds, 0, michael@0: ocStatus); michael@0: } michael@0: michael@0: //------------ Handle Incremental Reflow ----------------- michael@0: bool reflowInner; michael@0: bool reflowLegend; michael@0: nsIFrame* legend = GetLegend(); michael@0: nsIFrame* inner = GetInner(); michael@0: if (aReflowState.ShouldReflowAllKids()) { michael@0: reflowInner = inner != nullptr; michael@0: reflowLegend = legend != nullptr; michael@0: } else { michael@0: reflowInner = inner && NS_SUBTREE_DIRTY(inner); michael@0: reflowLegend = legend && NS_SUBTREE_DIRTY(legend); michael@0: } michael@0: michael@0: // We don't allow fieldsets to break vertically. If we did, we'd michael@0: // need logic here to push and pull overflow frames. michael@0: // Since we're not applying our padding in this frame, we need to add it here michael@0: // to compute the available width for our children. michael@0: nsSize availSize(aReflowState.ComputedWidth() + aReflowState.ComputedPhysicalPadding().LeftRight(), michael@0: NS_UNCONSTRAINEDSIZE); michael@0: NS_ASSERTION(!inner || michael@0: nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext, michael@0: inner, michael@0: nsLayoutUtils::MIN_WIDTH) <= michael@0: availSize.width, michael@0: "Bogus availSize.width; should be bigger"); michael@0: NS_ASSERTION(!legend || michael@0: nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext, michael@0: legend, michael@0: nsLayoutUtils::MIN_WIDTH) <= michael@0: availSize.width, michael@0: "Bogus availSize.width; should be bigger"); michael@0: michael@0: // get our border and padding michael@0: nsMargin border = aReflowState.ComputedPhysicalBorderPadding() - aReflowState.ComputedPhysicalPadding(); michael@0: michael@0: // Figure out how big the legend is if there is one. michael@0: // get the legend's margin michael@0: nsMargin legendMargin(0,0,0,0); michael@0: // reflow the legend only if needed michael@0: Maybe legendReflowState; michael@0: if (legend) { michael@0: legendReflowState.construct(aPresContext, aReflowState, legend, availSize); michael@0: } michael@0: if (reflowLegend) { michael@0: nsHTMLReflowMetrics legendDesiredSize(aReflowState); michael@0: michael@0: ReflowChild(legend, aPresContext, legendDesiredSize, legendReflowState.ref(), michael@0: 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); michael@0: #ifdef NOISY_REFLOW michael@0: printf(" returned (%d, %d)\n", legendDesiredSize.Width(), legendDesiredSize.Height()); michael@0: #endif michael@0: // figure out the legend's rectangle michael@0: legendMargin = legend->GetUsedMargin(); michael@0: mLegendRect.width = legendDesiredSize.Width() + legendMargin.left + legendMargin.right; michael@0: mLegendRect.height = legendDesiredSize.Height() + legendMargin.top + legendMargin.bottom; michael@0: mLegendRect.x = 0; michael@0: mLegendRect.y = 0; michael@0: michael@0: nscoord oldSpace = mLegendSpace; michael@0: mLegendSpace = 0; michael@0: if (mLegendRect.height > border.top) { michael@0: // center the border on the legend michael@0: mLegendSpace = mLegendRect.height - border.top; michael@0: } else { michael@0: mLegendRect.y = (border.top - mLegendRect.height)/2; michael@0: } michael@0: michael@0: // if the legend space changes then we need to reflow the michael@0: // content area as well. michael@0: if (mLegendSpace != oldSpace && inner) { michael@0: reflowInner = true; michael@0: } michael@0: michael@0: FinishReflowChild(legend, aPresContext, legendDesiredSize, michael@0: &legendReflowState.ref(), 0, 0, NS_FRAME_NO_MOVE_FRAME); michael@0: } else if (!legend) { michael@0: mLegendRect.SetEmpty(); michael@0: mLegendSpace = 0; michael@0: } else { michael@0: // mLegendSpace and mLegendRect haven't changed, but we need michael@0: // the used margin when placing the legend. michael@0: legendMargin = legend->GetUsedMargin(); michael@0: } michael@0: michael@0: // reflow the content frame only if needed michael@0: if (reflowInner) { michael@0: nsHTMLReflowState kidReflowState(aPresContext, aReflowState, inner, michael@0: availSize, -1, -1, nsHTMLReflowState::CALLER_WILL_INIT); michael@0: // Override computed padding, in case it's percentage padding michael@0: kidReflowState.Init(aPresContext, -1, -1, nullptr, michael@0: &aReflowState.ComputedPhysicalPadding()); michael@0: // Our child is "height:100%" but we actually want its height to be reduced michael@0: // by the amount of content-height the legend is eating up, unless our michael@0: // height is unconstrained (in which case the child's will be too). michael@0: if (aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE) { michael@0: kidReflowState.SetComputedHeight( michael@0: std::max(0, aReflowState.ComputedHeight() - mLegendSpace)); michael@0: } michael@0: michael@0: if (aReflowState.ComputedMinHeight() > 0) { michael@0: kidReflowState.ComputedMinHeight() = michael@0: std::max(0, aReflowState.ComputedMinHeight() - mLegendSpace); michael@0: } michael@0: michael@0: if (aReflowState.ComputedMaxHeight() != NS_UNCONSTRAINEDSIZE) { michael@0: kidReflowState.ComputedMaxHeight() = michael@0: std::max(0, aReflowState.ComputedMaxHeight() - mLegendSpace); michael@0: } michael@0: michael@0: nsHTMLReflowMetrics kidDesiredSize(kidReflowState, michael@0: aDesiredSize.mFlags); michael@0: // Reflow the frame michael@0: NS_ASSERTION(kidReflowState.ComputedPhysicalMargin() == nsMargin(0,0,0,0), michael@0: "Margins on anonymous fieldset child not supported!"); michael@0: nsPoint pt(border.left, border.top + mLegendSpace); michael@0: ReflowChild(inner, aPresContext, kidDesiredSize, kidReflowState, michael@0: pt.x, pt.y, 0, aStatus); michael@0: michael@0: FinishReflowChild(inner, aPresContext, kidDesiredSize, michael@0: &kidReflowState, pt.x, pt.y, 0); michael@0: NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus); michael@0: } michael@0: michael@0: nsRect contentRect; michael@0: if (inner) { michael@0: // We don't support margins on inner, so our content rect is just the michael@0: // inner's border-box. michael@0: contentRect = inner->GetRect(); michael@0: } michael@0: michael@0: // Our content rect must fill up the available width michael@0: if (availSize.width > contentRect.width) { michael@0: contentRect.width = availSize.width; michael@0: } michael@0: michael@0: if (legend) { michael@0: // the legend is postioned horizontally within the inner's content rect michael@0: // (so that padding on the fieldset affects the legend position). michael@0: nsRect innerContentRect = contentRect; michael@0: innerContentRect.Deflate(aReflowState.ComputedPhysicalPadding()); michael@0: // if the inner content rect is larger than the legend, we can align the legend michael@0: if (innerContentRect.width > mLegendRect.width) { michael@0: int32_t align = static_cast michael@0: (legend->GetContentInsertionFrame())->GetAlign(); michael@0: michael@0: switch (align) { michael@0: case NS_STYLE_TEXT_ALIGN_RIGHT: michael@0: mLegendRect.x = innerContentRect.XMost() - mLegendRect.width; michael@0: break; michael@0: case NS_STYLE_TEXT_ALIGN_CENTER: michael@0: // Note: rounding removed; there doesn't seem to be any need michael@0: mLegendRect.x = innerContentRect.width / 2 - mLegendRect.width / 2 + innerContentRect.x; michael@0: break; michael@0: default: michael@0: mLegendRect.x = innerContentRect.x; michael@0: break; michael@0: } michael@0: } else { michael@0: // otherwise make place for the legend michael@0: mLegendRect.x = innerContentRect.x; michael@0: innerContentRect.width = mLegendRect.width; michael@0: contentRect.width = mLegendRect.width + aReflowState.ComputedPhysicalPadding().LeftRight(); michael@0: } michael@0: michael@0: // place the legend michael@0: nsRect actualLegendRect(mLegendRect); michael@0: actualLegendRect.Deflate(legendMargin); michael@0: nsPoint actualLegendPos(actualLegendRect.TopLeft()); michael@0: legendReflowState.ref().ApplyRelativePositioning(&actualLegendPos); michael@0: legend->SetPosition(actualLegendPos); michael@0: nsContainerFrame::PositionFrameView(legend); michael@0: nsContainerFrame::PositionChildViews(legend); michael@0: } michael@0: michael@0: // Return our size and our result. michael@0: aDesiredSize.Height() = mLegendSpace + border.TopBottom() + michael@0: (inner ? inner->GetRect().height : 0); michael@0: aDesiredSize.Width() = contentRect.width + border.LeftRight(); michael@0: aDesiredSize.SetOverflowAreasToDesiredBounds(); michael@0: if (legend) michael@0: ConsiderChildOverflow(aDesiredSize.mOverflowAreas, legend); michael@0: if (inner) michael@0: ConsiderChildOverflow(aDesiredSize.mOverflowAreas, inner); michael@0: michael@0: // Merge overflow container bounds and status. michael@0: aDesiredSize.mOverflowAreas.UnionWith(ocBounds); michael@0: NS_MergeReflowStatusInto(&aStatus, ocStatus); michael@0: michael@0: FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus); michael@0: michael@0: InvalidateFrame(); michael@0: michael@0: NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsFieldSetFrame::AppendFrames(ChildListID aListID, michael@0: nsFrameList& aFrameList) michael@0: { michael@0: MOZ_CRASH("nsFieldSetFrame::AppendFrames not supported"); michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: nsresult michael@0: nsFieldSetFrame::InsertFrames(ChildListID aListID, michael@0: nsIFrame* aPrevFrame, michael@0: nsFrameList& aFrameList) michael@0: { michael@0: MOZ_CRASH("nsFieldSetFrame::InsertFrames not supported"); michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: nsresult michael@0: nsFieldSetFrame::RemoveFrame(ChildListID aListID, michael@0: nsIFrame* aOldFrame) michael@0: { michael@0: MOZ_CRASH("nsFieldSetFrame::RemoveFrame not supported"); michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: #ifdef ACCESSIBILITY michael@0: a11y::AccType michael@0: nsFieldSetFrame::AccessibleType() michael@0: { michael@0: return a11y::eHTMLGroupboxType; michael@0: } michael@0: #endif michael@0: michael@0: nscoord michael@0: nsFieldSetFrame::GetBaseline() const michael@0: { michael@0: nsIFrame* inner = GetInner(); michael@0: return inner->GetPosition().y + inner->GetBaseline(); michael@0: }