* Headers/Additions/GNUstepGUI/GSTheme.h: New GSThemeMargins struct.

Rename buttonBorderForCell:style:state: to buttonMarginsForCell:style:state:
and return the top/bottom/left/right margins instead of just two values.
(This is a theme API break.)
* Source/GSThemeDrawing.m: Implement buttonMarginsForCell:style:state:.
Also reduce the top and left margin of the default button by 1 pt, to
better reflect the button's appearance.
* Source/GSGuiPrivate.h: Add a GSRoundTowardsNegativeInfinity function
* Source/NSButtonCell.m (-drawImage:withFrame:inView:): Round the image
position down and to the right, as this seems to look the best.
* Source/NSButtonCell.m (-cellSize): Call new buttonMarginsForCell: method
* Source/NSButtonCell.m (-drawingRectForBounds:): Call new
buttonMarginsForCell: method


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@33743 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
ericwa 2011-08-15 23:12:37 +00:00
parent 8d20ff6316
commit abe0bb41f6
5 changed files with 137 additions and 57 deletions

View file

@ -1,3 +1,19 @@
2011-08-15 Eric Wasylishen <ewasylishen@gmail.com>
* Headers/Additions/GNUstepGUI/GSTheme.h: New GSThemeMargins struct.
Rename buttonBorderForCell:style:state: to buttonMarginsForCell:style:state:
and return the top/bottom/left/right margins instead of just two values.
(This is a theme API break.)
* Source/GSThemeDrawing.m: Implement buttonMarginsForCell:style:state:.
Also reduce the top and left margin of the default button by 1 pt, to
better reflect the button's appearance.
* Source/GSGuiPrivate.h: Add a GSRoundTowardsNegativeInfinity function
* Source/NSButtonCell.m (-drawImage:withFrame:inView:): Round the image
position down and to the right, as this seems to look the best.
* Source/NSButtonCell.m (-cellSize): Call new buttonMarginsForCell: method
* Source/NSButtonCell.m (-drawingRectForBounds:): Call new
buttonMarginsForCell: method
2011-08-15 Eric Wasylishen <ewasylishen@gmail.com> 2011-08-15 Eric Wasylishen <ewasylishen@gmail.com>
* Source/NSImage.m (GSResolutionOfImageRep): Specify behaviour when the * Source/NSImage.m (GSResolutionOfImageRep): Specify behaviour when the

View file

@ -287,7 +287,17 @@ APPKIT_EXPORT NSString *GSProgressIndicatorBarDeterminate;
*/ */
APPKIT_EXPORT NSString *GSColorWell; APPKIT_EXPORT NSString *GSColorWell;
/**
* Structure to describe the size of top/bottom/left/right margins inside
* a button
*/
typedef struct GSThemeMargins
{
CGFloat left;
CGFloat right;
CGFloat top;
CGFloat bottom;
} GSThemeMargins;
/** /**
* This defines how the values in a tile array should be used when * This defines how the values in a tile array should be used when
@ -732,7 +742,7 @@ APPKIT_EXPORT NSString *GSThemeWillDeactivateNotification;
/** /**
* Amount by which the button is inset by the border. * Amount by which the button is inset by the border.
*/ */
- (NSSize) buttonBorderForCell: (NSCell*)cell - (GSThemeMargins) buttonMarginsForCell: (NSCell*)cell
style: (int)style style: (int)style
state: (GSThemeControlState)state; state: (GSThemeControlState)state;

View file

@ -88,5 +88,20 @@ static inline CGFloat GSRoundTowardsInfinity(CGFloat x)
return floor(x + 0.5); return floor(x + 0.5);
} }
/**
* Rounds to the nearest integer, and in the case of ties, round to the
* smaller integer.
*
* For example:
* GSRoundTowardsNegativeInfinity(0.8) == 1.0
* GSRoundTowardsNegativeInfinity(0.5) == 0.0
* GSRoundTowardsNegativeInfinity(0.1) == 0.0
* GSRoundTowardsNegativeInfinity(-2.5) == -3.0
*/
static inline CGFloat GSRoundTowardsNegativeInfinity(CGFloat x)
{
return ceil(x - 0.5);
}
#endif /* _GNUstep_H_GSGuiPrivate */ #endif /* _GNUstep_H_GSGuiPrivate */

View file

