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 |