Back to index

lightning-sunbird  0.9+nobinonly
nsGfxCheckboxControlFrame.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 "nsGfxCheckboxControlFrame.h"
00039 #include "nsICheckButton.h"
00040 #include "nsHTMLAtoms.h"
00041 #include "nsHTMLParts.h"
00042 #include "nsIFormControl.h"
00043 #include "nsIContent.h"
00044 #include "nsIComponentManager.h"
00045 #include "nsHTMLAtoms.h"
00046 #include "nsIPresShell.h"
00047 #include "nsIDocument.h"
00048 #include "nsCSSRendering.h"
00049 #ifdef ACCESSIBILITY
00050 #include "nsIAccessibilityService.h"
00051 #endif
00052 #include "nsIServiceManager.h"
00053 #include "nsIDOMNode.h"
00054 #include "nsIDOMHTMLInputElement.h"
00055 #include "nsITheme.h"
00056 #include "imgIRequest.h"
00057 
00058 
00059 //------------------------------------------------------------
00060 nsresult
00061 NS_NewGfxCheckboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
00062 {
00063   NS_PRECONDITION(aNewFrame, "null OUT ptr");
00064   if (nsnull == aNewFrame) {
00065     return NS_ERROR_NULL_POINTER;
00066   }
00067   nsGfxCheckboxControlFrame* it = new (aPresShell) nsGfxCheckboxControlFrame;
00068   if (!it) {
00069     return NS_ERROR_OUT_OF_MEMORY;
00070   }
00071   *aNewFrame = it;
00072   return NS_OK;
00073 }
00074 
00075 
00076 //------------------------------------------------------------
00077 // Initialize GFX-rendered state
00078 nsGfxCheckboxControlFrame::nsGfxCheckboxControlFrame()
00079 : mCheckButtonFaceStyle(nsnull)
00080 {
00081 }
00082 
00083 nsGfxCheckboxControlFrame::~nsGfxCheckboxControlFrame()
00084 {
00085   if (mCheckButtonFaceStyle)
00086     mCheckButtonFaceStyle->Release();
00087 }
00088 
00089 
00090 //----------------------------------------------------------------------
00091 // nsISupports
00092 //----------------------------------------------------------------------
00093 // Frames are not refcounted, no need to AddRef
00094 NS_IMETHODIMP
00095 nsGfxCheckboxControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
00096 {
00097   NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!");
00098   if ( !aInstancePtr )
00099     return NS_ERROR_NULL_POINTER;
00100 
00101   if (aIID.Equals(NS_GET_IID(nsICheckboxControlFrame))) {
00102     *aInstancePtr = (void*) ((nsICheckboxControlFrame*) this);
00103     return NS_OK;
00104   }
00105 
00106   return nsFormControlFrame::QueryInterface(aIID, aInstancePtr);
00107 }
00108 
00109 #ifdef ACCESSIBILITY
00110 NS_IMETHODIMP nsGfxCheckboxControlFrame::GetAccessible(nsIAccessible** aAccessible)
00111 {
00112   nsCOMPtr<nsIAccessibilityService> accService = do_GetService("@mozilla.org/accessibilityService;1");
00113 
00114   if (accService) {
00115     return accService->CreateHTMLCheckboxAccessible(NS_STATIC_CAST(nsIFrame*, this), aAccessible);
00116   }
00117 
00118   return NS_ERROR_FAILURE;
00119 }
00120 #endif
00121 
00122 //--------------------------------------------------------------
00123 NS_IMETHODIMP
00124 nsGfxCheckboxControlFrame::SetCheckboxFaceStyleContext(nsStyleContext *aCheckboxFaceStyleContext)
00125 {
00126   mCheckButtonFaceStyle = aCheckboxFaceStyleContext;
00127   mCheckButtonFaceStyle->AddRef();
00128   return NS_OK;
00129 }
00130 
00131 
00132 //--------------------------------------------------------------
00133 nsStyleContext*
00134 nsGfxCheckboxControlFrame::GetAdditionalStyleContext(PRInt32 aIndex) const
00135 {
00136   switch (aIndex) {
00137   case NS_GFX_CHECKBOX_CONTROL_FRAME_FACE_CONTEXT_INDEX:
00138     return mCheckButtonFaceStyle;
00139     break;
00140   default:
00141     return nsnull;
00142   }
00143 }
00144 
00145 
00146 
00147 //--------------------------------------------------------------
00148 void
00149 nsGfxCheckboxControlFrame::SetAdditionalStyleContext(PRInt32 aIndex, 
00150                                                      nsStyleContext* aStyleContext)
00151 {
00152   switch (aIndex) {
00153   case NS_GFX_CHECKBOX_CONTROL_FRAME_FACE_CONTEXT_INDEX:
00154     if (mCheckButtonFaceStyle)
00155       mCheckButtonFaceStyle->Release();
00156     mCheckButtonFaceStyle = aStyleContext;
00157     if (aStyleContext)
00158       aStyleContext->AddRef();
00159     break;
00160   }
00161 }
00162 
00163 
00164 //------------------------------------------------------------
00165 NS_IMETHODIMP
00166 nsGfxCheckboxControlFrame::OnChecked(nsPresContext* aPresContext,
00167                                      PRBool aChecked)
00168 {
00169   Invalidate(GetOverflowRect(), PR_FALSE);
00170   return aChecked;
00171 }
00172 
00173 
00174 //------------------------------------------------------------
00175 void
00176 nsGfxCheckboxControlFrame::PaintCheckBox(nsPresContext* aPresContext,
00177                                          nsIRenderingContext& aRenderingContext,
00178                                          const nsRect& aDirtyRect,
00179                                          nsFramePaintLayer aWhichLayer)
00180 {
00181   const nsStyleDisplay* disp = GetStyleDisplay();
00182   if (disp->mAppearance) {
00183     nsITheme *theme = aPresContext->GetTheme();
00184     if (theme && theme->ThemeSupportsWidget(aPresContext, this, disp->mAppearance))
00185       return; // No need to paint the checkbox. The theme will do it.
00186   }
00187 
00188   // Get current checked state through content model.
00189   if (!GetCheckboxState())
00190     return;   // we're not checked, nothing to paint.
00191 
00192   aRenderingContext.PushState();
00193 
00194   nsMargin borderPadding(0,0,0,0);
00195   CalcBorderPadding(borderPadding);
00196 
00197   nsRect checkRect(0,0, mRect.width, mRect.height);
00198   checkRect.Deflate(borderPadding);
00199 
00200   const nsStyleColor* color = GetStyleColor();
00201   aRenderingContext.SetColor(color->mColor);
00202 
00203   nsFormControlHelper::PaintCheckMark(aRenderingContext,
00204                                       aPresContext->ScaledPixelsToTwips(),
00205                                       checkRect);
00206 
00207   aRenderingContext.PopState();
00208 }
00209 
00210 
00211 //------------------------------------------------------------
00212 NS_METHOD 
00213 nsGfxCheckboxControlFrame::Paint(nsPresContext*   aPresContext,
00214                               nsIRenderingContext& aRenderingContext,
00215                               const nsRect&        aDirtyRect,
00216                               nsFramePaintLayer    aWhichLayer,
00217                               PRUint32             aFlags)
00218 {
00219   PRBool isVisible;
00220   if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) {
00221     return NS_OK;
00222   }
00223 
00224   // Paint the background
00225   nsresult rv = nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
00226   if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
00227     PRBool doDefaultPainting = PR_TRUE;
00228     // Paint the checkmark
00229     const nsStyleBorder* myBorder = mCheckButtonFaceStyle->GetStyleBorder();
00230     if (!mCheckButtonFaceStyle && GetCheckboxState()) {
00231       const nsStyleBackground* myColor = mCheckButtonFaceStyle->GetStyleBackground();
00232 
00233       if (myColor->mBackgroundImage) {
00234         const nsStylePadding* myPadding = mCheckButtonFaceStyle->GetStylePadding();
00235         const nsStylePosition* myPosition = mCheckButtonFaceStyle->GetStylePosition();
00236 
00237         nscoord width = myPosition->mWidth.GetCoordValue();
00238         nscoord height = myPosition->mHeight.GetCoordValue();
00239          // Position the button centered within the radio control's rectangle.
00240         nscoord x = (mRect.width - width) / 2;
00241         nscoord y = (mRect.height - height) / 2;
00242         nsRect rect(x, y, width, height); 
00243 
00244         nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
00245                                         aDirtyRect, rect, *myBorder, *myPadding,
00246                                         PR_FALSE);
00247         nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
00248                                     aDirtyRect, rect, *myBorder, mCheckButtonFaceStyle, 0);
00249         doDefaultPainting = PR_FALSE;
00250       }
00251     } 
00252 
00253     nsRect rect(0, 0, mRect.width, mRect.height);
00254     const nsStyleOutline* myOutline = GetStyleOutline();
00255     nsCSSRendering::PaintOutline(aPresContext, aRenderingContext, this,
00256                                   aDirtyRect, rect, *myBorder, *myOutline,
00257                                   mStyleContext, 0);
00258 
00259     if (doDefaultPainting) {
00260       PaintCheckBox(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
00261     }
00262   }
00263   return rv;
00264 }
00265 
00266 //------------------------------------------------------------
00267 PRBool
00268 nsGfxCheckboxControlFrame::GetCheckboxState ( )
00269 {
00270   nsCOMPtr<nsIDOMHTMLInputElement> elem(do_QueryInterface(mContent));
00271   PRBool retval = PR_FALSE;
00272   elem->GetChecked(&retval);
00273   return retval;
00274 }
00275 
00276 //------------------------------------------------------------
00277 // Extra Debug Methods
00278 //------------------------------------------------------------
00279 #ifdef DEBUG_rodsXXX
00280 NS_IMETHODIMP
00281 nsGfxCheckboxControlFrame::Reflow(nsPresContext*          aPresContext, 
00282                                   nsHTMLReflowMetrics&     aDesiredSize,
00283                                   const nsHTMLReflowState& aReflowState, 
00284                                   nsReflowStatus&          aStatus)
00285 {
00286   DO_GLOBAL_REFLOW_COUNT("nsGfxCheckboxControlFrame", aReflowState.reason);
00287   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
00288   nsresult rv = nsFormControlFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
00289 
00290   COMPARE_QUIRK_SIZE("nsGfxCheckboxControlFrame", 13, 13) 
00291   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
00292   return rv;
00293 }
00294 #endif
00295 
00296 NS_IMETHODIMP
00297 nsGfxCheckboxControlFrame::OnContentReset()
00298 {
00299   return NS_OK;
00300 }