Back to index

lightning-sunbird  0.9+nobinonly
nsGroupBoxFrame.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 // YY need to pass isMultiple before create called
00039 
00040 #include "nsBoxFrame.h"
00041 #include "nsCSSRendering.h"
00042 #include "nsStyleContext.h"
00043 
00044 class nsGroupBoxFrame : public nsBoxFrame {
00045 public:
00046 
00047   nsGroupBoxFrame(nsIPresShell* aShell);
00048 
00049   NS_IMETHOD GetBorderAndPadding(nsMargin& aBorderAndPadding);
00050 
00051                                
00052   NS_METHOD Paint(nsPresContext*      aPresContext,
00053                   nsIRenderingContext& aRenderingContext,
00054                   const nsRect&        aDirtyRect,
00055                   nsFramePaintLayer    aWhichLayer,
00056                   PRUint32             aFlags);
00057 
00058 #ifdef DEBUG
00059   NS_IMETHOD GetFrameName(nsAString& aResult) const {
00060     return MakeFrameName(NS_LITERAL_STRING("GroupBoxFrame"), aResult);
00061   }
00062 #endif
00063 
00064   // make sure we our kids get our orient and align instead of us.
00065   // our child box has no content node so it will search for a parent with one.
00066   // that will be us.
00067   virtual void GetInitialOrientation(PRBool& aHorizontal) { aHorizontal = PR_FALSE; }
00068   virtual PRBool GetInitialHAlignment(Halignment& aHalign)  { aHalign = hAlign_Left; return PR_TRUE; } 
00069   virtual PRBool GetInitialVAlignment(Valignment& aValign)  { aValign = vAlign_Top; return PR_TRUE; } 
00070   virtual PRBool GetInitialAutoStretch(PRBool& aStretch)    { aStretch = PR_TRUE; return PR_TRUE; } 
00071 
00072   nsIBox* GetCaptionBox(nsPresContext* aPresContext, nsRect& aCaptionRect);
00073 };
00074 
00075 /*
00076 class nsGroupBoxInnerFrame : public nsBoxFrame {
00077 public:
00078 
00079     nsGroupBoxInnerFrame(nsIPresShell* aShell):nsBoxFrame(aShell) {}
00080 
00081 
00082 #ifdef DEBUG
00083   NS_IMETHOD GetFrameName(nsString& aResult) const {
00084     return MakeFrameName("GroupBoxFrameInner", aResult);
00085   }
00086 #endif
00087   
00088   // we are always flexible
00089   virtual PRBool GetDefaultFlex(PRInt32& aFlex) { aFlex = 1; return PR_TRUE; }
00090 
00091 };
00092 */
00093 
00094 nsresult
00095 NS_NewGroupBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
00096 {
00097   NS_PRECONDITION(aNewFrame, "null OUT ptr");
00098   if (nsnull == aNewFrame) {
00099     return NS_ERROR_NULL_POINTER;
00100   }
00101   nsGroupBoxFrame* it = new (aPresShell) nsGroupBoxFrame(aPresShell);
00102   if (!it) {
00103     return NS_ERROR_OUT_OF_MEMORY;
00104   }
00105   
00106   *aNewFrame = it;
00107   return NS_OK;
00108 }
00109 
00110 nsGroupBoxFrame::nsGroupBoxFrame(nsIPresShell* aShell):nsBoxFrame(aShell)
00111 {
00112 }
00113 
00114 
00115 // this is identical to nsHTMLContainerFrame::Paint except for the background and border. 
00116 NS_IMETHODIMP
00117 nsGroupBoxFrame::Paint(nsPresContext*      aPresContext,
00118                         nsIRenderingContext& aRenderingContext,
00119                         const nsRect&        aDirtyRect,
00120                         nsFramePaintLayer    aWhichLayer,
00121                         PRUint32             aFlags)
00122 {
00123   if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
00124     // Paint our background and border
00125 
00126     if (GetStyleVisibility()->IsVisible() && mRect.width && mRect.height) {
00127       PRIntn skipSides = 0;
00128       const nsStyleBorder* borderStyleData = GetStyleBorder();
00129       const nsStylePadding* paddingStyleData = GetStylePadding();
00130        
00131         const nsMargin& border = borderStyleData->GetBorder();
00132 
00133         nscoord yoff = 0;
00134 
00135         nsRect groupRect;
00136         nsIBox* groupBox = GetCaptionBox(aPresContext, groupRect);
00137 
00138         if (groupBox) {        
00139             // if the border is smaller than the legend. Move the border down
00140             // to be centered on the legend. 
00141 
00142             nsMargin groupMargin;
00143             groupBox->GetStyleMargin()->GetMargin(groupMargin);
00144             groupRect.Inflate(groupMargin);
00145          
00146             if (border.top < groupRect.height)
00147                 yoff = (groupRect.height - border.top)/2 + groupRect.y;
00148         }
00149 
00150         nsRect rect(0, yoff, mRect.width, mRect.height - yoff);
00151 
00152         nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
00153                                         aDirtyRect, rect, *borderStyleData,
00154                                         *paddingStyleData, PR_FALSE);
00155 
00156         if (groupBox) {
00157 
00158           // we should probably use PaintBorderEdges to do this but for now just use clipping
00159           // to achieve the same effect.
00160 
00161           // draw left side
00162           nsRect clipRect(rect);
00163           clipRect.width = groupRect.x - rect.x;
00164           clipRect.height = border.top;
00165 
00166           aRenderingContext.PushState();
00167           aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
00168           nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
00169                                       aDirtyRect, rect, *borderStyleData, mStyleContext, skipSides);
00170   
00171           aRenderingContext.PopState();
00172 
00173 
00174           // draw right side
00175           clipRect = rect;
00176           clipRect.x = groupRect.x + groupRect.width;
00177           clipRect.width -= (groupRect.x + groupRect.width);
00178           clipRect.height = border.top;
00179 
00180           aRenderingContext.PushState();
00181           aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
00182           nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
00183                                       aDirtyRect, rect, *borderStyleData, mStyleContext, skipSides);
00184   
00185           aRenderingContext.PopState();
00186 
00187           
00188         
00189           // draw bottom
00190 
00191           clipRect = rect;
00192           clipRect.y += border.top;
00193           clipRect.height = mRect.height - (yoff + border.top);
00194         
00195           aRenderingContext.PushState();
00196           aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
00197           nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
00198                                       aDirtyRect, rect, *borderStyleData, mStyleContext, skipSides);
00199   
00200           aRenderingContext.PopState();
00201           
00202         } else {
00203 
00204           
00205           nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
00206                                       aDirtyRect, nsRect(0,0,mRect.width, mRect.height), *borderStyleData, mStyleContext, skipSides);
00207         }
00208     }
00209   }
00210 
00211   PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
00212 
00213 #ifdef DEBUG
00214   if ((NS_FRAME_PAINT_LAYER_DEBUG == aWhichLayer) && GetShowFrameBorders()) {
00215     if (HasView()) {
00216       aRenderingContext.SetColor(NS_RGB(0,0,255));
00217     }
00218     else {
00219       aRenderingContext.SetColor(NS_RGB(255,0,0));
00220     }
00221     aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height);
00222   }
00223 #endif
00224   return NS_OK;
00225 }
00226 
00227 nsIBox*
00228 nsGroupBoxFrame::GetCaptionBox(nsPresContext* aPresContext, nsRect& aCaptionRect)
00229 {
00230     // first child is our grouped area
00231     nsIBox* box;
00232     GetChildBox(&box);
00233 
00234     // no area fail.
00235     if (!box)
00236       return nsnull;
00237 
00238     // get the first child in the grouped area, that is the caption
00239     box->GetChildBox(&box);
00240 
00241     // nothing in the area? fail
00242     if (!box)
00243       return nsnull;
00244 
00245     // now get the caption itself. It is in the caption frame.
00246     nsIBox* child = nsnull;
00247     box->GetChildBox(&child);
00248 
00249     if (child) {
00250        // convert to our coordinates.
00251        nsRect parentRect(box->GetRect());
00252        aCaptionRect = child->GetRect();
00253        aCaptionRect.x += parentRect.x;
00254        aCaptionRect.y += parentRect.y;
00255     }
00256 
00257     return child;
00258 }
00259 
00260 NS_IMETHODIMP
00261 nsGroupBoxFrame::GetBorderAndPadding(nsMargin& aBorderAndPadding)
00262 {
00263   aBorderAndPadding.SizeTo(0,0,0,0);
00264   return NS_OK;
00265 }
00266