@ -189,12 +189,13 @@
} }
} }
- (NSSize) buttonBorderForCell: (NSCell*)cell - (GSThemeMargins) buttonMarginsForCell: (NSCell*)cell
style: (int)style style: (int)style
state: (GSThemeControlState)state state: (GSThemeControlState)state
{ {
GSDrawTiles *tiles = nil; GSDrawTiles *tiles = nil;
NSString *name = [self nameForElement: cell]; NSString *name = [self nameForElement: cell];
GSThemeMargins margins;
if (name == nil) if (name == nil)
{ {
@ -214,36 +215,48 @@
case NSRoundRectBezelStyle: case NSRoundRectBezelStyle:
case NSTexturedRoundedBezelStyle: case NSTexturedRoundedBezelStyle:
case NSRoundedBezelStyle: case NSRoundedBezelStyle:
return NSMakeSize(5, 5); margins.left = 5; margins.top = 5; margins.right = 5; margins.bottom = 5;
return margins;
case NSTexturedSquareBezelStyle: case NSTexturedSquareBezelStyle:
return NSMakeSize(3, 3); margins.left = 3; margins.top = 3; margins.right = 3; margins.bottom = 3;
return margins;
case NSSmallSquareBezelStyle: case NSSmallSquareBezelStyle:
case NSRegularSquareBezelStyle: case NSRegularSquareBezelStyle:
case NSShadowlessSquareBezelStyle: case NSShadowlessSquareBezelStyle:
return NSMakeSize(2, 2); margins.left = 2; margins.top = 2; margins.right = 2; margins.bottom = 2;
return margins;
case NSThickSquareBezelStyle: case NSThickSquareBezelStyle:
return NSMakeSize(3, 3); margins.left = 3; margins.top = 3; margins.right = 3; margins.bottom = 3;
return margins;
case NSThickerSquareBezelStyle: case NSThickerSquareBezelStyle:
return NSMakeSize(4, 4); margins.left = 4; margins.top = 4; margins.right = 4; margins.bottom = 4;
return margins;
case NSCircularBezelStyle: case NSCircularBezelStyle:
return NSMakeSize(5, 5); margins.left = 5; margins.top = 5; margins.right = 5; margins.bottom = 5;
return margins;
case NSHelpButtonBezelStyle: case NSHelpButtonBezelStyle:
return NSMakeSize(2, 2); margins.left = 2; margins.top = 2; margins.right = 2; margins.bottom = 2;
return margins;
case NSDisclosureBezelStyle: case NSDisclosureBezelStyle:
case NSRoundedDisclosureBezelStyle: case NSRoundedDisclosureBezelStyle:
case NSRecessedBezelStyle: case NSRecessedBezelStyle:
// FIXME // FIXME
return NSMakeSize(0, 0); margins.left = 0; margins.top = 0; margins.right = 0; margins.bottom = 0;
return margins;
default: default:
return NSMakeSize(3, 3); margins.left = 2; margins.top = 2; margins.right = 3; margins.bottom = 3;
return margins;
} }
} }
else else
{ {
// FIXME: We assume the button's top and right padding are the same as // FIXME: Move this code to a method in GSDrawTiles?
// its bottom and left. // FIXME: Not correct, need to get the content area of the draw tiles
return NSMakeSize(tiles->contentRect.origin.x, margins.left = tiles->rects[TileCL].size.width;
tiles->contentRect.origin.y); margins.top = tiles->rects[TileTM].size.height;
margins.right = tiles->rects[TileCR].size.width;
margins.bottom = tiles->rects[TileBM].size.height;
return margins;
} }
} }

View file

