Give radio buttons and checkboxes a useful baseline, and switch checkboxes from text-bottom to baseline alignment (to match radios). b=402940 r+sr=bzbarsky a=blocking1.9+
authordbaron@dbaron.org
Fri, 07 Mar 2008 09:57:34 -0800
changeset 12732 2748ac8d0fb09bebf50eb9ca6397bb3ede076341
parent 12731 ff4f13158b42a3d00710c3ddce2da434a6a38a7d
child 12733 b84e56f3da4288a83f87876c2c008de5badc5944
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblocking1.9
bugs402940
milestone1.9b5pre
Give radio buttons and checkboxes a useful baseline, and switch checkboxes from text-bottom to baseline alignment (to match radios). b=402940 r+sr=bzbarsky a=blocking1.9+
layout/forms/nsFormControlFrame.cpp
layout/forms/nsFormControlFrame.h
layout/style/forms.css
widget/src/cocoa/nsNativeThemeCocoa.mm
widget/src/gtk2/nsNativeThemeGTK.cpp
widget/src/windows/nsNativeThemeWin.cpp
--- a/layout/forms/nsFormControlFrame.cpp
+++ b/layout/forms/nsFormControlFrame.cpp
@@ -89,16 +89,27 @@ nscoord
 nsFormControlFrame::GetIntrinsicHeight()
 {
   // Provide a reasonable default for sites that use an "auto" height.
   // Note that if you change this, you should change the values in forms.css
   // as well. This is the 13px default width minus the 2px default border.
   return nsPresContext::CSSPixelsToAppUnits(13 - 2 * 2);
 }
 
