[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / styled_text_field_cell.mm
blobc1f53b2cc173ad54d389aa6b3dcb64ae20e8b0f8
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/styled_text_field_cell.h"
7 #include "base/logging.h"
8 #include "chrome/browser/themes/theme_properties.h"
9 #include "chrome/browser/themes/theme_service.h"
10 #import "chrome/browser/ui/cocoa/nsview_additions.h"
11 #import "chrome/browser/ui/cocoa/themed_window.h"
12 #include "grit/theme_resources.h"
13 #import "ui/base/cocoa/nsgraphics_context_additions.h"
14 #include "ui/base/resource/resource_bundle.h"
15 #include "ui/gfx/font.h"
16 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
18 @implementation StyledTextFieldCell
20 - (CGFloat)topTextFrameOffset {
21   return 0.0;
24 - (CGFloat)bottomTextFrameOffset {
25   return 0.0;
28 - (CGFloat)cornerRadius {
29   return 0.0;
32 - (rect_path_utils::RoundedCornerFlags)roundedCornerFlags {
33   return rect_path_utils::RoundedCornerAll;
36 - (BOOL)shouldDrawBezel {
37   return NO;
40 - (NSRect)textFrameForFrameInternal:(NSRect)cellFrame {
41   CGFloat topOffset = [self topTextFrameOffset];
42   NSRect textFrame = cellFrame;
43   textFrame.origin.y += topOffset;
44   textFrame.size.height -= topOffset + [self bottomTextFrameOffset];
45   return textFrame;
48 // Returns the same value as textCursorFrameForFrame, but does not call it
49 // directly to avoid potential infinite loops.
50 - (NSRect)textFrameForFrame:(NSRect)cellFrame {
51   return [self textFrameForFrameInternal:cellFrame];
54 // Returns the same value as textFrameForFrame, but does not call it directly to
55 // avoid potential infinite loops.
56 - (NSRect)textCursorFrameForFrame:(NSRect)cellFrame {
57   return [self textFrameForFrameInternal:cellFrame];
60 // Override to show the I-beam cursor only in the area given by
61 // |textCursorFrameForFrame:|.
62 - (void)resetCursorRect:(NSRect)cellFrame inView:(NSView *)controlView {
63   [super resetCursorRect:[self textCursorFrameForFrame:cellFrame]
64                   inView:controlView];
67 // For NSTextFieldCell this is the area within the borders.  For our
68 // purposes, we count the info decorations as being part of the
69 // border.
70 - (NSRect)drawingRectForBounds:(NSRect)theRect {
71   return [super drawingRectForBounds:[self textFrameForFrame:theRect]];
74 // TODO(shess): This code is manually drawing the cell's border area,
75 // but otherwise the cell assumes -setBordered:YES for purposes of
76 // calculating things like the editing area.  This is probably
77 // incorrect.  I know that this affects -drawingRectForBounds:.
78 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
79   const CGFloat lineWidth = [controlView cr_lineWidth];
80   const CGFloat halfLineWidth = lineWidth / 2.0;
82   DCHECK([controlView isFlipped]);
83   rect_path_utils::RoundedCornerFlags roundedCornerFlags =
84       [self roundedCornerFlags];
86   // TODO(shess): This inset is also reflected by |kFieldVisualInset|
87   // in omnibox_popup_view_mac.mm.
88   const NSRect frame = NSInsetRect(cellFrame, 0, lineWidth);
89   const CGFloat radius = [self cornerRadius];
91   // Paint button background image if there is one (otherwise the border won't
92   // look right).
93   ThemeService* themeProvider =
94       static_cast<ThemeService*>([[controlView window] themeProvider]);
95   if (themeProvider) {
96     NSColor* backgroundImageColor = nil;
97     if (themeProvider->HasCustomImage(IDR_THEME_BUTTON_BACKGROUND)) {
98       backgroundImageColor =
99           themeProvider->GetNSImageColorNamed(IDR_THEME_BUTTON_BACKGROUND);
100     }
101     if (backgroundImageColor) {
102       // Set the phase to match window.
103       NSRect trueRect = [controlView convertRect:cellFrame toView:nil];
104       NSPoint midPoint = NSMakePoint(NSMinX(trueRect), NSMaxY(trueRect));
105       [[NSGraphicsContext currentContext] cr_setPatternPhase:midPoint
106                                                      forView:controlView];
108       // NOTE(shess): This seems like it should be using a 0.0 inset,
109       // but AFAICT using a halfLineWidth inset is important in mixing the
110       // toolbar background and the omnibox background.
111       rect_path_utils::FillRectWithInset(roundedCornerFlags, frame,
112                                          halfLineWidth, halfLineWidth, radius,
113                                          backgroundImageColor);
114     }
116     // Draw the outer stroke (over the background).
117     BOOL active = [[controlView window] isMainWindow];
118     NSColor* strokeColor = themeProvider->GetNSColor(
119         active ? ThemeProperties::COLOR_TOOLBAR_BUTTON_STROKE :
120                  ThemeProperties::COLOR_TOOLBAR_BUTTON_STROKE_INACTIVE);
121     rect_path_utils::FrameRectWithInset(roundedCornerFlags, frame, 0.0, 0.0,
122                                         radius, lineWidth, strokeColor);
123   }
125   // Fill interior with background color.
126   rect_path_utils::FillRectWithInset(roundedCornerFlags, frame, lineWidth,
127                                      lineWidth, radius,
128                                      [self backgroundColor]);
130   // Draw the shadow.  For the rounded-rect case, the shadow needs to
131   // slightly turn in at the corners.  |shadowFrame| is at the same
132   // midline as the inner border line on the top and left, but at the
133   // outer border line on the bottom and right.  The clipping change
134   // will clip the bottom and right edges (and corner).
135   {
136     gfx::ScopedNSGraphicsContextSaveGState state;
137     [rect_path_utils::RectPathWithInset(roundedCornerFlags, frame, lineWidth,
138                                         lineWidth, radius) addClip];
139     const NSRect shadowFrame =
140         NSOffsetRect(frame, halfLineWidth, halfLineWidth);
141     NSColor* shadowShade = [NSColor colorWithCalibratedWhite:0.0
142                                                        alpha:0.05 / lineWidth];
143     rect_path_utils::FrameRectWithInset(roundedCornerFlags, shadowFrame,
144                                         halfLineWidth, halfLineWidth,
145                                         radius - halfLineWidth, lineWidth,
146                                         shadowShade);
147   }
149   // Draw optional bezel below bottom stroke.
150   if ([self shouldDrawBezel] && themeProvider &&
151       themeProvider->UsingDefaultTheme()) {
153     NSColor* bezelColor = themeProvider->GetNSColor(
154         ThemeProperties::COLOR_TOOLBAR_BEZEL);
155     [[bezelColor colorWithAlphaComponent:0.5 / lineWidth] set];
156     NSRect bezelRect = NSMakeRect(cellFrame.origin.x,
157                                   NSMaxY(cellFrame) - lineWidth,
158                                   NSWidth(cellFrame),
159                                   lineWidth);
160     bezelRect = NSInsetRect(bezelRect, radius - halfLineWidth, 0.0);
161     NSRectFillUsingOperation(bezelRect, NSCompositeSourceOver);
162   }
164   // Draw the interior before the focus ring, to make sure nothing overlaps it.
165   [self drawInteriorWithFrame:cellFrame inView:controlView];
167   // Draw the focus ring if needed.
168   if ([self showsFirstResponder]) {
169     NSColor* color = [[NSColor keyboardFocusIndicatorColor]
170         colorWithAlphaComponent:0.5 / lineWidth];
171     rect_path_utils::FrameRectWithInset(roundedCornerFlags, frame, 0.0, 0.0,
172                                         radius, lineWidth * 2, color);
173   }
176 @end