* Headers/AppKit/NSImageCell.h:

* Headers/AppKit/NSCell.h: Move NSImageScaling constants to NSCell
* Source/NSImageCell.m:
* Source/NSCell.m: Refactor the image scaling logic to a private
method in NSCell, -_scaleImageWithSize:toFitInSize:scalingType:
which can be share by NSImageCell, NSButtonCell, and any other
cell classes that need it.
* Source/NSButtonCell.m:
* Headers/AppKit/NSButtonCell.h: Implement -imageScaling and
-setImageScaling methods. 
* Source/GSThemeDrawing.m:
* Headers/Additions/GNUstepGUI/GSTheme.h: Remove the
-drawImage:inButtonCell:withFrame:position: API intended
to let themes substitute images right before drawing,
as IMHO it's the wrong place to hook in new images (by
the time this method was caleld, sizing/positionging
was already done).


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@34160 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Eric Wasylishen 2011-11-11 23:10:15 +00:00
parent 45d5c38825
commit 60674d5076
9 changed files with 202 additions and 119 deletions

View file

@ -1,3 +1,23 @@
2011-11-11 Eric Wasylishen <ewasylishen@gmail.com>
* Headers/AppKit/NSImageCell.h:
* Headers/AppKit/NSCell.h: Move NSImageScaling constants to NSCell
* Source/NSImageCell.m:
* Source/NSCell.m: Refactor the image scaling logic to a private
method in NSCell, -_scaleImageWithSize:toFitInSize:scalingType:
which can be share by NSImageCell, NSButtonCell, and any other
cell classes that need it.
* Source/NSButtonCell.m:
* Headers/AppKit/NSButtonCell.h: Implement -imageScaling and
-setImageScaling methods.
* Source/GSThemeDrawing.m:
* Headers/Additions/GNUstepGUI/GSTheme.h: Remove the
-drawImage:inButtonCell:withFrame:position: API intended
to let themes substitute images right before drawing,
as IMHO it's the wrong place to hook in new images (by
the time this method was caleld, sizing/positionging
was already done).
2011-11-11 Fred Kiefer <FredKiefer@gmx.de>
* Source/GSXibLoader.m: Better handling for flattened properties

View file

@ -877,16 +877,6 @@ APPKIT_EXPORT NSString *GSThemeWillDeactivateNotification;
roundedLeft: (BOOL)roundedLeft
roundedRight: (BOOL)roundedRight;
/**
* In some themes it may be necessary to override the drawing
* of an image a button cell and replace it with a rendered
* version (from the native theme).
*/
- (void) drawImage: (NSImage *)image
inButtonCell: (NSButtonCell *) cell
withFrame: (NSRect) aRect
position: (NSPoint) position;
- (void) drawBackgroundForMenuView: (NSMenuView*)menuView
withFrame: (NSRect)bounds
dirtyRect: (NSRect)dirtyRect

View file

