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& rb = ui::ResourceBundle::GetSharedInstance(); |
156 [searchTextField_ setDelegate:self]; | 196 [searchTextField_ setDelegate:self]; |
157 [searchTextField_ setFont:ui::ResourceBundle::GetSharedInstance().GetFont( | 197 [searchTextField_ setFont:rb.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] setDefaultImage: |
| 212 rb.GetNativeImageNamed(IDR_APP_LIST_TOOLS_NORMAL).AsNSImage()]; |
| 213 [[menuButton_ hoverImageMenuButtonCell] setAlternateImage: |
| 214 rb.GetNativeImageNamed(IDR_APP_LIST_TOOLS_PRESSED).AsNSImage()]; |
| 215 [[menuButton_ hoverImageMenuButtonCell] setHoverImage: |
| 216 rb.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( |
| 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 |