diff options
Diffstat (limited to 'chromium/ui/app_list/cocoa/apps_search_results_controller.mm')
-rw-r--r-- | chromium/ui/app_list/cocoa/apps_search_results_controller.mm | 463 |
1 files changed, 0 insertions, 463 deletions
diff --git a/chromium/ui/app_list/cocoa/apps_search_results_controller.mm b/chromium/ui/app_list/cocoa/apps_search_results_controller.mm deleted file mode 100644 index 314f079e8ad..00000000000 --- a/chromium/ui/app_list/cocoa/apps_search_results_controller.mm +++ /dev/null @@ -1,463 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/apps_search_results_controller.h" - -#include "base/mac/foundation_util.h" -#include "base/mac/mac_util.h" -#include "base/strings/sys_string_conversions.h" -#include "skia/ext/skia_utils_mac.h" -#include "ui/app_list/app_list_constants.h" -#include "ui/app_list/app_list_model.h" -#import "ui/app_list/cocoa/apps_search_results_model_bridge.h" -#include "ui/app_list/search_result.h" -#import "ui/base/cocoa/flipped_view.h" -#include "ui/gfx/image/image_skia_util_mac.h" - -namespace { - -const CGFloat kPreferredRowHeight = 52; -const CGFloat kIconDimension = 32; -const CGFloat kIconPadding = 14; -const CGFloat kIconViewWidth = kIconDimension + 2 * kIconPadding; -const CGFloat kTextTrailPadding = kIconPadding; - -// Map background styles to represent selection and hover in the results list. -const NSBackgroundStyle kBackgroundNormal = NSBackgroundStyleLight; -const NSBackgroundStyle kBackgroundSelected = NSBackgroundStyleDark; -const NSBackgroundStyle kBackgroundHovered = NSBackgroundStyleRaised; - -} // namespace - -@interface AppsSearchResultsController () - -- (void)loadAndSetViewWithResultsFrameSize:(NSSize)size; -- (void)mouseDown:(NSEvent*)theEvent; -- (void)tableViewClicked:(id)sender; -- (app_list::AppListModel::SearchResults*)searchResults; -- (void)activateSelection; -- (BOOL)moveSelectionByDelta:(NSInteger)delta; -- (NSMenu*)contextMenuForRow:(NSInteger)rowIndex; - -@end - -@interface AppsSearchResultsCell : NSTextFieldCell -@end - -// Immutable class representing a search result in the NSTableView. -@interface AppsSearchResultRep : NSObject<NSCopying> { - @private - base::scoped_nsobject<NSAttributedString> attributedStringValue_; - base::scoped_nsobject<NSImage> resultIcon_; -} - -@property(readonly, nonatomic) NSAttributedString* attributedStringValue; -@property(readonly, nonatomic) NSImage* resultIcon; - -- (id)initWithSearchResult:(app_list::SearchResult*)result; - -- (NSMutableAttributedString*)createRenderText:(const base::string16&)content - tags:(const app_list::SearchResult::Tags&)tags; - -- (NSAttributedString*)createResultsAttributedStringWithModel - :(app_list::SearchResult*)result; - -@end - -// Simple extension to NSTableView that passes mouseDown events to the -// delegate so that drag events can be detected, and forwards requests for -// context menus. -@interface AppsSearchResultsTableView : NSTableView - -- (AppsSearchResultsController*)controller; - -@end - -@implementation AppsSearchResultsController - -@synthesize delegate = delegate_; - -- (id)initWithAppsSearchResultsFrameSize:(NSSize)size { - if ((self = [super init])) { - hoveredRowIndex_ = -1; - [self loadAndSetViewWithResultsFrameSize:size]; - } - return self; -} - -- (app_list::AppListModel::SearchResults*)results { - DCHECK([delegate_ appListModel]); - return [delegate_ appListModel]->results(); -} - -- (NSTableView*)tableView { - return tableView_; -} - -- (void)setDelegate:(id<AppsSearchResultsDelegate>)newDelegate { - bridge_.reset(); - delegate_ = newDelegate; - app_list::AppListModel* appListModel = [delegate_ appListModel]; - if (!appListModel || !appListModel->results()) { - [tableView_ reloadData]; - return; - } - - bridge_.reset(new app_list::AppsSearchResultsModelBridge(self)); - [tableView_ reloadData]; -} - -- (BOOL)handleCommandBySelector:(SEL)command { - if (command == @selector(insertNewline:) || - command == @selector(insertLineBreak:)) { - [self activateSelection]; - return YES; - } - - if (command == @selector(moveUp:)) - return [self moveSelectionByDelta:-1]; - - if (command == @selector(moveDown:)) - return [self moveSelectionByDelta:1]; - - return NO; -} - -- (void)loadAndSetViewWithResultsFrameSize:(NSSize)size { - tableView_.reset( - [[AppsSearchResultsTableView alloc] initWithFrame:NSZeroRect]); - // Refuse first responder so that focus stays with the search text field. - [tableView_ setRefusesFirstResponder:YES]; - [tableView_ setRowHeight:kPreferredRowHeight]; - [tableView_ setGridStyleMask:NSTableViewSolidHorizontalGridLineMask]; - [tableView_ setGridColor: - gfx::SkColorToSRGBNSColor(app_list::kResultBorderColor)]; - [tableView_ setBackgroundColor:[NSColor clearColor]]; - [tableView_ setAction:@selector(tableViewClicked:)]; - [tableView_ setDelegate:self]; - [tableView_ setDataSource:self]; - [tableView_ setTarget:self]; - - // Tracking to highlight an individual row on mouseover. - trackingArea_.reset( - [[CrTrackingArea alloc] initWithRect:NSZeroRect - options:NSTrackingInVisibleRect | - NSTrackingMouseEnteredAndExited | - NSTrackingMouseMoved | - NSTrackingActiveInKeyWindow - owner:self - userInfo:nil]); - [tableView_ addTrackingArea:trackingArea_.get()]; - - base::scoped_nsobject<NSTableColumn> resultsColumn( - [[NSTableColumn alloc] initWithIdentifier:@""]); - base::scoped_nsobject<NSCell> resultsDataCell( - [[AppsSearchResultsCell alloc] initTextCell:@""]); - [resultsColumn setDataCell:resultsDataCell]; - [resultsColumn setWidth:size.width]; - [tableView_ addTableColumn:resultsColumn]; - - // An NSTableView is normally put in a NSScrollView, but scrolling is not - // used for the app list. Instead, place it in a container with the desired - // size; flipped so the table is anchored to the top-left. - base::scoped_nsobject<FlippedView> containerView([[FlippedView alloc] - initWithFrame:NSMakeRect(0, 0, size.width, size.height)]); - - // The container is then anchored in an un-flipped view, initially hidden, - // so that |containerView| slides in from the top when showing results. - base::scoped_nsobject<NSView> clipView( - [[NSView alloc] initWithFrame:NSMakeRect(0, 0, size.width, 0)]); - - [containerView addSubview:tableView_]; - [clipView addSubview:containerView]; - [self setView:clipView]; -} - -- (void)mouseDown:(NSEvent*)theEvent { - lastMouseDownInView_ = [tableView_ convertPoint:[theEvent locationInWindow] - fromView:nil]; -} - -- (void)tableViewClicked:(id)sender { - const CGFloat kDragThreshold = 5; - // If the user clicked and then dragged elsewhere, ignore the click. - NSEvent* event = [[tableView_ window] currentEvent]; - NSPoint pointInView = [tableView_ convertPoint:[event locationInWindow] - fromView:nil]; - CGFloat deltaX = pointInView.x - lastMouseDownInView_.x; - CGFloat deltaY = pointInView.y - lastMouseDownInView_.y; - if (deltaX * deltaX + deltaY * deltaY <= kDragThreshold * kDragThreshold) - [self activateSelection]; - - // Mouse tracking is suppressed by the NSTableView during a drag, so ensure - // any hover state is cleaned up. - [self mouseMoved:event]; -} - -- (app_list::AppListModel::SearchResults*)searchResults { - app_list::AppListModel* appListModel = [delegate_ appListModel]; - DCHECK(bridge_); - DCHECK(appListModel); - DCHECK(appListModel->results()); - return appListModel->results(); -} - -- (void)activateSelection { - NSInteger selectedRow = [tableView_ selectedRow]; - if (!bridge_ || selectedRow < 0) - return; - - [delegate_ openResult:[self searchResults]->GetItemAt(selectedRow)]; -} - -- (BOOL)moveSelectionByDelta:(NSInteger)delta { - NSInteger rowCount = [tableView_ numberOfRows]; - if (rowCount <= 0) - return NO; - - NSInteger selectedRow = [tableView_ selectedRow]; - NSInteger targetRow; - if (selectedRow == -1) { - // No selection. Select first or last, based on direction. - targetRow = delta > 0 ? 0 : rowCount - 1; - } else { - targetRow = (selectedRow + delta) % rowCount; - if (targetRow < 0) - targetRow += rowCount; - } - - [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:targetRow] - byExtendingSelection:NO]; - return YES; -} - -- (NSMenu*)contextMenuForRow:(NSInteger)rowIndex { - DCHECK(bridge_); - if (rowIndex < 0) - return nil; - - [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:rowIndex] - byExtendingSelection:NO]; - return bridge_->MenuForItem(rowIndex); -} - -- (NSInteger)numberOfRowsInTableView:(NSTableView*)aTableView { - return bridge_ ? [self searchResults]->item_count() : 0; -} - -- (id)tableView:(NSTableView*)aTableView - objectValueForTableColumn:(NSTableColumn*)aTableColumn - row:(NSInteger)rowIndex { - // When the results were previously cleared, nothing will be selected. For - // that case, select the first row when it appears. - if (rowIndex == 0 && [tableView_ selectedRow] == -1) { - [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:0] - byExtendingSelection:NO]; - } - - base::scoped_nsobject<AppsSearchResultRep> resultRep( - [[AppsSearchResultRep alloc] - initWithSearchResult:[self searchResults]->GetItemAt(rowIndex)]); - return resultRep.autorelease(); -} - -- (void)tableView:(NSTableView*)tableView - willDisplayCell:(id)cell - forTableColumn:(NSTableColumn*)tableColumn - row:(NSInteger)rowIndex { - if (rowIndex == [tableView selectedRow]) - [cell setBackgroundStyle:kBackgroundSelected]; - else if (rowIndex == hoveredRowIndex_) - [cell setBackgroundStyle:kBackgroundHovered]; - else - [cell setBackgroundStyle:kBackgroundNormal]; -} - -- (void)mouseExited:(NSEvent*)theEvent { - if (hoveredRowIndex_ == -1) - return; - - [tableView_ setNeedsDisplayInRect:[tableView_ rectOfRow:hoveredRowIndex_]]; - hoveredRowIndex_ = -1; -} - -- (void)mouseMoved:(NSEvent*)theEvent { - NSPoint pointInView = [tableView_ convertPoint:[theEvent locationInWindow] - fromView:nil]; - NSInteger newIndex = [tableView_ rowAtPoint:pointInView]; - if (newIndex == hoveredRowIndex_) - return; - - if (newIndex != -1) - [tableView_ setNeedsDisplayInRect:[tableView_ rectOfRow:newIndex]]; - if (hoveredRowIndex_ != -1) - [tableView_ setNeedsDisplayInRect:[tableView_ rectOfRow:hoveredRowIndex_]]; - hoveredRowIndex_ = newIndex; -} - -@end - -@implementation AppsSearchResultRep - -- (NSAttributedString*)attributedStringValue { - return attributedStringValue_; -} - -- (NSImage*)resultIcon { - return resultIcon_; -} - -- (id)initWithSearchResult:(app_list::SearchResult*)result { - if ((self = [super init])) { - attributedStringValue_.reset( - [[self createResultsAttributedStringWithModel:result] retain]); - if (!result->icon().isNull()) { - resultIcon_.reset([gfx::NSImageFromImageSkiaWithColorSpace( - result->icon(), base::mac::GetSRGBColorSpace()) retain]); - } - } - return self; -} - -- (NSMutableAttributedString*)createRenderText:(const base::string16&)content - tags:(const app_list::SearchResult::Tags&)tags { - NSFont* boldFont = nil; - base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( - [[NSMutableParagraphStyle alloc] init]); - [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail]; - NSDictionary* defaultAttributes = @{ - NSForegroundColorAttributeName: - gfx::SkColorToSRGBNSColor(app_list::kResultDefaultTextColor), - NSParagraphStyleAttributeName: paragraphStyle - }; - - base::scoped_nsobject<NSMutableAttributedString> text( - [[NSMutableAttributedString alloc] - initWithString:base::SysUTF16ToNSString(content) - attributes:defaultAttributes]); - - for (app_list::SearchResult::Tags::const_iterator it = tags.begin(); - it != tags.end(); ++it) { - if (it->styles == app_list::SearchResult::Tag::NONE) - continue; - - if (it->styles & app_list::SearchResult::Tag::MATCH) { - if (!boldFont) { - NSFontManager* fontManager = [NSFontManager sharedFontManager]; - boldFont = [fontManager convertFont:[NSFont controlContentFontOfSize:0] - toHaveTrait:NSBoldFontMask]; - } - [text addAttribute:NSFontAttributeName - value:boldFont - range:it->range.ToNSRange()]; - } - - if (it->styles & app_list::SearchResult::Tag::DIM) { - NSColor* dimmedColor = - gfx::SkColorToSRGBNSColor(app_list::kResultDimmedTextColor); - [text addAttribute:NSForegroundColorAttributeName - value:dimmedColor - range:it->range.ToNSRange()]; - } else if (it->styles & app_list::SearchResult::Tag::URL) { - NSColor* urlColor = - gfx::SkColorToSRGBNSColor(app_list::kResultURLTextColor); - [text addAttribute:NSForegroundColorAttributeName - value:urlColor - range:it->range.ToNSRange()]; - } - } - - return text.autorelease(); -} - -- (NSAttributedString*)createResultsAttributedStringWithModel - :(app_list::SearchResult*)result { - NSMutableAttributedString* titleText = - [self createRenderText:result->title() - tags:result->title_tags()]; - if (!result->details().empty()) { - NSMutableAttributedString* detailText = - [self createRenderText:result->details() - tags:result->details_tags()]; - base::scoped_nsobject<NSAttributedString> lineBreak( - [[NSAttributedString alloc] initWithString:@"\n"]); - [titleText appendAttributedString:lineBreak]; - [titleText appendAttributedString:detailText]; - } - return titleText; -} - -- (id)copyWithZone:(NSZone*)zone { - return [self retain]; -} - -@end - -@implementation AppsSearchResultsTableView - -- (AppsSearchResultsController*)controller { - return base::mac::ObjCCastStrict<AppsSearchResultsController>( - [self delegate]); -} - -- (void)mouseDown:(NSEvent*)theEvent { - [[self controller] mouseDown:theEvent]; - [super mouseDown:theEvent]; -} - -- (NSMenu*)menuForEvent:(NSEvent*)theEvent { - NSPoint pointInView = [self convertPoint:[theEvent locationInWindow] - fromView:nil]; - return [[self controller] contextMenuForRow:[self rowAtPoint:pointInView]]; -} - -@end - -@implementation AppsSearchResultsCell - -- (void)drawWithFrame:(NSRect)cellFrame - inView:(NSView*)controlView { - if ([self backgroundStyle] != kBackgroundNormal) { - if ([self backgroundStyle] == kBackgroundSelected) - [gfx::SkColorToSRGBNSColor(app_list::kSelectedColor) set]; - else - [gfx::SkColorToSRGBNSColor(app_list::kHighlightedColor) set]; - - // Extend up by one pixel to draw over cell border. - NSRect backgroundRect = cellFrame; - backgroundRect.origin.y -= 1; - backgroundRect.size.height += 1; - NSRectFill(backgroundRect); - } - - NSAttributedString* titleText = [self attributedStringValue]; - NSRect titleRect = cellFrame; - titleRect.size.width -= kTextTrailPadding + kIconViewWidth; - titleRect.origin.x += kIconViewWidth; - titleRect.origin.y += - floor(NSHeight(cellFrame) / 2 - [titleText size].height / 2); - // Ensure no drawing occurs outside of the cell. - titleRect = NSIntersectionRect(titleRect, cellFrame); - - [titleText drawInRect:titleRect]; - - NSImage* resultIcon = [[self objectValue] resultIcon]; - if (!resultIcon) - return; - - NSSize iconSize = [resultIcon size]; - NSRect iconRect = NSMakeRect( - floor(NSMinX(cellFrame) + kIconViewWidth / 2 - iconSize.width / 2), - floor(NSMinY(cellFrame) + kPreferredRowHeight / 2 - iconSize.height / 2), - std::min(iconSize.width, kIconDimension), - std::min(iconSize.height, kIconDimension)); - [resultIcon drawInRect:iconRect - fromRect:NSZeroRect - operation:NSCompositeSourceOver - fraction:1.0 - respectFlipped:YES - hints:nil]; -} - -@end |