Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / app_list / cocoa / app_list_pager_view.mm
blobabd4a4d28f5956e837a0ae498c0fa24e8ba7a122
1 // Copyright 2013 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.
5 #import "ui/app_list/cocoa/app_list_pager_view.h"
7 #include "base/mac/foundation_util.h"
8 #include "skia/ext/skia_utils_mac.h"
9 #include "ui/app_list/app_list_constants.h"
10 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
12 namespace {
14 const CGFloat kButtonHeight = 6;
15 const CGFloat kButtonCornerRadius = 2;
16 const CGFloat kButtonStripPadding = 20;
18 }  // namespace
20 @interface AppListPagerView ()
22 @property(assign, nonatomic) NSInteger hoveredSegment;
24 - (NSInteger)segmentUnderLocation:(NSPoint)locationInWindow;
26 @end
28 @interface AppListPagerCell : NSSegmentedCell;
29 @end
31 @implementation AppListPagerView
33 @synthesize hoveredSegment = hoveredSegment_;
35 + (Class)cellClass {
36   return [AppListPagerCell class];
39 - (id)init {
40   if ((self = [super initWithFrame:NSZeroRect])) {
41     trackingArea_.reset(
42         [[CrTrackingArea alloc] initWithRect:NSZeroRect
43                                      options:NSTrackingInVisibleRect |
44                                              NSTrackingMouseEnteredAndExited |
45                                              NSTrackingMouseMoved |
46                                              NSTrackingActiveInKeyWindow
47                                        owner:self
48                                     userInfo:nil]);
49     [self addTrackingArea:trackingArea_.get()];
50     hoveredSegment_ = -1;
51   }
52   return self;
55 - (NSInteger)findAndHighlightSegmentAtLocation:(NSPoint)locationInWindow {
56   NSInteger segment = [self segmentUnderLocation:locationInWindow];
57   [self setHoveredSegment:segment];
58   return segment;
61 - (void)setHoveredSegment:(NSInteger)segment {
62   if (segment == hoveredSegment_)
63     return;
65   hoveredSegment_ = segment;
66   [self setNeedsDisplay:YES];
67   return;
70 - (NSInteger)segmentUnderLocation:(NSPoint)locationInWindow {
71   if ([self segmentCount] == 0)
72     return -1;
74   NSPoint pointInView = [self convertPoint:locationInWindow
75                                   fromView:nil];
76   if (![self mouse:pointInView inRect:[self bounds]])
77     return -1;
79   CGFloat segmentWidth = [self bounds].size.width / [self segmentCount];
80   return pointInView.x / segmentWidth;
83 - (BOOL)isHoveredForSegment:(NSInteger)segment {
84   return segment == hoveredSegment_;
87 - (void)mouseExited:(NSEvent*)theEvent {
88   [self setHoveredSegment:-1];
91 - (void)mouseMoved:(NSEvent*)theEvent {
92   [self findAndHighlightSegmentAtLocation:[theEvent locationInWindow]];
95 - (void)mouseDown:(NSEvent*)theEvent {
96   // Temporarily clear the highlight to give feedback.
97   [self setHoveredSegment:-1];
100 // The stock NSSegmentedControl ignores any clicks outside the non-default
101 // control height, so process all clicks here.
102 - (void)mouseUp:(NSEvent*)theEvent {
103   [self findAndHighlightSegmentAtLocation:[theEvent locationInWindow]];
104   if (hoveredSegment_ < 0)
105     return;
107   [self setSelectedSegment:hoveredSegment_];
108   [[self target] performSelector:[self action]
109                       withObject:self];
112 @end
114 @implementation AppListPagerCell
116 - (void)drawWithFrame:(NSRect)cellFrame
117                inView:(NSView*)controlView {
118   // Draw nothing if there are less than two segments.
119   if ([self segmentCount] < 2)
120     return;
122   cellFrame.size.width /= [self segmentCount];
123   for (NSInteger i = 0; i < [self segmentCount]; ++i) {
124     [self drawSegment:i
125               inFrame:cellFrame
126              withView:controlView];
127     cellFrame.origin.x += cellFrame.size.width;
128   }
131 - (void)drawSegment:(NSInteger)segment
132             inFrame:(NSRect)frame
133            withView:(NSView*)controlView {
134   gfx::ScopedNSGraphicsContextSaveGState context;
135   NSRect clipRect = NSMakeRect(
136       frame.origin.x + kButtonStripPadding / 2,
137       floor(frame.origin.y + (frame.size.height - kButtonHeight) / 2),
138       frame.size.width - kButtonStripPadding,
139       kButtonHeight);
140   [[NSBezierPath bezierPathWithRoundedRect:clipRect
141                                    xRadius:kButtonCornerRadius
142                                    yRadius:kButtonCornerRadius] addClip];
144   AppListPagerView* pagerControl =
145       base::mac::ObjCCastStrict<AppListPagerView>(controlView);
146   SkColor backgroundColor = [pagerControl hoveredSegment] == segment ?
147       app_list::kPagerHoverColor :
148       app_list::kPagerNormalColor;
150   [gfx::SkColorToSRGBNSColor(backgroundColor) set];
151   NSRectFill(frame);
153   if (![[self target] conformsToProtocol:@protocol(AppListPagerDelegate)])
154     return;
156   CGFloat selectedRatio = [[self target] visiblePortionOfPage:segment];
157   if (selectedRatio == 0.0)
158     return;
160   [gfx::SkColorToSRGBNSColor(app_list::kPagerSelectedColor) set];
161   if (selectedRatio < 0)
162     frame.origin.x += frame.size.width + frame.size.width * selectedRatio;
163   frame.size.width *= fabs(selectedRatio);
164   NSRectFill(frame);
167 @end