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 ad35dbaee19381932669003b770c1484a840bde1..f870d8262b769acb4cc7e7b1e6e3e3392f32dd64 100644 |
| --- a/ui/app_list/cocoa/apps_search_box_controller.mm |
| +++ b/ui/app_list/cocoa/apps_search_box_controller.mm |
| @@ -6,20 +6,32 @@ |
| #include "base/mac/foundation_util.h" |
| #include "base/strings/sys_string_conversions.h" |
| +#include "grit/ui_resources.h" |
| #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.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" |
| +#import "ui/base/cocoa/controls/hover_image_menu_button_cell.h" |
| +#import "ui/base/cocoa/menu_controller.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 () |
| @@ -112,6 +124,15 @@ void SearchBoxModelObserverBridge::TextChanged() { |
| @end |
| +@interface AppListMenuController : MenuController { |
| + @private |
| + AppsSearchBoxController* searchBoxController_; // Weak. Owns us. |
| +} |
| + |
| +- (id)initWithSearchBoxController:(AppsSearchBoxController*)parent; |
| + |
| +@end |
| + |
| @implementation AppsSearchBoxController |
| @synthesize delegate = delegate_; |
| @@ -131,18 +152,36 @@ void SearchBoxModelObserverBridge::TextChanged() { |
| } |
| - (void)setDelegate:(id<AppsSearchBoxDelegate>)delegate { |
| + [[menuButton_ menu] removeAllItems]; |
| + menuController_.reset(); |
| + appListMenu_.reset(); |
| bridge_.reset(); // Ensure observers are cleared before updating |delegate_|. |
| delegate_ = delegate; |
| if (!delegate_) |
| return; |
| bridge_.reset(new app_list::SearchBoxModelObserverBridge(self)); |
| + if (![delegate_ appListDelegate]) |
| + return; |
| + |
| + appListMenu_.reset(new app_list::AppListMenu([delegate_ appListDelegate])); |
| + menuController_.reset([[AppListMenuController alloc] |
| + initWithSearchBoxController:self]); |
| + [menuButton_ setMenu:[menuController_ menu]]; // Menu will populate here. |
| } |
| - (NSTextField*)searchTextField { |
| return searchTextField_; |
| } |
| +- (NSPopUpButton*)menuControl { |
| + return menuButton_; |
| +} |
| + |
| +- (app_list::AppListMenu*)appListMenu { |
| + return appListMenu_.get(); |
| +} |
| + |
| - (NSImageView*)searchImageView { |
| return searchImageView_; |
| } |
| @@ -153,15 +192,32 @@ void SearchBoxModelObserverBridge::TextChanged() { |
| kPadding, 0, kSearchIconDimension, NSHeight(viewBounds))]); |
| searchTextField_.reset([[SearchTextField alloc] initWithFrame:viewBounds]); |
| + ui::ResourceBundle& resourceBundle = ui::ResourceBundle::GetSharedInstance(); |
|
Robert Sesek
2013/06/11 18:07:47
optional nit: we normally just call this rb. It th
tapted
2013/06/12 00:01:10
Done.
|
| [searchTextField_ setDelegate:self]; |
| - [searchTextField_ setFont:ui::ResourceBundle::GetSharedInstance().GetFont( |
| + [searchTextField_ setFont:resourceBundle.GetFont( |
| ui::ResourceBundle::MediumFont).GetNativeFont()]; |
| [searchTextField_ |
| setMarginsWithLeftMargin:NSMaxX([searchImageView_ frame]) + kPadding |
| - rightMargin:kPadding]; |
| + rightMargin:kMenuButtonDimension + 2 * kPadding]; |
| + |
| + // Add the drop-down menu, with a custom button. |
| + NSRect buttonFrame = NSMakeRect( |
| + NSWidth(viewBounds) - kMenuButtonDimension - kPadding, |
| + floor(NSMidY(viewBounds) - kMenuButtonDimension / 2), |
| + kMenuButtonDimension, |
| + kMenuButtonDimension); |
| + menuButton_.reset([[HoverImageMenuButton alloc] initWithFrame:buttonFrame |
| + pullsDown:YES]); |
| + [[menuButton_ hoverImageMenuButtonCell] setImage:resourceBundle. |
| + GetNativeImageNamed(IDR_APP_LIST_TOOLS_NORMAL).AsNSImage()]; |
| + [[menuButton_ hoverImageMenuButtonCell] setAlternateImage:resourceBundle. |
| + GetNativeImageNamed(IDR_APP_LIST_TOOLS_PRESSED).AsNSImage()]; |
| + [[menuButton_ hoverImageMenuButtonCell] setHoverImage:resourceBundle. |
| + GetNativeImageNamed(IDR_APP_LIST_TOOLS_HOVER).AsNSImage()]; |
| [[self view] addSubview:searchImageView_]; |
| [[self view] addSubview:searchTextField_]; |
| + [[self view] addSubview:menuButton_]; |
| } |
| - (BOOL)control:(NSControl*)control |
| @@ -291,3 +347,48 @@ void SearchBoxModelObserverBridge::TextChanged() { |
| } |
| @end |
| + |
| +@implementation AppListMenuController |
| + |
| +- (id)initWithSearchBoxController:(AppsSearchBoxController*)parent { |
| + // Need to initialze super with a NULL model, otherwise it will immediately |
| + // try to populate, which can't be done until setting the parent. |
| + if ((self = [super initWithModel:NULL |
| + useWithPopUpButtonCell:YES])) { |
| + searchBoxController_ = parent; |
| + [super setModel:[parent appListMenu]->menu_model()]; |
| + } |
| + return self; |
| +} |
| + |
| +- (void)addItemToMenu:(NSMenu*)menu |
| + atIndex:(NSInteger)index |
| + fromModel:(ui::MenuModel*)model { |
| + [super addItemToMenu:menu |
| + atIndex:index |
| + fromModel:model]; |
| + if (model->GetCommandIdAt(index) != app_list::AppListMenu::CURRENT_USER) |
| + return; |
| + |
| + scoped_nsobject<NSView> customItemView([[CurrentUserMenuItemView alloc] |
| + initWithDelegate:[[searchBoxController_ delegate] appListDelegate]]); |
| + [[menu itemAtIndex:index] setView:customItemView]; |
| +} |
| + |
| +- (NSRect)confinementRectForMenu:(NSMenu*)menu |
| + onScreen:(NSScreen*)screen { |
| + NSPopUpButton* menuButton = [searchBoxController_ menuControl]; |
| + // 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. |
| + NSRect anchorRect = [menuButton convertRect:[menuButton bounds] |
| + toView:nil]; |
| + NSPoint anchorPoint = [[menuButton window] convertBaseToScreen:NSMakePoint( |
| + NSMaxX(anchorRect), |
| + NSMinY(anchorRect) - kMenuOffsetFromButton)]; |
| + NSRect confinementRect = [[menuButton window] frame]; |
| + confinementRect.size = NSMakeSize(anchorPoint.x - NSMinX(confinementRect), |
| + anchorPoint.y - NSMinY(confinementRect)); |
| + return confinementRect; |
| +} |
| + |
| +@end |