OLD | NEW |
---|---|
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/mac/foundation_util.h" | 7 #include "base/mac/foundation_util.h" |
8 #include "base/strings/sys_string_conversions.h" | 8 #include "base/strings/sys_string_conversions.h" |
9 #include "grit/ui_resources.h" | |
9 #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h" | 10 #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h" |
11 #include "ui/app_list/app_list_menu.h" | |
12 #import "ui/app_list/cocoa/current_user_menu_item_view.h" | |
10 #include "ui/app_list/search_box_model.h" | 13 #include "ui/app_list/search_box_model.h" |
11 #include "ui/app_list/search_box_model_observer.h" | 14 #include "ui/app_list/search_box_model_observer.h" |
15 #import "ui/base/cocoa/controls/hover_image_menu_button.h" | |
16 #import "ui/base/cocoa/controls/hover_image_menu_button_cell.h" | |
17 #import "ui/base/cocoa/menu_controller.h" | |
12 #include "ui/base/resource/resource_bundle.h" | 18 #include "ui/base/resource/resource_bundle.h" |
13 #include "ui/gfx/image/image_skia_util_mac.h" | 19 #include "ui/gfx/image/image_skia_util_mac.h" |
14 | 20 |
15 namespace { | 21 namespace { |
16 | 22 |
17 // Padding either side of the search icon. | 23 // Padding either side of the search icon and menu button. |
18 const CGFloat kPadding = 14; | 24 const CGFloat kPadding = 14; |
19 | 25 |
20 // Size of the search icon. | 26 // Size of the search icon. |
21 const CGFloat kSearchIconDimension = 32; | 27 const CGFloat kSearchIconDimension = 32; |
22 | 28 |
29 // Size of the menu button on the right. | |
30 const CGFloat kMenuButtonDimension = 29; | |
31 | |
32 // Vertical offset that the menu should appear below the menu button. | |
33 const CGFloat kMenuOffsetFromButton = 2; | |
34 | |
23 } | 35 } |
24 | 36 |
25 @interface AppsSearchBoxController () | 37 @interface AppsSearchBoxController () |
26 | 38 |
27 - (NSImageView*)searchImageView; | 39 - (NSImageView*)searchImageView; |
28 - (void)addSubviews; | 40 - (void)addSubviews; |
29 | 41 |
30 @end | 42 @end |
31 | 43 |
32 namespace app_list { | 44 namespace app_list { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
105 NSRect textFrameInset_; | 117 NSRect textFrameInset_; |
106 } | 118 } |
107 | 119 |
108 @property(readonly, nonatomic) NSRect textFrameInset; | 120 @property(readonly, nonatomic) NSRect textFrameInset; |
109 | 121 |
110 - (void)setMarginsWithLeftMargin:(CGFloat)leftMargin | 122 - (void)setMarginsWithLeftMargin:(CGFloat)leftMargin |
111 rightMargin:(CGFloat)rightMargin; | 123 rightMargin:(CGFloat)rightMargin; |
112 | 124 |
113 @end | 125 @end |
114 | 126 |
127 @interface AppListMenuController : MenuController { | |
128 @private | |
129 AppsSearchBoxController* searchBoxController_; // Weak. Owns us. | |
130 } | |
131 | |
132 - (id)initWithSearchBoxController:(AppsSearchBoxController*)parent; | |
133 | |
134 @end | |
135 | |
115 @implementation AppsSearchBoxController | 136 @implementation AppsSearchBoxController |
116 | 137 |
117 @synthesize delegate = delegate_; | 138 @synthesize delegate = delegate_; |
118 | 139 |
119 - (id)initWithFrame:(NSRect)frame { | 140 - (id)initWithFrame:(NSRect)frame { |
120 if ((self = [super init])) { | 141 if ((self = [super init])) { |
121 scoped_nsobject<NSView> containerView([[NSView alloc] initWithFrame:frame]); | 142 scoped_nsobject<NSView> containerView([[NSView alloc] initWithFrame:frame]); |
122 [self setView:containerView]; | 143 [self setView:containerView]; |
123 [self addSubviews]; | 144 [self addSubviews]; |
124 } | 145 } |
125 return self; | 146 return self; |
126 } | 147 } |
127 | 148 |
128 - (void)clearSearch { | 149 - (void)clearSearch { |
129 [searchTextField_ setStringValue:@""]; | 150 [searchTextField_ setStringValue:@""]; |
130 [self controlTextDidChange:nil]; | 151 [self controlTextDidChange:nil]; |
131 } | 152 } |
132 | 153 |
133 - (void)setDelegate:(id<AppsSearchBoxDelegate>)delegate { | 154 - (void)setDelegate:(id<AppsSearchBoxDelegate>)delegate { |
155 [[menuButton_ menu] removeAllItems]; | |
156 menuController_.reset(); | |
157 appListMenu_.reset(); | |
134 bridge_.reset(); // Ensure observers are cleared before updating |delegate_|. | 158 bridge_.reset(); // Ensure observers are cleared before updating |delegate_|. |
135 delegate_ = delegate; | 159 delegate_ = delegate; |
136 if (!delegate_) | 160 if (!delegate_) |
137 return; | 161 return; |
138 | 162 |
139 bridge_.reset(new app_list::SearchBoxModelObserverBridge(self)); | 163 bridge_.reset(new app_list::SearchBoxModelObserverBridge(self)); |
164 if (![delegate_ appListDelegate]) | |
165 return; | |
166 | |
167 appListMenu_.reset(new app_list::AppListMenu([delegate_ appListDelegate])); | |
168 menuController_.reset([[AppListMenuController alloc] | |
169 initWithSearchBoxController:self]); | |
170 [menuButton_ setMenu:[menuController_ menu]]; // Menu will populate here. | |
140 } | 171 } |
141 | 172 |
142 - (NSTextField*)searchTextField { | 173 - (NSTextField*)searchTextField { |
143 return searchTextField_; | 174 return searchTextField_; |
144 } | 175 } |
145 | 176 |
177 - (NSPopUpButton*)menuControl { | |
178 return menuButton_; | |
179 } | |
180 | |
181 - (app_list::AppListMenu*)appListMenu { | |
182 return appListMenu_.get(); | |
183 } | |
184 | |
146 - (NSImageView*)searchImageView { | 185 - (NSImageView*)searchImageView { |
147 return searchImageView_; | 186 return searchImageView_; |
148 } | 187 } |
149 | 188 |
150 - (void)addSubviews { | 189 - (void)addSubviews { |
151 NSRect viewBounds = [[self view] bounds]; | 190 NSRect viewBounds = [[self view] bounds]; |
152 searchImageView_.reset([[NSImageView alloc] initWithFrame:NSMakeRect( | 191 searchImageView_.reset([[NSImageView alloc] initWithFrame:NSMakeRect( |
153 kPadding, 0, kSearchIconDimension, NSHeight(viewBounds))]); | 192 kPadding, 0, kSearchIconDimension, NSHeight(viewBounds))]); |
154 | 193 |
155 searchTextField_.reset([[SearchTextField alloc] initWithFrame:viewBounds]); | 194 searchTextField_.reset([[SearchTextField alloc] initWithFrame:viewBounds]); |
195 ui::ResourceBundle& resourceBundle = ui::ResourceBundle::GetSharedInstance(); | |
156 [searchTextField_ setDelegate:self]; | 196 [searchTextField_ setDelegate:self]; |
157 [searchTextField_ setFont:ui::ResourceBundle::GetSharedInstance().GetFont( | 197 [searchTextField_ setFont:resourceBundle.GetFont( |
158 ui::ResourceBundle::MediumFont).GetNativeFont()]; | 198 ui::ResourceBundle::MediumFont).GetNativeFont()]; |
159 [searchTextField_ | 199 [searchTextField_ |
160 setMarginsWithLeftMargin:NSMaxX([searchImageView_ frame]) + kPadding | 200 setMarginsWithLeftMargin:NSMaxX([searchImageView_ frame]) + kPadding |
161 rightMargin:kPadding]; | 201 rightMargin:kMenuButtonDimension + 2 * kPadding]; |
202 | |
203 // Add the drop-down menu, with a custom button. | |
204 NSRect buttonFrame = NSMakeRect( | |
205 NSWidth(viewBounds) - kMenuButtonDimension - kPadding, | |
206 floor(NSMidY(viewBounds) - kMenuButtonDimension / 2), | |
207 kMenuButtonDimension, | |
208 kMenuButtonDimension); | |
209 menuButton_.reset([[HoverImageMenuButton alloc] initWithFrame:buttonFrame | |
210 pullsDown:YES]); | |
211 [[menuButton_ hoverImageMenuButtonCell] setImage:resourceBundle. | |
212 GetNativeImageNamed(IDR_APP_LIST_TOOLS_NORMAL).AsNSImage()]; | |
213 [[menuButton_ hoverImageMenuButtonCell] setAlternateImage:resourceBundle. | |
214 GetNativeImageNamed(IDR_APP_LIST_TOOLS_PRESSED).AsNSImage()]; | |
215 [[menuButton_ hoverImageMenuButtonCell] setHoverImage:resourceBundle. | |
216 GetNativeImageNamed(IDR_APP_LIST_TOOLS_HOVER).AsNSImage()]; | |
162 | 217 |
163 [[self view] addSubview:searchImageView_]; | 218 [[self view] addSubview:searchImageView_]; |
164 [[self view] addSubview:searchTextField_]; | 219 [[self view] addSubview:searchTextField_]; |
220 [[self view] addSubview:menuButton_]; | |
165 } | 221 } |
166 | 222 |
167 - (BOOL)control:(NSControl*)control | 223 - (BOOL)control:(NSControl*)control |
168 textView:(NSTextView*)textView | 224 textView:(NSTextView*)textView |
169 doCommandBySelector:(SEL)command { | 225 doCommandBySelector:(SEL)command { |
170 // Forward the message first, to handle grid or search results navigation. | 226 // Forward the message first, to handle grid or search results navigation. |
171 BOOL handled = [delegate_ control:control | 227 BOOL handled = [delegate_ control:control |
172 textView:textView | 228 textView:textView |
173 doCommandBySelector:command]; | 229 doCommandBySelector:command]; |
174 if (handled) | 230 if (handled) |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
284 length:(NSInteger)length { | 340 length:(NSInteger)length { |
285 [super selectWithFrame:[self textFrameForFrame:cellFrame] | 341 [super selectWithFrame:[self textFrameForFrame:cellFrame] |
286 inView:controlView | 342 inView:controlView |
287 editor:editor | 343 editor:editor |
288 delegate:delegate | 344 delegate:delegate |
289 start:start | 345 start:start |
290 length:length]; | 346 length:length]; |
291 } | 347 } |
292 | 348 |
293 @end | 349 @end |
350 | |
351 @implementation AppListMenuController | |
352 | |
353 - (id)initWithSearchBoxController:(AppsSearchBoxController*)parent { | |
354 // Need to initialze super with a NULL model, otherwise it will immediately | |
355 // try to populate, which can't be done until setting the parent. | |
356 if ((self = [super initWithModel:NULL | |
357 useWithPopUpButtonCell:YES])) { | |
358 searchBoxController_ = parent; | |
359 [super setModel:[parent appListMenu]->menu_model()]; | |
360 } | |
361 return self; | |
362 } | |
363 | |
364 - (void)addItemToMenu:(NSMenu*)menu | |
365 atIndex:(NSInteger)index | |
366 fromModel:(ui::MenuModel*)model { | |
367 [super addItemToMenu:menu | |
368 atIndex:index | |
369 fromModel:model]; | |
370 if (model->GetCommandIdAt(index) != app_list::AppListMenu::CURRENT_USER) | |
371 return; | |
372 | |
373 scoped_nsobject<NSView> customItemView([[CurrentUserMenuItemView alloc] | |
374 initWithDelegate:[[searchBoxController_ delegate] appListDelegate]]); | |
375 [[menu itemAtIndex:index] setView:customItemView]; | |
376 } | |
377 | |
378 - (NSRect)confinementRectForMenu:(NSMenu*)menu | |
379 onScreen:(NSScreen*)screen { | |
380 NSPopUpButton* menuButton = [searchBoxController_ menuControl]; | |
381 // Ensure the menu comes up below the menu button by trimming the window frame | |
382 // to a point anchored below the bottom right of the button. | |
383 NSRect anchorRect = [menuButton convertRect:[menuButton bounds] | |
384 toView:nil]; | |
385 NSPoint anchorPoint = [[menuButton window] convertBaseToScreen:NSMakePoint( | |
sail
2013/06/11 00:55:22
convertBaseToScreen is deprecated
tapted
2013/06/11 02:32:44
I know... but convertRectToScreen is not available
sail
2013/06/11 18:01:24
Actually this looks ok. We do this everywhere else
| |
386 NSMaxX(anchorRect), | |
387 NSMinY(anchorRect) - kMenuOffsetFromButton)]; | |
388 NSRect confinementRect = [[menuButton window] frame]; | |
389 confinementRect.size = NSMakeSize(anchorPoint.x - NSMinX(confinementRect), | |
390 anchorPoint.y - NSMinY(confinementRect)); | |
391 return confinementRect; | |
392 } | |
393 | |
394 @end | |
OLD | NEW |