@ -966,12 +966,32 @@ typedef struct _GSButtonCellFlags
// Draw image // Draw image
if (imageToDisplay != nil) if (imageToDisplay != nil)
{ {
NSSize size; const NSSize size = [imageToDisplay size];
NSPoint position;
size = [imageToDisplay size]; /* Calculate an offset from the cellFrame origin */
position.x = MAX(NSMidX(cellFrame) - (size.width / 2.), 0.);
position.y = MAX(NSMidY(cellFrame) - (size.height / 2.), 0.); NSPoint offset = NSMakePoint((NSWidth(cellFrame) - size.width) / 2.0,
(NSHeight(cellFrame) - size.height) / 2.0);
/* Pixel-align the offset */
if (controlView)
{
NSPoint inBase = [controlView convertPointToBase: offset];
// By convention we will round down and to the right.
// With the standard button design this looks good
// because the bottom and right edges of the button look 'heavier'
// so if the image's center must be offset from the button's geometric
// center, it looks beter if it's closer to the 'heavier' part
inBase.x = GSRoundTowardsInfinity(inBase.x);
inBase.y = [controlView isFlipped] ?
GSRoundTowardsInfinity(inBase.y) :
GSRoundTowardsNegativeInfinity(inBase.y);
offset = [controlView convertPointFromBase: inBase];
}
/* /*
* Images are always drawn with their bottom-left corner at the origin * Images are always drawn with their bottom-left corner at the origin
@ -979,25 +999,19 @@ typedef struct _GSButtonCellFlags
*/ */
if ([controlView isFlipped]) if ([controlView isFlipped])
{ {
position.y += size.height; offset.y += size.height;
} }
/* Pixel-align the drawing point */
if (controlView)
{ {
position = [controlView convertPointToBase: position]; const NSPoint position = NSMakePoint(cellFrame.origin.x + offset.x,
} cellFrame.origin.y + offset.y);
position = NSMakePoint(GSRoundTowardsInfinity(position.x), GSRoundTowardsInfinity(position.y));
if (controlView)
{
position = [controlView convertPointFromBase: position];
}
[[GSTheme theme] drawImage: imageToDisplay [[GSTheme theme] drawImage: imageToDisplay
inButtonCell: self inButtonCell: self
withFrame: cellFrame withFrame: cellFrame
position: position]; position: position];
} }
}
} }
- (void) drawTitle: (NSAttributedString*)titleToDisplay - (void) drawTitle: (NSAttributedString*)titleToDisplay
@ -1300,7 +1314,7 @@ typedef struct _GSButtonCellFlags
- (NSSize) cellSize - (NSSize) cellSize
{ {
NSSize s; NSSize s;
NSSize borderSize; GSThemeMargins border;
unsigned mask; unsigned mask;
NSImage *imageToDisplay; NSImage *imageToDisplay;
NSAttributedString *titleToDisplay; NSAttributedString *titleToDisplay;
@ -1400,12 +1414,17 @@ typedef struct _GSButtonCellFlags
buttonState = GSThemeSelectedState; buttonState = GSThemeSelectedState;
} }
borderSize = [[GSTheme theme] buttonBorderForCell: self border = [[GSTheme theme] buttonMarginsForCell: self
style: _bezel_style style: _bezel_style
state: buttonState]; state: buttonState];
} }
else else
borderSize = NSZeroSize; {
border.left = 0;
border.top = 0;
border.right = 0;
border.bottom = 0;
}
/* Add an additional 6 pixels horizontally so that the text is not /* Add an additional 6 pixels horizontally so that the text is not
* too near the boundaries of the button. Without them, autosized * too near the boundaries of the button. Without them, autosized
@ -1419,12 +1438,13 @@ typedef struct _GSButtonCellFlags
if ((_cell.is_bordered && (_cell.image_position != NSImageOnly)) if ((_cell.is_bordered && (_cell.image_position != NSImageOnly))
|| _cell.is_bezeled) || _cell.is_bezeled)
{ {
borderSize.width += 6; border.left += 6;
border.right += 6;
} }
// Add border size // Add border size
s.width += 2 * borderSize.width; s.width += border.left + border.right;
s.height += 2 * borderSize.height; s.height += border.top + border.bottom;
return s; return s;
} }
@ -1433,7 +1453,7 @@ typedef struct _GSButtonCellFlags
{ {
if (_cell.is_bordered) if (_cell.is_bordered)
{ {
NSSize borderSize; GSThemeMargins border;
unsigned mask; unsigned mask;
GSThemeControlState buttonState = GSThemeNormalState; GSThemeControlState buttonState = GSThemeNormalState;
NSRect interiorFrame; NSRect interiorFrame;
@ -1464,10 +1484,16 @@ typedef struct _GSButtonCellFlags
buttonState = GSThemeSelectedState; buttonState = GSThemeSelectedState;
} }
borderSize = [[GSTheme theme] buttonBorderForCell: self border = [[GSTheme theme] buttonMarginsForCell: self
style: _bezel_style style: _bezel_style
state: buttonState]; state: buttonState];
interiorFrame = NSInsetRect(theRect, borderSize.width, borderSize.height);
interiorFrame = theRect;
interiorFrame.origin.x += border.left;
interiorFrame.size.width -= border.left + border.right;
interiorFrame.origin.y += ([_control_view isFlipped] ?
border.top : border.bottom);
interiorFrame.size.height -= border.bottom + border.top;
/* Pushed in buttons contents are displaced to the bottom right 1px. */ /* Pushed in buttons contents are displaced to the bottom right 1px. */
if (mask & NSPushInCellMask) if (mask & NSPushInCellMask)