summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/cocoa/styled_text_field_cell.mm
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/ui/cocoa/styled_text_field_cell.mm')
-rw-r--r--chrome/browser/ui/cocoa/styled_text_field_cell.mm217
1 files changed, 217 insertions, 0 deletions
diff --git a/chrome/browser/ui/cocoa/styled_text_field_cell.mm b/chrome/browser/ui/cocoa/styled_text_field_cell.mm
new file mode 100644
index 0000000..56b0cf3
--- /dev/null
+++ b/chrome/browser/ui/cocoa/styled_text_field_cell.mm
@@ -0,0 +1,217 @@
+// Copyright (c) 2010 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/styled_text_field_cell.h"
+
+#include "app/resource_bundle.h"
+#include "base/logging.h"
+#include "chrome/browser/themes/browser_theme_provider.h"
+#import "chrome/browser/ui/cocoa/themed_window.h"
+#include "gfx/font.h"
+#include "grit/theme_resources.h"
+#import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h"
+
+namespace {
+
+NSBezierPath* RectPathWithInset(StyledTextFieldCellRoundedFlags roundedFlags,
+ const NSRect frame,
+ const CGFloat inset,
+ const CGFloat outerRadius) {
+ NSRect insetFrame = NSInsetRect(frame, inset, inset);
+
+ if (outerRadius > 0.0) {
+ CGFloat leftRadius = outerRadius - inset;
+ CGFloat rightRadius =
+ (roundedFlags == StyledTextFieldCellRoundedLeft) ? 0 : leftRadius;
+
+ return [NSBezierPath gtm_bezierPathWithRoundRect:insetFrame
+ topLeftCornerRadius:leftRadius
+ topRightCornerRadius:rightRadius
+ bottomLeftCornerRadius:leftRadius
+ bottomRightCornerRadius:rightRadius];
+ } else {
+ return [NSBezierPath bezierPathWithRect:insetFrame];
+ }
+}
+
+// Similar to |NSRectFill()|, additionally sets |color| as the fill
+// color. |outerRadius| greater than 0.0 uses rounded corners, with
+// inset backed out of the radius.
+void FillRectWithInset(StyledTextFieldCellRoundedFlags roundedFlags,
+ const NSRect frame,
+ const CGFloat inset,
+ const CGFloat outerRadius,
+ NSColor* color) {
+ NSBezierPath* path =
+ RectPathWithInset(roundedFlags, frame, inset, outerRadius);
+ [color setFill];
+ [path fill];
+}
+
+// Similar to |NSFrameRectWithWidth()|, additionally sets |color| as
+// the stroke color (as opposed to the fill color). |outerRadius|
+// greater than 0.0 uses rounded corners, with inset backed out of the
+// radius.
+void FrameRectWithInset(StyledTextFieldCellRoundedFlags roundedFlags,
+ const NSRect frame,
+ const CGFloat inset,
+ const CGFloat outerRadius,
+ const CGFloat lineWidth,
+ NSColor* color) {
+ const CGFloat finalInset = inset + (lineWidth / 2.0);
+ NSBezierPath* path =
+ RectPathWithInset(roundedFlags, frame, finalInset, outerRadius);
+ [color setStroke];
+ [path setLineWidth:lineWidth];
+ [path stroke];
+}
+
+// TODO(shess): Maybe we need a |cocoa_util.h|?
+class ScopedSaveGraphicsState {
+ public:
+ ScopedSaveGraphicsState()
+ : context_([NSGraphicsContext currentContext]) {
+ [context_ saveGraphicsState];
+ }
+ explicit ScopedSaveGraphicsState(NSGraphicsContext* context)
+ : context_(context) {
+ [context_ saveGraphicsState];
+ }
+ ~ScopedSaveGraphicsState() {
+ [context_ restoreGraphicsState];
+ }
+
+private:
+ NSGraphicsContext* context_;
+};
+
+} // namespace
+
+@implementation StyledTextFieldCell
+
+- (CGFloat)baselineAdjust {
+ return 0.0;
+}
+
+- (CGFloat)cornerRadius {
+ return 0.0;
+}
+
+- (StyledTextFieldCellRoundedFlags)roundedFlags {
+ return StyledTextFieldCellRoundedAll;
+}
+
+- (BOOL)shouldDrawBezel {
+ return NO;
+}
+
+// Returns the same value as textCursorFrameForFrame, but does not call it
+// directly to avoid potential infinite loops.
+- (NSRect)textFrameForFrame:(NSRect)cellFrame {
+ return NSInsetRect(cellFrame, 0, [self baselineAdjust]);
+}
+
+// Returns the same value as textFrameForFrame, but does not call it directly to
+// avoid potential infinite loops.
+- (NSRect)textCursorFrameForFrame:(NSRect)cellFrame {
+ return NSInsetRect(cellFrame, 0, [self baselineAdjust]);
+}
+
+// Override to show the I-beam cursor only in the area given by
+// |textCursorFrameForFrame:|.
+- (void)resetCursorRect:(NSRect)cellFrame inView:(NSView *)controlView {
+ [super resetCursorRect:[self textCursorFrameForFrame:cellFrame]
+ inView:controlView];
+}
+
+// For NSTextFieldCell this is the area within the borders. For our
+// purposes, we count the info decorations as being part of the
+// border.
+- (NSRect)drawingRectForBounds:(NSRect)theRect {
+ return [super drawingRectForBounds:[self textFrameForFrame:theRect]];
+}
+
+// TODO(shess): This code is manually drawing the cell's border area,
+// but otherwise the cell assumes -setBordered:YES for purposes of
+// calculating things like the editing area. This is probably
+// incorrect. I know that this affects -drawingRectForBounds:.
+- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
+ DCHECK([controlView isFlipped]);
+ StyledTextFieldCellRoundedFlags roundedFlags = [self roundedFlags];
+
+ // TODO(shess): This inset is also reflected by |kFieldVisualInset|
+ // in autocomplete_popup_view_mac.mm.
+ const NSRect frame = NSInsetRect(cellFrame, 0, 1);
+ const CGFloat radius = [self cornerRadius];
+
+ // Paint button background image if there is one (otherwise the border won't
+ // look right).
+ BrowserThemeProvider* themeProvider =
+ static_cast<BrowserThemeProvider*>([[controlView window] themeProvider]);
+ if (themeProvider) {
+ NSColor* backgroundImageColor =
+ themeProvider->GetNSImageColorNamed(IDR_THEME_BUTTON_BACKGROUND, false);
+ if (backgroundImageColor) {
+ // Set the phase to match window.
+ NSRect trueRect = [controlView convertRect:cellFrame toView:nil];
+ NSPoint midPoint = NSMakePoint(NSMinX(trueRect), NSMaxY(trueRect));
+ [[NSGraphicsContext currentContext] setPatternPhase:midPoint];
+
+ // NOTE(shess): This seems like it should be using a 0.0 inset,
+ // but AFAICT using a 0.5 inset is important in mixing the
+ // toolbar background and the omnibox background.
+ FillRectWithInset(roundedFlags, frame, 0.5, radius, backgroundImageColor);
+ }
+
+ // Draw the outer stroke (over the background).
+ BOOL active = [[controlView window] isMainWindow];
+ NSColor* strokeColor = themeProvider->GetNSColor(
+ active ? BrowserThemeProvider::COLOR_TOOLBAR_BUTTON_STROKE :
+ BrowserThemeProvider::COLOR_TOOLBAR_BUTTON_STROKE_INACTIVE,
+ true);
+ FrameRectWithInset(roundedFlags, frame, 0.0, radius, 1.0, strokeColor);
+ }
+
+ // Fill interior with background color.
+ FillRectWithInset(roundedFlags, frame, 1.0, radius, [self backgroundColor]);
+
+ // Draw the shadow. For the rounded-rect case, the shadow needs to
+ // slightly turn in at the corners. |shadowFrame| is at the same
+ // midline as the inner border line on the top and left, but at the
+ // outer border line on the bottom and right. The clipping change
+ // will clip the bottom and right edges (and corner).
+ {
+ ScopedSaveGraphicsState state;
+ [RectPathWithInset(roundedFlags, frame, 1.0, radius) addClip];
+ const NSRect shadowFrame = NSOffsetRect(frame, 0.5, 0.5);
+ NSColor* shadowShade = [NSColor colorWithCalibratedWhite:0.0 alpha:0.05];
+ FrameRectWithInset(roundedFlags, shadowFrame, 0.5, radius - 0.5,
+ 1.0, shadowShade);
+ }
+
+ // Draw optional bezel below bottom stroke.
+ if ([self shouldDrawBezel] && themeProvider &&
+ themeProvider->UsingDefaultTheme()) {
+
+ [themeProvider->GetNSColor(
+ BrowserThemeProvider::COLOR_TOOLBAR_BEZEL, true) set];
+ NSRect bezelRect = NSMakeRect(cellFrame.origin.x,
+ NSMaxY(cellFrame) - 0.5,
+ NSWidth(cellFrame),
+ 1.0);
+ bezelRect = NSInsetRect(bezelRect, radius - 0.5, 0.0);
+ NSRectFill(bezelRect);
+ }
+
+ // Draw the focus ring if needed.
+ if ([self showsFirstResponder]) {
+ NSColor* color =
+ [[NSColor keyboardFocusIndicatorColor] colorWithAlphaComponent:0.5];
+ FrameRectWithInset(roundedFlags, frame, 0.0, radius, 2.0, color);
+ }
+
+ [self drawInteriorWithFrame:cellFrame inView:controlView];
+}
+
+@end