blob: c96fc7ac906da2b58a907e0602683806fabe71da [file] [log] [blame]
// Copyright (c) 2012 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.
#include "chrome/browser/ui/cocoa/background_gradient_view.h"
#import "chrome/browser/themes/theme_properties.h"
#import "chrome/browser/themes/theme_service.h"
#import "chrome/browser/ui/cocoa/themed_window.h"
#include "chrome/grit/theme_resources.h"
#import "ui/base/cocoa/nsgraphics_context_additions.h"
#import "ui/base/cocoa/nsview_additions.h"
#include "ui/base/material_design/material_design_controller.h"
@implementation BackgroundGradientView
@synthesize showsDivider = showsDivider_;
@synthesize dividerEdge = dividerEdge_;
- (id)initWithFrame:(NSRect)frameRect {
if ((self = [super initWithFrame:frameRect])) {
[self commonInit];
return self;
- (id)initWithCoder:(NSCoder*)decoder {
if ((self = [super initWithCoder:decoder])) {
[self commonInit];
return self;
- (void)commonInit {
showsDivider_ = YES;
dividerEdge_ = NSMinYEdge;
- (void)setShowsDivider:(BOOL)show {
if (showsDivider_ == show)
showsDivider_ = show;
[self setNeedsDisplay:YES];
- (void)setDividerEdge:(NSRectEdge)dividerEdge {
if (dividerEdge_ == dividerEdge)
dividerEdge_ = dividerEdge;
[self setNeedsDisplay:YES];
- (NSPoint)patternPhase {
return [[self window]
- (void)drawBackground:(NSRect)dirtyRect {
[[NSGraphicsContext currentContext]
cr_setPatternPhase:[self patternPhase]
forView:[self cr_viewBeingDrawnTo]];
const ui::ThemeProvider* themeProvider = [[self window] themeProvider];
if (themeProvider && !themeProvider->UsingSystemTheme()) {
// If the background image is semi transparent then we need something
// to blend against. Using 20% black gives us a color similar to Windows.
[[NSColor colorWithCalibratedWhite:0.2 alpha:1.0] set];
[[self backgroundImageColor] set];
NSRectFillUsingOperation(dirtyRect, NSCompositeSourceOver);
if (showsDivider_) {
// Draw stroke
NSRect borderRect, contentRect;
NSDivideRect([self bounds], &borderRect, &contentRect, [self cr_lineWidth],
if (NSIntersectsRect(borderRect, dirtyRect)) {
[[self strokeColor] set];
NSRectFillUsingOperation(NSIntersectionRect(borderRect, dirtyRect),
- (NSColor*)strokeColor {
NSWindow* window = [self window];
// Some views have a child NSWindow between them and the window that is
// active (e.g, OmniboxPopupTopSeparatorView). For these, check the status
// of parentWindow instead. Note that this is not tracked correctly (but
// the views that do this appear to be removed when the window loses focus
// anyway).
if ([window parentWindow])
window = [window parentWindow];
const ui::ThemeProvider* themeProvider = [window themeProvider];
if (!themeProvider)
return [NSColor blackColor];
if (themeProvider->ShouldIncreaseContrast()) {
if ([window hasDarkTheme])
return [NSColor whiteColor];
return [NSColor blackColor];
return themeProvider->GetNSColor(
- (NSColor*)backgroundImageColor {
const ui::ThemeProvider* themeProvider = [[self window] themeProvider];
if (!themeProvider)
return [[self window] backgroundColor];
// Themes don't have an inactive image so only look for one if there's no
// theme.
BOOL isActive = [[self window] isMainWindow];
if (!isActive && themeProvider->UsingSystemTheme()) {
NSColor* color = themeProvider->GetNSImageColorNamed(
if (color)
return color;
return themeProvider->GetNSImageColorNamed(IDR_THEME_TOOLBAR);
- (void)viewDidMoveToWindow {
[super viewDidMoveToWindow];
if ([self window]) {
// The new window for the view may have a different focus state than the
// last window this view was part of.
// This happens when the view is moved into a TabWindowOverlayWindow for
// tab dragging.
[self windowDidChangeActive];
- (void)viewWillStartLiveResize {
[super viewWillStartLiveResize];
const ui::ThemeProvider* themeProvider = [[self window] themeProvider];
if (themeProvider && themeProvider->UsingSystemTheme()) {
// The default theme's background image is a subtle texture pattern that
// we can scale without being easily noticed. Optimize this case by
// skipping redraws during live resize.
[self setLayerContentsRedrawPolicy:
- (void)viewDidEndLiveResize {
[super viewDidEndLiveResize];
if ([self layerContentsRedrawPolicy] !=
NSViewLayerContentsRedrawDuringViewResize) {
// If we have been scaling the layer during live resize, now is the time to
// redraw the layer.
[self setLayerContentsRedrawPolicy:
[self setNeedsDisplay:YES];
- (void)setFrameOrigin:(NSPoint)origin {
// The background color depends on the view's vertical position. This impacts
// any child views that draw using this view's functions.
// When resizing the window, the view's vertical position (NSMinY) may change
// even though our relative position to the nearest window edge is still the
// same. Don't redraw unnecessarily in this case.
if (![self inLiveResize] && NSMinY([self frame]) != origin.y)
[self cr_recursivelySetNeedsDisplay:YES];
[super setFrameOrigin:origin];
// ThemedWindowDrawing implementation.
- (void)windowDidChangeTheme {
[self setNeedsDisplay:YES];
- (void)windowDidChangeActive {
[self setNeedsDisplay:YES];