LCOV - app.info - layout/forms/nsFieldSetFrame.cpp

LCOV - code coverage report
| Current view: | directory - layout/forms - nsFieldSetFrame.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 240 | 0 | 0.0 %
| Date: | 2012-07-07 | Functions: | 31 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *
          24                 :  * Alternatively, the contents of this file may be used under the terms of
          25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          28                 :  * of those above. If you wish to allow use of your version of this file only
          29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          30                 :  * use your version of this file under the terms of the MPL, indicate your
          31                 :  * decision by deleting the provisions above and replace them with the notice
          32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          33                 :  * the provisions above, a recipient may use your version of this file under
          34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          35                 :  *
          36                 :  * ***** END LICENSE BLOCK ***** */
          37                 :
          38                 : // YY need to pass isMultiple before create called
          39                 :
          40                 : //#include "nsFormControlFrame.h"
          41                 : #include "nsContainerFrame.h"
          42                 : #include "nsLegendFrame.h"
          43                 : #include "nsIDOMNode.h"
          44                 : #include "nsIDOMHTMLFieldSetElement.h"
          45                 : #include "nsIDOMHTMLLegendElement.h"
          46                 : #include "nsCSSRendering.h"
          47                 : //#include "nsIDOMHTMLCollection.h"
          48                 : #include "nsIContent.h"
          49                 : #include "nsIFrame.h"
          50                 : #include "nsISupports.h"
          51                 : #include "nsIAtom.h"
          52                 : #include "nsPresContext.h"
          53                 : #include "nsFrameManager.h"
          54                 : #include "nsHTMLParts.h"
          55                 : #include "nsGkAtoms.h"
          56                 : #include "nsStyleConsts.h"
          57                 : #include "nsFont.h"
          58                 : #include "nsCOMPtr.h"
          59                 : #ifdef ACCESSIBILITY
          60                 : #include "nsAccessibilityService.h"
          61                 : #endif
          62                 : #include "nsIServiceManager.h"
          63                 : #include "nsDisplayList.h"
          64                 : #include "nsRenderingContext.h"
          65                 :
          66                 : using namespace mozilla;
          67                 : using namespace mozilla::layout;
          68                 :
          69                 : class nsLegendFrame;
          70                 :
          71               0 : class nsFieldSetFrame : public nsContainerFrame {
          72                 : public:
          73                 :   NS_DECL_FRAMEARENA_HELPERS
          74                 :
          75                 :   nsFieldSetFrame(nsStyleContext* aContext);
          76                 :
          77                 :   NS_IMETHOD SetInitialChildList(ChildListID    aListID,
          78                 :                                  nsFrameList&   aChildList);
          79                 :
          80                 :   NS_HIDDEN_(nscoord)
          81                 :     GetIntrinsicWidth(nsRenderingContext* aRenderingContext,
          82                 :                       nsLayoutUtils::IntrinsicWidthType);
          83                 :   virtual nscoord GetMinWidth(nsRenderingContext* aRenderingContext);
          84                 :   virtual nscoord GetPrefWidth(nsRenderingContext* aRenderingContext);
          85                 :   virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
          86                 :                              nsSize aCBSize, nscoord aAvailableWidth,
          87                 :                              nsSize aMargin, nsSize aBorder, nsSize aPadding,
          88                 :                              bool aShrinkWrap);
          89                 :   virtual nscoord GetBaseline() const;
          90                 :   virtual void DestroyFrom(nsIFrame* aDestructRoot);
          91                 :
          92                 :   NS_IMETHOD Reflow(nsPresContext*           aPresContext,
          93                 :                     nsHTMLReflowMetrics&     aDesiredSize,
          94                 :                     const nsHTMLReflowState& aReflowState,
          95                 :                     nsReflowStatus&          aStatus);
          96                 :
          97                 :   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
          98                 :                               const nsRect&           aDirtyRect,
          99                 :                               const nsDisplayListSet& aLists);
         100                 :
         101                 :   void PaintBorderBackground(nsRenderingContext& aRenderingContext,
         102                 :     nsPoint aPt, const nsRect& aDirtyRect, PRUint32 aBGFlags);
         103                 :
         104                 :   NS_IMETHOD AppendFrames(ChildListID    aListID,
         105                 :                           nsFrameList&   aFrameList);
         106                 :   NS_IMETHOD InsertFrames(ChildListID    aListID,
         107                 :                           nsIFrame*      aPrevFrame,
         108                 :                           nsFrameList&   aFrameList);
         109                 :   NS_IMETHOD RemoveFrame(ChildListID    aListID,
         110                 :                          nsIFrame*      aOldFrame);
         111                 :
         112                 :   virtual nsIAtom* GetType() const;
         113                 :
         114                 : #ifdef ACCESSIBILITY
         115                 :   virtual already_AddRefed<nsAccessible> CreateAccessible();
         116                 : #endif
         117                 :
         118                 : #ifdef DEBUG
         119               0 :   NS_IMETHOD GetFrameName(nsAString& aResult) const {
         120               0 :     return MakeFrameName(NS_LITERAL_STRING("FieldSet"), aResult);
         121                 :   }
         122                 : #endif
         123                 :
         124                 : protected:
         125                 :
         126                 :   virtual PRIntn GetSkipSides() const;
         127                 :   void ReparentFrameList(const nsFrameList& aFrameList);
         128                 :
         129                 :   nsIFrame* mLegendFrame;
         130                 :   nsIFrame* mContentFrame;
         131                 :   nsRect    mLegendRect;
         132                 :   nscoord   mLegendSpace;
         133                 : };
         134                 :
         135                 : nsIFrame*
         136               0 : NS_NewFieldSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
         137                 : {
         138               0 :   return new (aPresShell) nsFieldSetFrame(aContext);
         139                 : }
         140                 :
         141               0 : NS_IMPL_FRAMEARENA_HELPERS(nsFieldSetFrame)
         142                 :
         143               0 : nsFieldSetFrame::nsFieldSetFrame(nsStyleContext* aContext)
         144               0 :   : nsContainerFrame(aContext)
         145                 : {
         146               0 :   mContentFrame = nsnull;
         147               0 :   mLegendFrame  = nsnull;
         148               0 :   mLegendSpace  = 0;
         149               0 : }
         150                 :
         151                 : void
         152               0 : nsFieldSetFrame::DestroyFrom(nsIFrame* aDestructRoot)
         153                 : {
         154               0 :   DestroyAbsoluteFrames(aDestructRoot);
         155               0 :   nsContainerFrame::DestroyFrom(aDestructRoot);
         156               0 : }
         157                 :
         158                 : nsIAtom*
         159               0 : nsFieldSetFrame::GetType() const
         160                 : {
         161               0 :   return nsGkAtoms::fieldSetFrame;
         162                 : }
         163                 :
         164                 : NS_IMETHODIMP
         165               0 : nsFieldSetFrame::SetInitialChildList(ChildListID    aListID,
         166                 :                                      nsFrameList&   aChildList)
         167                 : {
         168                 :   // Get the content and legend frames.
         169               0 :   if (!aChildList.OnlyChild()) {
         170               0 :     NS_ASSERTION(aChildList.GetLength() == 2, "Unexpected child list");
         171               0 :     mContentFrame = aChildList.LastChild();
         172               0 :     mLegendFrame  = aChildList.FirstChild();
         173                 :   } else {
         174               0 :     mContentFrame = aChildList.FirstChild();
         175               0 :     mLegendFrame  = nsnull;
         176                 :   }
         177                 :
         178                 :   // Queue up the frames for the content frame
         179               0 :   return nsContainerFrame::SetInitialChildList(kPrincipalList, aChildList);
         180                 : }
         181                 :
         182                 : class nsDisplayFieldSetBorderBackground : public nsDisplayItem {
         183                 : public:
         184               0 :   nsDisplayFieldSetBorderBackground(nsDisplayListBuilder* aBuilder,
         185                 :                                     nsFieldSetFrame* aFrame)
         186               0 :     : nsDisplayItem(aBuilder, aFrame) {
         187               0 :     MOZ_COUNT_CTOR(nsDisplayFieldSetBorderBackground);
         188               0 :   }
         189                 : #ifdef NS_BUILD_REFCNT_LOGGING
         190               0 :   virtual ~nsDisplayFieldSetBorderBackground() {
         191               0 :     MOZ_COUNT_DTOR(nsDisplayFieldSetBorderBackground);
         192               0 :   }
         193                 : #endif
         194                 :
         195                 :   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
         196                 :                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
         197                 :   virtual void Paint(nsDisplayListBuilder* aBuilder,
         198                 :                      nsRenderingContext* aCtx);
         199               0 :   NS_DISPLAY_DECL_NAME("FieldSetBorderBackground", TYPE_FIELDSET_BORDER_BACKGROUND)
         200                 : };
         201                 :
         202               0 : void nsDisplayFieldSetBorderBackground::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
         203                 :                                                 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
         204                 : {
         205                 :   // aPt is guaranteed to be in this item's bounds. We do the hit test based on the
         206                 :   // frame bounds even though our background doesn't cover the whole frame.
         207                 :   // It's not clear whether this is correct.
         208               0 :   aOutFrames->AppendElement(mFrame);
         209               0 : }
         210                 :
         211                 : void
         212               0 : nsDisplayFieldSetBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
         213                 :                                          nsRenderingContext* aCtx)
         214                 : {
         215                 :   static_cast<nsFieldSetFrame*>(mFrame)->
         216               0 :     PaintBorderBackground(*aCtx, ToReferenceFrame(),
         217               0 :                           mVisibleRect, aBuilder->GetBackgroundPaintFlags());
         218               0 : }
         219                 :
         220                 : NS_IMETHODIMP
         221               0 : nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
         222                 :                                   const nsRect&           aDirtyRect,
         223                 :                                   const nsDisplayListSet& aLists) {
         224                 :   // Paint our background and border in a special way.
         225                 :   // REVIEW: We don't really need to check frame emptiness here; if it's empty,
         226                 :   // the background/border display item won't do anything, and if it isn't empty,
         227                 :   // we need to paint the outline
         228               0 :   if (IsVisibleForPainting(aBuilder)) {
         229               0 :     if (GetStyleBorder()->mBoxShadow) {
         230                 :       nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
         231               0 :           nsDisplayBoxShadowOuter(aBuilder, this));
         232               0 :       NS_ENSURE_SUCCESS(rv, rv);
         233                 :     }
         234                 :
         235                 :     // don't bother checking to see if we really have a border or background.
         236                 :     // we usually will have a border.
         237                 :     nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
         238               0 :         nsDisplayFieldSetBorderBackground(aBuilder, this));
         239               0 :     NS_ENSURE_SUCCESS(rv, rv);
         240                 :
         241               0 :     rv = DisplayOutlineUnconditional(aBuilder, aLists);
         242               0 :     NS_ENSURE_SUCCESS(rv, rv);
         243                 :
         244               0 :     DO_GLOBAL_REFLOW_COUNT_DSP("nsFieldSetFrame");
         245                 :   }
         246                 :
         247               0 :   nsDisplayListCollection contentDisplayItems;
         248               0 :   if (mContentFrame) {
         249                 :     // Collect mContentFrame's display items into their own collection. We need
         250                 :     // to be calling BuildDisplayList on mContentFrame before mLegendFrame in
         251                 :     // case it contains out-of-flow frames whose placeholders are under
         252                 :     // mLegendFrame. However, we want mContentFrame's display items to be
         253                 :     // after mLegendFrame's display items in z-order, so we need to save them
         254                 :     // and append them later.
         255                 :     nsresult rv = BuildDisplayListForChild(aBuilder, mContentFrame, aDirtyRect,
         256               0 :                                            contentDisplayItems);
         257               0 :     NS_ENSURE_SUCCESS(rv, rv);
         258                 :   }
         259               0 :   if (mLegendFrame) {
         260                 :     // The legend's background goes on our BlockBorderBackgrounds list because
         261                 :     // it's a block child.
         262               0 :     nsDisplayListSet set(aLists, aLists.BlockBorderBackgrounds());
         263               0 :     nsresult rv = BuildDisplayListForChild(aBuilder, mLegendFrame, aDirtyRect, set);
         264               0 :     NS_ENSURE_SUCCESS(rv, rv);
         265                 :   }
         266                 :   // Put mContentFrame's display items on the master list. Note that
         267                 :   // this moves mContentFrame's border/background display items to our
         268                 :   // BorderBackground() list, which isn't really correct, but it's OK because
         269                 :   // mContentFrame is anonymous and can't have its own border and background.
         270               0 :   contentDisplayItems.MoveTo(aLists);
         271               0 :   return NS_OK;
         272                 : }
         273                 :
         274                 : void
         275               0 : nsFieldSetFrame::PaintBorderBackground(nsRenderingContext& aRenderingContext,
         276                 :     nsPoint aPt, const nsRect& aDirtyRect, PRUint32 aBGFlags)
         277                 : {
         278               0 :   PRIntn skipSides = GetSkipSides();
         279               0 :   const nsStyleBorder* borderStyle = GetStyleBorder();
         280                 :
         281               0 :   nscoord topBorder = borderStyle->GetActualBorderWidth(NS_SIDE_TOP);
         282               0 :   nscoord yoff = 0;
         283               0 :   nsPresContext* presContext = PresContext();
         284                 :
         285                 :   // if the border is smaller than the legend. Move the border down
         286                 :   // to be centered on the legend.
         287                 :   // FIXME: This means border-radius clamping is incorrect; we should
         288                 :   // override nsIFrame::GetBorderRadii.
         289               0 :   if (topBorder < mLegendRect.height)
         290               0 :     yoff = (mLegendRect.height - topBorder)/2;
         291                 :
         292               0 :   nsRect rect(aPt.x, aPt.y + yoff, mRect.width, mRect.height - yoff);
         293                 :
         294                 :   nsCSSRendering::PaintBackground(presContext, aRenderingContext, this,
         295               0 :                                   aDirtyRect, rect, aBGFlags);
         296                 :
         297                 :   nsCSSRendering::PaintBoxShadowInner(presContext, aRenderingContext,
         298               0 :                                       this, rect, aDirtyRect);
         299                 :
         300               0 :    if (mLegendFrame) {
         301                 :
         302                 :     // Use the rect of the legend frame, not mLegendRect, so we draw our
         303                 :     // border under the legend's left and right margins.
         304               0 :     nsRect legendRect = mLegendFrame->GetRect() + aPt;
         305                 :
         306                 :     // we should probably use PaintBorderEdges to do this but for now just use clipping
         307                 :     // to achieve the same effect.
         308                 :
         309                 :     // draw left side
         310               0 :     nsRect clipRect(rect);
         311               0 :     clipRect.width = legendRect.x - rect.x;
         312               0 :     clipRect.height = topBorder;
         313                 :
         314               0 :     aRenderingContext.PushState();
         315               0 :     aRenderingContext.IntersectClip(clipRect);
         316                 :     nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
         317               0 :                                 aDirtyRect, rect, mStyleContext, skipSides);
         318                 :
         319               0 :     aRenderingContext.PopState();
         320                 :
         321                 :
         322                 :     // draw right side
         323               0 :     clipRect = rect;
         324               0 :     clipRect.x = legendRect.XMost();
         325               0 :     clipRect.width = rect.XMost() - legendRect.XMost();
         326               0 :     clipRect.height = topBorder;
         327                 :
         328               0 :     aRenderingContext.PushState();
         329               0 :     aRenderingContext.IntersectClip(clipRect);
         330                 :     nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
         331               0 :                                 aDirtyRect, rect, mStyleContext, skipSides);
         332                 :
         333               0 :     aRenderingContext.PopState();
         334                 :
         335                 :
         336                 :     // draw bottom
         337               0 :     clipRect = rect;
         338               0 :     clipRect.y += topBorder;
         339               0 :     clipRect.height = mRect.height - (yoff + topBorder);
         340                 :
         341               0 :     aRenderingContext.PushState();
         342               0 :     aRenderingContext.IntersectClip(clipRect);
         343                 :     nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
         344               0 :                                 aDirtyRect, rect, mStyleContext, skipSides);
         345                 :
         346               0 :     aRenderingContext.PopState();
         347                 :   } else {
         348                 :
         349                 :     nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
         350                 :                                 aDirtyRect,
         351               0 :                                 nsRect(aPt, mRect.Size()),
         352               0 :                                 mStyleContext, skipSides);
         353                 :   }
         354               0 : }
         355                 :
         356                 : nscoord
         357               0 : nsFieldSetFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext,
         358                 :                                    nsLayoutUtils::IntrinsicWidthType aType)
         359                 : {
         360               0 :   nscoord legendWidth = 0;
         361               0 :   nscoord contentWidth = 0;
         362               0 :   if (mLegendFrame) {
         363                 :     legendWidth =
         364                 :       nsLayoutUtils::IntrinsicForContainer(aRenderingContext, mLegendFrame,
         365               0 :                                            aType);
         366                 :   }
         367                 :
         368               0 :   if (mContentFrame) {
         369                 :     contentWidth =
         370                 :       nsLayoutUtils::IntrinsicForContainer(aRenderingContext, mContentFrame,
         371               0 :                                            aType);
         372                 :   }
         373                 :
         374               0 :   return NS_MAX(legendWidth, contentWidth);
         375                 : }
         376                 :
         377                 :
         378                 : nscoord
         379               0 : nsFieldSetFrame::GetMinWidth(nsRenderingContext* aRenderingContext)
         380                 : {
         381               0 :   nscoord result = 0;
         382               0 :   DISPLAY_MIN_WIDTH(this, result);
         383                 :
         384               0 :   result = GetIntrinsicWidth(aRenderingContext, nsLayoutUtils::MIN_WIDTH);
         385               0 :   return result;
         386                 : }
         387                 :
         388                 : nscoord
         389               0 : nsFieldSetFrame::GetPrefWidth(nsRenderingContext* aRenderingContext)
         390                 : {
         391               0 :   nscoord result = 0;
         392               0 :   DISPLAY_PREF_WIDTH(this, result);
         393                 :
         394               0 :   result = GetIntrinsicWidth(aRenderingContext, nsLayoutUtils::PREF_WIDTH);
         395               0 :   return result;
         396                 : }
         397                 :
         398                 : /* virtual */ nsSize
         399               0 : nsFieldSetFrame::ComputeSize(nsRenderingContext *aRenderingContext,
         400                 :                              nsSize aCBSize, nscoord aAvailableWidth,
         401                 :                              nsSize aMargin, nsSize aBorder, nsSize aPadding,
         402                 :                              bool aShrinkWrap)
         403                 : {
         404                 :   nsSize result =
         405                 :     nsContainerFrame::ComputeSize(aRenderingContext, aCBSize, aAvailableWidth,
         406               0 :                                   aMargin, aBorder, aPadding, aShrinkWrap);
         407                 :
         408                 :   // Fieldsets never shrink below their min width.
         409                 :
         410                 :   // If we're a container for font size inflation, then shrink
         411                 :   // wrapping inside of us should not apply font size inflation.
         412               0 :   AutoMaybeNullInflationContainer an(this);
         413                 :
         414               0 :   nscoord minWidth = GetMinWidth(aRenderingContext);
         415               0 :   if (minWidth > result.width)
         416               0 :     result.width = minWidth;
         417                 :
         418                 :   return result;
         419                 : }
         420                 :
         421                 : NS_IMETHODIMP
         422               0 : nsFieldSetFrame::Reflow(nsPresContext*           aPresContext,
         423                 :                         nsHTMLReflowMetrics&     aDesiredSize,
         424                 :                         const nsHTMLReflowState& aReflowState,
         425                 :                         nsReflowStatus&          aStatus)
         426                 : {
         427               0 :   DO_GLOBAL_REFLOW_COUNT("nsFieldSetFrame");
         428               0 :   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
         429                 :
         430               0 :   NS_PRECONDITION(aReflowState.ComputedWidth() != NS_INTRINSICSIZE,
         431                 :                   "Should have a precomputed width!");
         432                 :
         433                 :   // Initialize OUT parameter
         434               0 :   aStatus = NS_FRAME_COMPLETE;
         435                 :
         436                 :   //------------ Handle Incremental Reflow -----------------
         437                 :   bool reflowContent;
         438                 :   bool reflowLegend;
         439                 :
         440               0 :   if (aReflowState.ShouldReflowAllKids()) {
         441               0 :     reflowContent = mContentFrame != nsnull;
         442               0 :     reflowLegend = mLegendFrame != nsnull;
         443                 :   } else {
         444               0 :     reflowContent = mContentFrame && NS_SUBTREE_DIRTY(mContentFrame);
         445               0 :     reflowLegend = mLegendFrame && NS_SUBTREE_DIRTY(mLegendFrame);
         446                 :   }
         447                 :
         448                 :   // We don't allow fieldsets to break vertically. If we did, we'd
         449                 :   // need logic here to push and pull overflow frames.
         450               0 :   nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE);
         451               0 :   NS_ASSERTION(!mContentFrame ||
         452                 :       nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext,
         453                 :                                            mContentFrame,
         454                 :                                            nsLayoutUtils::MIN_WIDTH) <=
         455                 :                availSize.width,
         456                 :                "Bogus availSize.width; should be bigger");
         457               0 :   NS_ASSERTION(!mLegendFrame ||
         458                 :       nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext,
         459                 :                                            mLegendFrame,
         460                 :                                            nsLayoutUtils::MIN_WIDTH) <=
         461                 :                availSize.width,
         462                 :                "Bogus availSize.width; should be bigger");
         463                 :
         464                 :   // get our border and padding
         465               0 :   const nsMargin &borderPadding = aReflowState.mComputedBorderPadding;
         466               0 :   nsMargin border = borderPadding - aReflowState.mComputedPadding;
         467                 :
         468                 :   // Figure out how big the legend is if there is one.
         469                 :   // get the legend's margin
         470               0 :   nsMargin legendMargin(0,0,0,0);
         471                 :   // reflow the legend only if needed
         472               0 :   if (reflowLegend) {
         473                 :     nsHTMLReflowState legendReflowState(aPresContext, aReflowState,
         474               0 :                                         mLegendFrame, availSize);
         475                 :
         476               0 :     nsHTMLReflowMetrics legendDesiredSize;
         477                 :
         478                 :     ReflowChild(mLegendFrame, aPresContext, legendDesiredSize, legendReflowState,
         479               0 :                 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
         480                 : #ifdef NOISY_REFLOW
         481                 :     printf("  returned (%d, %d)\n", legendDesiredSize.width, legendDesiredSize.height);
         482                 : #endif
         483                 :     // figure out the legend's rectangle
         484               0 :     legendMargin = mLegendFrame->GetUsedMargin();
         485               0 :     mLegendRect.width  = legendDesiredSize.width + legendMargin.left + legendMargin.right;
         486               0 :     mLegendRect.height = legendDesiredSize.height + legendMargin.top + legendMargin.bottom;
         487               0 :     mLegendRect.x = borderPadding.left;
         488               0 :     mLegendRect.y = 0;
         489                 :
         490               0 :     nscoord oldSpace = mLegendSpace;
         491               0 :     mLegendSpace = 0;
         492               0 :     if (mLegendRect.height > border.top) {
         493                 :       // center the border on the legend
         494               0 :       mLegendSpace = mLegendRect.height - border.top;
         495                 :     } else {
         496               0 :       mLegendRect.y = (border.top - mLegendRect.height)/2;
         497                 :     }
         498                 :
         499                 :     // if the legend space changes then we need to reflow the
         500                 :     // content area as well.
         501               0 :     if (mLegendSpace != oldSpace && mContentFrame) {
         502               0 :       reflowContent = true;
         503                 :     }
         504                 :
         505                 :     FinishReflowChild(mLegendFrame, aPresContext, &legendReflowState,
         506               0 :                       legendDesiredSize, 0, 0, NS_FRAME_NO_MOVE_FRAME);
         507               0 :   } else if (!mLegendFrame) {
         508               0 :     mLegendRect.SetEmpty();
         509               0 :     mLegendSpace = 0;
         510                 :   } else {
         511                 :     // mLegendSpace and mLegendRect haven't changed, but we need
         512                 :     // the used margin when placing the legend.
         513               0 :     legendMargin = mLegendFrame->GetUsedMargin();
         514                 :   }
         515                 :
         516                 :   // reflow the content frame only if needed
         517               0 :   if (reflowContent) {
         518                 :     nsHTMLReflowState kidReflowState(aPresContext, aReflowState, mContentFrame,
         519               0 :                                      availSize);
         520                 :     // Our child is "height:100%" but we actually want its height to be reduced
         521                 :     // by the amount of content-height the legend is eating up, unless our
         522                 :     // height is unconstrained (in which case the child's will be too).
         523               0 :     if (aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE) {
         524               0 :       kidReflowState.SetComputedHeight(NS_MAX(0, aReflowState.ComputedHeight() - mLegendSpace));
         525                 :     }
         526                 :
         527                 :     kidReflowState.mComputedMinHeight =
         528               0 :       NS_MAX(0, aReflowState.mComputedMinHeight - mLegendSpace);
         529                 :
         530               0 :     if (aReflowState.mComputedMaxHeight != NS_UNCONSTRAINEDSIZE) {
         531                 :       kidReflowState.mComputedMaxHeight =
         532               0 :         NS_MAX(0, aReflowState.mComputedMaxHeight - mLegendSpace);
         533                 :     }
         534                 :
         535               0 :     nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mFlags);
         536                 :     // Reflow the frame
         537               0 :     NS_ASSERTION(kidReflowState.mComputedMargin == nsMargin(0,0,0,0),
         538                 :                  "Margins on anonymous fieldset child not supported!");
         539               0 :     nsPoint pt(borderPadding.left, borderPadding.top + mLegendSpace);
         540                 :     ReflowChild(mContentFrame, aPresContext, kidDesiredSize, kidReflowState,
         541               0 :                 pt.x, pt.y, 0, aStatus);
         542                 :
         543                 :     FinishReflowChild(mContentFrame, aPresContext, &kidReflowState,
         544               0 :                       kidDesiredSize, pt.x, pt.y, 0);
         545               0 :     NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus);
         546                 :   }
         547                 :
         548               0 :   nsRect contentRect(0,0,0,0);
         549               0 :   if (mContentFrame) {
         550                 :     // We don't support margins on mContentFrame, so our "content rect" is just
         551                 :     // its rect.
         552               0 :     contentRect = mContentFrame->GetRect();
         553                 :   }
         554                 :
         555                 :   // use the computed width if the inner content does not fill it
         556               0 :   if (aReflowState.ComputedWidth() > contentRect.width) {
         557               0 :     contentRect.width = aReflowState.ComputedWidth();
         558                 :   }
         559                 :
         560               0 :   if (mLegendFrame) {
         561                 :     // if the content rect is larger then the  legend we can align the legend
         562               0 :     if (contentRect.width > mLegendRect.width) {
         563               0 :       PRInt32 align = static_cast<nsLegendFrame*>(mLegendFrame)->GetAlign();
         564                 :
         565               0 :       switch(align) {
         566                 :         case NS_STYLE_TEXT_ALIGN_RIGHT:
         567               0 :           mLegendRect.x = contentRect.width - mLegendRect.width + borderPadding.left;
         568               0 :           break;
         569                 :         case NS_STYLE_TEXT_ALIGN_CENTER:
         570                 :           // Note: rounding removed; there doesn't seem to be any need
         571               0 :           mLegendRect.x = contentRect.width / 2 - mLegendRect.width / 2 + borderPadding.left;
         572               0 :           break;
         573                 :       }
         574                 :
         575                 :     } else {
         576                 :       // otherwise make place for the legend
         577               0 :       contentRect.width = mLegendRect.width;
         578                 :     }
         579                 :     // place the legend
         580               0 :     nsRect actualLegendRect(mLegendRect);
         581               0 :     actualLegendRect.Deflate(legendMargin);
         582                 :
         583               0 :     nsPoint curOrigin = mLegendFrame->GetPosition();
         584                 :
         585                 :     // only if the origin changed
         586               0 :     if ((curOrigin.x != mLegendRect.x) || (curOrigin.y != mLegendRect.y)) {
         587               0 :       mLegendFrame->SetPosition(nsPoint(actualLegendRect.x , actualLegendRect.y));
         588               0 :       nsContainerFrame::PositionFrameView(mLegendFrame);
         589                 :
         590                 :       // We need to recursively process the legend frame's
         591                 :       // children since we're moving the frame after Reflow.
         592               0 :       nsContainerFrame::PositionChildViews(mLegendFrame);
         593                 :     }
         594                 :   }
         595                 :
         596                 :   // Return our size and our result
         597               0 :   if (aReflowState.ComputedHeight() == NS_INTRINSICSIZE) {
         598                 :     aDesiredSize.height = mLegendSpace +
         599               0 :                           borderPadding.TopBottom() +
         600               0 :                           contentRect.height;
         601                 :   } else {
         602               0 :     nscoord min = borderPadding.TopBottom() + mLegendRect.height;
         603                 :     aDesiredSize.height =
         604               0 :       aReflowState.ComputedHeight() + borderPadding.TopBottom();
         605               0 :     if (aDesiredSize.height < min)
         606               0 :       aDesiredSize.height = min;
         607                 :   }
         608               0 :   aDesiredSize.width = contentRect.width + borderPadding.LeftRight();
         609               0 :   aDesiredSize.SetOverflowAreasToDesiredBounds();
         610               0 :   if (mLegendFrame)
         611               0 :     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, mLegendFrame);
         612               0 :   if (mContentFrame)
         613               0 :     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, mContentFrame);
         614               0 :   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
         615                 :
         616               0 :   Invalidate(aDesiredSize.VisualOverflow());
         617                 :
         618               0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
         619               0 :   return NS_OK;
         620                 : }
         621                 :
         622                 : PRIntn
         623               0 : nsFieldSetFrame::GetSkipSides() const
         624                 : {
         625               0 :   return 0;
         626                 : }
         627                 :
         628                 : NS_IMETHODIMP
         629               0 : nsFieldSetFrame::AppendFrames(ChildListID    aListID,
         630                 :                               nsFrameList&   aFrameList)
         631                 : {
         632                 :   // aFrameList is not allowed to contain "the legend" for this fieldset
         633               0 :   ReparentFrameList(aFrameList);
         634               0 :   return mContentFrame->AppendFrames(aListID, aFrameList);
         635                 : }
         636                 :
         637                 : NS_IMETHODIMP
         638               0 : nsFieldSetFrame::InsertFrames(ChildListID    aListID,
         639                 :                               nsIFrame*      aPrevFrame,
         640                 :                               nsFrameList&   aFrameList)
         641                 : {
         642               0 :   NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this ||
         643                 :                aPrevFrame->GetParent() == mContentFrame,
         644                 :                "inserting after sibling frame with different parent");
         645                 :
         646                 :   // aFrameList is not allowed to contain "the legend" for this fieldset
         647               0 :   ReparentFrameList(aFrameList);
         648               0 :   if (NS_UNLIKELY(aPrevFrame == mLegendFrame)) {
         649               0 :     aPrevFrame = nsnull;
         650                 :   }
         651               0 :   return mContentFrame->InsertFrames(aListID, aPrevFrame, aFrameList);
         652                 : }
         653                 :
         654                 : NS_IMETHODIMP
         655               0 : nsFieldSetFrame::RemoveFrame(ChildListID    aListID,
         656                 :                              nsIFrame*      aOldFrame)
         657                 : {
         658                 :   // For reference, see bug 70648, bug 276104 and bug 236071.
         659               0 :   NS_ASSERTION(aOldFrame != mLegendFrame, "Cannot remove mLegendFrame here");
         660               0 :   return mContentFrame->RemoveFrame(aListID, aOldFrame);
         661                 : }
         662                 :
         663                 : #ifdef ACCESSIBILITY
         664                 : already_AddRefed<nsAccessible>
         665               0 : nsFieldSetFrame::CreateAccessible()
         666                 : {
         667               0 :   nsAccessibilityService* accService = nsIPresShell::AccService();
         668               0 :   if (accService) {
         669                 :     return accService->CreateHTMLGroupboxAccessible(mContent,
         670               0 :                                                     PresContext()->PresShell());
         671                 :   }
         672                 :
         673               0 :   return nsnull;
         674                 : }
         675                 : #endif
         676                 :
         677                 : void
         678               0 : nsFieldSetFrame::ReparentFrameList(const nsFrameList& aFrameList)
         679                 : {
         680               0 :   nsFrameManager* frameManager = PresContext()->FrameManager();
         681               0 :   for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
         682               0 :     NS_ASSERTION(mLegendFrame || e.get()->GetType() != nsGkAtoms::legendFrame,
         683                 :                  "The fieldset's legend is not allowed in this list");
         684               0 :     e.get()->SetParent(mContentFrame);
         685               0 :     frameManager->ReparentStyleContext(e.get());
         686                 :   }
         687               0 : }
         688                 :
         689                 : nscoord
         690               0 : nsFieldSetFrame::GetBaseline() const
         691                 : {
         692                 :   // We know mContentFrame is a block, so calling GetBaseline() on it will do
         693                 :   // the right thing (that being to return the baseline of the last line).
         694               0 :   NS_ASSERTION(nsLayoutUtils::GetAsBlock(mContentFrame),
         695                 :                "Unexpected mContentFrame");
         696               0 :   return mContentFrame->GetPosition().y + mContentFrame->GetBaseline();
         697                 : }

Generated by: LCOV version 1.7