Back to index

lightning-sunbird  0.9+nobinonly
nsGfxRadioControlFrame.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 #include "nsGfxRadioControlFrame.h"
00039 #include "nsHTMLAtoms.h"
00040 #include "nsHTMLParts.h"
00041 #include "nsIFormControl.h"
00042 #include "nsIContent.h"
00043 #include "nsWidgetsCID.h"
00044 #include "nsIComponentManager.h"
00045 #include "nsCOMPtr.h"
00046 #include "nsCSSRendering.h"
00047 #include "nsIPresShell.h"
00048 #include "nsIDocument.h"
00049 #ifdef ACCESSIBILITY
00050 #include "nsIAccessibilityService.h"
00051 #endif
00052 #include "nsIServiceManager.h"
00053 #include "nsIDOMNode.h"
00054 #include "nsITheme.h"
00055 
00056 nsresult
00057 NS_NewGfxRadioControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
00058 {
00059   NS_PRECONDITION(aNewFrame, "null OUT ptr");
00060   if (nsnull == aNewFrame) {
00061     return NS_ERROR_NULL_POINTER;
00062   }
00063   nsGfxRadioControlFrame* it = new (aPresShell) nsGfxRadioControlFrame;
00064   if (!it) {
00065     return NS_ERROR_OUT_OF_MEMORY;
00066   }
00067   *aNewFrame = it;
00068   return NS_OK;
00069 }
00070 
00071 nsGfxRadioControlFrame::nsGfxRadioControlFrame()
00072 {
00073    // Initialize GFX-rendered state
00074   mRadioButtonFaceStyle = nsnull;
00075 }
00076 
00077 nsGfxRadioControlFrame::~nsGfxRadioControlFrame()
00078 {
00079   if (mRadioButtonFaceStyle)
00080     mRadioButtonFaceStyle->Release();
00081 }
00082 
00083 // Frames are not refcounted, no need to AddRef
00084 NS_IMETHODIMP
00085 nsGfxRadioControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
00086 {
00087   NS_PRECONDITION(0 != aInstancePtr, "null ptr");
00088   if (NULL == aInstancePtr) {
00089     return NS_ERROR_NULL_POINTER;
00090   }
00091   if (aIID.Equals(NS_GET_IID(nsIRadioControlFrame))) {
00092     *aInstancePtr = (void*) ((nsIRadioControlFrame*) this);
00093     return NS_OK;
00094   }
00095 
00096   return nsFormControlFrame::QueryInterface(aIID, aInstancePtr);
00097 }
00098 
00099 #ifdef ACCESSIBILITY
00100 NS_IMETHODIMP nsGfxRadioControlFrame::GetAccessible(nsIAccessible** aAccessible)
00101 {
00102   nsCOMPtr<nsIAccessibilityService> accService = do_GetService("@mozilla.org/accessibilityService;1");
00103 
00104   if (accService) {
00105     return accService->CreateHTMLRadioButtonAccessible(NS_STATIC_CAST(nsIFrame*, this), aAccessible);
00106   }
00107 
00108   return NS_ERROR_FAILURE;
00109 }
00110 #endif
00111 
00112 //--------------------------------------------------------------
00113 nsStyleContext*
00114 nsGfxRadioControlFrame::GetAdditionalStyleContext(PRInt32 aIndex) const
00115 {
00116   switch (aIndex) {
00117   case NS_GFX_RADIO_CONTROL_FRAME_FACE_CONTEXT_INDEX:
00118     return mRadioButtonFaceStyle;
00119     break;
00120   default:
00121     return nsnull;
00122   }
00123 }
00124 
00125 //--------------------------------------------------------------
00126 void
00127 nsGfxRadioControlFrame::SetAdditionalStyleContext(PRInt32 aIndex, 
00128                                                   nsStyleContext* aStyleContext)
00129 {
00130   switch (aIndex) {
00131   case NS_GFX_RADIO_CONTROL_FRAME_FACE_CONTEXT_INDEX:
00132     if (mRadioButtonFaceStyle)
00133       mRadioButtonFaceStyle->Release();
00134     mRadioButtonFaceStyle = aStyleContext;
00135     if (aStyleContext)
00136       aStyleContext->AddRef();
00137     break;
00138   }
00139 }
00140 
00141 //--------------------------------------------------------------
00142 NS_IMETHODIMP
00143 nsGfxRadioControlFrame::SetRadioButtonFaceStyleContext(nsStyleContext *aRadioButtonFaceStyleContext)
00144 {
00145   mRadioButtonFaceStyle = aRadioButtonFaceStyleContext;
00146   mRadioButtonFaceStyle->AddRef();
00147   return NS_OK;
00148 }
00149 
00150 //--------------------------------------------------------------
00151 NS_IMETHODIMP
00152 nsGfxRadioControlFrame::HandleEvent(nsPresContext* aPresContext, 
00153                                           nsGUIEvent* aEvent,
00154                                           nsEventStatus* aEventStatus)
00155 {
00156   // Check for user-input:none style
00157   const nsStyleUserInterface* uiStyle = GetStyleUserInterface();
00158   if (uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE || uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED)
00159     return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
00160 
00161   // otherwise, do nothing. Events are handled by the DOM.
00162   return NS_OK;
00163 }
00164 
00165 //--------------------------------------------------------------
00166 void
00167 nsGfxRadioControlFrame::PaintRadioButton(nsPresContext* aPresContext,
00168                                       nsIRenderingContext& aRenderingContext,
00169                                       const nsRect& aDirtyRect)
00170 {
00171   const nsStyleDisplay* disp = GetStyleDisplay();
00172   if (disp->mAppearance) {
00173     nsITheme *theme = aPresContext->GetTheme();
00174     if (theme && theme->ThemeSupportsWidget(aPresContext, this, disp->mAppearance))
00175       return; // No need to paint the radio button. The theme will do it.
00176   }
00177 
00178   PRBool checked = PR_TRUE;
00179   GetCurrentCheckState(&checked); // Get check state from the content model
00180   const nsStyleBorder* myBorder = mRadioButtonFaceStyle->GetStyleBorder();
00181   if (checked) {
00182    // Paint the button for the radio button using CSS background rendering code
00183    if (nsnull != mRadioButtonFaceStyle) {
00184      const nsStyleBackground* myColor = mRadioButtonFaceStyle->GetStyleBackground();
00185      const nsStyleColor* color = mRadioButtonFaceStyle->GetStyleColor();
00186      const nsStylePadding* myPadding = mRadioButtonFaceStyle->GetStylePadding();
00187      const nsStylePosition* myPosition = mRadioButtonFaceStyle->GetStylePosition();
00188 
00189      nscoord width = myPosition->mWidth.GetCoordValue();
00190      nscoord height = myPosition->mHeight.GetCoordValue();
00191        // Position the button centered within the radio control's rectangle.
00192      nscoord x = (mRect.width - width) / 2;
00193      nscoord y = (mRect.height - height) / 2;
00194      nsRect rect(x, y, width, height); 
00195 
00196      // So we will use PaintBackgroundWithSC to paint the dot, 
00197      // but it uses the mBackgroundColor for painting and we need to use the mColor
00198      // so create a temporary style color struct and set it up appropriately
00199      // XXXldb It would make more sense to use
00200      // |aRenderingContext.FillEllipse| here, but on at least GTK that
00201      // doesn't draw a round enough circle.
00202      nsStyleBackground tmpColor     = *myColor;
00203      tmpColor.mBackgroundColor = color->mColor;
00204      nsCSSRendering::PaintBackgroundWithSC(aPresContext, aRenderingContext,
00205                                            this, aDirtyRect, rect,
00206                                            tmpColor, *myBorder, *myPadding, PR_FALSE);
00207      nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
00208                                   aDirtyRect, rect, *myBorder, mRadioButtonFaceStyle, 0);
00209    }
00210   }
00211 }
00212 
00213 //--------------------------------------------------------------
00214 NS_METHOD 
00215 nsGfxRadioControlFrame::Paint(nsPresContext*   aPresContext,
00216                            nsIRenderingContext& aRenderingContext,
00217                            const nsRect&        aDirtyRect,
00218                            nsFramePaintLayer    aWhichLayer,
00219                            PRUint32             aFlags)
00220 {
00221   PRBool isVisible;
00222   if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) {
00223     return NS_OK;
00224   }
00225      // Paint the background
00226   nsresult rv = nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
00227 
00228   if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
00229     PaintRadioButton(aPresContext, aRenderingContext, aDirtyRect);
00230   }
00231   nsRect rect(0, 0, mRect.width, mRect.height);
00232   const nsStyleOutline* myOutline = GetStyleOutline();
00233   const nsStyleBorder* myBorder = GetStyleBorder();
00234   nsCSSRendering::PaintOutline(aPresContext, aRenderingContext, this,
00235                                aDirtyRect, rect, *myBorder, *myOutline,
00236                                mStyleContext, 0);
00237   return rv;
00238 }
00239 
00240 
00241 //--------------------------------------------------------------
00242 NS_IMETHODIMP
00243 nsGfxRadioControlFrame::OnChecked(nsPresContext* aPresContext,
00244                                   PRBool aChecked)
00245 {
00246   Invalidate(GetOverflowRect(), PR_FALSE);
00247   return NS_OK;
00248 }
00249 
00250 
00251 //----------------------------------------------------------------------
00252 // Extra Debug Helper Methods
00253 //----------------------------------------------------------------------
00254 #ifdef DEBUG_rodsXXX
00255 NS_IMETHODIMP 
00256 nsGfxRadioControlFrame::Reflow(nsPresContext*          aPresContext, 
00257                                nsHTMLReflowMetrics&     aDesiredSize,
00258                                const nsHTMLReflowState& aReflowState, 
00259                                nsReflowStatus&          aStatus)
00260 {
00261   DO_GLOBAL_REFLOW_COUNT("nsGfxRadioControlFrame", aReflowState.reason);
00262   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
00263 
00264   nsresult rv = nsNativeFormControlFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
00265 
00266   COMPARE_QUIRK_SIZE("nsGfxRadioControlFrame", 12, 11) 
00267   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
00268   return rv;
00269 }
00270 #endif
00271 
00272 NS_IMETHODIMP
00273 nsGfxRadioControlFrame::OnContentReset()
00274 {
00275   return NS_OK;
00276 }