1 // Copyright (c) 2012 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 #include "chrome/browser/ui/cocoa/background_gradient_view.h"
7 #import "chrome/browser/themes/theme_properties.h"
8 #import "chrome/browser/themes/theme_service.h"
9 #import "chrome/browser/ui/cocoa/themed_window.h"
10 #include "grit/theme_resources.h"
11 #import "ui/base/cocoa/nsgraphics_context_additions.h"
12 #import "ui/base/cocoa/nsview_additions.h"
14 @interface BackgroundGradientView (Private)
16 - (NSColor*)backgroundImageColor;
19 @implementation BackgroundGradientView
21 @synthesize showsDivider = showsDivider_;
23 - (id)initWithFrame:(NSRect)frameRect {
24 if ((self = [super initWithFrame:frameRect])) {
30 - (id)initWithCoder:(NSCoder*)decoder {
31 if ((self = [super initWithCoder:decoder])) {
41 - (void)setShowsDivider:(BOOL)show {
42 if (showsDivider_ == show)
45 [self setNeedsDisplay:YES];
48 - (NSPoint)patternPhase {
50 themeImagePositionForAlignment:THEME_IMAGE_ALIGN_WITH_TAB_STRIP];
53 - (void)drawBackground:(NSRect)dirtyRect {
54 [[NSGraphicsContext currentContext]
55 cr_setPatternPhase:[self patternPhase]
56 forView:[self cr_viewBeingDrawnTo]];
58 ui::ThemeProvider* themeProvider = [[self window] themeProvider];
59 if (themeProvider && !themeProvider->UsingSystemTheme()) {
60 // If the background image is semi transparent then we need something
61 // to blend against. Using 20% black gives us a color similar to Windows.
62 [[NSColor colorWithCalibratedWhite:0.2 alpha:1.0] set];
63 NSRectFill(dirtyRect);
66 [[self backgroundImageColor] set];
67 NSRectFillUsingOperation(dirtyRect, NSCompositeSourceOver);
71 NSRect borderRect, contentRect;
72 NSDivideRect([self bounds], &borderRect, &contentRect, [self cr_lineWidth],
74 if (NSIntersectsRect(borderRect, dirtyRect)) {
75 [[self strokeColor] set];
76 NSRectFillUsingOperation(NSIntersectionRect(borderRect, dirtyRect),
77 NSCompositeSourceOver);
82 - (NSColor*)strokeColor {
83 NSWindow* window = [self window];
85 // Some views have a child NSWindow between them and the window that is
86 // active (e.g, OmniboxPopupTopSeparatorView). For these, check the status
87 // of parentWindow instead. Note that this is not tracked correctly (but
88 // the views that do this appear to be removed when the window loses focus
90 if ([window parentWindow])
91 window = [window parentWindow];
92 BOOL isActive = [window isMainWindow];
94 ui::ThemeProvider* themeProvider = [window themeProvider];
96 return [NSColor blackColor];
97 return themeProvider->GetNSColor(
98 isActive ? ThemeProperties::COLOR_TOOLBAR_STROKE :
99 ThemeProperties::COLOR_TOOLBAR_STROKE_INACTIVE);
102 - (NSColor*)backgroundImageColor {
103 ui::ThemeProvider* themeProvider = [[self window] themeProvider];
105 return [[self window] backgroundColor];
107 // Themes don't have an inactive image so only look for one if there's no
109 BOOL isActive = [[self window] isMainWindow];
110 if (!isActive && themeProvider->UsingSystemTheme()) {
111 NSColor* color = themeProvider->GetNSImageColorNamed(
112 IDR_THEME_TOOLBAR_INACTIVE);
117 return themeProvider->GetNSImageColorNamed(IDR_THEME_TOOLBAR);
120 - (void)viewDidMoveToWindow {
121 [super viewDidMoveToWindow];
123 // The new window for the view may have a different focus state than the
124 // last window this view was part of.
125 // This happens when the view is moved into a TabWindowOverlayWindow for
127 [self windowDidChangeActive];
131 - (void)viewWillStartLiveResize {
132 [super viewWillStartLiveResize];
134 ui::ThemeProvider* themeProvider = [[self window] themeProvider];
135 if (themeProvider && themeProvider->UsingSystemTheme()) {
136 // The default theme's background image is a subtle texture pattern that
137 // we can scale without being easily noticed. Optimize this case by
138 // skipping redraws during live resize.
139 [self setLayerContentsRedrawPolicy:
140 NSViewLayerContentsRedrawOnSetNeedsDisplay];
144 - (void)viewDidEndLiveResize {
145 [super viewDidEndLiveResize];
147 if ([self layerContentsRedrawPolicy] !=
148 NSViewLayerContentsRedrawDuringViewResize) {
149 // If we have been scaling the layer during live resize, now is the time to
151 [self setLayerContentsRedrawPolicy:
152 NSViewLayerContentsRedrawDuringViewResize];
153 [self setNeedsDisplay:YES];
157 - (void)setFrameOrigin:(NSPoint)origin {
158 // The background color depends on the view's vertical position. This impacts
159 // any child views that draw using this view's functions.
160 // When resizing the window, the view's vertical position (NSMinY) may change
161 // even though our relative position to the nearest window edge is still the
162 // same. Don't redraw unnecessarily in this case.
163 if (![self inLiveResize] && NSMinY([self frame]) != origin.y)
164 [self cr_recursivelySetNeedsDisplay:YES];
166 [super setFrameOrigin:origin];
169 // ThemedWindowDrawing implementation.
171 - (void)windowDidChangeTheme {
172 [self setNeedsDisplay:YES];
175 - (void)windowDidChangeActive {
176 [self setNeedsDisplay:YES];