I've a NSButton
with both an Image and Alternate Image. I would like the alternate image to be shown on hover. To solve this, I've extended the NSButton to show the alternate image when hovering the view. Is there a better solution to this?
My solution:
@interface HoverButton()
@property (nonatomic, strong) NSTrackingArea *trackingArea;
@property (nonatomic, strong) NSImage *imageTmp;
@end
@implementation HoverButton
-(void)mouseEntered:(NSEvent *)theEvent {
[super mouseEntered:theEvent];
[self updateImages];
self.image = self.alternateImage;
}
-(void)mouseExited:(NSEvent *)theEvent {
[super mouseExited:theEvent];
self.image = self.imageTmp;
}
- (void)updateImages {
self.imageTmp = self.image;
}
-(void)updateTrackingAreas
{
if(self.trackingArea != nil) {
[self removeTrackingArea:self.trackingArea];
}
int opts = (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways);
self.trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
options:opts
owner:self
userInfo:nil];
[self addTrackingArea:self.trackingArea];
}
@end
I would say this is better suited to an NSButtonCell
subclass. you can do it in one method and it won't apply to all NSButtons (I doubt thats what you actually want). Just set your button cell type in IB to your custom subclass.
here is some code I just wrote and tested that works:
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
if (_alternateImageOrKeyEquivalentFont && _bcFlags2.mouseInside) {
// the draw bezel call is optional. maybe you don't want it
[self drawBezelWithFrame:cellFrame inView:controlView];
[self drawImage:_alternateImageOrKeyEquivalentFont
withFrame:cellFrame
inView:controlView];
} else {
[super drawInteriorWithFrame:cellFrame
inView:controlView];
}
}
you will need to set the showsBorderOnlyWhileMouseInside
to YES
probably in an init
method for the cell.