Back to index

lightning-sunbird  0.9+nobinonly
nsButtonFrameRenderer.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 Communicator client 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 #include "nsButtonFrameRenderer.h"
00038 #include "nsIRenderingContext.h"
00039 #include "nsCSSRendering.h"
00040 #include "nsPresContext.h"
00041 #include "nsIView.h"
00042 #include "nsIViewManager.h"
00043 #include "nsHTMLAtoms.h"
00044 #include "nsCSSPseudoElements.h"
00045 #include "nsINameSpaceManager.h"
00046 #include "nsStyleSet.h"
00047 
00048 #define ACTIVE   "active"
00049 #define HOVER    "hover"
00050 #define FOCUS    "focus"
00051 
00052 MOZ_DECL_CTOR_COUNTER(nsButtonFrameRenderer)
00053 
00054 nsButtonFrameRenderer::nsButtonFrameRenderer()
00055 {
00056   MOZ_COUNT_CTOR(nsButtonFrameRenderer);
00057 }
00058 
00059 nsButtonFrameRenderer::~nsButtonFrameRenderer()
00060 {
00061   MOZ_COUNT_DTOR(nsButtonFrameRenderer);
00062 }
00063 
00064 void
00065 nsButtonFrameRenderer::SetFrame(nsFrame* aFrame, nsPresContext* aPresContext)
00066 {
00067   mFrame = aFrame;
00068   ReResolveStyles(aPresContext);
00069 }
00070 
00071 nsIFrame*
00072 nsButtonFrameRenderer::GetFrame()
00073 {
00074   return mFrame;
00075 }
00076 
00077 void
00078 nsButtonFrameRenderer::SetDisabled(PRBool aDisabled, PRBool notify)
00079 {
00080   if (aDisabled)
00081     mFrame->GetContent()->SetAttr(kNameSpaceID_None, nsHTMLAtoms::disabled, EmptyString(),
00082                                   notify);
00083   else
00084     mFrame->GetContent()->UnsetAttr(kNameSpaceID_None, nsHTMLAtoms::disabled, notify);
00085 }
00086 
00087 PRBool
00088 nsButtonFrameRenderer::isDisabled() 
00089 {
00090   // get the content
00091   nsAutoString value;
00092   if (NS_CONTENT_ATTR_HAS_VALUE ==
00093       mFrame->GetContent()->GetAttr(kNameSpaceID_None, nsHTMLAtoms::disabled, value))
00094     return PR_TRUE;
00095 
00096   return PR_FALSE;
00097 }
00098 
00099 void 
00100 nsButtonFrameRenderer::PaintButton     (nsPresContext* aPresContext,
00101           nsIRenderingContext& aRenderingContext,
00102           const nsRect& aDirtyRect,
00103           const nsRect& aRect)
00104 {
00105   //printf("painted width='%d' height='%d'\n",aRect.width, aRect.height);
00106 
00107   // draw the border and background inside the focus and outline borders
00108   PaintBorderAndBackground(aPresContext, aRenderingContext, aDirtyRect, aRect);
00109 
00110   // draw the focus and outline borders
00111   PaintOutlineAndFocusBorders(aPresContext, aRenderingContext, aDirtyRect, aRect);
00112 }
00113 
00114 void
00115 nsButtonFrameRenderer::PaintOutlineAndFocusBorders(nsPresContext* aPresContext,
00116           nsIRenderingContext& aRenderingContext,
00117           const nsRect& aDirtyRect,
00118           const nsRect& aRect)
00119 {
00120   // once we have all that let draw the focus if we have it. We will need to draw 2 focuses.
00121   // the inner and the outer. This is so we can do any kind of look and feel some buttons have
00122   // focus on the outside like mac and motif. While others like windows have it inside (dotted line).
00123   // Usually only one will be specifed. But I guess you could have both if you wanted to.
00124 
00125   nsRect rect;
00126 
00127   if (mOuterFocusStyle) {
00128     // ---------- paint the outer focus border -------------
00129 
00130     GetButtonOuterFocusRect(aRect, rect);
00131 
00132     const nsStyleBorder* border = mOuterFocusStyle->GetStyleBorder();
00133     nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame,
00134                                 aDirtyRect, rect, *border, mOuterFocusStyle, 0);
00135   }
00136 
00137   if (mInnerFocusStyle) { 
00138     // ---------- paint the inner focus border -------------
00139 
00140     GetButtonInnerFocusRect(aRect, rect);
00141 
00142     const nsStyleBorder* border = mInnerFocusStyle->GetStyleBorder();
00143     nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame,
00144                                 aDirtyRect, rect, *border, mInnerFocusStyle, 0);
00145   }
00146 }
00147 
00148 
00149 void
00150 nsButtonFrameRenderer::PaintBorderAndBackground(nsPresContext* aPresContext,
00151           nsIRenderingContext& aRenderingContext,
00152           const nsRect& aDirtyRect,
00153           const nsRect& aRect)
00154 
00155 {
00156   // get the button rect this is inside the focus and outline rects
00157   nsRect buttonRect;
00158   GetButtonRect(aRect, buttonRect);
00159 
00160   nsStyleContext* context = mFrame->GetStyleContext();
00161 
00162   const nsStyleBorder* border = context->GetStyleBorder();
00163   const nsStylePadding* padding = context->GetStylePadding();
00164 
00165   nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, mFrame,
00166                                   aDirtyRect, buttonRect, *border, *padding,
00167                                   PR_FALSE);
00168   nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame,
00169                               aDirtyRect, buttonRect, *border, context, 0);
00170 }
00171 
00172 
00173 void
00174 nsButtonFrameRenderer::GetButtonOutlineRect(const nsRect& aRect, nsRect& outlineRect)
00175 {
00176   outlineRect = aRect;
00177   outlineRect.Inflate(GetButtonOutlineBorderAndPadding());
00178 }
00179 
00180 
00181 void
00182 nsButtonFrameRenderer::GetButtonOuterFocusRect(const nsRect& aRect, nsRect& focusRect)
00183 {
00184   focusRect = aRect;
00185 }
00186 
00187 void
00188 nsButtonFrameRenderer::GetButtonRect(const nsRect& aRect, nsRect& r)
00189 {
00190   r = aRect;
00191   r.Deflate(GetButtonOuterFocusBorderAndPadding());
00192 }
00193 
00194 
00195 void
00196 nsButtonFrameRenderer::GetButtonInnerFocusRect(const nsRect& aRect, nsRect& focusRect)
00197 {
00198   GetButtonRect(aRect, focusRect);
00199   focusRect.Deflate(GetButtonBorderAndPadding());
00200   focusRect.Deflate(GetButtonInnerFocusMargin());
00201 }
00202 
00203 void
00204 nsButtonFrameRenderer::GetButtonContentRect(const nsRect& aRect, nsRect& r)
00205 {
00206   GetButtonInnerFocusRect(aRect, r);
00207   r.Deflate(GetButtonInnerFocusBorderAndPadding());
00208 }
00209 
00210 
00211 nsMargin
00212 nsButtonFrameRenderer::GetButtonOuterFocusBorderAndPadding()
00213 {
00214   nsMargin focusBorderAndPadding(0,0,0,0);
00215 
00216   if (mOuterFocusStyle) {
00217     nsStyleBorderPadding  bPad;
00218     mOuterFocusStyle->GetBorderPaddingFor(bPad);
00219     if (!bPad.GetBorderPadding(focusBorderAndPadding)) {
00220       NS_NOTYETIMPLEMENTED("percentage border");
00221     }
00222   }
00223 
00224   return focusBorderAndPadding;
00225 }
00226 
00227 nsMargin
00228 nsButtonFrameRenderer::GetButtonBorderAndPadding()
00229 {
00230   nsStyleContext* context = mFrame->GetStyleContext();
00231 
00232   nsMargin innerFocusBorderAndPadding(0,0,0,0);
00233   nsStyleBorderPadding  bPad;
00234   context->GetBorderPaddingFor(bPad);
00235   if (!bPad.GetBorderPadding(innerFocusBorderAndPadding)) {
00236     NS_NOTYETIMPLEMENTED("percentage border");
00237   }
00238   return innerFocusBorderAndPadding;
00239 }
00240 
00244 nsMargin
00245 nsButtonFrameRenderer::GetButtonInnerFocusMargin()
00246 {
00247   nsMargin innerFocusMargin(0,0,0,0);
00248 
00249   if (mInnerFocusStyle) {
00250     // get the outer focus border and padding
00251     const nsStyleMargin* margin = mInnerFocusStyle->GetStyleMargin();
00252     margin->GetMargin(innerFocusMargin);
00253   }
00254 
00255   return innerFocusMargin;
00256 }
00257 
00258 nsMargin
00259 nsButtonFrameRenderer::GetButtonInnerFocusBorderAndPadding()
00260 {
00261   nsMargin innerFocusBorderAndPadding(0,0,0,0);
00262 
00263   if (mInnerFocusStyle) {
00264     // get the outer focus border and padding
00265     nsStyleBorderPadding  bPad;
00266     mInnerFocusStyle->GetBorderPaddingFor(bPad);
00267     if (!bPad.GetBorderPadding(innerFocusBorderAndPadding)) {
00268       NS_NOTYETIMPLEMENTED("percentage border");
00269     }
00270   }
00271 
00272   return innerFocusBorderAndPadding;
00273 }
00274 
00275 nsMargin
00276 nsButtonFrameRenderer::GetButtonOutlineBorderAndPadding()
00277 {
00278   nsMargin borderAndPadding(0,0,0,0);
00279   return borderAndPadding;
00280 }
00281 
00282 // gets the full size of our border with all the focus borders
00283 nsMargin
00284 nsButtonFrameRenderer::GetFullButtonBorderAndPadding()
00285 {
00286   return GetAddedButtonBorderAndPadding() + GetButtonBorderAndPadding();
00287 }
00288 
00289 // gets all the focus borders and padding that will be added to the regular border
00290 nsMargin
00291 nsButtonFrameRenderer::GetAddedButtonBorderAndPadding()
00292 {
00293   return GetButtonOuterFocusBorderAndPadding() + GetButtonInnerFocusMargin() + GetButtonInnerFocusBorderAndPadding();
00294 }
00295 
00299 void 
00300 nsButtonFrameRenderer::ReResolveStyles(nsPresContext* aPresContext)
00301 {
00302   // get all the styles
00303   nsStyleContext* context = mFrame->GetStyleContext();
00304   nsStyleSet *styleSet = aPresContext->StyleSet();
00305 
00306   // style for the inner such as a dotted line (Windows)
00307   mInnerFocusStyle = styleSet->ProbePseudoStyleFor(mFrame->GetContent(),
00308                                                    nsCSSPseudoElements::mozFocusInner,
00309                                                    context);
00310 
00311   // style for outer focus like a ridged border (MAC).
00312   mOuterFocusStyle = styleSet->ProbePseudoStyleFor(mFrame->GetContent(),
00313                                                    nsCSSPseudoElements::mozFocusOuter,
00314                                                    context);
00315 }
00316 
00317 nsStyleContext*
00318 nsButtonFrameRenderer::GetStyleContext(PRInt32 aIndex) const
00319 {
00320   switch (aIndex) {
00321   case NS_BUTTON_RENDERER_FOCUS_INNER_CONTEXT_INDEX:
00322     return mInnerFocusStyle;
00323   case NS_BUTTON_RENDERER_FOCUS_OUTER_CONTEXT_INDEX:
00324     return mOuterFocusStyle;
00325   default:
00326     return nsnull;
00327   }
00328 }
00329 
00330 void 
00331 nsButtonFrameRenderer::SetStyleContext(PRInt32 aIndex, nsStyleContext* aStyleContext)
00332 {
00333   switch (aIndex) {
00334   case NS_BUTTON_RENDERER_FOCUS_INNER_CONTEXT_INDEX:
00335     mInnerFocusStyle = aStyleContext;
00336     break;
00337   case NS_BUTTON_RENDERER_FOCUS_OUTER_CONTEXT_INDEX:
00338     mOuterFocusStyle = aStyleContext;
00339     break;
00340   }
00341 }