Back to index

lightning-sunbird  0.9+nobinonly
nsHTMLButtonControlFrame.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 "nsHTMLButtonControlFrame.h"
00039 
00040 #include "nsCOMPtr.h"
00041 #include "nsHTMLContainerFrame.h"
00042 #include "nsFormControlHelper.h"
00043 #include "nsIFormControlFrame.h"
00044 #include "nsHTMLParts.h"
00045 #include "nsIFormControl.h"
00046 
00047 #include "nsIRenderingContext.h"
00048 #include "nsPresContext.h"
00049 #include "nsIPresShell.h"
00050 #include "nsStyleContext.h"
00051 #include "nsLeafFrame.h"
00052 #include "nsCSSRendering.h"
00053 #include "nsISupports.h"
00054 #include "nsHTMLAtoms.h"
00055 #include "nsCSSAnonBoxes.h"
00056 #include "nsIImage.h"
00057 #include "nsStyleConsts.h"
00058 #include "nsIWidget.h"
00059 #include "nsIComponentManager.h"
00060 #include "nsIDocument.h"
00061 #include "nsButtonFrameRenderer.h"
00062 #include "nsFormControlFrame.h"
00063 #include "nsFrameManager.h"
00064 #include "nsINameSpaceManager.h"
00065 #include "nsReflowPath.h"
00066 #include "nsIServiceManager.h"
00067 #include "nsIDOMHTMLButtonElement.h"
00068 #include "nsIDOMHTMLInputElement.h"
00069 #include "nsStyleSet.h"
00070 #ifdef ACCESSIBILITY
00071 #include "nsIAccessibilityService.h"
00072 #endif
00073 
00074 nsresult
00075 NS_NewHTMLButtonControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
00076 {
00077   NS_PRECONDITION(aNewFrame, "null OUT ptr");
00078   if (nsnull == aNewFrame) {
00079     return NS_ERROR_NULL_POINTER;
00080   }
00081   nsHTMLButtonControlFrame* it = new (aPresShell) nsHTMLButtonControlFrame;
00082   if (!it) {
00083     return NS_ERROR_OUT_OF_MEMORY;
00084   }
00085   *aNewFrame = it;
00086   return NS_OK;
00087 }
00088 
00089 nsHTMLButtonControlFrame::nsHTMLButtonControlFrame()
00090   : nsHTMLContainerFrame()
00091 {
00092   mInline = PR_TRUE;
00093 
00094   mCacheSize.width             = -1;
00095   mCacheSize.height            = -1;
00096   mCachedMaxElementWidth       = -1;
00097 }
00098 
00099 nsHTMLButtonControlFrame::~nsHTMLButtonControlFrame()
00100 {
00101 }
00102 
00103 NS_IMETHODIMP
00104 nsHTMLButtonControlFrame::Destroy(nsPresContext *aPresContext)
00105 {
00106   nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE);
00107   return nsHTMLContainerFrame::Destroy(aPresContext);
00108 }
00109 
00110 NS_IMETHODIMP
00111 nsHTMLButtonControlFrame::Init(nsPresContext*  aPresContext,
00112               nsIContent*      aContent,
00113               nsIFrame*        aParent,
00114               nsStyleContext*  aContext,
00115               nsIFrame*        aPrevInFlow)
00116 {
00117   nsresult  rv = nsHTMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
00118   mRenderer.SetFrame(this,aPresContext);
00119    // cache our display type
00120   mInline = (NS_STYLE_DISPLAY_BLOCK != GetStyleDisplay()->mDisplay);
00121 
00122   PRUint32 flags = NS_BLOCK_SPACE_MGR;
00123   if (mInline) {
00124     flags |= NS_BLOCK_SHRINK_WRAP;
00125   }
00126 
00127   nsIFrame* areaFrame;
00128   nsIPresShell *shell = aPresContext->PresShell();
00129   NS_NewAreaFrame(shell, &areaFrame, flags);
00130   mFrames.SetFrames(areaFrame);
00131 
00132   // Resolve style and initialize the frame
00133   nsRefPtr<nsStyleContext> styleContext;
00134   styleContext = shell->StyleSet()->ResolvePseudoStyleFor(mContent,
00135                                                           nsCSSAnonBoxes::buttonContent,
00136                                                           mStyleContext);
00137   mFrames.FirstChild()->Init(aPresContext, mContent, this, styleContext, nsnull);
00138 
00139   return rv;
00140 }
00141 
00142 nsrefcnt nsHTMLButtonControlFrame::AddRef(void)
00143 {
00144   NS_WARNING("not supported");
00145   return 1;
00146 }
00147 
00148 nsrefcnt nsHTMLButtonControlFrame::Release(void)
00149 {
00150   NS_WARNING("not supported");
00151   return 1;
00152 }
00153 
00154 // Frames are not refcounted, no need to AddRef
00155 NS_IMETHODIMP
00156 nsHTMLButtonControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
00157 {
00158   NS_PRECONDITION(0 != aInstancePtr, "null ptr");
00159   if (NULL == aInstancePtr) {
00160     return NS_ERROR_NULL_POINTER;
00161   }
00162   if (aIID.Equals(NS_GET_IID(nsIFormControlFrame))) {
00163     *aInstancePtr = (void*) ((nsIFormControlFrame*) this);
00164     return NS_OK;
00165   }
00166 
00167   return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr);
00168 }
00169 
00170 #ifdef ACCESSIBILITY
00171 NS_IMETHODIMP nsHTMLButtonControlFrame::GetAccessible(nsIAccessible** aAccessible)
00172 {
00173   nsCOMPtr<nsIAccessibilityService> accService = do_GetService("@mozilla.org/accessibilityService;1");
00174 
00175   if (accService) {
00176     nsIContent* content = GetContent();
00177     nsCOMPtr<nsIDOMHTMLButtonElement> buttonElement(do_QueryInterface(content));
00178     if (buttonElement) //If turned XBL-base form control off, the frame contains HTML 4 button
00179       return accService->CreateHTML4ButtonAccessible(NS_STATIC_CAST(nsIFrame*, this), aAccessible);
00180     nsCOMPtr<nsIDOMHTMLInputElement> inputElement(do_QueryInterface(content));
00181     if (inputElement) //If turned XBL-base form control on, the frame contains normal HTML button
00182       return accService->CreateHTMLButtonAccessible(NS_STATIC_CAST(nsIFrame*, this), aAccessible);
00183   }
00184 
00185   return NS_ERROR_FAILURE;
00186 }
00187 #endif
00188 
00189 
00190 NS_IMETHODIMP_(PRInt32)
00191 nsHTMLButtonControlFrame::GetFormControlType() const
00192 {
00193   return nsFormControlHelper::GetType(mContent);
00194 }
00195 
00196 NS_IMETHODIMP
00197 nsHTMLButtonControlFrame::GetName(nsAString* aResult)
00198 {
00199   return nsFormControlHelper::GetName(mContent, aResult);
00200 }
00201 
00202 NS_IMETHODIMP
00203 nsHTMLButtonControlFrame::GetValue(nsAString* aResult)
00204 {
00205   return nsFormControlHelper::GetValueAttr(mContent, aResult);
00206 }
00207 
00208 void
00209 nsHTMLButtonControlFrame::ReParentFrameList(nsFrameManager* aFrameManager,
00210                                             nsIFrame* aFrameList)
00211 {
00212   // get the new parent context from the first child: that is the
00213   // frame that the subsequent children will be made children of
00214   nsStyleContext* newParentContext = mFrames.FirstChild()->GetStyleContext();
00215 
00216   // Set the parent for each of the child frames
00217   for (nsIFrame* frame = aFrameList; frame; frame = frame->GetNextSibling()) {
00218     frame->SetParent(mFrames.FirstChild());
00219     // now reparent the contexts for the reparented frame too
00220     aFrameManager->ReParentStyleContext(frame);
00221   }
00222 
00223   // Set NS_FRAME_HAS_CHILD_WITH_VIEW on the area frame if needed, bug 276236.
00224   mFrames.FirstChild()->AddStateBits(GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW);
00225 }
00226 
00227 PRBool
00228 nsHTMLButtonControlFrame::IsReset(PRInt32 type)
00229 {
00230   if (NS_FORM_BUTTON_RESET == type) {
00231     return PR_TRUE;
00232   } else {
00233     return PR_FALSE;
00234   }
00235 }
00236 
00237 PRBool
00238 nsHTMLButtonControlFrame::IsSubmit(PRInt32 type)
00239 {
00240   if (NS_FORM_BUTTON_SUBMIT == type) {
00241     return PR_TRUE;
00242   } else {
00243     return PR_FALSE;
00244   }
00245 }
00246 
00247 void 
00248 nsHTMLButtonControlFrame::SetFocus(PRBool aOn, PRBool aRepaint)
00249 {
00250 }
00251 
00252 void
00253 nsHTMLButtonControlFrame::ScrollIntoView(nsPresContext* aPresContext)
00254 {
00255   if (aPresContext) {
00256     nsIPresShell *presShell = aPresContext->GetPresShell();
00257     if (presShell) {
00258      presShell->ScrollFrameIntoView(this,
00259                    NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
00260 
00261     }
00262   }
00263 }
00264 
00265 NS_IMETHODIMP
00266 nsHTMLButtonControlFrame::HandleEvent(nsPresContext* aPresContext, 
00267                                       nsGUIEvent*     aEvent,
00268                                       nsEventStatus*  aEventStatus)
00269 {
00270   // if disabled do nothing
00271   if (mRenderer.isDisabled()) {
00272     return NS_OK;
00273   }
00274 
00275   // mouse clicks are handled by content
00276   // we don't want our children to get any events. So just pass it to frame.
00277   return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
00278 }
00279 
00280 
00281 NS_IMETHODIMP
00282 nsHTMLButtonControlFrame::GetFrameForPoint(const nsPoint& aPoint,
00283                                            nsFramePaintLayer aWhichLayer,
00284                                            nsIFrame** aFrame)
00285 {
00286   if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND &&
00287       mRect.Contains(aPoint)) {
00288     if (GetStyleVisibility()->IsVisible()) {
00289       *aFrame = this;
00290       return NS_OK;
00291     }
00292   }
00293   return NS_ERROR_FAILURE;
00294 }
00295 
00296 NS_IMETHODIMP
00297 nsHTMLButtonControlFrame::SetInitialChildList(nsPresContext* aPresContext,
00298                                               nsIAtom*        aListName,
00299                                               nsIFrame*       aChildList)
00300 {
00301   // NOTE: the whole reparenting should not need to happen: see bugzilla bug 51767
00302   ReParentFrameList(aPresContext->FrameManager(), aChildList);
00303   
00304   return mFrames.FirstChild()->SetInitialChildList(aPresContext, aListName, aChildList);
00305 }
00306 
00307 NS_IMETHODIMP
00308 nsHTMLButtonControlFrame::Paint(nsPresContext*      aPresContext,
00309                                 nsIRenderingContext& aRenderingContext,
00310                                 const nsRect&        aDirtyRect,
00311                                 nsFramePaintLayer    aWhichLayer,
00312                                 PRUint32             aFlags)
00313 {
00314   PRBool isVisible;
00315   if (aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND ||
00316       (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible)) {
00317     return NS_OK;
00318   }
00319 
00320   nsRect rect(0, 0, mRect.width, mRect.height);
00321   mRenderer.PaintButton(aPresContext, aRenderingContext, aDirtyRect, rect);
00322 
00323 #if 0 // old way
00324   PaintChildren(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_BACKGROUND);
00325   PaintChildren(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_FLOATS);
00326   PaintChildren(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_FOREGROUND);
00327 
00328 #else // temporary
00329     // XXX This is temporary
00330   // clips to it's size minus the border 
00331   // but the real problem is the FirstChild (the AreaFrame)
00332   // isn't being constrained properly
00333   // Bug #17474
00334   const nsStyleBorder* borderStyle = GetStyleBorder();
00335   nsMargin border;
00336   border.SizeTo(0, 0, 0, 0);
00337   borderStyle->CalcBorderFor(this, border);
00338 
00339   rect.Deflate(border);
00340   aRenderingContext.PushState();
00341 
00342   aRenderingContext.SetClipRect(rect, nsClipCombine_kIntersect);
00343 
00344   PaintChildren(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_BACKGROUND);
00345   PaintChildren(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_FLOATS);
00346   PaintChildren(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_FOREGROUND);
00347 
00348   aRenderingContext.PopState();
00349 
00350 #endif
00351 
00352   // Paint outline
00353   const nsStyleOutline* outlineStyle = GetStyleOutline();
00354   nsCSSRendering::PaintOutline(aPresContext, aRenderingContext, this,
00355                                aDirtyRect, rect, *borderStyle, *outlineStyle,
00356                                mStyleContext, 0);
00357 
00358   // to draw border when selected in editor
00359   return nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
00360 }
00361 
00362 NS_IMETHODIMP 
00363 nsHTMLButtonControlFrame::AddComputedBorderPaddingToDesiredSize(nsHTMLReflowMetrics& aDesiredSize,
00364                                                                 const nsHTMLReflowState& aSuggestedReflowState)
00365 {
00366   aDesiredSize.width  += aSuggestedReflowState.mComputedBorderPadding.left + aSuggestedReflowState.mComputedBorderPadding.right;
00367   aDesiredSize.height += aSuggestedReflowState.mComputedBorderPadding.top + aSuggestedReflowState.mComputedBorderPadding.bottom;
00368   return NS_OK;
00369 }
00370 
00371 NS_IMETHODIMP 
00372 nsHTMLButtonControlFrame::Reflow(nsPresContext* aPresContext,
00373                                nsHTMLReflowMetrics& aDesiredSize,
00374                                const nsHTMLReflowState& aReflowState,
00375                                nsReflowStatus& aStatus)
00376 {
00377   DO_GLOBAL_REFLOW_COUNT("nsHTMLButtonControlFrame", aReflowState.reason);
00378   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
00379 
00380   if (eReflowReason_Initial == aReflowState.reason) {
00381     nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_TRUE);
00382   }
00383 
00384 #if 0
00385   nsresult skiprv = nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementWidth, aPresContext, 
00386                                                          aDesiredSize, aReflowState, aStatus);
00387   if (NS_SUCCEEDED(skiprv)) {
00388     return skiprv;
00389   }
00390 #endif
00391 
00392   // Reflow the child
00393   nsIFrame* firstKid = mFrames.FirstChild();
00394   nsSize availSize(aReflowState.mComputedWidth, NS_INTRINSICSIZE);
00395 
00396   // Indent the child inside us by the the focus border. We must do this separate from the
00397   // regular border.
00398   nsMargin focusPadding = mRenderer.GetAddedButtonBorderAndPadding();
00399 
00400   
00401   if (NS_INTRINSICSIZE != availSize.width) {
00402     availSize.width -= focusPadding.left + focusPadding.right;
00403     availSize.width = PR_MAX(availSize.width,0);
00404   }
00405   if (NS_AUTOHEIGHT != availSize.height) {
00406     availSize.height -= focusPadding.top + focusPadding.bottom;
00407     availSize.height = PR_MAX(availSize.height,0);
00408   }
00409   
00410   // XXX Proper handling of incremental reflow...
00411   nsReflowReason reason = aReflowState.reason;
00412   if (eReflowReason_Incremental == reason) {
00413     // See if it's targeted at us
00414     nsHTMLReflowCommand *command = aReflowState.path->mReflowCommand;
00415     if (command) {
00416       // I'm not sure what exactly this Invalidate is for
00417       Invalidate(nsRect(0,0,mRect.width,mRect.height), PR_FALSE);
00418 
00419       nsReflowType  reflowType;
00420       command->GetType(reflowType);
00421       if (eReflowType_StyleChanged == reflowType) {
00422         reason = eReflowReason_StyleChange;
00423       }
00424       else {
00425         reason = eReflowReason_Resize;
00426       }
00427     }
00428   }
00429 
00430   // Reflow the contents of the button a first time.
00431   ReflowButtonContents(aPresContext, aDesiredSize, aReflowState, firstKid,
00432                        availSize, reason, focusPadding, aStatus);
00433 
00434   // If we just performed the first pass of a shrink-wrap reflow (which will have
00435   // found the requested size of the children, but not placed them), perform
00436   // the second pass of a shrink-wrap reflow (which places the children
00437   // within this parent button which has now shrink-wrapped around them).
00438   if (availSize.width == NS_SHRINKWRAPWIDTH) {
00439     nsSize newAvailSize(aDesiredSize.width, NS_INTRINSICSIZE);
00440 
00441     ReflowButtonContents(aPresContext, aDesiredSize, aReflowState, firstKid,
00442                          newAvailSize, eReflowReason_Resize, focusPadding, aStatus);
00443   }
00444 
00445   // If computed use the computed values.
00446   if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) 
00447     aDesiredSize.width = aReflowState.mComputedWidth;
00448   else 
00449     aDesiredSize.width  += focusPadding.left + focusPadding.right;
00450 
00451   if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) 
00452     aDesiredSize.height = aReflowState.mComputedHeight;
00453   else
00454     aDesiredSize.height += focusPadding.top + focusPadding.bottom;
00455 
00456   AddComputedBorderPaddingToDesiredSize(aDesiredSize, aReflowState);
00457 
00458   //aDesiredSize.width  += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right;
00459   //aDesiredSize.height += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom;
00460 
00461   if (aDesiredSize.mComputeMEW) {
00462     aDesiredSize.SetMEWToActualWidth(aReflowState.mStylePosition->mWidth.GetUnit());
00463   }
00464 
00465   // Make sure we obey min/max-width and min/max-height
00466   if (aDesiredSize.width > aReflowState.mComputedMaxWidth) {
00467     aDesiredSize.width = aReflowState.mComputedMaxWidth;
00468   }
00469   if (aDesiredSize.width < aReflowState.mComputedMinWidth) {
00470     aDesiredSize.width = aReflowState.mComputedMinWidth;
00471   } 
00472 
00473   if (aDesiredSize.height > aReflowState.mComputedMaxHeight) {
00474     aDesiredSize.height = aReflowState.mComputedMaxHeight;
00475   }
00476   if (aDesiredSize.height < aReflowState.mComputedMinHeight) {
00477     aDesiredSize.height = aReflowState.mComputedMinHeight;
00478   }
00479 
00480   aDesiredSize.ascent  += aReflowState.mComputedBorderPadding.top + focusPadding.top;
00481   aDesiredSize.descent = aDesiredSize.height - aDesiredSize.ascent;
00482 
00483   aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width, aDesiredSize.height);
00484   ConsiderChildOverflow(aDesiredSize.mOverflowArea, firstKid);
00485   FinishAndStoreOverflow(&aDesiredSize);
00486 
00487   aStatus = NS_FRAME_COMPLETE;
00488 
00489   nsFormControlFrame::SetupCachedSizes(mCacheSize, mCachedAscent,
00490                                        mCachedMaxElementWidth, aDesiredSize);
00491   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
00492   return NS_OK;
00493 }
00494 
00495 void
00496 nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext,
00497                                                nsHTMLReflowMetrics& aDesiredSize,
00498                                                const nsHTMLReflowState& aReflowState,
00499                                                nsIFrame* aFirstKid,
00500                                                const nsSize& aAvailSize,
00501                                                nsReflowReason aReason,
00502                                                nsMargin aFocusPadding,
00503                                                nsReflowStatus& aStatus)
00504 {
00505   nsHTMLReflowState reflowState(aPresContext, aReflowState, aFirstKid, aAvailSize, aReason);
00506 
00507   ReflowChild(aFirstKid, aPresContext, aDesiredSize, reflowState,
00508               aFocusPadding.left + aReflowState.mComputedBorderPadding.left,
00509               aFocusPadding.top + aReflowState.mComputedBorderPadding.top,
00510               0, aStatus);
00511   
00512   // calculate the min internal size so the contents gets centered correctly
00513   // minInternalWidth is not being used at all and causes a warning--commenting
00514   // out until someone wants it.
00515   //  nscoord minInternalWidth  = aReflowState.mComputedMinWidth  == 0?0:aReflowState.mComputedMinWidth - 
00516   //    (aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right);
00517   nscoord minInternalHeight = aReflowState.mComputedMinHeight == 0?0:aReflowState.mComputedMinHeight - 
00518     (aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom);
00519 
00520   // center child vertically
00521   nscoord yoff = 0;
00522   if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) {
00523     yoff = (aReflowState.mComputedHeight - aDesiredSize.height)/2;
00524     if (yoff < 0) {
00525       yoff = 0;
00526     }
00527   } else if (aDesiredSize.height < minInternalHeight) {
00528     yoff = (minInternalHeight - aDesiredSize.height) / 2;
00529   }
00530 
00531   // Adjust the ascent by our offset (since we moved the child's
00532   // baseline by that much).
00533   aDesiredSize.ascent += yoff;
00534   
00535   // Place the child.  If we have a non-intrinsic width, we want to
00536   // reduce the left padding as needed to try and fit the text in the
00537   // button
00538   nscoord xoffset = aFocusPadding.left + aReflowState.mComputedBorderPadding.left;
00539   if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) {
00540     // First, how much did we "overflow"?  This is the width of our
00541     // kid plus our special focus stuff (which did not get accounted
00542     // for in calculating aReflowState.mComputedWidth minus the width
00543     // we're forced to be.
00544     nscoord extrawidth =
00545       aDesiredSize.width + aFocusPadding.left + aFocusPadding.right
00546       - aReflowState.mComputedWidth;
00547     if (extrawidth > 0) {
00548       // Split it evenly between right and left
00549       extrawidth /= 2;
00550       // But do not shoot out the left side of the button, please
00551       extrawidth = PR_MIN(extrawidth, aReflowState.mComputedPadding.left);
00552       xoffset -= extrawidth;
00553     }
00554   }
00555   
00556   // Place the child
00557   FinishReflowChild(aFirstKid, aPresContext, &reflowState, aDesiredSize,
00558                     xoffset,
00559                     yoff + aFocusPadding.top + aReflowState.mComputedBorderPadding.top, 0);
00560 }
00561 
00562 /* virtual */ PRBool
00563 nsHTMLButtonControlFrame::IsContainingBlock() const
00564 {
00565   return PR_TRUE;
00566 }
00567 
00568 PRIntn
00569 nsHTMLButtonControlFrame::GetSkipSides() const
00570 {
00571   return 0;
00572 }
00573 
00574 NS_IMETHODIMP
00575 nsHTMLButtonControlFrame::GetFormContent(nsIContent*& aContent) const
00576 {
00577   aContent = GetContent();
00578   NS_IF_ADDREF(aContent);
00579   return NS_OK;
00580 }
00581 
00582 nscoord 
00583 nsHTMLButtonControlFrame::GetVerticalInsidePadding(nsPresContext* aPresContext,
00584                                                    float aPixToTwip, 
00585                                                    nscoord aInnerHeight) const
00586 {
00587    return 0;
00588 }
00589 
00590 nscoord 
00591 nsHTMLButtonControlFrame::GetHorizontalInsidePadding(nsPresContext* aPresContext,
00592                                                float aPixToTwip, 
00593                                                nscoord aInnerWidth,
00594                                                nscoord aCharWidth) const
00595 {
00596   return 0;
00597 }
00598 
00599 NS_IMETHODIMP nsHTMLButtonControlFrame::SetProperty(nsPresContext* aPresContext,
00600                                                     nsIAtom* aName, const nsAString& aValue)
00601 {
00602   if (nsHTMLAtoms::value == aName) {
00603     return mContent->SetAttr(kNameSpaceID_None, nsHTMLAtoms::value,
00604                              aValue, PR_TRUE);
00605   }
00606   return NS_OK;
00607 }
00608 
00609 NS_IMETHODIMP nsHTMLButtonControlFrame::GetProperty(nsIAtom* aName, nsAString& aValue)
00610 {
00611   if (nsHTMLAtoms::value == aName)
00612     mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::value, aValue);
00613 
00614   return NS_OK;
00615 }
00616 
00617 nsStyleContext*
00618 nsHTMLButtonControlFrame::GetAdditionalStyleContext(PRInt32 aIndex) const
00619 {
00620   return mRenderer.GetStyleContext(aIndex);
00621 }
00622 
00623 void
00624 nsHTMLButtonControlFrame::SetAdditionalStyleContext(PRInt32 aIndex, 
00625                                                     nsStyleContext* aStyleContext)
00626 {
00627   mRenderer.SetStyleContext(aIndex, aStyleContext);
00628 }
00629 
00630 
00631 NS_IMETHODIMP nsHTMLButtonControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight)
00632 {
00633 //  mSuggestedWidth = aWidth;
00634 //  mSuggestedHeight = aHeight;
00635   return NS_OK;
00636 }
00637 
00638 
00639 
00640 NS_IMETHODIMP 
00641 nsHTMLButtonControlFrame::AppendFrames(nsIAtom*        aListName,
00642                                        nsIFrame*       aFrameList)
00643 {
00644   ReParentFrameList(GetPresContext()->FrameManager(), aFrameList);
00645   return mFrames.FirstChild()->AppendFrames(aListName, aFrameList);
00646 }
00647 
00648 NS_IMETHODIMP
00649 nsHTMLButtonControlFrame::InsertFrames(nsIAtom*        aListName,
00650                                        nsIFrame*       aPrevFrame,
00651                                        nsIFrame*       aFrameList)
00652 {
00653   ReParentFrameList(GetPresContext()->FrameManager(), aFrameList);
00654   return mFrames.FirstChild()->InsertFrames(aListName, aPrevFrame, aFrameList);
00655 }
00656 
00657 NS_IMETHODIMP
00658 nsHTMLButtonControlFrame::RemoveFrame(nsIAtom*        aListName,
00659                                       nsIFrame*       aOldFrame)
00660 {
00661   return mFrames.FirstChild()->RemoveFrame(aListName, aOldFrame);
00662 }
00663 
00664 NS_IMETHODIMP
00665 nsHTMLButtonControlFrame::ReplaceFrame(nsIAtom*        aListName,
00666                                        nsIFrame*       aOldFrame,
00667                                        nsIFrame*       aNewFrame)
00668 {
00669   ReParentFrameList(GetPresContext()->FrameManager(), aNewFrame);
00670   return mFrames.FirstChild()->ReplaceFrame(aListName, aOldFrame, aNewFrame);
00671 }
00672 
00673 NS_IMETHODIMP
00674 nsHTMLButtonControlFrame::OnContentReset()
00675 {
00676   return NS_OK;
00677 }