+nscoord
+nsFormControlFrame::GetBaseline() const
+{
+  NS_ASSERTION(!NS_SUBTREE_DIRTY(this),
+               "frame must not be dirty");
+  // Treat radio buttons and checkboxes as having an intrinsic baseline
+  // at the bottom of the control (use the bottom content edge rather
+  // than the bottom margin edge).
+  return mRect.height - GetUsedBorderAndPadding().bottom;
+}
+
 NS_METHOD
 nsFormControlFrame::Reflow(nsPresContext*          aPresContext,
                            nsHTMLReflowMetrics&     aDesiredSize,
                            const nsHTMLReflowState& aReflowState,
                            nsReflowStatus&          aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("nsFormControlFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
--- a/layout/forms/nsFormControlFrame.h
+++ b/layout/forms/nsFormControlFrame.h
@@ -37,20 +37,20 @@
 
 #ifndef nsFormControlFrame_h___
 #define nsFormControlFrame_h___
 
 #include "nsIFormControlFrame.h"
 #include "nsLeafFrame.h"
 
 /** 
-  * nsFormControlFrame is the base class for frames of form controls. It
-  * provides a uniform way of creating widgets, resizing, and painting.
-  * @see nsLeafFrame and its base classes for more info
-  */
+ * nsFormControlFrame is the base class for radio buttons and
+ * checkboxes.  It also has two static methods (RegUnRegAccessKey and
+ * GetScreenHeight) that are used by other form controls.
+ */
 class nsFormControlFrame : public nsLeafFrame,
                            public nsIFormControlFrame
 {
 
 public:
   /**
     * Main constructor
     * @param aContent the content representing this frame
@@ -69,16 +69,18 @@ public:
   /** 
     * Respond to a gui event
     * @see nsIFrame::HandleEvent
     */
   NS_IMETHOD HandleEvent(nsPresContext* aPresContext, 
                          nsGUIEvent* aEvent,
                          nsEventStatus* aEventStatus);
 
+  virtual nscoord GetBaseline() const;
+
   /**
     * Respond to the request to resize and/or reflow
     * @see nsIFrame::Reflow
     */
   NS_IMETHOD Reflow(nsPresContext*      aCX,
                     nsHTMLReflowMetrics& aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&      aStatus);
--- a/layout/style/forms.css
+++ b/layout/style/forms.css
@@ -394,17 +394,16 @@ input[type="radio"] {
 
 /* check boxes */
 input[type="checkbox"] {
   -moz-appearance: checkbox-small;
   width: 13px;
   height: 13px;
   margin: 3px 3px 3px 4px;
   padding: 0 !important;
-  vertical-align: text-bottom;
   cursor: default;
   -moz-binding: none;
 
   -moz-border-radius: 0 !important;
 }
 
 /* common features of radio buttons and check boxes */
 
--- a/widget/src/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/src/cocoa/nsNativeThemeCocoa.mm
@@ -1314,19 +1314,27 @@ nsNativeThemeCocoa::GetWidgetBorder(nsID
 PRBool
 nsNativeThemeCocoa::GetWidgetPadding(nsIDeviceContext* aContext, 
                                      nsIFrame* aFrame,
                                      PRUint8 aWidgetType,
                                      nsMargin* aResult)
 {
   // We don't want CSS padding being used for certain widgets.
   // See bug 381639 for an example of why.
-  if (aWidgetType == NS_THEME_BUTTON) {
-    aResult->SizeTo(0, 0, 0, 0);
-    return PR_TRUE;
+  switch (aWidgetType) {
+    case NS_THEME_BUTTON:
+    // Radios and checkboxes return a fixed size in GetMinimumWidgetSize
+    // and have a meaningful baseline, so they can't have
+    // author-specified padding.
+    case NS_THEME_CHECKBOX:
+    case NS_THEME_CHECKBOX_SMALL:
+    case NS_THEME_RADIO:
+    case NS_THEME_RADIO_SMALL:
+      aResult->SizeTo(0, 0, 0, 0);
+      return PR_TRUE;
   }
   return PR_FALSE;
 }
 
 
 PRBool
 nsNativeThemeCocoa::GetWidgetOverflow(nsIDeviceContext* aContext, nsIFrame* aFrame,
                                       PRUint8 aWidgetType, nsRect* aResult)
--- a/widget/src/gtk2/nsNativeThemeGTK.cpp
+++ b/widget/src/gtk2/nsNativeThemeGTK.cpp
@@ -890,23 +890,31 @@ nsNativeThemeGTK::GetWidgetBorder(nsIDev
   return NS_OK;
 }
 
 PRBool
 nsNativeThemeGTK::GetWidgetPadding(nsIDeviceContext* aContext,
                                    nsIFrame* aFrame, PRUint8 aWidgetType,
                                    nsMargin* aResult)
 {
-  if (aWidgetType == NS_THEME_BUTTON_FOCUS ||
-      aWidgetType == NS_THEME_TOOLBAR_BUTTON ||
-      aWidgetType == NS_THEME_TOOLBAR_DUAL_BUTTON ||
-      aWidgetType == NS_THEME_TAB_SCROLLARROW_BACK ||
-      aWidgetType == NS_THEME_TAB_SCROLLARROW_FORWARD) {
-    aResult->SizeTo(0, 0, 0, 0);
-    return PR_TRUE;
+  switch (aWidgetType) {
+    case NS_THEME_BUTTON_FOCUS:
+    case NS_THEME_TOOLBAR_BUTTON:
+    case NS_THEME_TOOLBAR_DUAL_BUTTON:
+    case NS_THEME_TAB_SCROLLARROW_BACK :
+    case NS_THEME_TAB_SCROLLARROW_FORWARD:
+    // Radios and checkboxes return a fixed size in GetMinimumWidgetSize
+    // and have a meaningful baseline, so they can't have
+    // author-specified padding.
+    case NS_THEME_CHECKBOX:
+    case NS_THEME_CHECKBOX_SMALL:
+    case NS_THEME_RADIO:
+    case NS_THEME_RADIO_SMALL:
+      aResult->SizeTo(0, 0, 0, 0);
+      return PR_TRUE;
   }
 
   return PR_FALSE;
 }
 
 PRBool
 nsNativeThemeGTK::GetWidgetOverflow(nsIDeviceContext* aContext,
                                     nsIFrame* aFrame, PRUint8 aWidgetType,
--- a/widget/src/windows/nsNativeThemeWin.cpp
+++ b/widget/src/windows/nsNativeThemeWin.cpp
@@ -1493,16 +1493,28 @@ nsNativeThemeWin::GetWidgetBorder(nsIDev
 }
 
 PRBool
 nsNativeThemeWin::GetWidgetPadding(nsIDeviceContext* aContext, 
                                    nsIFrame* aFrame,
                                    PRUint8 aWidgetType,
                                    nsMargin* aResult)
 {
+  switch (aWidgetType) {
+    // Radios and checkboxes return a fixed size in GetMinimumWidgetSize
+    // and have a meaningful baseline, so they can't have
+    // author-specified padding.
+    case NS_THEME_CHECKBOX:
+    case NS_THEME_CHECKBOX_SMALL:
+    case NS_THEME_RADIO:
+    case NS_THEME_RADIO_SMALL:
+      aResult->SizeTo(0, 0, 0, 0);
+      return PR_TRUE;
+  }
+
   HANDLE theme = GetTheme(aWidgetType);
   if (!theme && aWidgetType != NS_THEME_MENUITEMTEXT)
     return PR_FALSE;
 
   if (aWidgetType == NS_THEME_MENUPOPUP)
   {
     SIZE popupSize;
     getThemePartSize(theme, NULL, MENU_POPUPBORDERS, /* state */ 0, NULL, TS_TRUE, &popupSize);