@ -136,6 +136,7 @@ typedef enum _NSGradientType {
#define _image_dims_when_disabled _cell.subclass_bool_two
#define _shows_border_only_while_mouse_inside _cell.subclass_bool_three
#define _mouse_inside _cell.subclass_bool_four
NSImageScaling _imageScaling;
}
//
@ -165,6 +166,10 @@ typedef enum _NSGradientType {
- (NSCellImagePosition)imagePosition;
- (void)setAlternateImage: (NSImage *)anImage;
- (void)setImagePosition: (NSCellImagePosition)aPosition;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
- (NSImageScaling)imageScaling;
- (void)setImageScaling:(NSImageScaling)scaling;
#endif
//
// Setting the Repeat Interval

View file

@ -118,6 +118,29 @@ enum {
NSMixedState = -1
};
/**
* <p>Enumeration of the ways that you can display an image in an
* NSImageCell. The available ones are:</p>
* <p><code>NSScaleNone</code>: The image is always displayed with
* its natural size. If it's bigger than the cell size, it is
* cropped.</p>
* <p><code>NSScaleProportionally</code>: If the image is bigger
* than the cell size, it is displayed in its natural size. If it
* is smaller than the cell size, it is resized down proportionally
* to fit the cell size.</p>
* <p><code>NSScaleToFit</code>: The image is always resized (up
* or down) to fit exactly in the cell size.</p>
*/
typedef enum {
NSScaleProportionally = 0,
NSScaleToFit = 1,
NSScaleNone = 2,
NSImageScaleProportionallyDown = 0,
NSImageScaleAxesIndependently = 1,
NSImageScaleNone = 2,
NSImageScaleProportionallyUpOrDown = 3
} NSImageScaling;
@interface NSCell : NSObject <NSCopying, NSCoding>
{
// Attributes

View file

@ -33,29 +33,6 @@
#import <AppKit/NSCell.h>
/**
* <p>Enumeration of the ways that you can display an image in an
* NSImageCell. The available ones are:</p>
* <p><code>NSScaleNone</code>: The image is always displayed with
* its natural size. If it's bigger than the cell size, it is
* cropped.</p>
* <p><code>NSScaleProportionally</code>: If the image is bigger
* than the cell size, it is displayed in its natural size. If it
* is smaller than the cell size, it is resized down proportionally
* to fit the cell size.</p>
* <p><code>NSScaleToFit</code>: The image is always resized (up
* or down) to fit exactly in the cell size.</p>
*/
typedef enum {
NSScaleProportionally = 0,
NSScaleToFit = 1,
NSScaleNone = 2,
NSImageScaleProportionallyDown = 0,
NSImageScaleAxesIndependently = 1,
NSImageScaleNone = 2,
NSImageScaleProportionallyUpOrDown = 3
} NSImageScaling;
/**
* <p>Enumeration of the ways that you can align an image inside an
* NSImageCell when the image is not taking up all the space inside

View file

@ -803,25 +803,6 @@
}
}
- (void) drawImage: (NSImage *)image
inButtonCell: (NSButtonCell *) cell
withFrame: (NSRect) aRect
position: (NSPoint) position
{
BOOL enabled = [cell isEnabled];
BOOL dims = [cell imageDimsWhenDisabled];
if (!enabled && dims)
{
[image dissolveToPoint: position fraction: 0.5];
}
else
{
[image compositeToPoint: position
operation: NSCompositeSourceOver];
}
}
- (void) drawBackgroundForMenuView: (NSMenuView*)menuView
withFrame: (NSRect)bounds
dirtyRect: (NSRect)dirtyRect

View file

@ -106,6 +106,12 @@ typedef struct _GSButtonCellFlags
#endif
} GSButtonCellFlags;
@interface NSCell (Private)
- (NSSize) _scaleImageWithSize: (NSSize)imageSize
toFitInSize: (NSSize)canvasSize
scalingType: (NSImageScaling)scalingType;
@end
/**<p> TODO Description</p>
*/
@implementation NSButtonCell
@ -137,6 +143,7 @@ typedef struct _GSButtonCellFlags
_keyEquivalent = @"";
_altContents = @"";
_gradient_type = NSGradientNone;
[self setImageScaling: NSImageScaleNone];
return self;
}
@ -480,6 +487,16 @@ typedef struct _GSButtonCellFlags
return _cell.image_position;
}
- (NSImageScaling) imageScaling
{
return _imageScaling;
}
- (void) setImageScaling: (NSImageScaling)scaling
{
_imageScaling = scaling;
}
- (void) setImage: (NSImage *)anImage
{
if (_cell.image_position == NSNoImage)
@ -966,14 +983,26 @@ typedef struct _GSButtonCellFlags
// Draw image
if (imageToDisplay != nil)
{
const NSSize size = [imageToDisplay size];
NSSize size = [self _scaleImageWithSize: [imageToDisplay size]
toFitInSize: cellFrame.size
scalingType: _imageScaling];
/* Pixel-align size */
if (controlView)
{
NSSize sizeInBase = [controlView convertSizeToBase: size];
sizeInBase.width = GSRoundTowardsInfinity(sizeInBase.width);
sizeInBase.height = GSRoundTowardsInfinity(sizeInBase.height);
size = [controlView convertSizeFromBase: sizeInBase];
}
/* Calculate an offset from the cellFrame origin */
NSPoint offset = NSMakePoint((NSWidth(cellFrame) - size.width) / 2.0,
(NSHeight(cellFrame) - size.height) / 2.0);
/* Pixel-align the offset */
/* Pixel-align the offset */
if (controlView)
{
@ -993,24 +1022,21 @@ typedef struct _GSButtonCellFlags
offset = [controlView convertPointFromBase: inBase];
}
/*
* Images are always drawn with their bottom-left corner at the origin
* so we must adjust the position to take account of a flipped view.
*/
if ([controlView isFlipped])
{
offset.y += size.height;
}
/* Draw the image */
{
const NSPoint position = NSMakePoint(cellFrame.origin.x + offset.x,
cellFrame.origin.y + offset.y);
[[GSTheme theme] drawImage: imageToDisplay
inButtonCell: self
withFrame: cellFrame
position: position];
}
const NSRect rect = NSMakeRect(cellFrame.origin.x + offset.x,
cellFrame.origin.y + offset.y,
size.width,
size.height);
const CGFloat fraction = (![self isEnabled] &&
[self imageDimsWhenDisabled]) ? 0.5 : 1.0;
[imageToDisplay drawInRect: rect
fromRect: NSZeroRect
operation: NSCompositeSourceOver
fraction: fraction
respectFlipped: YES
hints: nil];
}
}
@ -1642,6 +1668,23 @@ typedef struct _GSButtonCellFlags
bFlags2 |= [self showsBorderOnlyWhileMouseInside] ? 0x8 : 0;
bFlags2 |= (([self bezelStyle] & 0x7) | (([self bezelStyle] & 0x18) << 2));
bFlags2 |= [self keyEquivalentModifierMask] << 8;
switch ([self imageScaling])
{
case NSImageScaleProportionallyDown:
bFlags2 |= (2 << 6);
break;
case NSImageScaleAxesIndependently:
bFlags2 |= (3 << 6);
break;
case NSImageScaleNone:
default:
break;
case NSImageScaleProportionallyUpOrDown:
bFlags2 |= (1 << 6);
break;
}
[aCoder encodeInt: bFlags2 forKey: @"NSButtonFlags2"];
// alternate image encoding...
@ -1793,6 +1836,7 @@ typedef struct _GSButtonCellFlags
}
if ([aDecoder containsValueForKey: @"NSButtonFlags2"])
{
NSUInteger imageScale;
int bFlags2;
bFlags2 = [aDecoder decodeIntForKey: @"NSButtonFlags2"];
@ -1800,6 +1844,24 @@ typedef struct _GSButtonCellFlags
[self setBezelStyle: (bFlags2 & 0x7) | ((bFlags2 & 0x20) >> 2)];
[self setKeyEquivalentModifierMask: ((bFlags2 >> 8) &
NSDeviceIndependentModifierFlagsMask)];
switch (bFlags2 & (3 << 6))
{
case 2:
imageScale = NSImageScaleProportionallyDown;
break;
case 3:
imageScale = NSImageScaleAxesIndependently;
break;
case 0:
default:
imageScale = NSImageScaleNone;
break;
case 1:
imageScale = NSImageScaleProportionallyUpOrDown;
break;
}
[self setImageScaling: imageScale];
}
if ([aDecoder containsValueForKey: @"NSAlternateImage"])
{
@ -1882,6 +1944,8 @@ typedef struct _GSButtonCellFlags
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &tmp];
_shows_border_only_while_mouse_inside = tmp;
}
// Not encoded in non-keyed archive
_imageScaling = NSImageScaleNone;
}
// Hack to correct a Gorm problem, there "\n" is used instead of "\r".

