Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / image_button_cell.mm
blob35dede3732e9654fa2fa025c172f988185b43c2c
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "chrome/browser/ui/cocoa/image_button_cell.h"
7 #include "base/logging.h"
8 #import "chrome/browser/themes/theme_service.h"
9 #import "chrome/browser/ui/cocoa/nsview_additions.h"
10 #import "chrome/browser/ui/cocoa/rect_path_utils.h"
11 #import "chrome/browser/ui/cocoa/themed_window.h"
12 #include "ui/base/resource/resource_bundle.h"
13 #include "ui/gfx/image/image.h"
14 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
16 // When the window doesn't have focus then we want to draw the button with a
17 // slightly lighter color. We do this by just reducing the alpha.
18 const CGFloat kImageNoFocusAlpha = 0.65;
20 @interface ImageButtonCell (Private)
21 - (void)sharedInit;
22 - (image_button_cell::ButtonState)currentButtonState;
23 - (NSImage*)imageForID:(NSInteger)imageID
24            controlView:(NSView*)controlView;
25 @end
27 @implementation ImageButtonCell
29 @synthesize isMouseInside = isMouseInside_;
31 // For nib instantiations
32 - (id)initWithCoder:(NSCoder*)decoder {
33   if ((self = [super initWithCoder:decoder])) {
34     [self sharedInit];
35   }
36   return self;
39 // For programmatic instantiations
40 - (id)initTextCell:(NSString*)string {
41   if ((self = [super initTextCell:string])) {
42     [self sharedInit];
43   }
44   return self;
47 - (void)sharedInit {
48   [self setHighlightsBy:NSNoCellMask];
50   // We need to set this so that we can override |-mouseEntered:| and
51   // |-mouseExited:| to change the button image on hover states.
52   [self setShowsBorderOnlyWhileMouseInside:YES];
55 - (NSImage*)imageForState:(image_button_cell::ButtonState)state
56                      view:(NSView*)controlView{
57   if (image_[state].imageId)
58     return [self imageForID:image_[state].imageId controlView:controlView];
59   return image_[state].image;
62 - (void)drawImageWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
63   image_button_cell::ButtonState state = [self currentButtonState];
64   BOOL windowHasFocus = [[controlView window] isMainWindow] ||
65                         [[controlView window] isKeyWindow];
66   CGFloat alpha = [self imageAlphaForWindowState:[controlView window]];
67   NSImage* image = [self imageForState:state view:controlView];
69   if (!windowHasFocus) {
70     NSImage* defaultImage = [self
71       imageForState:image_button_cell::kDefaultStateBackground
72                view:controlView];
73     NSImage* hoverImage = [self
74       imageForState:image_button_cell::kHoverStateBackground
75                view:controlView];
76     if ([self currentButtonState] == image_button_cell::kDefaultState &&
77         defaultImage) {
78       image = defaultImage;
79       alpha = 1.0;
80     } else if ([self currentButtonState] == image_button_cell::kHoverState &&
81         hoverImage) {
82       image = hoverImage;
83       alpha = 1.0;
84     }
85   }
87   NSRect imageRect;
88   imageRect.size = [image size];
89   imageRect.origin.x = cellFrame.origin.x +
90     roundf((NSWidth(cellFrame) - NSWidth(imageRect)) / 2.0);
91   imageRect.origin.y = cellFrame.origin.y +
92     roundf((NSHeight(cellFrame) - NSHeight(imageRect)) / 2.0);
94   [image drawInRect:imageRect
95            fromRect:NSZeroRect
96           operation:NSCompositeSourceOver
97            fraction:alpha
98      respectFlipped:YES
99               hints:nil];
102 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
103   [self drawImageWithFrame:cellFrame inView:controlView];
104   // Only draw custom focus ring if the 10.7 focus ring APIs are not available.
105   // TODO(groby): Remove once we build against the 10.7 SDK.
106   if (![self respondsToSelector:@selector(drawFocusRingMaskWithFrame:inView:)])
107     [self drawFocusRingWithFrame:cellFrame inView:controlView];
110 - (void)setImageID:(NSInteger)imageID
111     forButtonState:(image_button_cell::ButtonState)state {
112   DCHECK_GE(state, 0);
113   DCHECK_LT(state, image_button_cell::kButtonStateCount);
115   image_[state].image.reset();
116   image_[state].imageId = imageID;
117   [[self controlView] setNeedsDisplay:YES];
120 // Sets the image for the given button state using an image.
121 - (void)setImage:(NSImage*)image
122   forButtonState:(image_button_cell::ButtonState)state {
123   DCHECK_GE(state, 0);
124   DCHECK_LT(state, image_button_cell::kButtonStateCount);
126   image_[state].image.reset([image retain]);
127   image_[state].imageId = 0;
128   [[self controlView] setNeedsDisplay:YES];
131 - (CGFloat)imageAlphaForWindowState:(NSWindow*)window {
132   BOOL windowHasFocus = [window isMainWindow] || [window isKeyWindow];
133   return windowHasFocus ? 1.0 : kImageNoFocusAlpha;
136 - (void)drawFocusRingWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
137   if (![self showsFirstResponder])
138     return;
139   gfx::ScopedNSGraphicsContextSaveGState scoped_state;
140   const CGFloat lineWidth = [controlView cr_lineWidth];
141   rect_path_utils::FrameRectWithInset(rect_path_utils::RoundedCornerAll,
142                                       NSInsetRect(cellFrame, 0, lineWidth),
143                                       0.0,            // insetX
144                                       0.0,            // insetY
145                                       3.0,            // outerRadius
146                                       lineWidth * 2,  // lineWidth
147                                       [controlView
148                                           cr_keyboardFocusIndicatorColor]);
151 - (image_button_cell::ButtonState)currentButtonState {
152   bool (^has)(image_button_cell::ButtonState) =
153       ^(image_button_cell::ButtonState state) {
154           return image_[state].image || image_[state].imageId;
155       };
156   if (![self isEnabled] && has(image_button_cell::kDisabledState))
157     return image_button_cell::kDisabledState;
158   if ([self isHighlighted] && has(image_button_cell::kPressedState))
159     return image_button_cell::kPressedState;
160   if ([self isMouseInside] && has(image_button_cell::kHoverState))
161     return image_button_cell::kHoverState;
162   return image_button_cell::kDefaultState;
165 - (NSImage*)imageForID:(NSInteger)imageID
166            controlView:(NSView*)controlView {
167   if (!imageID)
168     return nil;
170   ui::ThemeProvider* themeProvider = [[controlView window] themeProvider];
171   if (!themeProvider)
172     return nil;
174   return themeProvider->GetNSImageNamed(imageID);
177 - (void)setIsMouseInside:(BOOL)isMouseInside {
178   if (isMouseInside_ != isMouseInside) {
179     isMouseInside_ = isMouseInside;
180     NSView<ImageButton>* control =
181         static_cast<NSView<ImageButton>*>([self controlView]);
182     if ([control respondsToSelector:@selector(mouseInsideStateDidChange:)]) {
183       [control mouseInsideStateDidChange:isMouseInside];
184     }
185     [control setNeedsDisplay:YES];
186   }
189 - (void)setShowsBorderOnlyWhileMouseInside:(BOOL)show {
190   VLOG_IF(1, !show) << "setShowsBorderOnlyWhileMouseInside:NO ignored";
193 - (BOOL)showsBorderOnlyWhileMouseInside {
194   // Always returns YES so that buttons always get mouse tracking even when
195   // disabled. The reload button (and possibly others) depend on this.
196   return YES;
199 - (void)mouseEntered:(NSEvent*)theEvent {
200   [self setIsMouseInside:YES];
203 - (void)mouseExited:(NSEvent*)theEvent {
204   [self setIsMouseInside:NO];
207 @end