Home | History | Annotate | Download | only in infobars
      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/infobars/infobar_gradient_view.h"
      6 
      7 #include "base/mac/scoped_nsobject.h"
      8 #import "chrome/browser/themes/theme_properties.h"
      9 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
     10 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
     11 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
     12 #import "chrome/browser/ui/cocoa/nsview_additions.h"
     13 #import "chrome/browser/ui/cocoa/themed_window.h"
     14 #include "components/infobars/core/infobar.h"
     15 #include "skia/ext/skia_utils_mac.h"
     16 #include "ui/base/theme_provider.h"
     17 
     18 @implementation InfoBarGradientView
     19 
     20 @synthesize arrowHeight = arrowHeight_;
     21 @synthesize arrowHalfWidth = arrowHalfWidth_;
     22 @synthesize arrowX = arrowX_;
     23 @synthesize hasTip = hasTip_;
     24 
     25 - (id)initWithFrame:(NSRect)frame {
     26   if ((self = [super initWithFrame:frame])) {
     27     hasTip_ = YES;
     28   }
     29   return self;
     30 }
     31 
     32 - (id)initWithCoder:(NSCoder*)decoder {
     33   if ((self = [super initWithCoder:decoder])) {
     34     hasTip_ = YES;
     35   }
     36   return self;
     37 }
     38 
     39 - (void)setInfobarType:(infobars::InfoBarDelegate::Type)infobarType {
     40   SkColor topColor = infobars::InfoBar::GetTopColor(infobarType);
     41   SkColor bottomColor = infobars::InfoBar::GetBottomColor(infobarType);
     42   base::scoped_nsobject<NSGradient> gradient([[NSGradient alloc]
     43       initWithStartingColor:gfx::SkColorToCalibratedNSColor(topColor)
     44                 endingColor:gfx::SkColorToCalibratedNSColor(bottomColor)]);
     45   [self setGradient:gradient];
     46 }
     47 
     48 - (NSColor*)strokeColor {
     49   ui::ThemeProvider* themeProvider = [[self window] themeProvider];
     50   if (!themeProvider)
     51     return [NSColor blackColor];
     52 
     53   BOOL active = [[self window] isMainWindow];
     54   return themeProvider->GetNSColor(
     55       active ? ThemeProperties::COLOR_TOOLBAR_STROKE :
     56                ThemeProperties::COLOR_TOOLBAR_STROKE_INACTIVE);
     57 }
     58 
     59 - (void)drawRect:(NSRect)rect {
     60   NSRect bounds = [self bounds];
     61   bounds.size.height = infobars::InfoBar::kDefaultBarTargetHeight;
     62 
     63   CGFloat tipXOffset = arrowX_ - arrowHalfWidth_;
     64 
     65   // Around the bounds of the infobar, continue drawing the path into which the
     66   // gradient will be drawn.
     67   NSBezierPath* infoBarPath = [NSBezierPath bezierPath];
     68   [infoBarPath moveToPoint:NSMakePoint(NSMinX(bounds), NSMaxY(bounds))];
     69 
     70   // Draw the tip.
     71   if (hasTip_) {
     72     [infoBarPath lineToPoint:NSMakePoint(tipXOffset, NSMaxY(bounds))];
     73     [infoBarPath relativeLineToPoint:NSMakePoint(arrowHalfWidth_,
     74                                                  arrowHeight_)];
     75     [infoBarPath relativeLineToPoint:NSMakePoint(arrowHalfWidth_,
     76                                                  -arrowHeight_)];
     77   }
     78   [infoBarPath lineToPoint:NSMakePoint(NSMaxX(bounds), NSMaxY(bounds))];
     79 
     80   // Save off the top path of the infobar.
     81   base::scoped_nsobject<NSBezierPath> topPath([infoBarPath copy]);
     82 
     83   [infoBarPath lineToPoint:NSMakePoint(NSMaxX(bounds), NSMinY(bounds))];
     84   [infoBarPath lineToPoint:NSMakePoint(NSMinX(bounds), NSMinY(bounds))];
     85   [infoBarPath closePath];
     86 
     87   // Draw the gradient.
     88   [[self gradient] drawInBezierPath:infoBarPath angle:270];
     89 
     90   NSColor* strokeColor = [self strokeColor];
     91   if (strokeColor) {
     92     [strokeColor set];
     93 
     94     // Stroke the bottom of the infobar.
     95     NSRect borderRect, contentRect;
     96     NSDivideRect(bounds, &borderRect, &contentRect, 1, NSMinYEdge);
     97     NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
     98 
     99     // Re-stroke the top because the tip will have no stroke. This will draw
    100     // over the divider drawn by the bottom of the tabstrip.
    101     [topPath stroke];
    102   }
    103 
    104   // Add an inner stroke.
    105   const CGFloat kHighlightTipHeight = arrowHeight_ - 1;
    106   NSBezierPath* highlightPath = [NSBezierPath bezierPath];
    107   [highlightPath moveToPoint:NSMakePoint(NSMinX(bounds), NSMaxY(bounds) - 1)];
    108   if (hasTip_) {
    109     [highlightPath relativeLineToPoint:NSMakePoint(tipXOffset + 1, 0)];
    110     [highlightPath relativeLineToPoint:NSMakePoint(arrowHalfWidth_ - 1,
    111                                                    kHighlightTipHeight)];
    112     [highlightPath relativeLineToPoint:NSMakePoint(arrowHalfWidth_ - 1,
    113                                                    -kHighlightTipHeight)];
    114   }
    115   [highlightPath lineToPoint:NSMakePoint(NSMaxX(bounds), NSMaxY(bounds) - 1)];
    116 
    117   [[NSColor colorWithDeviceWhite:1.0 alpha:1.0] setStroke];
    118   [highlightPath stroke];
    119 }
    120 
    121 - (BOOL)mouseDownCanMoveWindow {
    122   return NO;
    123 }
    124 
    125 // This view is intentionally not opaque because it overlaps with the findbar.
    126 
    127 - (BOOL)accessibilityIsIgnored {
    128   return NO;
    129 }
    130 
    131 - (id)accessibilityAttributeValue:(NSString*)attribute {
    132   if ([attribute isEqual:NSAccessibilityRoleAttribute])
    133     return NSAccessibilityGroupRole;
    134 
    135   return [super accessibilityAttributeValue:attribute];
    136 }
    137 
    138 - (void)setHasTip:(BOOL)hasTip {
    139   if (hasTip_ == hasTip)
    140     return;
    141   hasTip_ = hasTip;
    142   [self setNeedsDisplay:YES];
    143 }
    144 
    145 @end
    146