blob: fe6dcb9f6504a0c61637f461ecffefc33ac21212 [file] [log] [blame]
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "chrome/browser/ui/cocoa/image_button_cell.h"
#include "base/logging.h"
#import "chrome/browser/themes/theme_service.h"
#import "chrome/browser/ui/cocoa/image_utils.h"
#import "chrome/browser/ui/cocoa/themed_window.h"
#include "ui/gfx/image/image.h"
namespace {
// Adjust the overlay position relative to the top right of the button image.
const CGFloat kOverlayOffsetX = -3;
const CGFloat kOverlayOffsetY = 5;
// When the window doesn't have focus then we want to draw the button with a
// slightly lighter color. We do this by just reducing the alpha.
const CGFloat kImageNoFocusAlpha = 0.65;
} // namespace
@interface ImageButtonCell (Private)
- (void)sharedInit;
- (image_button_cell::ButtonState)currentButtonState;
- (NSImage*)imageForID:(NSInteger)imageID
controlView:(NSView*)controlView;
@end
@implementation ImageButtonCell
@synthesize isMouseInside = isMouseInside_;
@synthesize overlayImageID = overlayImageID_;
// For nib instantiations
- (id)initWithCoder:(NSCoder*)decoder {
if ((self = [super initWithCoder:decoder])) {
[self sharedInit];
}
return self;
}
// For programmatic instantiations
- (id)initTextCell:(NSString*)string {
if ((self = [super initTextCell:string])) {
[self sharedInit];
}
return self;
}
- (void)sharedInit {
[self setHighlightsBy:NSNoCellMask];
// We need to set this so that we can override |-mouseEntered:| and
// |-mouseExited:| to change the button image on hover states.
[self setShowsBorderOnlyWhileMouseInside:YES];
}
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
BOOL windowHasFocus = [[controlView window] isMainWindow] ||
[[controlView window] isKeyWindow];
CGFloat alpha = windowHasFocus ? 1.0 : kImageNoFocusAlpha;
NSImage* image = [self imageForID:imageID_[[self currentButtonState]]
controlView:controlView];
NSRect imageRect;
imageRect.size = [image size];
imageRect.origin.x = cellFrame.origin.x +
roundf((cellFrame.size.width - imageRect.size.width) / 2.0);
imageRect.origin.y = cellFrame.origin.y +
roundf((cellFrame.size.height - imageRect.size.height) / 2.0);
[image drawInRect:imageRect
fromRect:NSZeroRect
operation:NSCompositeSourceOver
fraction:alpha
neverFlipped:YES];
if (overlayImageID_) {
NSImage* overlayImage = [self imageForID:overlayImageID_
controlView:controlView];
NSRect overlayRect;
overlayRect.size = [overlayImage size];
overlayRect.origin.x = NSMaxX(imageRect) - overlayRect.size.width +
kOverlayOffsetX;
overlayRect.origin.y = NSMinY(imageRect) + kOverlayOffsetY;
[overlayImage drawInRect:overlayRect
fromRect:NSZeroRect
operation:NSCompositeSourceOver
fraction:1.0
neverFlipped:YES];
}
}
- (void)setImageID:(NSInteger)imageID
forButtonState:(image_button_cell::ButtonState)state {
DCHECK_GE(state, 0);
DCHECK_LT(state, image_button_cell::kButtonStateCount);
if (imageID_[state] != imageID) {
imageID_[state] = imageID;
[[self controlView] setNeedsDisplay:YES];
}
}
- (void)setOverlayImageID:(NSInteger)imageID {
if (overlayImageID_ != imageID) {
overlayImageID_ = imageID;
[[self controlView] setNeedsDisplay:YES];
}
}
- (image_button_cell::ButtonState)currentButtonState {
if (![self isEnabled] && imageID_[image_button_cell::kDisabledState])
return image_button_cell::kDisabledState;
else if ([self isHighlighted] && imageID_[image_button_cell::kPressedState])
return image_button_cell::kPressedState;
else if ([self isMouseInside] && imageID_[image_button_cell::kHoverState])
return image_button_cell::kHoverState;
else
return image_button_cell::kDefaultState;
}
- (NSImage*)imageForID:(NSInteger)imageID
controlView:(NSView*)controlView {
if (!imageID)
return nil;
ui::ThemeProvider* themeProvider = [[controlView window] themeProvider];
if (!themeProvider)
return nil;
return themeProvider->GetNSImageNamed(imageID, true);
}
- (void)setIsMouseInside:(BOOL)isMouseInside {
if (isMouseInside_ != isMouseInside) {
isMouseInside_ = isMouseInside;
[[self controlView] setNeedsDisplay:YES];
}
}
- (void)mouseEntered:(NSEvent*)theEvent {
[self setIsMouseInside:YES];
}
- (void)mouseExited:(NSEvent*)theEvent {
[self setIsMouseInside:NO];
}
@end