Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: ui/app_list/cocoa/app_list_view_controller.mm

Issue 2131463002: Purge the App Launcher code from Mac (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Zap mac-specific icon assets Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #import "ui/app_list/cocoa/app_list_view_controller.h"
6
7 #include <stddef.h>
8
9 #include "base/mac/foundation_util.h"
10 #include "base/mac/mac_util.h"
11 #include "base/macros.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/sys_string_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "skia/ext/skia_utils_mac.h"
16 #include "ui/app_list/app_list_constants.h"
17 #include "ui/app_list/app_list_model.h"
18 #include "ui/app_list/app_list_view_delegate.h"
19 #include "ui/app_list/app_list_view_delegate_observer.h"
20 #import "ui/app_list/cocoa/app_list_pager_view.h"
21 #import "ui/app_list/cocoa/apps_grid_controller.h"
22 #include "ui/app_list/search_box_model.h"
23 #import "ui/base/cocoa/flipped_view.h"
24 #import "ui/gfx/image/image_skia_util_mac.h"
25 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
26
27 namespace {
28
29 // The roundedness of the corners of the bubble.
30 const CGFloat kBubbleCornerRadius = 3;
31
32 // Height of the pager.
33 const CGFloat kPagerPreferredHeight = 57;
34
35 // Height of separator line drawn between the searchbox and grid view.
36 const CGFloat kTopSeparatorSize = 1;
37
38 // Height of the search input.
39 const CGFloat kSearchInputHeight = 48;
40
41 // Minimum margin on either side of the pager. If the pager grows beyond this,
42 // the segment size is reduced.
43 const CGFloat kMinPagerMargin = 40;
44 // Maximum width of a single segment.
45 const CGFloat kMaxSegmentWidth = 80;
46
47 // Duration of the animation for sliding in and out search results.
48 const NSTimeInterval kResultsAnimationDuration = 0.2;
49
50 // Properties of the message rectangle, if it is shown.
51 const NSRect kMessageRect = {{12, 12}, {370, 91}};
52 const CGFloat kMessageCornerRadius = 2;
53 const CGFloat kSpacingBelowMessageTitle = 6;
54 const SkColor kMessageBackgroundColor = SkColorSetRGB(0xFF, 0xFD, 0xE7);
55 const SkColor kMessageStrokeColor = SkColorSetARGB(0x3d, 0x00, 0x00, 0x00);
56 // The inset should be 16px, but NSTextView has its own inset of 3.
57 const CGFloat kMessageTextInset = 13;
58
59 } // namespace
60
61 @interface BackgroundView : FlippedView;
62 @end
63
64 @implementation BackgroundView
65
66 - (void)drawRect:(NSRect)dirtyRect {
67 gfx::ScopedNSGraphicsContextSaveGState context;
68 NSRect boundsRect = [self bounds];
69 NSRect searchAreaRect = NSMakeRect(0, 0,
70 NSWidth(boundsRect), kSearchInputHeight);
71 NSRect separatorRect = NSMakeRect(0, NSMaxY(searchAreaRect),
72 NSWidth(boundsRect), kTopSeparatorSize);
73
74 [[NSBezierPath bezierPathWithRoundedRect:boundsRect
75 xRadius:kBubbleCornerRadius
76 yRadius:kBubbleCornerRadius] addClip];
77
78 [skia::SkColorToSRGBNSColor(app_list::kContentsBackgroundColor) set];
79 NSRectFill(boundsRect);
80 [skia::SkColorToSRGBNSColor(app_list::kSearchBoxBackground) set];
81 NSRectFill(searchAreaRect);
82 [skia::SkColorToSRGBNSColor(app_list::kTopSeparatorColor) set];
83 NSRectFill(separatorRect);
84 }
85
86 @end
87
88 @interface MessageBackgroundView : FlippedView
89 @end
90
91 @implementation MessageBackgroundView
92
93 - (void)drawRect:(NSRect)dirtyRect {
94 NSRect boundsRect = [self bounds];
95 gfx::ScopedNSGraphicsContextSaveGState context;
96 [[NSBezierPath bezierPathWithRoundedRect:boundsRect
97 xRadius:kMessageCornerRadius
98 yRadius:kMessageCornerRadius] addClip];
99
100 [skia::SkColorToSRGBNSColor(kMessageStrokeColor) set];
101 NSRectFill(boundsRect);
102
103 [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(boundsRect, 1, 1)
104 xRadius:kMessageCornerRadius
105 yRadius:kMessageCornerRadius] addClip];
106 [skia::SkColorToSRGBNSColor(kMessageBackgroundColor) set];
107 NSRectFill(boundsRect);
108 }
109
110 @end
111
112 @interface AppListViewController ()
113
114 - (void)updateMessage;
115 - (void)loadAndSetView;
116 - (void)revealSearchResults:(BOOL)show;
117
118 @end
119
120 namespace app_list {
121
122 class AppListModelObserverBridge : public AppListViewDelegateObserver {
123 public:
124 AppListModelObserverBridge(AppListViewController* parent);
125 ~AppListModelObserverBridge() override;
126
127 private:
128 // Overridden from app_list::AppListViewDelegateObserver:
129 void OnProfilesChanged() override;
130 void OnShutdown() override;
131
132 AppListViewController* parent_; // Weak. Owns us.
133
134 DISALLOW_COPY_AND_ASSIGN(AppListModelObserverBridge);
135 };
136
137 AppListModelObserverBridge::AppListModelObserverBridge(
138 AppListViewController* parent)
139 : parent_(parent) {
140 [parent_ delegate]->AddObserver(this);
141 }
142
143 AppListModelObserverBridge::~AppListModelObserverBridge() {
144 [parent_ delegate]->RemoveObserver(this);
145 }
146
147 void AppListModelObserverBridge::OnProfilesChanged() {
148 [parent_ onProfilesChanged];
149 }
150
151 void AppListModelObserverBridge::OnShutdown() {
152 [parent_ setDelegate:nil];
153 }
154
155 } // namespace app_list
156
157 @implementation AppListViewController
158
159 - (id)init {
160 if ((self = [super init])) {
161 appsGridController_.reset([[AppsGridController alloc] init]);
162 [self loadAndSetView];
163
164 [self totalPagesChanged];
165 [self selectedPageChanged:0];
166 [appsGridController_ setPaginationObserver:self];
167 }
168 return self;
169 }
170
171 - (void)dealloc {
172 // Ensure that setDelegate(NULL) has been called before destruction, because
173 // dealloc can be called at odd times, and Objective C destruction order does
174 // not properly tear down these dependencies.
175 DCHECK(delegate_ == NULL);
176 [appsGridController_ setPaginationObserver:nil];
177 [super dealloc];
178 }
179
180 - (AppsSearchBoxController*)searchBoxController {
181 return appsSearchBoxController_;
182 }
183
184 - (BOOL)showingSearchResults {
185 return showingSearchResults_;
186 }
187
188 - (AppsGridController*)appsGridController {
189 return appsGridController_;
190 }
191
192 - (NSSegmentedControl*)pagerControl {
193 return pagerControl_;
194 }
195
196 - (NSView*)backgroundView {
197 return backgroundView_;
198 }
199
200 - (app_list::AppListViewDelegate*)delegate {
201 return delegate_;
202 }
203
204 - (void)setDelegate:(app_list::AppListViewDelegate*)newDelegate {
205 if (delegate_) {
206 // Ensure the search box is cleared when switching profiles.
207 if ([self searchBoxModel])
208 [self searchBoxModel]->SetText(base::string16());
209
210 // First clean up, in reverse order.
211 app_list_model_observer_bridge_.reset();
212 [appsSearchResultsController_ setDelegate:nil];
213 [appsSearchBoxController_ setDelegate:nil];
214 [appsGridController_ setDelegate:nil];
215 [messageText_ setDelegate:nil];
216 }
217 delegate_ = newDelegate;
218 if (delegate_) {
219 [loadingIndicator_ stopAnimation:self];
220 } else {
221 [loadingIndicator_ startAnimation:self];
222 return;
223 }
224
225 [appsGridController_ setDelegate:delegate_];
226 [appsSearchBoxController_ setDelegate:self];
227 [appsSearchResultsController_ setDelegate:self];
228 app_list_model_observer_bridge_.reset(
229 new app_list::AppListModelObserverBridge(self));
230 [self onProfilesChanged];
231 [self updateMessage];
232 }
233
234 - (void)updateMessage {
235 if (![AppsGridController hasFewerRows])
236 return;
237
238 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
239 NSFont* messageFont = rb.GetFontWithDelta(0).GetNativeFont();
240 NSFont* titleFont = rb.GetFontWithDelta(2).GetNativeFont();
241
242 base::string16 title = delegate_->GetMessageTitle();
243 size_t messageBreak;
244 base::string16 messageFull = delegate_->GetMessageText(&messageBreak);
245 base::string16 shortcutName = delegate_->GetAppsShortcutName();
246 base::string16 learnMore = delegate_->GetLearnMoreText();
247 base::string16 learnMoreUrl = delegate_->GetLearnMoreLink();
248
249 base::string16 messagePre = messageFull.substr(0, messageBreak);
250 base::string16 messagePost = messageFull.substr(messageBreak);
251
252 NSURL* linkURL = [NSURL URLWithString:base::SysUTF16ToNSString(learnMoreUrl)];
253 gfx::ImageSkia* icon = delegate_->GetAppsIcon();
254
255 // Shift the baseline up so that the graphics align centered. 4 looks nice. It
256 // happens to be the image size minus the font size, but that's a coincidence.
257 const CGFloat kBaselineShift = 4;
258 base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
259 [[NSMutableParagraphStyle alloc] init]);
260 [paragraphStyle setLineSpacing:kSpacingBelowMessageTitle + kBaselineShift];
261
262 NSNumber* baselineOffset = [NSNumber numberWithFloat:kBaselineShift];
263 base::scoped_nsobject<NSMutableAttributedString> text(
264 [[NSMutableAttributedString alloc]
265 initWithString:base::SysUTF16ToNSString(title)
266 attributes:@{
267 NSParagraphStyleAttributeName : paragraphStyle,
268 NSFontAttributeName : titleFont
269 }]);
270
271 NSDictionary* defaultAttributes = @{
272 NSFontAttributeName : messageFont,
273 NSBaselineOffsetAttributeName : baselineOffset
274 };
275
276 base::scoped_nsobject<NSAttributedString> lineBreak(
277 [[NSAttributedString alloc] initWithString:@"\n"
278 attributes:defaultAttributes]);
279 base::scoped_nsobject<NSAttributedString> space([[NSAttributedString alloc]
280 initWithString:@" "
281 attributes:defaultAttributes]);
282 base::scoped_nsobject<NSAttributedString> messagePreString(
283 [[NSAttributedString alloc]
284 initWithString:base::SysUTF16ToNSString(messagePre)
285 attributes:defaultAttributes]);
286 base::scoped_nsobject<NSAttributedString> messagePostString(
287 [[NSAttributedString alloc]
288 initWithString:base::SysUTF16ToNSString(messagePost)
289 attributes:defaultAttributes]);
290
291 // NSUnderlineStyleNone is broken.
292 base::scoped_nsobject<NSAttributedString> learnMoreString(
293 [[NSAttributedString alloc]
294 initWithString:base::SysUTF16ToNSString(learnMore)
295 attributes:@{
296 NSParagraphStyleAttributeName : paragraphStyle,
297 NSFontAttributeName : messageFont,
298 NSLinkAttributeName : linkURL,
299 NSBaselineOffsetAttributeName : baselineOffset,
300 NSUnderlineStyleAttributeName :
301 [NSNumber numberWithInt:NSUnderlineStyleNone]
302 }]);
303 base::scoped_nsobject<NSAttributedString> shortcutStringText(
304 [[NSAttributedString alloc]
305 initWithString:base::SysUTF16ToNSString(shortcutName)
306 attributes:defaultAttributes]);
307 base::scoped_nsobject<NSMutableAttributedString> shortcutString(
308 [[NSMutableAttributedString alloc] init]);
309 if (icon) {
310 NSImage* image = gfx::NSImageFromImageSkia(*icon);
311 // The image has a bunch of representations. Ensure the smallest is used.
312 // (Going smaller would make pixels all manky, so don't do that).
313 [image setSize:NSMakeSize(16, 16)];
314
315 base::scoped_nsobject<NSTextAttachmentCell> attachmentCell(
316 [[NSTextAttachmentCell alloc] initImageCell:image]);
317 base::scoped_nsobject<NSTextAttachment> attachment(
318 [[NSTextAttachment alloc] init]);
319 [attachment setAttachmentCell:attachmentCell];
320 [shortcutString
321 appendAttributedString:[NSAttributedString
322 attributedStringWithAttachment:attachment]];
323 [shortcutString appendAttributedString:space];
324 }
325 [shortcutString appendAttributedString:shortcutStringText];
326
327 [text appendAttributedString:lineBreak];
328 [text appendAttributedString:messagePreString];
329 [text appendAttributedString:shortcutString];
330 [text appendAttributedString:messagePostString];
331 [text appendAttributedString:space];
332 [text appendAttributedString:learnMoreString];
333
334 [[messageText_ textStorage] setAttributedString:text];
335 [messageText_ sizeToFit];
336
337 // If the user scroller preference is to always show scrollbars, and the
338 // translated message is long, the scroll track may be present. This means
339 // text will be under the scroller. We only want vertical scrolling, but
340 // reducing the width puts the scroll track in a weird spot. So, increase the
341 // width of the scroll view to move the track into the padding towards the
342 // message background border, then reduce the width of the text view. The
343 // non-overlay scroller still looks kinda weird but hopefully not many will
344 // actually see it.
345 CGFloat overlap =
346 NSWidth([messageText_ bounds]) - [messageScrollView_ contentSize].width;
347 if (overlap > 0) {
348 NSRect rect = [messageScrollView_ frame];
349 rect.size.width += kMessageTextInset - 2;
350 [messageScrollView_ setFrame:rect];
351 overlap -= kMessageTextInset - 2;
352 DCHECK_GT(overlap, 0);
353 rect = [messageText_ frame];
354 rect.size.width -= overlap;
355 [messageText_ setFrame:rect];
356 [messageText_ sizeToFit];
357
358 // And after doing all that for some reason Cocoa scrolls to the bottom. So
359 // fix that.
360 [[messageScrollView_ documentView] scrollPoint:NSMakePoint(0, 0)];
361 }
362
363 [messageText_ setDelegate:self];
364 }
365
366 - (void)loadAndSetView {
367 pagerControl_.reset([[AppListPagerView alloc] init]);
368 [pagerControl_ setTarget:appsGridController_];
369 [pagerControl_ setAction:@selector(onPagerClicked:)];
370
371 NSRect gridFrame = [[appsGridController_ view] frame];
372
373 base::scoped_nsobject<NSView> messageTextBackground;
374 if ([AppsGridController hasFewerRows]) {
375 messageTextBackground.reset(
376 [[MessageBackgroundView alloc] initWithFrame:kMessageRect]);
377 NSRect frameRect =
378 NSInsetRect(kMessageRect, kMessageTextInset, kMessageTextInset);
379 messageText_.reset([[NSTextView alloc] initWithFrame:frameRect]);
380 // Provide a solid background here (as well as the background) so that
381 // subpixel AA works.
382 [messageText_
383 setBackgroundColor:skia::SkColorToSRGBNSColor(kMessageBackgroundColor)];
384 [messageText_ setDrawsBackground:YES];
385 [messageText_ setEditable:NO];
386 // Ideally setSelectable:NO would also be set here, but that disables mouse
387 // events completely, breaking the "Learn more" link. Instead, selection is
388 // "disabled" via a delegate method which Apple's documentation suggests. In
389 // reality, selection still happens, it just disappears once the mouse is
390 // released. To avoid the selection appearing, also set selected text to
391 // have no special attributes. Sadly, the mouse cursor still displays an
392 // I-beam, but hacking cursor rectangles on the view so that the "Learn
393 // More" link is still correctly handled is too hard.
394 [messageText_ setSelectedTextAttributes:@{}];
395 gridFrame.origin.y += NSMaxY([messageTextBackground frame]);
396 }
397
398 [[appsGridController_ view] setFrame:gridFrame];
399
400 NSRect contentsRect =
401 NSMakeRect(0, kSearchInputHeight + kTopSeparatorSize, NSWidth(gridFrame),
402 NSMaxY(gridFrame) + kPagerPreferredHeight -
403 [AppsGridController scrollerPadding]);
404
405 contentsView_.reset([[FlippedView alloc] initWithFrame:contentsRect]);
406
407 // The contents view contains animations both from an NSCollectionView and the
408 // app list's own transitive drag layers. On Mavericks, the subviews need to
409 // have access to a compositing layer they can share. Otherwise the compositor
410 // makes tearing artifacts. However, doing this on Mountain Lion or earler
411 // results in flickering whilst an item is installing.
412 if (base::mac::IsOSMavericksOrLater())
413 [contentsView_ setWantsLayer:YES];
414
415 backgroundView_.reset(
416 [[BackgroundView alloc] initWithFrame:
417 NSMakeRect(0, 0, NSMaxX(contentsRect), NSMaxY(contentsRect))]);
418 appsSearchBoxController_.reset(
419 [[AppsSearchBoxController alloc] initWithFrame:
420 NSMakeRect(0, 0, NSWidth(contentsRect), kSearchInputHeight)]);
421 appsSearchResultsController_.reset(
422 [[AppsSearchResultsController alloc] initWithAppsSearchResultsFrameSize:
423 [contentsView_ bounds].size]);
424 base::scoped_nsobject<NSView> containerView(
425 [[NSView alloc] initWithFrame:[backgroundView_ frame]]);
426
427 loadingIndicator_.reset(
428 [[NSProgressIndicator alloc] initWithFrame:NSZeroRect]);
429 [loadingIndicator_ setStyle:NSProgressIndicatorSpinningStyle];
430 [loadingIndicator_ sizeToFit];
431 NSRect indicatorRect = [loadingIndicator_ frame];
432 indicatorRect.origin.x = NSWidth(contentsRect) / 2 - NSMidX(indicatorRect);
433 indicatorRect.origin.y = NSHeight(contentsRect) / 2 - NSMidY(indicatorRect);
434 [loadingIndicator_ setFrame:indicatorRect];
435 [loadingIndicator_ setDisplayedWhenStopped:NO];
436 [loadingIndicator_ startAnimation:self];
437
438 if (messageText_) {
439 [contentsView_ addSubview:messageTextBackground];
440
441 // Add a scroll view in case the translation is long and doesn't fit. Mac
442 // likes to hide scrollbars, so add to the height so the user can see part
443 // of the next line of text: just extend out into the padding towards the
444 // text background's border. Subtract at least 2: one for the border stroke
445 // and one for a bit of padding.
446 NSRect frameRect = [messageText_ frame];
447 frameRect.size.height += kMessageTextInset - 2;
448 messageScrollView_.reset([[NSScrollView alloc] initWithFrame:frameRect]);
449 [messageScrollView_ setHasVerticalScroller:YES];
450 [messageScrollView_ setAutohidesScrollers:YES];
451
452 // Now the message is going into an NSScrollView, origin should be 0, 0.
453 frameRect = [messageText_ frame];
454 frameRect.origin = NSMakePoint(0, 0);
455 [messageText_ setFrame:frameRect];
456
457 [messageScrollView_ setDocumentView:messageText_];
458 [contentsView_ addSubview:messageScrollView_];
459 }
460 [contentsView_ addSubview:[appsGridController_ view]];
461 [contentsView_ addSubview:pagerControl_];
462 [contentsView_ addSubview:loadingIndicator_];
463 [backgroundView_ addSubview:contentsView_];
464 [backgroundView_ addSubview:[appsSearchResultsController_ view]];
465 [backgroundView_ addSubview:[appsSearchBoxController_ view]];
466 [containerView addSubview:backgroundView_];
467 [self setView:containerView];
468 }
469
470 - (void)revealSearchResults:(BOOL)show {
471 if (show == showingSearchResults_)
472 return;
473
474 showingSearchResults_ = show;
475 NSSize contentsSize = [contentsView_ frame].size;
476 NSRect resultsTargetRect = NSMakeRect(
477 0, kSearchInputHeight + kTopSeparatorSize,
478 contentsSize.width, contentsSize.height);
479 NSRect contentsTargetRect = resultsTargetRect;
480
481 // Shows results by sliding the grid and pager down to the bottom of the view.
482 // Hides results by collapsing the search results container to a height of 0.
483 if (show)
484 contentsTargetRect.origin.y += NSHeight(contentsTargetRect);
485 else
486 resultsTargetRect.size.height = 0;
487
488 [[NSAnimationContext currentContext] setDuration:kResultsAnimationDuration];
489 [[contentsView_ animator] setFrame:contentsTargetRect];
490 [[[appsSearchResultsController_ view] animator] setFrame:resultsTargetRect];
491 }
492
493 - (void)totalPagesChanged {
494 size_t pageCount = [appsGridController_ pageCount];
495 [pagerControl_ setSegmentCount:pageCount];
496
497 NSRect viewFrame = [[pagerControl_ superview] bounds];
498 CGFloat segmentWidth = std::min(
499 kMaxSegmentWidth,
500 (viewFrame.size.width - 2 * kMinPagerMargin) / pageCount);
501
502 for (size_t i = 0; i < pageCount; ++i) {
503 [pagerControl_ setWidth:segmentWidth
504 forSegment:i];
505 [[pagerControl_ cell] setTag:i
506 forSegment:i];
507 }
508
509 // Center in view.
510 [pagerControl_ sizeToFit];
511 [pagerControl_ setFrame:
512 NSMakeRect(NSMidX(viewFrame) - NSMidX([pagerControl_ bounds]),
513 viewFrame.size.height - kPagerPreferredHeight,
514 [pagerControl_ bounds].size.width,
515 kPagerPreferredHeight)];
516 }
517
518 - (void)selectedPageChanged:(int)newSelected {
519 [pagerControl_ selectSegmentWithTag:newSelected];
520 }
521
522 - (void)pageVisibilityChanged {
523 [pagerControl_ setNeedsDisplay:YES];
524 }
525
526 - (NSInteger)pagerSegmentAtLocation:(NSPoint)locationInWindow {
527 return [pagerControl_ findAndHighlightSegmentAtLocation:locationInWindow];
528 }
529
530 - (app_list::SearchBoxModel*)searchBoxModel {
531 app_list::AppListModel* appListModel = [appsGridController_ model];
532 return appListModel ? appListModel->search_box() : NULL;
533 }
534
535 - (app_list::AppListViewDelegate*)appListDelegate {
536 return [self delegate];
537 }
538
539 - (BOOL)control:(NSControl*)control
540 textView:(NSTextView*)textView
541 doCommandBySelector:(SEL)command {
542 if (showingSearchResults_)
543 return [appsSearchResultsController_ handleCommandBySelector:command];
544
545 // If anything has been written, let the search view handle it.
546 if ([[control stringValue] length] > 0)
547 return NO;
548
549 // Handle escape.
550 if (command == @selector(complete:) ||
551 command == @selector(cancel:) ||
552 command == @selector(cancelOperation:)) {
553 if (delegate_)
554 delegate_->Dismiss();
555 return YES;
556 }
557
558 // Possibly handle grid navigation.
559 return [appsGridController_ handleCommandBySelector:command];
560 }
561
562 - (void)modelTextDidChange {
563 app_list::SearchBoxModel* searchBoxModel = [self searchBoxModel];
564 if (!searchBoxModel || !delegate_)
565 return;
566
567 base::string16 query;
568 base::TrimWhitespace(searchBoxModel->text(), base::TRIM_ALL, &query);
569 BOOL shouldShowSearch = !query.empty();
570 [self revealSearchResults:shouldShowSearch];
571 if (shouldShowSearch)
572 delegate_->StartSearch();
573 else
574 delegate_->StopSearch();
575 }
576
577 - (app_list::AppListModel*)appListModel {
578 return [appsGridController_ model];
579 }
580
581 - (void)openResult:(app_list::SearchResult*)result {
582 if (delegate_) {
583 delegate_->OpenSearchResult(
584 result, false /* auto_launch */, 0 /* event flags */);
585 }
586 }
587
588 - (void)onProfilesChanged {
589 [appsSearchBoxController_ rebuildMenu];
590 }
591
592 // NSTextViewDelegate implementation.
593
594 - (BOOL)textView:(NSTextView*)textView
595 clickedOnLink:(id)link
596 atIndex:(NSUInteger)charIndex {
597 DCHECK(delegate_);
598 delegate_->OpenLearnMoreLink();
599 return YES;
600 }
601
602 - (NSArray*)textView:(NSTextView*)aTextView
603 willChangeSelectionFromCharacterRanges:(NSArray*)oldSelectedCharRanges
604 toCharacterRanges:(NSArray*)newSelectedCharRanges {
605 return oldSelectedCharRanges;
606 }
607
608 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698