OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "app/gfx/canvas.h" | 7 #include "app/gfx/canvas.h" |
8 #include "app/l10n_util.h" | 8 #include "app/l10n_util.h" |
9 #include "grit/app_strings.h" | 9 #include "grit/app_strings.h" |
10 #include "views/controls/menu/menu_config.h" | 10 #include "views/controls/menu/menu_config.h" |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 // static | 59 // static |
60 int MenuItemView::pref_menu_height_; | 60 int MenuItemView::pref_menu_height_; |
61 | 61 |
62 MenuItemView::MenuItemView(MenuDelegate* delegate) { | 62 MenuItemView::MenuItemView(MenuDelegate* delegate) { |
63 // NOTE: don't check the delegate for NULL, UpdateMenuPartSizes supplies a | 63 // NOTE: don't check the delegate for NULL, UpdateMenuPartSizes supplies a |
64 // NULL delegate. | 64 // NULL delegate. |
65 Init(NULL, 0, SUBMENU, delegate); | 65 Init(NULL, 0, SUBMENU, delegate); |
66 } | 66 } |
67 | 67 |
68 MenuItemView::~MenuItemView() { | 68 MenuItemView::~MenuItemView() { |
69 if (controller_) { | 69 // TODO(sky): ownership is bit wrong now. In particular if a nested message |
70 // We're currently showing. | 70 // loop is running deletion can't be done, otherwise the stack gets |
71 | 71 // thoroughly screwed. The destructor should be made private, and |
72 // We can't delete ourselves while we're blocking. | 72 // MenuController should be the only place handling deletion of the menu. |
73 DCHECK(!controller_->IsBlockingRun()); | |
74 | |
75 // Invoking Cancel is going to call us back and notify the delegate. | |
76 // Notifying the delegate from the destructor can be problematic. To avoid | |
77 // this the delegate is set to NULL. | |
78 delegate_ = NULL; | |
79 | |
80 controller_->Cancel(true); | |
81 } | |
82 delete submenu_; | 73 delete submenu_; |
83 } | 74 } |
84 | 75 |
85 void MenuItemView::RunMenuAt(gfx::NativeWindow parent, | 76 void MenuItemView::RunMenuAt(gfx::NativeWindow parent, |
| 77 MenuButton* button, |
86 const gfx::Rect& bounds, | 78 const gfx::Rect& bounds, |
87 AnchorPosition anchor, | 79 AnchorPosition anchor, |
88 bool has_mnemonics) { | 80 bool has_mnemonics) { |
89 PrepareForRun(has_mnemonics); | 81 PrepareForRun(has_mnemonics); |
90 | 82 |
91 int mouse_event_flags; | 83 int mouse_event_flags; |
92 | 84 |
93 MenuController* controller = MenuController::GetActiveInstance(); | 85 MenuController* controller = MenuController::GetActiveInstance(); |
94 if (controller && !controller->IsBlockingRun()) { | 86 if (controller && !controller->IsBlockingRun()) { |
95 // A menu is already showing, but it isn't a blocking menu. Cancel it. | 87 // A menu is already showing, but it isn't a blocking menu. Cancel it. |
(...skipping 12 matching lines...) Expand all Loading... |
108 // A menu is already showing, use the same controller. | 100 // A menu is already showing, use the same controller. |
109 | 101 |
110 // Don't support blocking from within non-blocking. | 102 // Don't support blocking from within non-blocking. |
111 DCHECK(controller->IsBlockingRun()); | 103 DCHECK(controller->IsBlockingRun()); |
112 } | 104 } |
113 | 105 |
114 controller_ = controller; | 106 controller_ = controller; |
115 | 107 |
116 // Run the loop. | 108 // Run the loop. |
117 MenuItemView* result = | 109 MenuItemView* result = |
118 controller->Run(parent, this, bounds, anchor, &mouse_event_flags); | 110 controller->Run(parent, button, this, bounds, anchor, &mouse_event_flags); |
119 | 111 |
120 RemoveEmptyMenus(); | 112 RemoveEmptyMenus(); |
121 | 113 |
122 controller_ = NULL; | 114 controller_ = NULL; |
123 | 115 |
124 if (owns_controller) { | 116 if (owns_controller) { |
125 // We created the controller and need to delete it. | 117 // We created the controller and need to delete it. |
126 if (MenuController::GetActiveInstance() == controller) | 118 if (MenuController::GetActiveInstance() == controller) |
127 MenuController::SetActiveInstance(NULL); | 119 MenuController::SetActiveInstance(NULL); |
128 delete controller; | 120 delete controller; |
(...skipping 15 matching lines...) Expand all Loading... |
144 if (current_controller) { | 136 if (current_controller) { |
145 current_controller->Cancel(true); | 137 current_controller->Cancel(true); |
146 } | 138 } |
147 | 139 |
148 // Always create a new controller for non-blocking. | 140 // Always create a new controller for non-blocking. |
149 controller_ = new MenuController(false); | 141 controller_ = new MenuController(false); |
150 | 142 |
151 // Set the instance, that way it can be canceled by another menu. | 143 // Set the instance, that way it can be canceled by another menu. |
152 MenuController::SetActiveInstance(controller_); | 144 MenuController::SetActiveInstance(controller_); |
153 | 145 |
154 controller_->Run(parent, this, bounds, anchor, NULL); | 146 controller_->Run(parent, NULL, this, bounds, anchor, NULL); |
155 } | 147 } |
156 | 148 |
157 void MenuItemView::Cancel() { | 149 void MenuItemView::Cancel() { |
158 if (controller_ && !canceled_) { | 150 if (controller_ && !canceled_) { |
159 canceled_ = true; | 151 canceled_ = true; |
160 controller_->Cancel(true); | 152 controller_->Cancel(true); |
161 } | 153 } |
162 } | 154 } |
163 | 155 |
164 SubmenuView* MenuItemView::CreateSubmenu() { | 156 SubmenuView* MenuItemView::CreateSubmenu() { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 // Our delegate is null when invoked from the destructor. | 322 // Our delegate is null when invoked from the destructor. |
331 delegate_->DropMenuClosed(this); | 323 delegate_->DropMenuClosed(this); |
332 } | 324 } |
333 // WARNING: its possible the delegate deleted us at this point. | 325 // WARNING: its possible the delegate deleted us at this point. |
334 } | 326 } |
335 | 327 |
336 void MenuItemView::PrepareForRun(bool has_mnemonics) { | 328 void MenuItemView::PrepareForRun(bool has_mnemonics) { |
337 // Currently we only support showing the root. | 329 // Currently we only support showing the root. |
338 DCHECK(!parent_menu_item_); | 330 DCHECK(!parent_menu_item_); |
339 | 331 |
340 // Don't invoke run from within run on the same menu. | |
341 DCHECK(!controller_); | |
342 | |
343 // Force us to have a submenu. | 332 // Force us to have a submenu. |
344 CreateSubmenu(); | 333 CreateSubmenu(); |
345 | 334 |
346 canceled_ = false; | 335 canceled_ = false; |
347 | 336 |
348 has_mnemonics_ = has_mnemonics; | 337 has_mnemonics_ = has_mnemonics; |
349 | 338 |
350 AddEmptyMenus(); | 339 AddEmptyMenus(); |
351 | 340 |
352 if (!MenuController::GetActiveInstance()) { | 341 if (!MenuController::GetActiveInstance()) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 } | 415 } |
427 | 416 |
428 int MenuItemView::GetBottomMargin() { | 417 int MenuItemView::GetBottomMargin() { |
429 MenuItemView* root = GetRootMenuItem(); | 418 MenuItemView* root = GetRootMenuItem(); |
430 return root && root->has_icons_ | 419 return root && root->has_icons_ |
431 ? MenuConfig::instance().item_bottom_margin : | 420 ? MenuConfig::instance().item_bottom_margin : |
432 MenuConfig::instance().item_no_icon_bottom_margin; | 421 MenuConfig::instance().item_no_icon_bottom_margin; |
433 } | 422 } |
434 | 423 |
435 } // namespace views | 424 } // namespace views |
OLD | NEW |