View file

@ -3015,4 +3015,66 @@ static NSColor *dtxtCol;
}
}
/**
* Private method used by NSImageCell and NSButtonCell for calculating
* scaled image size
*/
static inline NSSize
scaleProportionally(NSSize imageSize, NSSize canvasSize, BOOL scaleUpOrDown)
{
CGFloat ratio;
if (imageSize.width <= 0
|| imageSize.height <= 0)
{
return NSMakeSize(0, 0);
}
/* Get the smaller ratio and scale the image size by it. */
ratio = MIN(canvasSize.width / imageSize.width,
canvasSize.height / imageSize.height);
/* Only scale down, unless scaleUpOrDown is YES */
if (ratio < 1.0 || scaleUpOrDown)
{
imageSize.width *= ratio;
imageSize.height *= ratio;
}
return imageSize;
}
- (NSSize) _scaleImageWithSize: (NSSize)imageSize
toFitInSize: (NSSize)canvasSize
scalingType: (NSImageScaling)scalingType
{
NSSize result;
switch (scalingType)
{
case NSImageScaleProportionallyDown: // == NSScaleProportionally
{
result = scaleProportionally (imageSize, canvasSize, NO);
break;
}
case NSImageScaleAxesIndependently: // == NSScaleToFit
{
result = canvasSize;
break;
}
default:
case NSImageScaleNone: // == NSScaleNone
{
result = imageSize;
break;
}
case NSImageScaleProportionallyUpOrDown:
{
result = scaleProportionally (imageSize, canvasSize, YES);
break;
}
}
return result;
}
@end

