Upstream version 7.35.139.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / background_gradient_view.mm
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.
4
5 #include "chrome/browser/ui/cocoa/background_gradient_view.h"
6
7 #import "chrome/browser/themes/theme_properties.h"
8 #import "chrome/browser/themes/theme_service.h"
9 #import "chrome/browser/ui/cocoa/nsview_additions.h"
10 #import "chrome/browser/ui/cocoa/themed_window.h"
11 #include "grit/theme_resources.h"
12
13 @interface BackgroundGradientView (Private)
14 - (void)commonInit;
15 - (NSColor*)backgroundImageColor;
16 @end
17
18 @implementation BackgroundGradientView
19
20 @synthesize showsDivider = showsDivider_;
21
22 - (id)initWithFrame:(NSRect)frameRect {
23   if ((self = [super initWithFrame:frameRect])) {
24     [self commonInit];
25   }
26   return self;
27 }
28
29 - (id)initWithCoder:(NSCoder*)decoder {
30   if ((self = [super initWithCoder:decoder])) {
31     [self commonInit];
32   }
33   return self;
34 }
35
36 - (void)dealloc {
37   [[NSNotificationCenter defaultCenter] removeObserver:self];
38   [super dealloc];
39 }
40
41 - (void)commonInit {
42   showsDivider_ = YES;
43 }
44
45 - (void)setShowsDivider:(BOOL)show {
46   if (showsDivider_ == show)
47     return;
48   showsDivider_ = show;
49   [self setNeedsDisplay:YES];
50 }
51
52 - (void)drawBackgroundWithOpaque:(BOOL)opaque {
53   const NSRect bounds = [self bounds];
54
55   if (opaque) {
56     // If the background image is semi transparent then we need something
57     // to blend against. Using 20% black gives us a color similar to Windows.
58     [[NSColor colorWithCalibratedWhite:0.2 alpha:1.0] set];
59     NSRectFill(bounds);
60   }
61
62   [[self backgroundImageColor] set];
63   NSRectFillUsingOperation(bounds, NSCompositeSourceOver);
64
65   if (showsDivider_) {
66     // Draw bottom stroke
67     [[self strokeColor] set];
68     NSRect borderRect, contentRect;
69     NSDivideRect(bounds, &borderRect, &contentRect, [self cr_lineWidth],
70                  NSMinYEdge);
71     NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
72   }
73 }
74
75 - (NSColor*)strokeColor {
76   NSWindow* window = [self window];
77
78   // Some views have a child NSWindow between them and the window that is
79   // active (e.g, OmniboxPopupTopSeparatorView). For these, check the status
80   // of parentWindow instead. Note that this is not tracked correctly (but
81   // the views that do this appear to be removed when the window loses focus
82   // anyway).
83   if ([window parentWindow])
84     window = [window parentWindow];
85   BOOL isActive = [window isMainWindow];
86
87   ui::ThemeProvider* themeProvider = [window themeProvider];
88   if (!themeProvider)
89     return [NSColor blackColor];
90   return themeProvider->GetNSColor(
91       isActive ? ThemeProperties::COLOR_TOOLBAR_STROKE :
92                  ThemeProperties::COLOR_TOOLBAR_STROKE_INACTIVE);
93 }
94
95 - (NSColor*)backgroundImageColor {
96   ThemeService* themeProvider =
97       static_cast<ThemeService*>([[self window] themeProvider]);
98   if (!themeProvider)
99     return [[self window] backgroundColor];
100
101   // Themes don't have an inactive image so only look for one if there's no
102   // theme.
103   BOOL isActive = [[self window] isMainWindow];
104   if (!isActive && themeProvider->UsingDefaultTheme()) {
105     NSColor* color = themeProvider->GetNSImageColorNamed(
106         IDR_THEME_TOOLBAR_INACTIVE);
107     if (color)
108       return color;
109   }
110
111   return themeProvider->GetNSImageColorNamed(IDR_THEME_TOOLBAR);
112 }
113
114 - (void)windowFocusDidChange:(NSNotification*)notification {
115   // Some child views will indirectly use BackgroundGradientView by calling an
116   // ancestor's draw function (e.g, BookmarkButtonView). Call setNeedsDisplay
117   // on all descendants to ensure that these views re-draw.
118   // TODO(ccameron): Enable these views to listen for focus notifications
119   // directly.
120   [self cr_recursivelySetNeedsDisplay:YES];
121 }
122
123 - (void)viewWillMoveToWindow:(NSWindow*)window {
124   if ([self window]) {
125     [[NSNotificationCenter defaultCenter]
126         removeObserver:self
127                   name:NSWindowDidBecomeKeyNotification
128                 object:[self window]];
129     [[NSNotificationCenter defaultCenter]
130         removeObserver:self
131                   name:NSWindowDidBecomeMainNotification
132                 object:[self window]];
133   }
134   if (window) {
135     [[NSNotificationCenter defaultCenter]
136         addObserver:self
137            selector:@selector(windowFocusDidChange:)
138                name:NSWindowDidBecomeMainNotification
139              object:window];
140     [[NSNotificationCenter defaultCenter]
141         addObserver:self
142            selector:@selector(windowFocusDidChange:)
143                name:NSWindowDidResignMainNotification
144              object:window];
145     // The new window for the view may have a different focus state than the
146     // last window this view was part of. Force a re-draw to ensure that the
147     // view draws the right state.
148     [self windowFocusDidChange:nil];
149   }
150   [super viewWillMoveToWindow:window];
151 }
152
153 - (void)setFrameOrigin:(NSPoint)origin {
154   // The background color depends on the view's vertical position. This impacts
155   // any child views that draw using this view's functions.
156   if (NSMinY([self frame]) != origin.y)
157     [self cr_recursivelySetNeedsDisplay:YES];
158
159   [super setFrameOrigin:origin];
160 }
161
162 @end