Chromium Code Reviews| Index: ui/app_list/cocoa/apps_search_box_controller.mm |
| diff --git a/ui/app_list/cocoa/apps_search_box_controller.mm b/ui/app_list/cocoa/apps_search_box_controller.mm |
| index aa0c65265a8f081b25d9aa216406549f1630312f..cebb7cce86bbb1bc81809ba7466b8e45bbd0007d 100644 |
| --- a/ui/app_list/cocoa/apps_search_box_controller.mm |
| +++ b/ui/app_list/cocoa/apps_search_box_controller.mm |
| @@ -5,25 +5,39 @@ |
| #import "ui/app_list/cocoa/apps_search_box_controller.h" |
| #include "base/strings/sys_string_conversions.h" |
| +#include "grit/ui_resources.h" |
| +#include "ui/app_list/app_list_menu.h" |
| +#import "ui/app_list/cocoa/current_user_menu_item_view.h" |
| #include "ui/app_list/search_box_model.h" |
| #include "ui/app_list/search_box_model_observer.h" |
| +#import "ui/base/cocoa/controls/hover_image_menu_button.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #include "ui/gfx/image/image_skia_util_mac.h" |
| namespace { |
| -// Padding either side of the search icon. |
| +// Padding either side of the search icon and menu button. |
| const CGFloat kPadding = 14; |
| // Size of the search icon. |
| const CGFloat kSearchIconDimension = 32; |
| +// Size of the menu button on the right. |
| +const CGFloat kMenuButtonDimension = 29; |
| + |
| +// Vertical offset that the menu should appear below the menu button. |
| +const CGFloat kMenuOffsetFromButton = 2; |
| + |
| } |
| @interface AppsSearchBoxController () |
| - (NSImageView*)searchImage; |
| - (void)addSubviews; |
| +- (void)menuItemSelected:(NSMenuItem*)sender; |
| + |
| +- (void)addItemToMenu:(NSMenu*)menu |
| + forIndex:(int)index; |
| @end |
| @@ -109,7 +123,10 @@ void SearchBoxModelObserverBridge::TextChanged() { |
| - (void)setDelegate:(id<AppsSearchBoxDelegate>)delegate { |
| delegate_ = delegate; |
| + app_list::AppListViewDelegate* appListDelegate = [delegate appListDelegate]; |
| app_list::SearchBoxModel* searchBoxModel = [delegate searchBoxModel]; |
| + appListMenu_.reset(appListDelegate ? |
| + new app_list::AppListMenu(appListDelegate) : NULL); |
| bridge_.reset(searchBoxModel ? |
| new app_list::SearchBoxModelObserverBridge(self, searchBoxModel) : NULL); |
| } |
| @@ -118,6 +135,14 @@ void SearchBoxModelObserverBridge::TextChanged() { |
| return searchInput_; |
| } |
| +- (NSPopUpButton*)menuControl { |
| + return menuButton_; |
| +} |
| + |
| +- (app_list::AppListMenu*)appListMenu { |
| + return appListMenu_.get(); |
| +} |
| + |
| - (NSImageView*)searchImage { |
| return searchImage_; |
| } |
| @@ -127,12 +152,13 @@ void SearchBoxModelObserverBridge::TextChanged() { |
| searchImage_.reset([[NSImageView alloc] initWithFrame:NSMakeRect( |
| kPadding, 0, kSearchIconDimension, viewSize.height)]); |
| + ui::ResourceBundle& resourceBundle = ui::ResourceBundle::GetSharedInstance(); |
| searchInput_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]); |
| [searchInput_ setFocusRingType:NSFocusRingTypeNone]; |
| [searchInput_ setDrawsBackground:NO]; |
| [searchInput_ setBordered:NO]; |
| [searchInput_ setDelegate:self]; |
| - [searchInput_ setFont:ui::ResourceBundle::GetSharedInstance().GetFont( |
| + [searchInput_ setFont:resourceBundle.GetFont( |
| ui::ResourceBundle::MediumFont).GetNativeFont()]; |
| // Find the preferred height for those text properties, and center. |
| @@ -142,11 +168,88 @@ void SearchBoxModelObserverBridge::TextChanged() { |
| [searchInput_ setFrame:NSMakeRect( |
| inputXOffset, |
| floor(viewSize.height / 2 - inputHeight / 2), |
| - viewSize.width - inputXOffset - kPadding, |
| + viewSize.width - inputXOffset - kMenuButtonDimension - 2 * kPadding, |
| inputHeight)]; |
| + // Add the drop-down menu, with a custom button. |
| + NSRect buttonFrame = NSMakeRect( |
| + NSMaxX([searchInput_ frame]) + kPadding, |
| + floor(viewSize.height / 2 - kMenuButtonDimension / 2), |
| + kMenuButtonDimension, |
| + kMenuButtonDimension); |
| + menuButton_.reset([[HoverImageMenuButton alloc] initWithFrame:buttonFrame |
| + pullsDown:YES]); |
| + [[menuButton_ menu] setDelegate:self]; |
| + [[menuButton_ cell] setImage:resourceBundle.GetNativeImageNamed( |
|
sail
2013/05/31 19:07:03
use hoverImageMenuButtonCell accessor instead?
tapted
2013/06/03 12:49:18
Done.
|
| + IDR_APP_LIST_TOOLS_NORMAL).AsNSImage()]; |
| + [[menuButton_ cell] setAlternateImage:resourceBundle.GetNativeImageNamed( |
| + IDR_APP_LIST_TOOLS_PRESSED).AsNSImage()]; |
| + [[menuButton_ cell] setHoverImage:resourceBundle.GetNativeImageNamed( |
| + IDR_APP_LIST_TOOLS_HOVER).AsNSImage()]; |
| + |
| [[self view] addSubview:searchImage_]; |
| [[self view] addSubview:searchInput_]; |
| + [[self view] addSubview:menuButton_]; |
| +} |
| + |
| +- (void)menuItemSelected:(NSMenuItem*)sender { |
| + if (!appListMenu_) |
|
sail
2013/05/31 19:07:03
is this possible?
tapted
2013/06/03 12:49:18
Initially I wasn't sure, but I realised the menu i
|
| + return; |
| + |
| + appListMenu_->menu_model()->ActivatedAt([sender tag]); |
| +} |
| + |
| +- (void)menuNeedsUpdate:(NSMenu*)menu { |
| + if (!appListMenu_ || [menu numberOfItems] != 1) |
| + return; |
| + |
| + int itemCount = appListMenu_->menu_model()->GetItemCount(); |
|
sail
2013/05/31 19:07:03
do this in addSubviews instead?
tapted
2013/06/03 12:49:18
I initially did it here because it means the creat
|
| + for (int i = 0; i < itemCount; ++i) { |
| + [self addItemToMenu:menu |
| + forIndex:i]; |
| + } |
| +} |
| + |
| +- (void)addItemToMenu:(NSMenu*)menu |
|
Robert Sesek
2013/05/31 19:16:09
Have you considered using MenuController? https://
tapted
2013/06/03 12:54:24
I have! But, it would need further refactoring to
|
| + forIndex:(int)index { |
| + DCHECK(appListMenu_); |
| + ui::MenuModel* menuModel = appListMenu_->menu_model(); |
| + if (menuModel->GetTypeAt(index) == ui::MenuModel::TYPE_SEPARATOR) { |
| + [menu addItem:[NSMenuItem separatorItem]]; |
| + return; |
| + } |
| + |
| + string16 labelText = menuModel->GetLabelAt(index); |
| + scoped_nsobject<NSMenuItem> item( |
| + [[NSMenuItem alloc] initWithTitle:base::SysUTF16ToNSString(labelText) |
| + action:@selector(menuItemSelected:) |
| + keyEquivalent:[NSString string]]); |
| + [item setTag:index]; |
| + [item setTarget:self]; |
| + |
| + if (menuModel->GetCommandIdAt(index) == app_list::AppListMenu::CURRENT_USER) { |
| + scoped_nsobject<NSView> customItemView([[CurrentUserMenuItemView alloc] |
| + initWithDelegate:[delegate_ appListDelegate] |
| + usingFont:[menu font]]); |
| + |
| + [item setView:customItemView]; |
| + } |
| + |
| + [menu addItem:item]; |
| +} |
| + |
| +- (NSRect)confinementRectForMenu:(NSMenu*)menu |
| + onScreen:(NSScreen*)screen { |
| + // Ensure the menu comes up below the menu button by trimming the window frame |
| + // to a point anchored below the bottom right of the button. |
| + NSPoint anchor = NSMakePoint(kMenuButtonDimension, |
| + kMenuButtonDimension + kMenuOffsetFromButton); |
| + anchor = [menuButton_ convertPoint:anchor |
| + toView:nil]; |
| + anchor = [[menuButton_ window] convertBaseToScreen:anchor]; |
| + NSRect rect = [[menuButton_ window] frame]; |
| + rect.size = NSMakeSize(anchor.x - NSMinX(rect), anchor.y - NSMinY(rect)); |
|
sail
2013/05/31 19:07:03
how about just converting [menuButton_ bounds] to
tapted
2013/06/03 12:49:18
Sadly, NSWindow convertRectToScreen: is OSX 10.7+
|
| + return rect; |
| } |
| - (BOOL)control:(NSControl*)control |