View file

@ -36,6 +36,12 @@
#import "GNUstepGUI/GSTheme.h"
#import "GSGuiPrivate.h"
@interface NSCell (Private)
- (NSSize) _scaleImageWithSize: (NSSize)imageSize
toFitInSize: (NSSize)canvasSize
scalingType: (NSImageScaling)scalingType;
@end
@implementation NSImageCell
//
@ -171,25 +177,6 @@ yBottomInRect(NSSize innerSize, NSRect outerRect, BOOL flipped)
return NSMinY(outerRect);
}
static inline NSSize
scaleProportionally(NSSize imageSize, NSRect canvasRect, BOOL scaleUpOrDown)
{
float ratio;
/* Get the smaller ratio and scale the image size by it. */
ratio = MIN(NSWidth(canvasRect) / imageSize.width,
NSHeight(canvasRect) / imageSize.height);
/* Only scale down, unless scaleUpOrDown is YES */
if (ratio < 1.0 || scaleUpOrDown)
{
imageSize.width *= ratio;
imageSize.height *= ratio;
}
return imageSize;
}
- (void) drawInteriorWithFrame: (NSRect)cellFrame inView: (NSView *)controlView
{
NSPoint position;
@ -205,35 +192,9 @@ scaleProportionally(NSSize imageSize, NSRect canvasRect, BOOL scaleUpOrDown)
cellFrame = [self drawingRectForBounds: cellFrame];
realImageSize = [_cell_image size];
switch (_imageScaling)
{
case NSScaleProportionally:
{
NSDebugLLog(@"NSImageCell", @"NSScaleProportionally");
imageSize = scaleProportionally (realImageSize, cellFrame, NO);
break;
}
case NSScaleToFit:
{
NSDebugLLog(@"NSImageCell", @"NSScaleToFit");
imageSize = cellFrame.size;
break;
}
default:
case NSScaleNone:
{
NSDebugLLog(@"NSImageCell", @"NSScaleNone");
imageSize = realImageSize;
break;
}
case NSImageScaleProportionallyUpOrDown:
{
NSDebugLLog(@"NSImageCell", @"NSImageScaleProportionallyUpOrDown");
imageSize = scaleProportionally (realImageSize, cellFrame, YES);
break;
}
}
imageSize = [self _scaleImageWithSize: realImageSize
toFitInSize: cellFrame.size
scalingType: _imageScaling];
switch (_imageAlignment)
{