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

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

Issue 15955003: Menu for the OSX app launcher. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Refactor HoverImageMenuButton into /ui/base/cocoa/controls Created 7 years, 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ui/app_list/cocoa/apps_search_box_controller.h" 5 #import "ui/app_list/cocoa/apps_search_box_controller.h"
6 6
7 #include "base/strings/sys_string_conversions.h" 7 #include "base/strings/sys_string_conversions.h"
8 #include "grit/ui_resources.h"
9 #include "ui/app_list/app_list_menu.h"
10 #import "ui/app_list/cocoa/current_user_menu_item_view.h"
8 #include "ui/app_list/search_box_model.h" 11 #include "ui/app_list/search_box_model.h"
9 #include "ui/app_list/search_box_model_observer.h" 12 #include "ui/app_list/search_box_model_observer.h"
13 #import "ui/base/cocoa/controls/hover_image_menu_button.h"
10 #include "ui/base/resource/resource_bundle.h" 14 #include "ui/base/resource/resource_bundle.h"
11 #include "ui/gfx/image/image_skia_util_mac.h" 15 #include "ui/gfx/image/image_skia_util_mac.h"
12 16
13 namespace { 17 namespace {
14 18
15 // Padding either side of the search icon. 19 // Padding either side of the search icon and menu button.
16 const CGFloat kPadding = 14; 20 const CGFloat kPadding = 14;
17 21
18 // Size of the search icon. 22 // Size of the search icon.
19 const CGFloat kSearchIconDimension = 32; 23 const CGFloat kSearchIconDimension = 32;
20 24
25 // Size of the menu button on the right.
26 const CGFloat kMenuButtonDimension = 29;
27
28 // Vertical offset that the menu should appear below the menu button.
29 const CGFloat kMenuOffsetFromButton = 2;
30
21 } 31 }
22 32
23 @interface AppsSearchBoxController () 33 @interface AppsSearchBoxController ()
24 34
25 - (NSImageView*)searchImage; 35 - (NSImageView*)searchImage;
26 - (void)addSubviews; 36 - (void)addSubviews;
37 - (void)menuItemSelected:(NSMenuItem*)sender;
38
39 - (void)addItemToMenu:(NSMenu*)menu
40 forIndex:(int)index;
27 41
28 @end 42 @end
29 43
30 namespace app_list { 44 namespace app_list {
31 45
32 class SearchBoxModelObserverBridge : public SearchBoxModelObserver { 46 class SearchBoxModelObserverBridge : public SearchBoxModelObserver {
33 public: 47 public:
34 SearchBoxModelObserverBridge(AppsSearchBoxController* parent, 48 SearchBoxModelObserverBridge(AppsSearchBoxController* parent,
35 SearchBoxModel* model); 49 SearchBoxModel* model);
36 virtual ~SearchBoxModelObserverBridge(); 50 virtual ~SearchBoxModelObserverBridge();
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 return self; 116 return self;
103 } 117 }
104 118
105 - (void)clearSearch { 119 - (void)clearSearch {
106 [searchInput_ setStringValue:[NSString string]]; 120 [searchInput_ setStringValue:[NSString string]];
107 [self controlTextDidChange:nil]; 121 [self controlTextDidChange:nil];
108 } 122 }
109 123
110 - (void)setDelegate:(id<AppsSearchBoxDelegate>)delegate { 124 - (void)setDelegate:(id<AppsSearchBoxDelegate>)delegate {
111 delegate_ = delegate; 125 delegate_ = delegate;
126 app_list::AppListViewDelegate* appListDelegate = [delegate appListDelegate];
112 app_list::SearchBoxModel* searchBoxModel = [delegate searchBoxModel]; 127 app_list::SearchBoxModel* searchBoxModel = [delegate searchBoxModel];
128 appListMenu_.reset(appListDelegate ?
129 new app_list::AppListMenu(appListDelegate) : NULL);
113 bridge_.reset(searchBoxModel ? 130 bridge_.reset(searchBoxModel ?
114 new app_list::SearchBoxModelObserverBridge(self, searchBoxModel) : NULL); 131 new app_list::SearchBoxModelObserverBridge(self, searchBoxModel) : NULL);
115 } 132 }
116 133
117 - (NSTextField*)textField { 134 - (NSTextField*)textField {
118 return searchInput_; 135 return searchInput_;
119 } 136 }
120 137
138 - (NSPopUpButton*)menuControl {
139 return menuButton_;
140 }
141
142 - (app_list::AppListMenu*)appListMenu {
143 return appListMenu_.get();
144 }
145
121 - (NSImageView*)searchImage { 146 - (NSImageView*)searchImage {
122 return searchImage_; 147 return searchImage_;
123 } 148 }
124 149
125 - (void)addSubviews { 150 - (void)addSubviews {
126 NSSize viewSize = [[self view] bounds].size; 151 NSSize viewSize = [[self view] bounds].size;
127 searchImage_.reset([[NSImageView alloc] initWithFrame:NSMakeRect( 152 searchImage_.reset([[NSImageView alloc] initWithFrame:NSMakeRect(
128 kPadding, 0, kSearchIconDimension, viewSize.height)]); 153 kPadding, 0, kSearchIconDimension, viewSize.height)]);
129 154
155 ui::ResourceBundle& resourceBundle = ui::ResourceBundle::GetSharedInstance();
130 searchInput_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]); 156 searchInput_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]);
131 [searchInput_ setFocusRingType:NSFocusRingTypeNone]; 157 [searchInput_ setFocusRingType:NSFocusRingTypeNone];
132 [searchInput_ setDrawsBackground:NO]; 158 [searchInput_ setDrawsBackground:NO];
133 [searchInput_ setBordered:NO]; 159 [searchInput_ setBordered:NO];
134 [searchInput_ setDelegate:self]; 160 [searchInput_ setDelegate:self];
135 [searchInput_ setFont:ui::ResourceBundle::GetSharedInstance().GetFont( 161 [searchInput_ setFont:resourceBundle.GetFont(
136 ui::ResourceBundle::MediumFont).GetNativeFont()]; 162 ui::ResourceBundle::MediumFont).GetNativeFont()];
137 163
138 // Find the preferred height for those text properties, and center. 164 // Find the preferred height for those text properties, and center.
139 [searchInput_ sizeToFit]; 165 [searchInput_ sizeToFit];
140 CGFloat inputXOffset = kSearchIconDimension + 2 * kPadding; 166 CGFloat inputXOffset = kSearchIconDimension + 2 * kPadding;
141 CGFloat inputHeight = NSHeight([searchInput_ bounds]); 167 CGFloat inputHeight = NSHeight([searchInput_ bounds]);
142 [searchInput_ setFrame:NSMakeRect( 168 [searchInput_ setFrame:NSMakeRect(
143 inputXOffset, 169 inputXOffset,
144 floor(viewSize.height / 2 - inputHeight / 2), 170 floor(viewSize.height / 2 - inputHeight / 2),
145 viewSize.width - inputXOffset - kPadding, 171 viewSize.width - inputXOffset - kMenuButtonDimension - 2 * kPadding,
146 inputHeight)]; 172 inputHeight)];
147 173
174 // Add the drop-down menu, with a custom button.
175 NSRect buttonFrame = NSMakeRect(
176 NSMaxX([searchInput_ frame]) + kPadding,
177 floor(viewSize.height / 2 - kMenuButtonDimension / 2),
178 kMenuButtonDimension,
179 kMenuButtonDimension);
180 menuButton_.reset([[HoverImageMenuButton alloc] initWithFrame:buttonFrame
181 pullsDown:YES]);
182 [[menuButton_ menu] setDelegate:self];
183 [[menuButton_ cell] setImage:resourceBundle.GetNativeImageNamed(
sail 2013/05/31 19:07:03 use hoverImageMenuButtonCell accessor instead?
tapted 2013/06/03 12:49:18 Done.
184 IDR_APP_LIST_TOOLS_NORMAL).AsNSImage()];
185 [[menuButton_ cell] setAlternateImage:resourceBundle.GetNativeImageNamed(
186 IDR_APP_LIST_TOOLS_PRESSED).AsNSImage()];
187 [[menuButton_ cell] setHoverImage:resourceBundle.GetNativeImageNamed(
188 IDR_APP_LIST_TOOLS_HOVER).AsNSImage()];
189
148 [[self view] addSubview:searchImage_]; 190 [[self view] addSubview:searchImage_];
149 [[self view] addSubview:searchInput_]; 191 [[self view] addSubview:searchInput_];
192 [[self view] addSubview:menuButton_];
193 }
194
195 - (void)menuItemSelected:(NSMenuItem*)sender {
196 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
197 return;
198
199 appListMenu_->menu_model()->ActivatedAt([sender tag]);
200 }
201
202 - (void)menuNeedsUpdate:(NSMenu*)menu {
203 if (!appListMenu_ || [menu numberOfItems] != 1)
204 return;
205
206 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
207 for (int i = 0; i < itemCount; ++i) {
208 [self addItemToMenu:menu
209 forIndex:i];
210 }
211 }
212
213 - (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
214 forIndex:(int)index {
215 DCHECK(appListMenu_);
216 ui::MenuModel* menuModel = appListMenu_->menu_model();
217 if (menuModel->GetTypeAt(index) == ui::MenuModel::TYPE_SEPARATOR) {
218 [menu addItem:[NSMenuItem separatorItem]];
219 return;
220 }
221
222 string16 labelText = menuModel->GetLabelAt(index);
223 scoped_nsobject<NSMenuItem> item(
224 [[NSMenuItem alloc] initWithTitle:base::SysUTF16ToNSString(labelText)
225 action:@selector(menuItemSelected:)
226 keyEquivalent:[NSString string]]);
227 [item setTag:index];
228 [item setTarget:self];
229
230 if (menuModel->GetCommandIdAt(index) == app_list::AppListMenu::CURRENT_USER) {
231 scoped_nsobject<NSView> customItemView([[CurrentUserMenuItemView alloc]
232 initWithDelegate:[delegate_ appListDelegate]
233 usingFont:[menu font]]);
234
235 [item setView:customItemView];
236 }
237
238 [menu addItem:item];
239 }
240
241 - (NSRect)confinementRectForMenu:(NSMenu*)menu
242 onScreen:(NSScreen*)screen {
243 // Ensure the menu comes up below the menu button by trimming the window frame
244 // to a point anchored below the bottom right of the button.
245 NSPoint anchor = NSMakePoint(kMenuButtonDimension,
246 kMenuButtonDimension + kMenuOffsetFromButton);
247 anchor = [menuButton_ convertPoint:anchor
248 toView:nil];
249 anchor = [[menuButton_ window] convertBaseToScreen:anchor];
250 NSRect rect = [[menuButton_ window] frame];
251 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+
252 return rect;
150 } 253 }
151 254
152 - (BOOL)control:(NSControl*)control 255 - (BOOL)control:(NSControl*)control
153 textView:(NSTextView*)textView 256 textView:(NSTextView*)textView
154 doCommandBySelector:(SEL)command { 257 doCommandBySelector:(SEL)command {
155 // Forward the message first, to handle grid or search results navigation. 258 // Forward the message first, to handle grid or search results navigation.
156 BOOL handled = [delegate_ control:control 259 BOOL handled = [delegate_ control:control
157 textView:textView 260 textView:textView
158 doCommandBySelector:command]; 261 doCommandBySelector:command];
159 if (handled) 262 if (handled)
160 return YES; 263 return YES;
161 264
162 // Escape when there is text clears the search input. 265 // Escape when there is text clears the search input.
163 if (command == @selector(complete:)) { 266 if (command == @selector(complete:)) {
164 [self clearSearch]; 267 [self clearSearch];
165 return YES; 268 return YES;
166 } 269 }
167 270
168 return NO; 271 return NO;
169 } 272 }
170 273
171 - (void)controlTextDidChange:(NSNotification*)notification { 274 - (void)controlTextDidChange:(NSNotification*)notification {
172 if (bridge_) 275 if (bridge_)
173 bridge_->updateModel(base::SysNSStringToUTF16([searchInput_ stringValue])); 276 bridge_->updateModel(base::SysNSStringToUTF16([searchInput_ stringValue]));
174 277
175 [delegate_ modelTextDidChange]; 278 [delegate_ modelTextDidChange];
176 } 279 }
177 280
178 @end 281 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698