summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/bookmark_bar_toolbar_view.mm
blob: f2c8494a0c359aea8ab4413aaa566c65645b2bf7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright (c) 2009 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/cocoa/bookmark_bar_toolbar_view.h"

#include "app/theme_provider.h"
#include "gfx/rect.h"
#import "chrome/browser/cocoa/bookmark_bar_constants.h"
#import "chrome/browser/cocoa/bookmark_bar_controller.h"
#import "chrome/browser/cocoa/browser_window_controller.h"
#import "chrome/browser/cocoa/themed_window.h"
#include "chrome/browser/ntp_background_util.h"
#include "chrome/browser/themes/browser_theme_provider.h"
#include "gfx/canvas_skia_paint.h"

const CGFloat kBorderRadius = 3.0;

@interface BookmarkBarToolbarView (Private)
- (void)drawRectAsBubble:(NSRect)rect;
@end

@implementation BookmarkBarToolbarView

- (BOOL)isOpaque {
  return [controller_ isInState:bookmarks::kDetachedState];
}

- (void)drawRect:(NSRect)rect {
  if ([controller_ isInState:bookmarks::kDetachedState] ||
      [controller_ isAnimatingToState:bookmarks::kDetachedState] ||
      [controller_ isAnimatingFromState:bookmarks::kDetachedState]) {
    [self drawRectAsBubble:rect];
  } else {
    NSPoint phase = [[self window] themePatternPhase];
    [[NSGraphicsContext currentContext] setPatternPhase:phase];
    [self drawBackground];
  }
}

- (void)drawRectAsBubble:(NSRect)rect {
  // The state of our morph; 1 is total bubble, 0 is the regular bar. We use it
  // to morph the bubble to a regular bar (shape and colour).
  CGFloat morph = [controller_ detachedMorphProgress];

  NSRect bounds = [self bounds];

  ThemeProvider* themeProvider = [controller_ themeProvider];
  if (!themeProvider)
    return;

  NSGraphicsContext* context = [NSGraphicsContext currentContext];
  [context saveGraphicsState];

  // Draw the background.
  {
    // CanvasSkiaPaint draws to the NSGraphicsContext during its destructor, so
    // explicitly scope this.
    //
    // Paint the entire bookmark bar, even if the damage rect is much smaller
    // because PaintBackgroundDetachedMode() assumes that area's origin is
    // (0, 0) and that its size is the size of the bookmark bar.
    //
    // In practice, this sounds worse than it is because redraw time is still
    // minimal compared to the pause between frames of animations. We were
    // already repainting the rest of the bookmark bar below without setting a
    // clip area, anyway. Also, the only time we weren't asked to redraw the
    // whole bookmark bar is when the find bar is drawn over it.
    gfx::CanvasSkiaPaint canvas(bounds, true);
    gfx::Rect area(0, 0, NSWidth(bounds), NSHeight(bounds));

    NtpBackgroundUtil::PaintBackgroundDetachedMode(themeProvider, &canvas,
        area, [controller_ currentTabContentsHeight]);
  }

  // Draw our bookmark bar border on top of the background.
  NSRect frameRect =
      NSMakeRect(
          morph * bookmarks::kNTPBookmarkBarPadding,
          morph * bookmarks::kNTPBookmarkBarPadding,
          NSWidth(bounds) - 2 * morph * bookmarks::kNTPBookmarkBarPadding,
          NSHeight(bounds) - 2 * morph * bookmarks::kNTPBookmarkBarPadding);
  // Now draw a bezier path with rounded rectangles around the area.
  frameRect = NSInsetRect(frameRect, morph * 0.5, morph * 0.5);
  NSBezierPath* border =
      [NSBezierPath bezierPathWithRoundedRect:frameRect
                                      xRadius:(morph * kBorderRadius)
                                      yRadius:(morph * kBorderRadius)];

  // Draw the rounded rectangle.
  NSColor* toolbarColor =
      themeProvider->GetNSColor(BrowserThemeProvider::COLOR_TOOLBAR, true);
  CGFloat alpha = morph * [toolbarColor alphaComponent];
  [[toolbarColor colorWithAlphaComponent:alpha] set];  // Set with opacity.
  [border fill];

  // Fade in/out the background.
  [context saveGraphicsState];
  [border setClip];
  CGContextRef cgContext = (CGContextRef)[context graphicsPort];
  CGContextBeginTransparencyLayer(cgContext, NULL);
  CGContextSetAlpha(cgContext, 1 - morph);
  [context setPatternPhase:[[self window] themePatternPhase]];
  [self drawBackground];
  CGContextEndTransparencyLayer(cgContext);
  [context restoreGraphicsState];

  // Draw the border of the rounded rectangle.
  NSColor* borderColor = themeProvider->GetNSColor(
      BrowserThemeProvider::COLOR_TOOLBAR_BUTTON_STROKE, true);
  alpha = morph * [borderColor alphaComponent];
  [[borderColor colorWithAlphaComponent:alpha] set];  // Set with opacity.
  [border stroke];

  // Fade in/out the divider.
  // TODO(viettrungluu): It's not obvious that this divider lines up exactly
  // with |BackgroundGradientView|'s (in fact, it probably doesn't).
  NSColor* strokeColor = [self strokeColor];
  alpha = (1 - morph) * [strokeColor alphaComponent];
  [[strokeColor colorWithAlphaComponent:alpha] set];
  NSBezierPath* divider = [NSBezierPath bezierPath];
  NSPoint dividerStart =
      NSMakePoint(morph * bookmarks::kNTPBookmarkBarPadding + morph * 0.5,
                  morph * bookmarks::kNTPBookmarkBarPadding + morph * 0.5);
  CGFloat dividerWidth =
      NSWidth(bounds) - 2 * morph * bookmarks::kNTPBookmarkBarPadding - 2 * 0.5;
  [divider moveToPoint:dividerStart];
  [divider relativeLineToPoint:NSMakePoint(dividerWidth, 0)];
  [divider stroke];

  // Restore the graphics context.
  [context restoreGraphicsState];
}

@end  // @implementation BookmarkBarToolbarView