app_list_view_controller.mm revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu// Copyright 2013 The Chromium Authors. All rights reserved. 2e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu// Use of this source code is governed by a BSD-style license that can be 3e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu// found in the LICENSE file. 4e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 5e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#import "ui/app_list/cocoa/app_list_view_controller.h" 6e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 7e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include "base/mac/foundation_util.h" 8e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include "base/strings/string_util.h" 9e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include "base/strings/sys_string_conversions.h" 10e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include "skia/ext/skia_utils_mac.h" 11e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include "ui/app_list/app_list_constants.h" 12e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include "ui/app_list/app_list_model.h" 13e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include "ui/app_list/app_list_model_observer.h" 14e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include "ui/app_list/app_list_view_delegate.h" 15e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include "ui/app_list/signin_delegate.h" 16e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#import "ui/app_list/cocoa/app_list_pager_view.h" 17e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#import "ui/app_list/cocoa/apps_grid_controller.h" 18e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#import "ui/app_list/cocoa/signin_view_controller.h" 19e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#import "ui/base/cocoa/flipped_view.h" 20e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include "ui/app_list/search_box_model.h" 21e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" 22e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 23e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugunamespace { 24e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 25e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu// The roundedness of the corners of the bubble. 26e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguconst CGFloat kBubbleCornerRadius = 3; 27e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 28e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu// Height of the pager. 29e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguconst CGFloat kPagerPreferredHeight = 57; 30e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 31e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu// Height of separator line drawn between the searchbox and grid view. 32e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguconst CGFloat kTopSeparatorSize = 1; 33e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 34e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu// Height of the search input. 35e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguconst CGFloat kSearchInputHeight = 48; 36e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 37e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu// Minimum margin on either side of the pager. If the pager grows beyond this, 38e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu// the segment size is reduced. 39e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguconst CGFloat kMinPagerMargin = 40; 40e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu// Maximum width of a single segment. 41e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguconst CGFloat kMaxSegmentWidth = 80; 42e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 43e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu// Duration of the animation for sliding in and out search results. 44e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguconst NSTimeInterval kResultsAnimationDuration = 0.2; 45e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 46e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} // namespace 47e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 48e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu@interface BackgroundView : FlippedView; 49e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu@end 50e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 51e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu@implementation BackgroundView 52e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 53e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (void)drawRect:(NSRect)dirtyRect { 54e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu gfx::ScopedNSGraphicsContextSaveGState context; 55e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSRect boundsRect = [self bounds]; 56e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSRect searchAreaRect = NSMakeRect(0, 0, 57e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSWidth(boundsRect), kSearchInputHeight); 58e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSRect separatorRect = NSMakeRect(0, NSMaxY(searchAreaRect), 59e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSWidth(boundsRect), kTopSeparatorSize); 60e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 61e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[NSBezierPath bezierPathWithRoundedRect:boundsRect 62e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu xRadius:kBubbleCornerRadius 63e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu yRadius:kBubbleCornerRadius] addClip]; 64e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 65e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [gfx::SkColorToSRGBNSColor(app_list::kContentsBackgroundColor) set]; 66e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSRectFill(boundsRect); 67e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [gfx::SkColorToSRGBNSColor(app_list::kSearchBoxBackground) set]; 68e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSRectFill(searchAreaRect); 69e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [gfx::SkColorToSRGBNSColor(app_list::kTopSeparatorColor) set]; 70e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSRectFill(separatorRect); 71e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 72e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 73e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu@end 74e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 75e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu@interface AppListViewController () 76e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 77e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (void)loadAndSetView; 78e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (void)revealSearchResults:(BOOL)show; 79e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 80e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu@end 81e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 82e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugunamespace app_list { 83e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 84e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguclass AppListModelObserverBridge : public AppListModelObserver { 85e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu public: 86e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu AppListModelObserverBridge(AppListViewController* parent); 87e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu virtual ~AppListModelObserverBridge(); 88e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 89e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu private: 90e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu // Overridden from app_list::AppListModelObserver: 91e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu virtual void OnAppListModelUsersChanged() OVERRIDE; 92e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu virtual void OnAppListModelSigninStatusChanged() OVERRIDE; 93e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 94e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu AppListViewController* parent_; // Weak. Owns us. 95e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 96e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu DISALLOW_COPY_AND_ASSIGN(AppListModelObserverBridge); 97e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu}; 98e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 99e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra ModaduguAppListModelObserverBridge::AppListModelObserverBridge( 100e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu AppListViewController* parent) 101e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu : parent_(parent) { 102e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[parent_ appsGridController] model]->AddObserver(this); 103e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 104e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 105e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra ModaduguAppListModelObserverBridge::~AppListModelObserverBridge() { 106e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[parent_ appsGridController] model]->RemoveObserver(this); 107e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 108e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 109e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguvoid AppListModelObserverBridge::OnAppListModelUsersChanged() { 110e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [parent_ onSigninStatusChanged]; 111e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 112e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 113e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguvoid AppListModelObserverBridge::OnAppListModelSigninStatusChanged() { 114e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [parent_ onSigninStatusChanged]; 115e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 116e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 117e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} // namespace app_list 118e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 119e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu@implementation AppListViewController 120e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 121e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (id)init { 122e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu if ((self = [super init])) { 123e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu appsGridController_.reset([[AppsGridController alloc] init]); 124e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [self loadAndSetView]; 125e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 126e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [self totalPagesChanged]; 127e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [self selectedPageChanged:0]; 128e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [appsGridController_ setPaginationObserver:self]; 129e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu } 130e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu return self; 131e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 132e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 133e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (void)dealloc { 134e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu // Ensure that setDelegate(NULL) has been called before destruction, because 135e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu // dealloc can be called at odd times, and Objective C destruction order does 136221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom // not properly tear down these dependencies. 137e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu DCHECK(delegate_ == NULL); 138e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [appsGridController_ setPaginationObserver:nil]; 139e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [super dealloc]; 140e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 141e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 142e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (AppsGridController*)appsGridController { 143e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu return appsGridController_; 144e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 145e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 146e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (NSSegmentedControl*)pagerControl { 147e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu return pagerControl_; 148e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 149e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 150e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (NSView*)backgroundView { 151e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu return backgroundView_; 152e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 153e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 154e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (app_list::AppListViewDelegate*)delegate { 155e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu return delegate_.get(); 156e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 157e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 158e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (void)setDelegate:(scoped_ptr<app_list::AppListViewDelegate>)newDelegate 159e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu withTestModel:(scoped_ptr<app_list::AppListModel>)newModel { 160e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu if (delegate_) { 161e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu // First clean up, in reverse order. 162e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu app_list_model_observer_bridge_.reset(); 163e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [appsSearchResultsController_ setDelegate:nil]; 164e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [appsSearchBoxController_ setDelegate:nil]; 165e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu } 166e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu delegate_.reset(newDelegate.release()); 167e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [appsGridController_ setDelegate:delegate_.get()]; 168e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu if (newModel.get()) 169e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [appsGridController_ setModel:newModel.Pass()]; 170e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [appsSearchBoxController_ setDelegate:self]; 171e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [appsSearchResultsController_ setDelegate:self]; 172e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu app_list_model_observer_bridge_.reset( 173e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu new app_list::AppListModelObserverBridge(self)); 174221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom [self onSigninStatusChanged]; 175e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 176e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 177e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (void)setDelegate:(scoped_ptr<app_list::AppListViewDelegate>)newDelegate { 178e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [self setDelegate:newDelegate.Pass() 179e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu withTestModel:scoped_ptr<app_list::AppListModel>()]; 180e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 181e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 182e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu-(void)loadAndSetView { 183e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu pagerControl_.reset([[AppListPagerView alloc] init]); 184e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [pagerControl_ setTarget:appsGridController_]; 185e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [pagerControl_ setAction:@selector(onPagerClicked:)]; 186e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 187e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSRect gridFrame = [[appsGridController_ view] frame]; 188e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSRect contentsRect = NSMakeRect(0, kSearchInputHeight + kTopSeparatorSize, 189e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSWidth(gridFrame), NSHeight(gridFrame) + kPagerPreferredHeight - 190e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [AppsGridController scrollerPadding]); 191e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 192e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu contentsView_.reset([[FlippedView alloc] initWithFrame:contentsRect]); 193e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu backgroundView_.reset( 194e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[BackgroundView alloc] initWithFrame: 195e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSMakeRect(0, 0, NSMaxX(contentsRect), NSMaxY(contentsRect))]); 196e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu appsSearchBoxController_.reset( 197e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[AppsSearchBoxController alloc] initWithFrame: 198e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSMakeRect(0, 0, NSWidth(contentsRect), kSearchInputHeight)]); 199e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu appsSearchResultsController_.reset( 200e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[AppsSearchResultsController alloc] initWithAppsSearchResultsFrameSize: 201e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [contentsView_ bounds].size]); 202e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu base::scoped_nsobject<NSView> containerView( 203e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[NSView alloc] initWithFrame:[backgroundView_ frame]]); 204e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 205e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [contentsView_ addSubview:[appsGridController_ view]]; 206e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [contentsView_ addSubview:pagerControl_]; 207e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [backgroundView_ addSubview:contentsView_]; 208e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [backgroundView_ addSubview:[appsSearchResultsController_ view]]; 209e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [backgroundView_ addSubview:[appsSearchBoxController_ view]]; 210e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [containerView addSubview:backgroundView_]; 211e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [self setView:containerView]; 212e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 213e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 214e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (void)revealSearchResults:(BOOL)show { 215e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu if (show == showingSearchResults_) 216e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu return; 217e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 218e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu showingSearchResults_ = show; 219e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSSize contentsSize = [contentsView_ frame].size; 220e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSRect resultsTargetRect = NSMakeRect( 221e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 0, kSearchInputHeight + kTopSeparatorSize, 222e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu contentsSize.width, contentsSize.height); 223e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSRect contentsTargetRect = resultsTargetRect; 224e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 225e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu // Shows results by sliding the grid and pager down to the bottom of the view. 226e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu // Hides results by collapsing the search results container to a height of 0. 227e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu if (show) 228e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu contentsTargetRect.origin.y += NSHeight(contentsTargetRect); 229e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu else 230e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu resultsTargetRect.size.height = 0; 231e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 232e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[NSAnimationContext currentContext] setDuration:kResultsAnimationDuration]; 233e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[contentsView_ animator] setFrame:contentsTargetRect]; 234e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[[appsSearchResultsController_ view] animator] setFrame:resultsTargetRect]; 235e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 236e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 237e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (void)totalPagesChanged { 238e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu size_t pageCount = [appsGridController_ pageCount]; 239e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [pagerControl_ setSegmentCount:pageCount]; 240e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 241e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSRect viewFrame = [[pagerControl_ superview] bounds]; 242e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu CGFloat segmentWidth = std::min( 243e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu kMaxSegmentWidth, 244e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu (viewFrame.size.width - 2 * kMinPagerMargin) / pageCount); 245e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 246e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu for (size_t i = 0; i < pageCount; ++i) { 247e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [pagerControl_ setWidth:segmentWidth 248e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu forSegment:i]; 249e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[pagerControl_ cell] setTag:i 250e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu forSegment:i]; 251e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu } 252e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 253e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu // Center in view. 254e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [pagerControl_ sizeToFit]; 255e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [pagerControl_ setFrame: 256e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu NSMakeRect(NSMidX(viewFrame) - NSMidX([pagerControl_ bounds]), 257e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu viewFrame.size.height - kPagerPreferredHeight, 258e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [pagerControl_ bounds].size.width, 259e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu kPagerPreferredHeight)]; 260e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 261e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 262e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (void)selectedPageChanged:(int)newSelected { 263e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [pagerControl_ selectSegmentWithTag:newSelected]; 264e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 265e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 266e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (void)pageVisibilityChanged { 267e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [pagerControl_ setNeedsDisplay:YES]; 268e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 269e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 270e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (NSInteger)pagerSegmentAtLocation:(NSPoint)locationInWindow { 271e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu return [pagerControl_ findAndHighlightSegmentAtLocation:locationInWindow]; 272e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 273e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 274e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (app_list::SearchBoxModel*)searchBoxModel { 275e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu app_list::AppListModel* appListModel = [appsGridController_ model]; 276e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu return appListModel ? appListModel->search_box() : NULL; 277e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 278e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 279e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (app_list::AppListViewDelegate*)appListDelegate { 280e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu return [self delegate]; 281e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 282e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 283e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (BOOL)control:(NSControl*)control 284e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu textView:(NSTextView*)textView 285976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom doCommandBySelector:(SEL)command { 286976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom if (showingSearchResults_) 287976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom return [appsSearchResultsController_ handleCommandBySelector:command]; 288976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom 289976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom // If anything has been written, let the search view handle it. 290976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom if ([[control stringValue] length] > 0) 291976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom return NO; 292976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom 293976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom // Handle escape. 294976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom if (command == @selector(complete:) || 295976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom command == @selector(cancel:) || 296976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom command == @selector(cancelOperation:)) { 297976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom if (delegate_) 298976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom delegate_->Dismiss(); 299976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom return YES; 300976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom } 301976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom 302e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu // Possibly handle grid navigation. 303e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu return [appsGridController_ handleCommandBySelector:command]; 304976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom} 305976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom 306976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom- (void)modelTextDidChange { 307976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom app_list::SearchBoxModel* searchBoxModel = [self searchBoxModel]; 308976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom if (!searchBoxModel || !delegate_) 309976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom return; 310976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom 311976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom base::string16 query; 312976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom TrimWhitespace(searchBoxModel->text(), TRIM_ALL, &query); 313976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom BOOL shouldShowSearch = !query.empty(); 314976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom [self revealSearchResults:shouldShowSearch]; 315976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom if (shouldShowSearch) 316e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu delegate_->StartSearch(); 317e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu else 318e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu delegate_->StopSearch(); 319e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 320e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 321e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (app_list::AppListModel*)appListModel { 322e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu return [appsGridController_ model]; 323e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 324e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 325e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (void)openResult:(app_list::SearchResult*)result { 326e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu if (delegate_) 327e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu delegate_->OpenSearchResult(result, 0 /* event flags */); 328e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 329e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [appsSearchBoxController_ clearSearch]; 330e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 331e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 332e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (void)redoSearch { 333e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [self modelTextDidChange]; 334e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 335e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 336e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu- (void)onSigninStatusChanged { 337e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [appsSearchBoxController_ rebuildMenu]; 338e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu app_list::SigninDelegate* signinDelegate = 339e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu delegate_ ? delegate_->GetSigninDelegate() : NULL; 340e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu BOOL show_signin_view = 341e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu signinDelegate && ![appsGridController_ model]->signed_in(); 342e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 343e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[signinViewController_ view] removeFromSuperview]; 344e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu signinViewController_.reset(); 345e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 346e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu if (!show_signin_view) { 347e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [backgroundView_ setHidden:NO]; 348e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu return; 349e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu } 350e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 351e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [backgroundView_ setHidden:YES]; 352e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu signinViewController_.reset( 353e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[SigninViewController alloc] initWithFrame:[backgroundView_ frame] 354e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu cornerRadius:kBubbleCornerRadius 355e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu delegate:signinDelegate]); 356e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu [[self view] addSubview:[signinViewController_ view]]; 357e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu} 358e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu 359e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu@end 360e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu