Add OakRolloverButton

This commit is contained in:
Allan Odgaard
2014-09-22 21:52:45 +02:00
parent 7ebd14876c
commit b7088bac3d
2 changed files with 168 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
#include <oak/misc.h>
PUBLIC @interface OakRolloverButton : NSButton
@property (nonatomic) NSImage* regularImage;
@property (nonatomic) NSImage* pressedImage;
@property (nonatomic) NSImage* rolloverImage;
@property (nonatomic) NSImage* inactiveRegularImage;
@property (nonatomic) NSImage* inactivePressedImage;
@property (nonatomic) NSImage* inactiveRolloverImage;
@property (nonatomic) BOOL disableWindowOrderingForFirstMouse;
@end

View File

@@ -0,0 +1,157 @@
#import "OakRolloverButton.h"
typedef NS_ENUM(NSUInteger, OakImageState) {
OakImageStateRegular = 0,
OakImageStatePressed,
OakImageStateRollover,
OakImageStateInactiveRegular,
OakImageStateInactivePressed,
OakImageStateInactiveRollover,
OakImageStateCount
};
@interface OakRolloverButton ()
{
NSImage* _images[OakImageStateCount];
}
@property (nonatomic) BOOL active;
@property (nonatomic) BOOL mouseInside;
@property (nonatomic) NSTrackingArea* trackingArea;
@end
@implementation OakRolloverButton
- (id)initWithFrame:(NSRect)aFrame
{
if((self = [super initWithFrame:aFrame]))
{
self.buttonType = NSMomentaryChangeButton;
self.bordered = NO;
[self setContentCompressionResistancePriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal];
[self setContentCompressionResistancePriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationVertical];
[self setContentHuggingPriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal];
[self setContentHuggingPriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationVertical];
}
return self;
}
- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent*)anEvent
{
return _disableWindowOrderingForFirstMouse;
}
- (void)mouseDown:(NSEvent*)anEvent
{
if(_disableWindowOrderingForFirstMouse)
[NSApp preventWindowOrdering];
[super mouseDown:anEvent];
}
- (void)setImage:(NSImage*)anImage forState:(OakImageState)imageState
{
if(_images[imageState] == anImage)
return;
_images[imageState] = anImage;
[self updateImage];
}
- (NSImage*)regularImage { return _images[OakImageStateRegular]; }
- (NSImage*)pressedImage { return _images[OakImageStatePressed]; }
- (NSImage*)rolloverImage { return _images[OakImageStateRollover]; }
- (NSImage*)inactiveRegularImage { return _images[OakImageStateInactiveRegular]; }
- (NSImage*)inactivePressedImage { return _images[OakImageStateInactivePressed]; }
- (NSImage*)inactiveRolloverImage { return _images[OakImageStateInactiveRollover]; }
- (void)setRegularImage:(NSImage*)anImage { [self setImage:anImage forState:OakImageStateRegular]; }
- (void)setPressedImage:(NSImage*)anImage { [self setImage:anImage forState:OakImageStatePressed]; }
- (void)setRolloverImage:(NSImage*)anImage { [self setImage:anImage forState:OakImageStateRollover]; }
- (void)setInactiveRegularImage:(NSImage*)anImage { [self setImage:anImage forState:OakImageStateInactiveRegular]; }
- (void)setInactivePressedImage:(NSImage*)anImage { [self setImage:anImage forState:OakImageStateInactivePressed]; }
- (void)setInactiveRolloverImage:(NSImage*)anImage { [self setImage:anImage forState:OakImageStateInactiveRollover]; }
- (void)updateImage
{
NSImage* image = _images[OakImageStateRegular];
NSImage* altImage = _images[OakImageStatePressed];
if(_mouseInside)
{
image = _images[OakImageStateRollover] ?: image;
if(!_active)
image = _images[OakImageStateInactiveRollover] ?: image;
}
else if(!_active)
{
image = _images[OakImageStateInactiveRegular] ?: image;
altImage = _images[OakImageStateInactivePressed] ?: image;
}
self.image = image;
self.alternateImage = altImage;
}
- (void)viewWillMoveToWindow:(NSWindow*)newWindow
{
if(self.window)
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidBecomeMainNotification object:self.window];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResignMainNotification object:self.window];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidBecomeKeyNotification object:self.window];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResignKeyNotification object:self.window];
}
if(newWindow)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidChangeMainOrKey:) name:NSWindowDidBecomeMainNotification object:newWindow];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidChangeMainOrKey:) name:NSWindowDidResignMainNotification object:newWindow];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidChangeMainOrKey:) name:NSWindowDidBecomeKeyNotification object:newWindow];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidChangeMainOrKey:) name:NSWindowDidResignKeyNotification object:newWindow];
}
self.active = ([newWindow styleMask] & NSFullScreenWindowMask) || [newWindow isMainWindow] || [newWindow isKeyWindow];
}
- (void)windowDidChangeMainOrKey:(NSNotification*)aNotification
{
self.active = ([self.window styleMask] & NSFullScreenWindowMask) || [self.window isMainWindow] || [self.window isKeyWindow];
}
- (void)updateTrackingAreas
{
[super updateTrackingAreas];
self.mouseInside = NSMouseInRect([self convertPoint:[self.window mouseLocationOutsideOfEventStream] fromView:nil], [self visibleRect], [self isFlipped]);
if(_trackingArea)
[self removeTrackingArea:_trackingArea];
NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited|NSTrackingActiveAlways|(_mouseInside ? NSTrackingAssumeInside : 0);
_trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:options owner:self userInfo:nil];
[self addTrackingArea:_trackingArea];
}
- (void)mouseEntered:(NSEvent*)anEvent
{
self.mouseInside = YES;
}
- (void)mouseExited:(NSEvent*)anEvent
{
self.mouseInside = NO;
}
- (void)setActive:(BOOL)flag
{
if(_active == flag)
return;
_active = flag;
[self updateImage];
}
- (void)setMouseInside:(BOOL)flag
{
if(_mouseInside == flag)
return;
_mouseInside = flag;
[self updateImage];
}
@end