OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #include "views/controls/menu/menu_item_view.h" | 5 #include "views/controls/menu/menu_item_view.h" |
6 | 6 |
7 #include "base/utf_string_conversions.h" | 7 #include "base/utf_string_conversions.h" |
8 #include "grit/app_strings.h" | 8 #include "grit/app_strings.h" |
9 #include "ui/base/accessibility/accessible_view_state.h" | 9 #include "ui/base/accessibility/accessible_view_state.h" |
10 #include "ui/base/l10n/l10n_util.h" | 10 #include "ui/base/l10n/l10n_util.h" |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
94 Init(NULL, 0, SUBMENU, delegate); | 94 Init(NULL, 0, SUBMENU, delegate); |
95 } | 95 } |
96 | 96 |
97 MenuItemView::~MenuItemView() { | 97 MenuItemView::~MenuItemView() { |
98 // TODO(sky): ownership is bit wrong now. In particular if a nested message | 98 // TODO(sky): ownership is bit wrong now. In particular if a nested message |
99 // loop is running deletion can't be done, otherwise the stack gets | 99 // loop is running deletion can't be done, otherwise the stack gets |
100 // thoroughly screwed. The destructor should be made private, and | 100 // thoroughly screwed. The destructor should be made private, and |
101 // MenuController should be the only place handling deletion of the menu. | 101 // MenuController should be the only place handling deletion of the menu. |
102 // (57890). | 102 // (57890). |
103 delete submenu_; | 103 delete submenu_; |
104 DeleteRemovedItems(); | |
104 } | 105 } |
105 | 106 |
106 bool MenuItemView::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) { | 107 bool MenuItemView::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) { |
107 *tooltip = UTF16ToWideHack(tooltip_); | 108 *tooltip = UTF16ToWideHack(tooltip_); |
108 if (!tooltip->empty()) | 109 if (!tooltip->empty()) |
109 return true; | 110 return true; |
110 if (GetType() != SEPARATOR) { | 111 if (GetType() != SEPARATOR) { |
111 gfx::Point location(p); | 112 gfx::Point location(p); |
112 ConvertPointToScreen(this, &location); | 113 ConvertPointToScreen(this, &location); |
113 *tooltip = GetDelegate()->GetTooltipText(command_, location); | 114 *tooltip = GetDelegate()->GetTooltipText(command_, location); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
243 controller_->Run(parent, NULL, this, bounds, anchor, NULL); | 244 controller_->Run(parent, NULL, this, bounds, anchor, NULL); |
244 } | 245 } |
245 | 246 |
246 void MenuItemView::Cancel() { | 247 void MenuItemView::Cancel() { |
247 if (controller_ && !canceled_) { | 248 if (controller_ && !canceled_) { |
248 canceled_ = true; | 249 canceled_ = true; |
249 controller_->Cancel(MenuController::EXIT_ALL); | 250 controller_->Cancel(MenuController::EXIT_ALL); |
250 } | 251 } |
251 } | 252 } |
252 | 253 |
254 MenuItemView* MenuItemView::AddMenuItemAt(int index, | |
255 int item_id, | |
256 const std::wstring& label, | |
257 const SkBitmap& icon, | |
258 Type type) { | |
259 DCHECK_LE(0, index); | |
260 if (!submenu_) | |
261 CreateSubmenu(); | |
262 DCHECK_GE(submenu_->child_count(), index); | |
263 if (type == SEPARATOR) { | |
264 submenu_->AddChildViewAt(new MenuSeparator(), index); | |
265 return NULL; | |
266 } | |
267 MenuItemView* item = new MenuItemView(this, item_id, type); | |
268 if (label.empty() && GetDelegate()) | |
269 item->SetTitle(GetDelegate()->GetLabel(item_id)); | |
270 else | |
271 item->SetTitle(label); | |
272 item->SetIcon(icon); | |
273 if (type == SUBMENU) | |
274 item->CreateSubmenu(); | |
275 submenu_->AddChildViewAt(item, index); | |
276 return item; | |
277 } | |
278 | |
279 void MenuItemView::RemoveMenuItemAt(int index) | |
280 { | |
sky
2011/05/06 16:17:00
{ on previous line.
rhashimoto
2011/05/11 00:44:53
Done.
| |
281 DCHECK(submenu_); | |
282 DCHECK_LE(0, index); | |
283 DCHECK_GT(submenu_->child_count(), index); | |
284 | |
285 View* item = submenu_->GetChildViewAt(index); | |
286 DCHECK(item); | |
287 submenu_->RemoveChildView(item); | |
288 | |
289 // RemoveChildView() does not delete the item, which is a good thing | |
290 // in case a submenu is being displayed while items are being removed. | |
291 // Deletion will be done in DeleteRemovedItems(). | |
292 removed_items_.push_back(item); | |
sky
2011/05/06 16:17:00
Why do we need to do this? BookmarkMenuController
rhashimoto
2011/05/11 00:44:53
The use case is for the ChromiumOS network menu wh
| |
293 } | |
294 | |
253 MenuItemView* MenuItemView::AppendMenuItemFromModel(ui::MenuModel* model, | 295 MenuItemView* MenuItemView::AppendMenuItemFromModel(ui::MenuModel* model, |
254 int index, | 296 int index, |
255 int id) { | 297 int id) { |
256 SkBitmap icon; | 298 SkBitmap icon; |
257 bool has_icon = false; | 299 bool has_icon = false; |
258 std::wstring label; | 300 std::wstring label; |
259 MenuItemView::Type type; | 301 MenuItemView::Type type; |
260 ui::MenuModel::ItemType menu_type = model->GetTypeAt(index); | 302 ui::MenuModel::ItemType menu_type = model->GetTypeAt(index); |
261 switch (menu_type) { | 303 switch (menu_type) { |
262 case ui::MenuModel::TYPE_COMMAND: | 304 case ui::MenuModel::TYPE_COMMAND: |
(...skipping 22 matching lines...) Expand all Loading... | |
285 break; | 327 break; |
286 } | 328 } |
287 | 329 |
288 return AppendMenuItemImpl(id, label, has_icon ? icon : SkBitmap(), type); | 330 return AppendMenuItemImpl(id, label, has_icon ? icon : SkBitmap(), type); |
289 } | 331 } |
290 | 332 |
291 MenuItemView* MenuItemView::AppendMenuItemImpl(int item_id, | 333 MenuItemView* MenuItemView::AppendMenuItemImpl(int item_id, |
292 const std::wstring& label, | 334 const std::wstring& label, |
293 const SkBitmap& icon, | 335 const SkBitmap& icon, |
294 Type type) { | 336 Type type) { |
295 if (!submenu_) | 337 const int index = submenu_ ? submenu_->child_count() : 0; |
296 CreateSubmenu(); | 338 return AddMenuItemAt(index, item_id, label, icon, type); |
297 if (type == SEPARATOR) { | |
298 submenu_->AddChildView(new MenuSeparator()); | |
299 return NULL; | |
300 } | |
301 MenuItemView* item = new MenuItemView(this, item_id, type); | |
302 if (label.empty() && GetDelegate()) | |
303 item->SetTitle(GetDelegate()->GetLabel(item_id)); | |
304 else | |
305 item->SetTitle(label); | |
306 item->SetIcon(icon); | |
307 if (type == SUBMENU) | |
308 item->CreateSubmenu(); | |
309 submenu_->AddChildView(item); | |
310 return item; | |
311 } | 339 } |
312 | 340 |
313 SubmenuView* MenuItemView::CreateSubmenu() { | 341 SubmenuView* MenuItemView::CreateSubmenu() { |
314 if (!submenu_) | 342 if (!submenu_) |
315 submenu_ = new SubmenuView(this); | 343 submenu_ = new SubmenuView(this); |
316 return submenu_; | 344 return submenu_; |
317 } | 345 } |
318 | 346 |
319 bool MenuItemView::HasSubmenu() const { | 347 bool MenuItemView::HasSubmenu() const { |
320 return (submenu_ != NULL); | 348 return (submenu_ != NULL); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
413 GetMenuItemByID(id); | 441 GetMenuItemByID(id); |
414 if (result) | 442 if (result) |
415 return result; | 443 return result; |
416 } | 444 } |
417 } | 445 } |
418 return NULL; | 446 return NULL; |
419 } | 447 } |
420 | 448 |
421 void MenuItemView::ChildrenChanged() { | 449 void MenuItemView::ChildrenChanged() { |
422 MenuController* controller = GetMenuController(); | 450 MenuController* controller = GetMenuController(); |
423 if (!controller) | 451 if (controller) { |
424 return; // We're not showing, nothing to do. | 452 // Handles the case where we were empty and are no longer empty. |
453 RemoveEmptyMenus(); | |
425 | 454 |
426 // Handles the case where we were empty and are no longer empty. | 455 // Handles the case where we were not empty, but now are. |
427 RemoveEmptyMenus(); | 456 AddEmptyMenus(); |
428 | 457 |
429 // Handles the case where we were not empty, but now are. | 458 controller->MenuChildrenChanged(this); |
430 AddEmptyMenus(); | |
431 | 459 |
432 controller->MenuChildrenChanged(this); | 460 if (submenu_) { |
461 // Force a paint and layout. This handles the case of the top | |
462 // level window's size remaining the same, resulting in no | |
463 // change to the submenu's size and no layout. | |
464 submenu_->Layout(); | |
465 submenu_->SchedulePaint(); | |
466 } | |
467 } | |
433 | 468 |
434 if (submenu_) { | 469 DeleteRemovedItems(); |
435 // Force a paint and layout. This handles the case of the top level window's | |
436 // size remaining the same, resulting in no change to the submenu's size and | |
437 // no layout. | |
438 submenu_->Layout(); | |
439 submenu_->SchedulePaint(); | |
440 } | |
441 } | 470 } |
442 | 471 |
443 void MenuItemView::Layout() { | 472 void MenuItemView::Layout() { |
444 if (!has_children()) | 473 if (!has_children()) |
445 return; | 474 return; |
446 | 475 |
447 // Child views are laid out right aligned and given the full height. To right | 476 // Child views are laid out right aligned and given the full height. To right |
448 // align start with the last view and progress to the first. | 477 // align start with the last view and progress to the first. |
449 for (int i = child_count() - 1, x = width() - item_right_margin_; i >= 0; | 478 for (int i = child_count() - 1, x = width() - item_right_margin_; i >= 0; |
450 --i) { | 479 --i) { |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
682 return width; | 711 return width; |
683 } | 712 } |
684 | 713 |
685 string16 MenuItemView::GetAcceleratorText() { | 714 string16 MenuItemView::GetAcceleratorText() { |
686 Accelerator accelerator; | 715 Accelerator accelerator; |
687 return (GetDelegate() && | 716 return (GetDelegate() && |
688 GetDelegate()->GetAccelerator(GetCommand(), &accelerator)) ? | 717 GetDelegate()->GetAccelerator(GetCommand(), &accelerator)) ? |
689 accelerator.GetShortcutText() : string16(); | 718 accelerator.GetShortcutText() : string16(); |
690 } | 719 } |
691 | 720 |
721 void MenuItemView::DeleteRemovedItems() { | |
722 for (size_t i = 0; i < removed_items_.size(); ++i) | |
sky
2011/05/06 16:17:00
STLDeleteElements in each place instead of this me
rhashimoto
2011/05/11 00:44:53
Done.
| |
723 delete removed_items_[i]; | |
724 removed_items_.clear(); | |
725 } | |
726 | |
692 } // namespace views | 727 } // namespace views |
OLD | NEW |