Chromium Code Reviews| 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 |