gpu: Tweak Android WebGL test expectations
[chromium-blink-merge.git] / ui / app_list / cocoa / app_list_view_controller.mm
blobe464721664235ada916d2c7c999ea7b45dc75f15
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_view_controller.h"
7 #include "base/mac/foundation_util.h"
8 #include "base/strings/string_util.h"
9 #include "skia/ext/skia_utils_mac.h"
10 #include "ui/app_list/app_list_constants.h"
11 #include "ui/app_list/app_list_model.h"
12 #include "ui/app_list/app_list_view_delegate.h"
13 #include "ui/app_list/signin_delegate.h"
14 #include "ui/app_list/signin_delegate_observer.h"
15 #import "ui/app_list/cocoa/app_list_pager_view.h"
16 #import "ui/app_list/cocoa/apps_grid_controller.h"
17 #import "ui/app_list/cocoa/signin_view_controller.h"
18 #import "ui/base/cocoa/flipped_view.h"
19 #include "ui/app_list/search_box_model.h"
20 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
22 namespace {
24 // The roundedness of the corners of the bubble.
25 const CGFloat kBubbleCornerRadius = 3;
27 // Height of the pager.
28 const CGFloat kPagerPreferredHeight = 57;
30 // Height of separator line drawn between the searchbox and grid view.
31 const CGFloat kTopSeparatorSize = 1;
33 // Height of the search input.
34 const CGFloat kSearchInputHeight = 48;
36 // Minimum margin on either side of the pager. If the pager grows beyond this,
37 // the segment size is reduced.
38 const CGFloat kMinPagerMargin = 40;
39 // Maximum width of a single segment.
40 const CGFloat kMaxSegmentWidth = 80;
42 // Duration of the animation for sliding in and out search results.
43 const NSTimeInterval kResultsAnimationDuration = 0.2;
45 }  // namespace
47 @interface BackgroundView : FlippedView;
48 @end
50 @implementation BackgroundView
52 - (void)drawRect:(NSRect)dirtyRect {
53   gfx::ScopedNSGraphicsContextSaveGState context;
54   NSRect boundsRect = [self bounds];
55   NSRect searchAreaRect = NSMakeRect(0, 0,
56                                      NSWidth(boundsRect), kSearchInputHeight);
57   NSRect separatorRect = NSMakeRect(0, NSMaxY(searchAreaRect),
58                                     NSWidth(boundsRect), kTopSeparatorSize);
60   [[NSBezierPath bezierPathWithRoundedRect:boundsRect
61                                    xRadius:kBubbleCornerRadius
62                                    yRadius:kBubbleCornerRadius] addClip];
64   [gfx::SkColorToSRGBNSColor(app_list::kContentsBackgroundColor) set];
65   NSRectFill(boundsRect);
66   [gfx::SkColorToSRGBNSColor(app_list::kSearchBoxBackground) set];
67   NSRectFill(searchAreaRect);
68   [gfx::SkColorToSRGBNSColor(app_list::kTopSeparatorColor) set];
69   NSRectFill(separatorRect);
72 @end
74 @interface AppListViewController ()
76 - (void)loadAndSetView;
77 - (void)revealSearchResults:(BOOL)show;
78 - (app_list::SigninDelegate*)signinDelegate;
80 @end
82 namespace app_list {
84 class SigninDelegateObserverBridge : public SigninDelegateObserver {
85  public:
86   SigninDelegateObserverBridge(AppListViewController* parent)
87       : parent_(parent) {
88     [parent_ signinDelegate]->AddObserver(this);
89   }
91   virtual ~SigninDelegateObserverBridge() {
92     [parent_ signinDelegate]->RemoveObserver(this);
93   }
95  private:
96   // SigninDelegateObserver override:
97   virtual void OnSigninSuccess() OVERRIDE {
98     [parent_ onSigninStatusChanged];
99   }
101   AppListViewController* parent_;  // Weak. Owns us.
103   DISALLOW_COPY_AND_ASSIGN(SigninDelegateObserverBridge);
106 }  // namespace app_list
108 @implementation AppListViewController
110 - (id)init {
111   if ((self = [super init])) {
112     appsGridController_.reset([[AppsGridController alloc] init]);
113     [self loadAndSetView];
115     [self totalPagesChanged];
116     [self selectedPageChanged:0];
117     [appsGridController_ setPaginationObserver:self];
118   }
119   return self;
122 - (void)dealloc {
123   // Ensure that setDelegate(NULL) has been called before destruction, because
124   // dealloc can be called at odd times, and Objective C destruction order does
125   // not properly tear down these dependencies.
126   DCHECK(delegate_ == NULL);
127   [appsGridController_ setPaginationObserver:nil];
128   [super dealloc];
131 - (AppsGridController*)appsGridController {
132   return appsGridController_;
135 - (NSSegmentedControl*)pagerControl {
136   return pagerControl_;
139 - (NSView*)backgroundView {
140   return backgroundView_;
143 - (app_list::AppListViewDelegate*)delegate {
144   return delegate_.get();
147 - (void)setDelegate:(scoped_ptr<app_list::AppListViewDelegate>)newDelegate
148       withTestModel:(scoped_ptr<app_list::AppListModel>)newModel {
149   if (delegate_) {
150     // First clean up, in reverse order.
151     signin_observer_bridge_.reset();
152     [appsSearchResultsController_ setDelegate:nil];
153     [appsSearchBoxController_ setDelegate:nil];
154   }
155   delegate_.reset(newDelegate.release());
156   [appsGridController_ setDelegate:delegate_.get()];
157   if (newModel.get())
158     [appsGridController_ setModel:newModel.Pass()];
159   [appsSearchBoxController_ setDelegate:self];
160   [appsSearchResultsController_ setDelegate:self];
161   [self onSigninStatusChanged];
164 - (void)setDelegate:(scoped_ptr<app_list::AppListViewDelegate>)newDelegate {
165   [self setDelegate:newDelegate.Pass()
166       withTestModel:scoped_ptr<app_list::AppListModel>()];
169 -(void)loadAndSetView {
170   pagerControl_.reset([[AppListPagerView alloc] init]);
171   [pagerControl_ setTarget:appsGridController_];
172   [pagerControl_ setAction:@selector(onPagerClicked:)];
174   NSRect gridFrame = [[appsGridController_ view] frame];
175   NSRect contentsRect = NSMakeRect(0, kSearchInputHeight + kTopSeparatorSize,
176       NSWidth(gridFrame), NSHeight(gridFrame) + kPagerPreferredHeight -
177           [AppsGridController scrollerPadding]);
179   contentsView_.reset([[FlippedView alloc] initWithFrame:contentsRect]);
180   backgroundView_.reset(
181       [[BackgroundView alloc] initWithFrame:
182               NSMakeRect(0, 0, NSMaxX(contentsRect), NSMaxY(contentsRect))]);
183   appsSearchBoxController_.reset(
184       [[AppsSearchBoxController alloc] initWithFrame:
185           NSMakeRect(0, 0, NSWidth(contentsRect), kSearchInputHeight)]);
186   appsSearchResultsController_.reset(
187       [[AppsSearchResultsController alloc] initWithAppsSearchResultsFrameSize:
188           [contentsView_ bounds].size]);
189   base::scoped_nsobject<NSView> containerView(
190       [[NSView alloc] initWithFrame:[backgroundView_ frame]]);
192   [contentsView_ addSubview:[appsGridController_ view]];
193   [contentsView_ addSubview:pagerControl_];
194   [backgroundView_ addSubview:contentsView_];
195   [backgroundView_ addSubview:[appsSearchResultsController_ view]];
196   [backgroundView_ addSubview:[appsSearchBoxController_ view]];
197   [containerView addSubview:backgroundView_];
198   [self setView:containerView];
201 - (void)revealSearchResults:(BOOL)show {
202   if (show == showingSearchResults_)
203     return;
205   showingSearchResults_ = show;
206   NSSize contentsSize = [contentsView_ frame].size;
207   NSRect resultsTargetRect = NSMakeRect(
208       0, kSearchInputHeight + kTopSeparatorSize,
209       contentsSize.width, contentsSize.height);
210   NSRect contentsTargetRect = resultsTargetRect;
212   // Shows results by sliding the grid and pager down to the bottom of the view.
213   // Hides results by collapsing the search results container to a height of 0.
214   if (show)
215     contentsTargetRect.origin.y += NSHeight(contentsTargetRect);
216   else
217     resultsTargetRect.size.height = 0;
219   [[NSAnimationContext currentContext] setDuration:kResultsAnimationDuration];
220   [[contentsView_ animator] setFrame:contentsTargetRect];
221   [[[appsSearchResultsController_ view] animator] setFrame:resultsTargetRect];
224 - (void)totalPagesChanged {
225   size_t pageCount = [appsGridController_ pageCount];
226   [pagerControl_ setSegmentCount:pageCount];
228   NSRect viewFrame = [[pagerControl_ superview] bounds];
229   CGFloat segmentWidth = std::min(
230       kMaxSegmentWidth,
231       (viewFrame.size.width - 2 * kMinPagerMargin) / pageCount);
233   for (size_t i = 0; i < pageCount; ++i) {
234     [pagerControl_ setWidth:segmentWidth
235                  forSegment:i];
236     [[pagerControl_ cell] setTag:i
237                       forSegment:i];
238   }
240   // Center in view.
241   [pagerControl_ sizeToFit];
242   [pagerControl_ setFrame:
243       NSMakeRect(NSMidX(viewFrame) - NSMidX([pagerControl_ bounds]),
244                  viewFrame.size.height - kPagerPreferredHeight,
245                  [pagerControl_ bounds].size.width,
246                  kPagerPreferredHeight)];
249 - (void)selectedPageChanged:(int)newSelected {
250   [pagerControl_ selectSegmentWithTag:newSelected];
253 - (void)pageVisibilityChanged {
254   [pagerControl_ setNeedsDisplay:YES];
257 - (NSInteger)pagerSegmentAtLocation:(NSPoint)locationInWindow {
258   return [pagerControl_ findAndHighlightSegmentAtLocation:locationInWindow];
261 - (app_list::SearchBoxModel*)searchBoxModel {
262   app_list::AppListModel* appListModel = [appsGridController_ model];
263   return appListModel ? appListModel->search_box() : NULL;
266 - (app_list::AppListViewDelegate*)appListDelegate {
267   return [self delegate];
270 - (BOOL)control:(NSControl*)control
271                textView:(NSTextView*)textView
272     doCommandBySelector:(SEL)command {
273   if (showingSearchResults_)
274     return [appsSearchResultsController_ handleCommandBySelector:command];
276   // If anything has been written, let the search view handle it.
277   if ([[control stringValue] length] > 0)
278     return NO;
280   // Handle escape.
281   if (command == @selector(complete:) ||
282       command == @selector(cancel:) ||
283       command == @selector(cancelOperation:)) {
284     if (delegate_)
285       delegate_->Dismiss();
286     return YES;
287   }
289   // Possibly handle grid navigation.
290   return [appsGridController_ handleCommandBySelector:command];
293 - (void)modelTextDidChange {
294   app_list::SearchBoxModel* searchBoxModel = [self searchBoxModel];
295   if (!searchBoxModel || !delegate_)
296     return;
298   base::string16 query;
299   TrimWhitespace(searchBoxModel->text(), TRIM_ALL, &query);
300   BOOL shouldShowSearch = !query.empty();
301   [self revealSearchResults:shouldShowSearch];
302   if (shouldShowSearch)
303     delegate_->StartSearch();
304   else
305     delegate_->StopSearch();
308 - (app_list::AppListModel*)appListModel {
309   return [appsGridController_ model];
312 - (void)openResult:(app_list::SearchResult*)result {
313   if (delegate_)
314     delegate_->OpenSearchResult(result, 0 /* event flags */);
316   [appsSearchBoxController_ clearSearch];
319 - (void)onSigninStatusChanged {
320   [appsSearchBoxController_ rebuildMenu];
321   app_list::SigninDelegate* signinDelegate = [self signinDelegate];
322   BOOL needsSignin = signinDelegate && signinDelegate->NeedSignin();
323   if (!needsSignin) {
324     [[signinViewController_ view] removeFromSuperview];
325     signin_observer_bridge_.reset();
326     signinViewController_.reset();
327     [backgroundView_ setHidden:NO];
328     return;
329   }
331   [backgroundView_ setHidden:YES];
332   signinViewController_.reset(
333       [[SigninViewController alloc] initWithFrame:[backgroundView_ frame]
334                                      cornerRadius:kBubbleCornerRadius
335                                          delegate:signinDelegate]);
336   signin_observer_bridge_.reset(
337       new app_list::SigninDelegateObserverBridge(self));
338   [[self view] addSubview:[signinViewController_ view]];
341 - (app_list::SigninDelegate*)signinDelegate {
342   return delegate_ ? delegate_->GetSigninDelegate() : NULL;
345 @end