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

Side by Side Diff: views/controls/menu/menu_item_view.cc

Issue 7720012: Moves ownership of MenuItemView to MenuRunner as well as responbility (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix unit test Created 9 years, 4 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 (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/i18n/case_conversion.h" 7 #include "base/i18n/case_conversion.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "base/utf_string_conversions.h" 9 #include "base/utf_string_conversions.h"
10 #include "grit/ui_strings.h" 10 #include "grit/ui_strings.h"
11 #include "ui/base/accessibility/accessible_view_state.h" 11 #include "ui/base/accessibility/accessible_view_state.h"
12 #include "ui/base/l10n/l10n_util.h" 12 #include "ui/base/l10n/l10n_util.h"
13 #include "ui/base/models/menu_model.h" 13 #include "ui/base/models/menu_model.h"
14 #include "ui/gfx/canvas.h" 14 #include "ui/gfx/canvas.h"
15 #include "views/controls/button/menu_button.h" 15 #include "views/controls/button/menu_button.h"
16 #include "views/controls/button/text_button.h" 16 #include "views/controls/button/text_button.h"
17 #include "views/controls/menu/menu_config.h" 17 #include "views/controls/menu/menu_config.h"
18 #include "views/controls/menu/menu_controller.h" 18 #include "views/controls/menu/menu_controller.h"
19 #include "views/controls/menu/menu_separator.h" 19 #include "views/controls/menu/menu_separator.h"
20 #include "views/controls/menu/submenu_view.h" 20 #include "views/controls/menu/submenu_view.h"
21 21
22 #if defined(OS_WIN)
23 #include "base/win/win_util.h"
24 #endif
25
26 namespace views { 22 namespace views {
27 23
28 namespace { 24 namespace {
29 25
30 // EmptyMenuMenuItem --------------------------------------------------------- 26 // EmptyMenuMenuItem ---------------------------------------------------------
31 27
32 // EmptyMenuMenuItem is used when a menu has no menu items. EmptyMenuMenuItem 28 // EmptyMenuMenuItem is used when a menu has no menu items. EmptyMenuMenuItem
33 // is itself a MenuItemView, but it uses a different ID so that it isn't 29 // is itself a MenuItemView, but it uses a different ID so that it isn't
34 // identified as a MenuItemView. 30 // identified as a MenuItemView.
35 31
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 has_icons_(false), 89 has_icons_(false),
94 top_margin_(-1), 90 top_margin_(-1),
95 bottom_margin_(-1), 91 bottom_margin_(-1),
96 requested_menu_position_(POSITION_BEST_FIT), 92 requested_menu_position_(POSITION_BEST_FIT),
97 actual_menu_position_(requested_menu_position_) { 93 actual_menu_position_(requested_menu_position_) {
98 // NOTE: don't check the delegate for NULL, UpdateMenuPartSizes supplies a 94 // NOTE: don't check the delegate for NULL, UpdateMenuPartSizes supplies a
99 // NULL delegate. 95 // NULL delegate.
100 Init(NULL, 0, SUBMENU, delegate); 96 Init(NULL, 0, SUBMENU, delegate);
101 } 97 }
102 98
103 MenuItemView::~MenuItemView() {
104 // TODO(sky): ownership is bit wrong now. In particular if a nested message
105 // loop is running deletion can't be done, otherwise the stack gets
106 // thoroughly screwed. The destructor should be made private, and
107 // MenuController should be the only place handling deletion of the menu.
108 // (57890).
109 delete submenu_;
110 STLDeleteElements(&removed_items_);
111 }
112
113 void MenuItemView::ChildPreferredSizeChanged(View* child) { 99 void MenuItemView::ChildPreferredSizeChanged(View* child) {
114 pref_size_.SetSize(0, 0); 100 pref_size_.SetSize(0, 0);
115 PreferredSizeChanged(); 101 PreferredSizeChanged();
116 } 102 }
117 103
118 bool MenuItemView::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) { 104 bool MenuItemView::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) {
119 *tooltip = UTF16ToWideHack(tooltip_); 105 *tooltip = UTF16ToWideHack(tooltip_);
120 if (!tooltip->empty()) 106 if (!tooltip->empty())
121 return true; 107 return true;
122 108
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 171
186 // Append accelerator text. 172 // Append accelerator text.
187 if (!accelerator_text.empty()) { 173 if (!accelerator_text.empty()) {
188 accessible_name.push_back(' '); 174 accessible_name.push_back(' ');
189 accessible_name.append(accelerator_text); 175 accessible_name.append(accelerator_text);
190 } 176 }
191 177
192 return accessible_name; 178 return accessible_name;
193 } 179 }
194 180
195 void MenuItemView::RunMenuAt(Widget* parent,
196 MenuButton* button,
197 const gfx::Rect& bounds,
198 AnchorPosition anchor,
199 bool has_mnemonics) {
200 // Show mnemonics if the button has focus or alt is pressed.
201 bool show_mnemonics = button ? button->HasFocus() : false;
202 #if defined(OS_WIN)
203 // We don't currently need this on gtk as showing the menu gives focus to the
204 // button first.
205 if (!show_mnemonics)
206 show_mnemonics = base::win::IsAltPressed();
207 #endif
208 PrepareForRun(has_mnemonics, show_mnemonics);
209 int mouse_event_flags;
210
211 MenuController* controller = MenuController::GetActiveInstance();
212 if (controller && !controller->IsBlockingRun()) {
213 // A menu is already showing, but it isn't a blocking menu. Cancel it.
214 // We can get here during drag and drop if the user right clicks on the
215 // menu quickly after the drop.
216 controller->Cancel(MenuController::EXIT_ALL);
217 controller = NULL;
218 }
219 // TODO(sky): remove volatile, used in tracking 90860.
220 volatile bool owns_controller = false;
221 if (!controller) {
222 // No menus are showing, show one.
223 controller = new MenuController(true);
224 MenuController::SetActiveInstance(controller);
225 owns_controller = true;
226 } else {
227 // A menu is already showing, use the same controller.
228
229 // Don't support blocking from within non-blocking.
230 DCHECK(controller->IsBlockingRun());
231 }
232
233 controller_ = controller;
234
235 // Run the loop.
236 MenuItemView* result =
237 controller->Run(parent, button, this, bounds, anchor, &mouse_event_flags);
238
239 RemoveEmptyMenus();
240
241 controller_ = NULL;
242
243 if (owns_controller) {
244 // We created the controller and need to delete it.
245 if (MenuController::GetActiveInstance() == controller)
246 MenuController::SetActiveInstance(NULL);
247 delete controller;
248 }
249 // Make sure all the windows we created to show the menus have been
250 // destroyed.
251 DestroyAllMenuHosts();
252 if (result && delegate_)
253 delegate_->ExecuteCommand(result->GetCommand(), mouse_event_flags);
254 }
255
256 void MenuItemView::RunMenuForDropAt(Widget* parent,
257 const gfx::Rect& bounds,
258 AnchorPosition anchor) {
259 PrepareForRun(false, false);
260
261 // If there is a menu, hide it so that only one menu is shown during dnd.
262 MenuController* current_controller = MenuController::GetActiveInstance();
263 if (current_controller) {
264 current_controller->Cancel(MenuController::EXIT_ALL);
265 }
266
267 // Always create a new controller for non-blocking.
268 controller_ = new MenuController(false);
269
270 // Set the instance, that way it can be canceled by another menu.
271 MenuController::SetActiveInstance(controller_);
272
273 controller_->Run(parent, NULL, this, bounds, anchor, NULL);
274 }
275
276 void MenuItemView::Cancel() { 181 void MenuItemView::Cancel() {
277 if (controller_ && !canceled_) { 182 if (controller_ && !canceled_) {
278 canceled_ = true; 183 canceled_ = true;
279 controller_->Cancel(MenuController::EXIT_ALL); 184 controller_->Cancel(MenuController::EXIT_ALL);
280 } 185 }
281 } 186 }
282 187
283 MenuItemView* MenuItemView::AddMenuItemAt(int index, 188 MenuItemView* MenuItemView::AddMenuItemAt(int index,
284 int item_id, 189 int item_id,
285 const std::wstring& label, 190 const std::wstring& label,
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 has_mnemonics_(false), 457 has_mnemonics_(false),
553 show_mnemonics_(false), 458 show_mnemonics_(false),
554 has_icons_(false), 459 has_icons_(false),
555 top_margin_(-1), 460 top_margin_(-1),
556 bottom_margin_(-1), 461 bottom_margin_(-1),
557 requested_menu_position_(POSITION_BEST_FIT), 462 requested_menu_position_(POSITION_BEST_FIT),
558 actual_menu_position_(requested_menu_position_) { 463 actual_menu_position_(requested_menu_position_) {
559 Init(parent, command, type, NULL); 464 Init(parent, command, type, NULL);
560 } 465 }
561 466
467 MenuItemView::~MenuItemView() {
468 delete submenu_;
469 STLDeleteElements(&removed_items_);
470 }
471
562 std::string MenuItemView::GetClassName() const { 472 std::string MenuItemView::GetClassName() const {
563 return kViewClassName; 473 return kViewClassName;
564 } 474 }
565 475
566 // Calculates all sizes that we can from the OS. 476 // Calculates all sizes that we can from the OS.
567 // 477 //
568 // This is invoked prior to Running a menu. 478 // This is invoked prior to Running a menu.
569 void MenuItemView::UpdateMenuPartSizes(bool has_icons) { 479 void MenuItemView::UpdateMenuPartSizes(bool has_icons) {
570 MenuConfig::Reset(); 480 MenuConfig::Reset();
571 const MenuConfig& config = MenuConfig::instance(); 481 const MenuConfig& config = MenuConfig::instance();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 set_id(kMenuItemViewID); 516 set_id(kMenuItemViewID);
607 has_icons_ = false; 517 has_icons_ = false;
608 518
609 // Don't request enabled status from the root menu item as it is just 519 // Don't request enabled status from the root menu item as it is just
610 // a container for real items. EMPTY items will be disabled. 520 // a container for real items. EMPTY items will be disabled.
611 MenuDelegate* root_delegate = GetDelegate(); 521 MenuDelegate* root_delegate = GetDelegate();
612 if (parent && type != EMPTY && root_delegate) 522 if (parent && type != EMPTY && root_delegate)
613 SetEnabled(root_delegate->IsCommandEnabled(command)); 523 SetEnabled(root_delegate->IsCommandEnabled(command));
614 } 524 }
615 525
616 void MenuItemView::DropMenuClosed(bool notify_delegate) {
617 DCHECK(controller_);
618 DCHECK(!controller_->IsBlockingRun());
619 if (MenuController::GetActiveInstance() == controller_)
620 MenuController::SetActiveInstance(NULL);
621 delete controller_;
622 controller_ = NULL;
623
624 RemoveEmptyMenus();
625
626 if (notify_delegate && delegate_) {
627 // Our delegate is null when invoked from the destructor.
628 delegate_->DropMenuClosed(this);
629 }
630 // WARNING: its possible the delegate deleted us at this point.
631 }
632
633 void MenuItemView::PrepareForRun(bool has_mnemonics, bool show_mnemonics) { 526 void MenuItemView::PrepareForRun(bool has_mnemonics, bool show_mnemonics) {
634 // Currently we only support showing the root. 527 // Currently we only support showing the root.
635 DCHECK(!parent_menu_item_); 528 DCHECK(!parent_menu_item_);
636 529
637 // Force us to have a submenu. 530 // Force us to have a submenu.
638 CreateSubmenu(); 531 CreateSubmenu();
639 actual_menu_position_ = requested_menu_position_; 532 actual_menu_position_ = requested_menu_position_;
640 canceled_ = false; 533 canceled_ = false;
641 534
642 has_mnemonics_ = has_mnemonics; 535 has_mnemonics_ = has_mnemonics;
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 return string16(); 689 return string16();
797 } 690 }
798 691
799 Accelerator accelerator; 692 Accelerator accelerator;
800 return (GetDelegate() && 693 return (GetDelegate() &&
801 GetDelegate()->GetAccelerator(GetCommand(), &accelerator)) ? 694 GetDelegate()->GetAccelerator(GetCommand(), &accelerator)) ?
802 accelerator.GetShortcutText() : string16(); 695 accelerator.GetShortcutText() : string16();
803 } 696 }
804 697
805 } // namespace views 698 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698