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/mac_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"
14 const CGFloat kButtonHeight = 6;
15 const CGFloat kButtonCornerRadius = 2;
16 const CGFloat kButtonStripPadding = 20;
20 @interface AppListPagerView ()
22 @property(assign, nonatomic) NSInteger hoveredSegment;
24 - (NSInteger)segmentUnderLocation:(NSPoint)locationInWindow;
28 @interface AppListPagerCell : NSSegmentedCell;
31 @implementation AppListPagerView
33 @synthesize hoveredSegment = hoveredSegment_;
36 return [AppListPagerCell class];
40 if ((self = [super initWithFrame:NSZeroRect])) {
42 [[CrTrackingArea alloc] initWithRect:NSZeroRect
43 options:NSTrackingInVisibleRect |
44 NSTrackingMouseEnteredAndExited |
45 NSTrackingMouseMoved |
46 NSTrackingActiveInKeyWindow
49 [self addTrackingArea:trackingArea_.get()];
55 - (NSInteger)findAndHighlightSegmentAtLocation:(NSPoint)locationInWindow {
56 NSInteger segment = [self segmentUnderLocation:locationInWindow];
57 [self setHoveredSegment:segment];
61 - (void)setHoveredSegment:(NSInteger)segment {
62 if (segment == hoveredSegment_)
65 hoveredSegment_ = segment;
66 [self setNeedsDisplay:YES];
70 - (NSInteger)segmentUnderLocation:(NSPoint)locationInWindow {
71 if ([self segmentCount] == 0)
74 NSPoint pointInView = [self convertPoint:locationInWindow
76 if (![self mouse:pointInView inRect:[self bounds]])
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)
107 [self setSelectedSegment:hoveredSegment_];
108 [[self target] performSelector:[self action]
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)
122 cellFrame.size.width /= [self segmentCount];
123 for (NSInteger i = 0; i < [self segmentCount]; ++i) {
126 withView:controlView];
127 cellFrame.origin.x += cellFrame.size.width;
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,
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];
153 if (![[self target] conformsToProtocol:@protocol(AppListPagerDelegate)])
156 CGFloat selectedRatio = [[self target] visiblePortionOfPage:segment];
157 if (selectedRatio == 0.0)
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);