[re-landing] allow buttons to render at smaller sizes than Mac OS X itself will draw using HITheme. Also fixes 376695, allow buttons to accept padding. b=379297 r=cbarrett r=mano sr=pinkerton

This commit is contained in:
joshmoz@gmail.com 2007-05-02 16:47:53 -07:00
Родитель eb14eb6945
Коммит a9dddfe17f
4 изменённых файлов: 68 добавлений и 68 удалений

Просмотреть файл

@ -1121,7 +1121,8 @@ sidebarheader > .tabs-closebutton > .toolbarbutton-text {
#feed-button {
-moz-binding: url("chrome://global/content/bindings/button.xml#menu");
-moz-appearance: none;
min-width: 0px;
min-width: 0;
min-height: 0;
margin-right: 1px !important;
}

Просмотреть файл

@ -50,6 +50,8 @@ button {
/* The margin used here come from the Aqua Human Interface Guidelines,
there should be 12 pixels between two buttons. */
margin: 6px;
min-width: 79px;
min-height: 22px;
color: ButtonText;
}

Просмотреть файл

@ -24,16 +24,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=371080
width="5"
id="button1"
height="5"/>
<!-- This Mac OS X native button should be 68 pixels wide from
the dark border line on the left to the dark border line on
the right. It should be 18 pixels tall from the dark border
line on the top to the dark border line on the bottom -->
<button class="smallbutton"
style="-moz-appearance: button-small;"
label="OK"
width="5"
id="button2"
height="5"/>
<script class="testbody" type="application/javascript">
<![CDATA[
@ -50,10 +40,8 @@ function checkButtonDimensions() {
dump("TEST DEBUG: function 'is()' defined as: " + is + "\n");
try {
is($("button1").boxObject.width, 68, "mac button has correct width");
is($("button1").boxObject.height, 22, "mac button has correct height");
is($("button2").boxObject.width, 68, "mac small button has correct width");
is($("button2").boxObject.height, 19, "mac small button has correct height");
is($("button1").boxObject.width, 79, "mac button width");
is($("button1").boxObject.height, 22, "mac button height");
} catch (ex) {
dump("TEST DEBUG: " + ex + "\n");
}

Просмотреть файл

@ -58,6 +58,8 @@
#include "gfxContext.h"
#include "gfxQuartzSurface.h"
#import <Cocoa/Cocoa.h>
#define DRAW_IN_FRAME_DEBUG 0
#define SCROLLBARS_VISUAL_DEBUG 0
@ -111,6 +113,14 @@ nsNativeThemeCocoa::DrawCheckboxRadio(CGContextRef cgContext, ThemeButtonKind in
HIThemeDrawButton(&inBoxRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL);
}
// We use an offscreen buffer and image scaling to make HITheme draw buttons at any height.
// Minimum height that HITheme will draw a normal push button:
#define MIN_UNSCALED_BUTTON_HEIGHT 22
// Minimum size for buttons that we can create with scaling:
#define MIN_SCALED_BUTTON_WIDTH 28
#define MIN_SCALED_BUTTON_HEIGHT 12
// Difference between the height given to HITheme for a button and the button it actually draws:
#define NATIVE_BUTTON_HEIGHT_DIFF 2
void
nsNativeThemeCocoa::DrawButton(CGContextRef cgContext, ThemeButtonKind inKind,
@ -118,13 +128,16 @@ nsNativeThemeCocoa::DrawButton(CGContextRef cgContext, ThemeButtonKind inKind,
ThemeButtonValue inValue, ThemeButtonAdornment inAdornment,
PRInt32 inState)
{
HIThemeButtonDrawInfo bdi;
if (inBoxRect.size.width < MIN_SCALED_BUTTON_WIDTH ||
inBoxRect.size.height < MIN_SCALED_BUTTON_HEIGHT)
return;
HIThemeButtonDrawInfo bdi;
bdi.version = 0;
bdi.kind = inKind;
bdi.value = inValue;
bdi.adornment = inAdornment;
if (inDisabled)
bdi.state = kThemeStateUnavailable;
else if ((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER))
@ -138,27 +151,58 @@ nsNativeThemeCocoa::DrawButton(CGContextRef cgContext, ThemeButtonKind inKind,
if (inIsDefault && !inDisabled)
bdi.adornment |= kThemeAdornmentDefault;
// Certain buttons draw outside their frame with nsITheme, we adjust for that here.
HIRect drawRect = inBoxRect;
if (inKind == kThemePushButton ||
inKind == kThemePopupButton) {
// These kinds of buttons draw 2 pixels too tall.
drawRect.size.height -= 2;
// If any of the origin and size offset arithmatic seems strange here, check out the
// actual dimensions of an HITheme button compared to the rect you pass to HIThemeDrawButton.
if (inBoxRect.size.height < MIN_UNSCALED_BUTTON_HEIGHT) {
// We'll use these two values to size the button we draw offscreen
float offscreenWidth = inBoxRect.size.width;
float offscreenHeight = MIN_UNSCALED_BUTTON_HEIGHT;
if (inBoxRect.size.height > offscreenHeight)
offscreenHeight = inBoxRect.size.height;
// create an offscreen image
NSImage* image = [[NSImage alloc] initWithSize:NSMakeSize(offscreenWidth, offscreenHeight)];
[image setDataRetained:YES];
[image setScalesWhenResized:YES];
// set up HITheme button to draw
HIRect drawFrame;
drawFrame.origin.x = 0;
drawFrame.origin.y = NATIVE_BUTTON_HEIGHT_DIFF;
drawFrame.size.width = offscreenWidth;
drawFrame.size.height = offscreenHeight - NATIVE_BUTTON_HEIGHT_DIFF;
// draw into offscreen image
[image lockFocus];
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationLow];
HIThemeDrawButton(&drawFrame, &bdi, (CGContext*)[[NSGraphicsContext currentContext] graphicsPort], kHIThemeOrientationInverted, NULL);
[image unlockFocus];
// resize vertically
[image setSize:NSMakeSize(offscreenWidth, inBoxRect.size.height)];
// render to the given CGContextRef
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]];
[image compositeToPoint:NSMakePoint(inBoxRect.origin.x, inBoxRect.origin.y + inBoxRect.size.height)
operation:NSCompositeSourceOver];
[NSGraphicsContext restoreGraphicsState];
[image release];
}
else if (inKind == kThemePushButtonSmall) {
// These kinds of buttons draw 2 pixels too wide, one pixel too far down, and
// two pixels too tall.
drawRect.origin.x += 1;
drawRect.origin.y -= 1;
drawRect.size.width -= 2;
else {
HIRect drawFrame;
drawFrame.origin.x = inBoxRect.origin.x;
drawFrame.origin.y = inBoxRect.origin.y;
drawFrame.size.width = inBoxRect.size.width;
drawFrame.size.height = inBoxRect.size.height - NATIVE_BUTTON_HEIGHT_DIFF;
HIThemeDrawButton(&drawFrame, &bdi, cgContext, kHIThemeOrientationNormal, NULL);
}
#if DRAW_IN_FRAME_DEBUG
CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.8);
CGContextFillRect(cgContext, inBoxRect);
#endif
HIThemeDrawButton(&drawRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL);
}
@ -594,17 +638,7 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame
case NS_THEME_BUTTON:
case NS_THEME_BUTTON_SMALL: {
// Normal push buttons can only draw with a height of 20+ pixels. Small push
// buttons can only draw at a height of 17 pixels. We can't draw buttons with
// a height of 18 or 19 pixels, at least not with HITheme. So, we go down to
// 17 pixel buttons when asked to draw 18 or 19 so that we don't draw outside
// the frame. We just have to live with this until we switch to another API
// for control rendering. Remember that the frame for a 20 pixel tall button
// is 22 pixels because of the border and shadow.
ThemeButtonKind buttonKind = kThemePushButton;
if (macRect.size.height < 22)
buttonKind = kThemePushButtonSmall;
DrawButton(cgContext, buttonKind, macRect,
DrawButton(cgContext, kThemePushButton, macRect,
IsDefaultButton(aFrame), IsDisabled(aFrame),
kThemeButtonOn, kThemeAdornmentNone, eventState);
}
@ -887,20 +921,6 @@ nsNativeThemeCocoa::GetWidgetPadding(nsIDeviceContext* aContext,
aResult->SizeTo(nativePadding, nativePadding, nativePadding, nativePadding);
return PR_TRUE;
}
case NS_THEME_BUTTON:
case NS_THEME_DROPDOWN:
case NS_THEME_DROPDOWN_BUTTON:
{
// The border/shadow on the bottom of the button means we have to
// draw the text a little higher than normal.
aResult->SizeTo(0, -1, 0, 1);
return PR_TRUE;
}
case NS_THEME_BUTTON_SMALL:
{
aResult->SizeTo(0, 0, 0, 0);
return PR_TRUE;
}
}
return PR_FALSE;
@ -954,20 +974,9 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsIRenderingContext* aContext,
switch (aWidgetType) {
case NS_THEME_BUTTON:
{
// Height value is adjusted for shadow and border.
SInt32 buttonHeight = 0;
::GetThemeMetric(kThemeMetricPushButtonHeight, &buttonHeight);
aResult->SizeTo(kAquaMinButtonWidth, buttonHeight + 2);
break;
}
case NS_THEME_BUTTON_SMALL:
{
// Height value is adjusted for shadow and border.
SInt32 buttonHeight = 0;
::GetThemeMetric(kThemeMetricSmallPushButtonHeight, &buttonHeight);
aResult->SizeTo(kAquaMinButtonWidth, buttonHeight + 2);
aResult->SizeTo(MIN_SCALED_BUTTON_WIDTH, MIN_SCALED_BUTTON_HEIGHT);
break;
}