summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/hover_close_button.mm
blob: 7620e9517d57d30f9b2aba00ec91a87bddc9c603 (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
// Copyright (c) 2010 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/hover_close_button.h"

#include "app/l10n_util.h"
#include "base/scoped_nsobject.h"
#include "grit/generated_resources.h"
#import "third_party/molokocacao/NSBezierPath+MCAdditions.h"

namespace  {
// Convenience function to return the middle point of the given |rect|.
static NSPoint MidRect(NSRect rect) {
  return NSMakePoint(NSMidX(rect), NSMidY(rect));
}

const CGFloat kCircleRadiusPercentage = 0.415;
const CGFloat kCircleHoverWhite = 0.565;
const CGFloat kCircleClickWhite = 0.396;
const CGFloat kXShadowAlpha = 0.75;
const CGFloat kXShadowCircleAlpha = 0.1;
}  // namespace

@interface HoverCloseButton(Private)
- (void)setUpDrawingPaths;
@end

@implementation HoverCloseButton

- (id)initWithFrame:(NSRect)frameRect {
  if ((self = [super initWithFrame:frameRect])) {
    [self commonInit];
  }
  return self;
}

- (void)awakeFromNib {
  [super awakeFromNib];
  [self commonInit];
}

- (void)drawRect:(NSRect)rect {
  if (!circlePath_.get() || !xPath_.get())
    [self setUpDrawingPaths];

  // If the user is hovering over the button, a light/dark gray circle is drawn
  // behind the 'x'.
  if (hoverState_ != kHoverStateNone) {
    // Adjust the darkness of the circle depending on whether it is being
    // clicked.
    CGFloat white = (hoverState_ == kHoverStateMouseOver) ?
        kCircleHoverWhite : kCircleClickWhite;
    [[NSColor colorWithCalibratedWhite:white alpha:1.0] set];
    [circlePath_ fill];
  }

  [[NSColor whiteColor] set];
  [xPath_ fill];

  // Give the 'x' an inner shadow for depth. If the button is in a hover state
  // (circle behind it), then adjust the shadow accordingly (not as harsh).
  NSShadow* shadow = [[[NSShadow alloc] init] autorelease];
  CGFloat alpha = (hoverState_ != kHoverStateNone) ?
      kXShadowCircleAlpha : kXShadowAlpha;
  [shadow setShadowColor:[NSColor colorWithCalibratedWhite:0.15
                                                     alpha:alpha]];
  [shadow setShadowOffset:NSMakeSize(0.0, 0.0)];
  [shadow setShadowBlurRadius:2.5];
  [xPath_ fillWithInnerShadow:shadow];
}

- (void)commonInit {
  // Set accessibility description.
  NSString* description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_CLOSE);
  [[self cell]
      accessibilitySetOverrideValue:description
                       forAttribute:NSAccessibilityDescriptionAttribute];
}

- (void)setUpDrawingPaths {
  NSPoint viewCenter = MidRect([self bounds]);

  circlePath_.reset([[NSBezierPath bezierPath] retain]);
  [circlePath_ moveToPoint:viewCenter];
  CGFloat radius = kCircleRadiusPercentage * NSWidth([self bounds]);
  [circlePath_ appendBezierPathWithArcWithCenter:viewCenter
                                          radius:radius
                                      startAngle:0.0
                                        endAngle:365.0];

  // Construct an 'x' by drawing two intersecting rectangles in the shape of a
  // cross and then rotating the path by 45 degrees.
  xPath_.reset([[NSBezierPath bezierPath] retain]);
  [xPath_ appendBezierPathWithRect:NSMakeRect(3.5, 7.0, 9.0, 2.0)];
  [xPath_ appendBezierPathWithRect:NSMakeRect(7.0, 3.5, 2.0, 9.0)];

  NSPoint pathCenter = MidRect([xPath_ bounds]);

  NSAffineTransform* transform = [NSAffineTransform transform];
  [transform translateXBy:viewCenter.x yBy:viewCenter.y];
  [transform rotateByDegrees:45.0];
  [transform translateXBy:-pathCenter.x yBy:-pathCenter.y];

  [xPath_ transformUsingAffineTransform:transform];
}

@end