OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/ui/views/extensions/browser_action_overflow_menu_contro ller.h" | 5 #include "chrome/browser/ui/views/extensions/browser_action_overflow_menu_contro ller.h" |
6 | 6 |
7 #include "base/memory/scoped_vector.h" | |
7 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
8 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
9 #include "chrome/browser/extensions/extension_action.h" | 10 #include "chrome/browser/extensions/extension_action.h" |
10 #include "chrome/browser/extensions/extension_context_menu_model.h" | 11 #include "chrome/browser/extensions/extension_context_menu_model.h" |
11 #include "chrome/browser/extensions/extension_toolbar_model.h" | 12 #include "chrome/browser/extensions/extension_toolbar_model.h" |
12 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
13 #include "chrome/browser/ui/browser.h" | 14 #include "chrome/browser/ui/browser.h" |
14 #include "chrome/browser/ui/browser_list.h" | |
15 #include "chrome/browser/ui/views/extensions/browser_action_drag_data.h" | 15 #include "chrome/browser/ui/views/extensions/browser_action_drag_data.h" |
16 #include "chrome/browser/ui/views/toolbar/browser_action_view.h" | 16 #include "chrome/browser/ui/views/toolbar/browser_action_view.h" |
17 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h" | 17 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h" |
18 #include "extensions/browser/extension_registry.h" | 18 #include "extensions/browser/extension_registry.h" |
19 #include "extensions/common/extension.h" | 19 #include "extensions/common/extension.h" |
20 #include "extensions/common/extension_set.h" | 20 #include "extensions/common/extension_set.h" |
21 #include "ui/views/border.h" | |
22 #include "ui/views/controls/button/label_button_border.h" | |
23 #include "ui/views/controls/menu/menu_delegate.h" | |
21 #include "ui/views/controls/menu/menu_item_view.h" | 24 #include "ui/views/controls/menu/menu_item_view.h" |
22 #include "ui/views/controls/menu/menu_runner.h" | 25 #include "ui/views/controls/menu/menu_runner.h" |
26 #include "ui/views/metrics.h" | |
27 | |
28 namespace { | |
23 | 29 |
24 // In the browser actions container's chevron menu, a menu item view's icon | 30 // In the browser actions container's chevron menu, a menu item view's icon |
25 // comes from BrowserActionView::GetIconWithBadge() when the menu item view is | 31 // comes from BrowserActionView::GetIconWithBadge() when the menu item view is |
26 // created. But, the browser action's icon may not be loaded in time because it | 32 // created. But, the browser action's icon may not be loaded in time because it |
27 // is read from file system in another thread. | 33 // is read from file system in another thread. |
28 // The IconUpdater will update the menu item view's icon when the browser | 34 // The IconUpdater will update the menu item view's icon when the browser |
29 // action's icon has been updated. | 35 // action's icon has been updated. |
30 class IconUpdater : public BrowserActionView::IconObserver { | 36 class IconUpdater : public BrowserActionView::IconObserver { |
31 public: | 37 public: |
32 IconUpdater(views::MenuItemView* menu_item_view, BrowserActionView* view) | 38 IconUpdater(views::MenuItemView* menu_item_view, BrowserActionView* view) |
33 : menu_item_view_(menu_item_view), | 39 : menu_item_view_(menu_item_view), |
34 view_(view) { | 40 view_(view) { |
35 DCHECK(menu_item_view); | 41 DCHECK(menu_item_view); |
36 DCHECK(view); | 42 DCHECK(view); |
37 view->set_icon_observer(this); | 43 view->set_icon_observer(this); |
38 } | 44 } |
39 virtual ~IconUpdater() { | 45 virtual ~IconUpdater() { |
40 view_->set_icon_observer(NULL); | 46 view_->set_icon_observer(NULL); |
41 } | 47 } |
42 | 48 |
43 // Overridden from BrowserActionView::IconObserver: | 49 // BrowserActionView::IconObserver: |
44 virtual void OnIconUpdated(const gfx::ImageSkia& icon) OVERRIDE { | 50 virtual void OnIconUpdated(const gfx::ImageSkia& icon) OVERRIDE { |
45 menu_item_view_->SetIcon(icon); | 51 menu_item_view_->SetIcon(icon); |
46 } | 52 } |
47 | 53 |
48 private: | 54 private: |
49 // The menu item view whose icon might be updated. | 55 // The menu item view whose icon might be updated. |
50 views::MenuItemView* menu_item_view_; | 56 views::MenuItemView* menu_item_view_; |
51 | 57 |
52 // The view to be observed. When its icon changes, update the corresponding | 58 // The view to be observed. When its icon changes, update the corresponding |
53 // menu item view's icon. | 59 // menu item view's icon. |
54 BrowserActionView* view_; | 60 BrowserActionView* view_; |
55 | 61 |
56 DISALLOW_COPY_AND_ASSIGN(IconUpdater); | 62 DISALLOW_COPY_AND_ASSIGN(IconUpdater); |
57 }; | 63 }; |
58 | 64 |
59 BrowserActionOverflowMenuController::BrowserActionOverflowMenuController( | 65 } // namespace |
60 BrowserActionsContainer* owner, | 66 |
61 Browser* browser, | 67 // This class handles the overflow menu for browser actions (showing the menu, |
62 views::MenuButton* menu_button, | 68 // drag and drop, etc). This class manages its own lifetime. |
63 const std::vector<BrowserActionView*>& views, | 69 class ChevronMenuButton::MenuController : public views::MenuDelegate { |
64 int start_index, | 70 public: |
71 MenuController(ChevronMenuButton* owner, | |
72 BrowserActionsContainer* browser_actions_container, | |
73 bool for_drop); | |
74 virtual ~MenuController(); | |
75 | |
76 // Shows the overflow menu. | |
77 void RunMenu(views::Widget* widget); | |
78 | |
79 // Closes the overflow menu (and its context menu if open as well). | |
80 void CloseMenu(); | |
81 | |
82 private: | |
83 // Overridden from views::MenuDelegate: | |
Peter Kasting
2014/09/25 01:06:43
Nit: "Overridden from" not necessary
Devlin
2014/09/25 15:56:49
Dang, caught it on line 49 but not here. Removed.
| |
84 virtual bool IsCommandEnabled(int id) const OVERRIDE; | |
85 virtual void ExecuteCommand(int id) OVERRIDE; | |
86 virtual bool ShowContextMenu(views::MenuItemView* source, | |
87 int id, | |
88 const gfx::Point& p, | |
89 ui::MenuSourceType source_type) OVERRIDE; | |
90 virtual void DropMenuClosed(views::MenuItemView* menu) OVERRIDE; | |
91 // These drag functions offer support for dragging icons into the overflow | |
92 // menu. | |
Peter Kasting
2014/09/25 01:06:43
So, MenuButton and MenuDelegate both have these dr
Devlin
2014/09/25 15:56:49
Unfortunately, there really isn't a good way. The
| |
93 virtual bool GetDropFormats( | |
94 views::MenuItemView* menu, | |
95 int* formats, | |
96 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) OVERRIDE; | |
97 virtual bool AreDropTypesRequired(views::MenuItemView* menu) OVERRIDE; | |
98 virtual bool CanDrop(views::MenuItemView* menu, | |
99 const ui::OSExchangeData& data) OVERRIDE; | |
100 virtual int GetDropOperation(views::MenuItemView* item, | |
101 const ui::DropTargetEvent& event, | |
102 DropPosition* position) OVERRIDE; | |
103 virtual int OnPerformDrop(views::MenuItemView* menu, | |
104 DropPosition position, | |
105 const ui::DropTargetEvent& event) OVERRIDE; | |
106 // These three drag functions offer support for dragging icons out of the | |
107 // overflow menu. | |
108 virtual bool CanDrag(views::MenuItemView* menu) OVERRIDE; | |
109 virtual void WriteDragData(views::MenuItemView* sender, | |
110 ui::OSExchangeData* data) OVERRIDE; | |
111 virtual int GetDragOperations(views::MenuItemView* sender) OVERRIDE; | |
112 | |
113 // Returns the offset into |views_| for the given |id|. | |
114 size_t IndexForId(int id) const; | |
115 | |
116 // The owning ChevronMenuButton. | |
117 ChevronMenuButton* owner_; | |
118 | |
119 // A pointer to the browser action container. | |
120 BrowserActionsContainer* browser_actions_container_; | |
121 | |
122 // The overflow menu for the menu button. Owned by |menu_runner_|. | |
123 views::MenuItemView* menu_; | |
124 | |
125 // Resposible for running the menu. | |
126 scoped_ptr<views::MenuRunner> menu_runner_; | |
127 | |
128 // The index into the BrowserActionView vector, indicating where to start | |
129 // picking browser actions to draw. | |
130 int start_index_; | |
131 | |
132 // Whether this controller is being used for drop. | |
133 bool for_drop_; | |
134 | |
135 // The vector keeps all icon updaters associated with menu item views in the | |
136 // controller. The icon updater will update the menu item view's icon when | |
137 // the browser action view's icon has been updated. | |
138 ScopedVector<IconUpdater> icon_updaters_; | |
139 | |
140 DISALLOW_COPY_AND_ASSIGN(MenuController); | |
141 }; | |
142 | |
143 ChevronMenuButton::MenuController::MenuController( | |
144 ChevronMenuButton* owner, | |
145 BrowserActionsContainer* browser_actions_container, | |
65 bool for_drop) | 146 bool for_drop) |
66 : owner_(owner), | 147 : owner_(owner), |
67 browser_(browser), | 148 browser_actions_container_(browser_actions_container), |
68 observer_(NULL), | |
69 menu_button_(menu_button), | |
70 menu_(NULL), | 149 menu_(NULL), |
71 views_(views), | 150 start_index_( |
72 start_index_(start_index), | 151 browser_actions_container_->VisibleBrowserActionsAfterAnimation()), |
73 for_drop_(for_drop) { | 152 for_drop_(for_drop) { |
74 menu_ = new views::MenuItemView(this); | 153 menu_ = new views::MenuItemView(this); |
75 menu_runner_.reset(new views::MenuRunner( | 154 menu_runner_.reset(new views::MenuRunner( |
76 menu_, for_drop_ ? views::MenuRunner::FOR_DROP : 0)); | 155 menu_, for_drop_ ? views::MenuRunner::FOR_DROP : 0)); |
77 menu_->set_has_icons(true); | 156 menu_->set_has_icons(true); |
78 | 157 |
79 size_t command_id = 1; // Menu id 0 is reserved, start with 1. | 158 size_t command_id = 1; // Menu id 0 is reserved, start with 1. |
80 for (size_t i = start_index; i < views_.size(); ++i) { | 159 for (size_t i = start_index_; |
81 BrowserActionView* view = views_[i]; | 160 i < browser_actions_container_->num_browser_actions(); ++i) { |
161 BrowserActionView* view = | |
162 browser_actions_container_->GetBrowserActionViewAt(i); | |
82 views::MenuItemView* menu_item = menu_->AppendMenuItemWithIcon( | 163 views::MenuItemView* menu_item = menu_->AppendMenuItemWithIcon( |
83 command_id, | 164 command_id, |
84 base::UTF8ToUTF16(view->extension()->name()), | 165 base::UTF8ToUTF16(view->extension()->name()), |
85 view->GetIconWithBadge()); | 166 view->GetIconWithBadge()); |
86 | 167 |
87 // Set the tooltip for this item. | 168 // Set the tooltip for this item. |
88 base::string16 tooltip = base::UTF8ToUTF16( | 169 base::string16 tooltip = base::UTF8ToUTF16( |
89 view->extension_action()->GetTitle( | 170 view->extension_action()->GetTitle( |
90 view->view_controller()->GetCurrentTabId())); | 171 view->view_controller()->GetCurrentTabId())); |
91 menu_->SetTooltip(tooltip, command_id); | 172 menu_->SetTooltip(tooltip, command_id); |
92 | 173 |
93 icon_updaters_.push_back(new IconUpdater(menu_item, view)); | 174 icon_updaters_.push_back(new IconUpdater(menu_item, view)); |
94 | 175 |
95 ++command_id; | 176 ++command_id; |
96 } | 177 } |
97 } | 178 } |
98 | 179 |
99 BrowserActionOverflowMenuController::~BrowserActionOverflowMenuController() { | 180 ChevronMenuButton::MenuController::~MenuController() { |
100 if (observer_) | |
101 observer_->NotifyMenuDeleted(this); | |
102 } | 181 } |
103 | 182 |
104 bool BrowserActionOverflowMenuController::RunMenu(views::Widget* window) { | 183 void ChevronMenuButton::MenuController::RunMenu(views::Widget* window) { |
105 gfx::Rect bounds = menu_button_->bounds(); | 184 gfx::Rect bounds = owner_->bounds(); |
106 gfx::Point screen_loc; | 185 gfx::Point screen_loc; |
107 views::View::ConvertPointToScreen(menu_button_, &screen_loc); | 186 views::View::ConvertPointToScreen(owner_, &screen_loc); |
108 bounds.set_x(screen_loc.x()); | 187 bounds.set_x(screen_loc.x()); |
109 bounds.set_y(screen_loc.y()); | 188 bounds.set_y(screen_loc.y()); |
110 | 189 |
111 views::MenuAnchorPosition anchor = views::MENU_ANCHOR_TOPRIGHT; | 190 if (menu_runner_->RunMenuAt(window, |
112 // As we maintain our own lifetime we can safely ignore the result. | 191 owner_, |
113 ignore_result(menu_runner_->RunMenuAt( | 192 bounds, |
114 window, menu_button_, bounds, anchor, ui::MENU_SOURCE_NONE)); | 193 views::MENU_ANCHOR_TOPRIGHT, |
194 ui::MENU_SOURCE_NONE) == | |
195 views::MenuRunner::MENU_DELETED) | |
196 return; | |
197 | |
115 if (!for_drop_) { | 198 if (!for_drop_) { |
116 // Give the context menu (if any) a chance to execute the user-selected | 199 // Give the context menu (if any) a chance to execute the user-selected |
117 // command. | 200 // command. |
118 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 201 base::MessageLoop::current()->PostTask( |
202 FROM_HERE, | |
203 base::Bind(&ChevronMenuButton::MenuDone, | |
204 owner_->weak_factory_.GetWeakPtr())); | |
119 } | 205 } |
120 return true; | |
121 } | 206 } |
122 | 207 |
123 void BrowserActionOverflowMenuController::CancelMenu() { | 208 void ChevronMenuButton::MenuController::CloseMenu() { |
124 menu_->Cancel(); | 209 menu_->Cancel(); |
125 } | 210 } |
126 | 211 |
127 void BrowserActionOverflowMenuController::NotifyBrowserActionViewsDeleting() { | 212 bool ChevronMenuButton::MenuController::IsCommandEnabled(int id) const { |
128 icon_updaters_.clear(); | 213 BrowserActionView* view = |
129 } | 214 browser_actions_container_->GetBrowserActionViewAt(start_index_ + id - 1); |
130 | |
131 bool BrowserActionOverflowMenuController::IsCommandEnabled(int id) const { | |
132 BrowserActionView* view = views_[start_index_ + id - 1]; | |
133 return view->IsEnabled(view->view_controller()->GetCurrentTabId()); | 215 return view->IsEnabled(view->view_controller()->GetCurrentTabId()); |
134 } | 216 } |
135 | 217 |
136 void BrowserActionOverflowMenuController::ExecuteCommand(int id) { | 218 void ChevronMenuButton::MenuController::ExecuteCommand(int id) { |
137 views_[start_index_ + id - 1]->view_controller()->ExecuteActionByUser(); | 219 browser_actions_container_->GetBrowserActionViewAt(start_index_ + id - 1)-> |
220 view_controller()->ExecuteActionByUser(); | |
138 } | 221 } |
139 | 222 |
140 bool BrowserActionOverflowMenuController::ShowContextMenu( | 223 bool ChevronMenuButton::MenuController::ShowContextMenu( |
141 views::MenuItemView* source, | 224 views::MenuItemView* source, |
142 int id, | 225 int id, |
143 const gfx::Point& p, | 226 const gfx::Point& p, |
144 ui::MenuSourceType source_type) { | 227 ui::MenuSourceType source_type) { |
145 BrowserActionView* view = views_[start_index_ + id - 1]; | 228 BrowserActionView* view = browser_actions_container_->GetBrowserActionViewAt( |
229 start_index_ + id - 1); | |
146 if (!view->extension()->ShowConfigureContextMenus()) | 230 if (!view->extension()->ShowConfigureContextMenus()) |
147 return false; | 231 return false; |
148 | 232 |
149 scoped_refptr<ExtensionContextMenuModel> context_menu_contents = | 233 scoped_refptr<ExtensionContextMenuModel> context_menu_contents = |
150 new ExtensionContextMenuModel( | 234 new ExtensionContextMenuModel(view->extension(), |
151 view->extension(), browser_, view->view_controller()); | 235 view->view_controller()->browser(), |
236 view->view_controller()); | |
152 views::MenuRunner context_menu_runner(context_menu_contents.get(), | 237 views::MenuRunner context_menu_runner(context_menu_contents.get(), |
153 views::MenuRunner::HAS_MNEMONICS | | 238 views::MenuRunner::HAS_MNEMONICS | |
154 views::MenuRunner::IS_NESTED | | 239 views::MenuRunner::IS_NESTED | |
155 views::MenuRunner::CONTEXT_MENU); | 240 views::MenuRunner::CONTEXT_MENU); |
156 | 241 |
157 // We can ignore the result as we delete ourself. | 242 // We can ignore the result as we delete ourself. |
158 // This blocks until the user choses something or dismisses the menu. | 243 // This blocks until the user chooses something or dismisses the menu. |
159 ignore_result(context_menu_runner.RunMenuAt(menu_button_->GetWidget(), | 244 if (context_menu_runner.RunMenuAt(owner_->GetWidget(), |
160 NULL, | 245 NULL, |
161 gfx::Rect(p, gfx::Size()), | 246 gfx::Rect(p, gfx::Size()), |
162 views::MENU_ANCHOR_TOPLEFT, | 247 views::MENU_ANCHOR_TOPLEFT, |
163 source_type)); | 248 source_type) == |
249 views::MenuRunner::MENU_DELETED) | |
250 return true; | |
164 | 251 |
165 // The user is done with the context menu, so we can close the underlying | 252 // The user is done with the context menu, so we can close the underlying |
166 // menu. | 253 // menu. |
167 menu_->Cancel(); | 254 menu_->Cancel(); |
168 | 255 |
169 return true; | 256 return true; |
170 } | 257 } |
171 | 258 |
172 void BrowserActionOverflowMenuController::DropMenuClosed( | 259 void ChevronMenuButton::MenuController::DropMenuClosed( |
173 views::MenuItemView* menu) { | 260 views::MenuItemView* menu) { |
174 delete this; | 261 owner_->MenuDone(); |
175 } | 262 } |
176 | 263 |
177 bool BrowserActionOverflowMenuController::GetDropFormats( | 264 bool ChevronMenuButton::MenuController::GetDropFormats( |
178 views::MenuItemView* menu, | 265 views::MenuItemView* menu, |
179 int* formats, | 266 int* formats, |
180 std::set<OSExchangeData::CustomFormat>* custom_formats) { | 267 std::set<OSExchangeData::CustomFormat>* custom_formats) { |
181 return BrowserActionDragData::GetDropFormats(custom_formats); | 268 return BrowserActionDragData::GetDropFormats(custom_formats); |
182 } | 269 } |
183 | 270 |
184 bool BrowserActionOverflowMenuController::AreDropTypesRequired( | 271 bool ChevronMenuButton::MenuController::AreDropTypesRequired( |
185 views::MenuItemView* menu) { | 272 views::MenuItemView* menu) { |
186 return BrowserActionDragData::AreDropTypesRequired(); | 273 return BrowserActionDragData::AreDropTypesRequired(); |
187 } | 274 } |
188 | 275 |
189 bool BrowserActionOverflowMenuController::CanDrop( | 276 bool ChevronMenuButton::MenuController::CanDrop( |
190 views::MenuItemView* menu, const OSExchangeData& data) { | 277 views::MenuItemView* menu, const OSExchangeData& data) { |
191 return BrowserActionDragData::CanDrop(data, owner_->profile()); | 278 return BrowserActionDragData::CanDrop(data, |
279 browser_actions_container_->profile()); | |
192 } | 280 } |
193 | 281 |
194 int BrowserActionOverflowMenuController::GetDropOperation( | 282 int ChevronMenuButton::MenuController::GetDropOperation( |
195 views::MenuItemView* item, | 283 views::MenuItemView* item, |
196 const ui::DropTargetEvent& event, | 284 const ui::DropTargetEvent& event, |
197 DropPosition* position) { | 285 DropPosition* position) { |
198 // Don't allow dropping from the BrowserActionContainer into slot 0 of the | 286 // Don't allow dropping from the BrowserActionContainer into slot 0 of the |
199 // overflow menu since once the move has taken place the item you are dragging | 287 // overflow menu since once the move has taken place the item you are dragging |
200 // falls right out of the menu again once the user releases the button | 288 // falls right out of the menu again once the user releases the button |
201 // (because we don't shrink the BrowserActionContainer when you do this). | 289 // (because we don't shrink the BrowserActionContainer when you do this). |
202 if ((item->GetCommand() == 0) && (*position == DROP_BEFORE)) { | 290 if ((item->GetCommand() == 0) && (*position == DROP_BEFORE)) { |
203 BrowserActionDragData drop_data; | 291 BrowserActionDragData drop_data; |
204 if (!drop_data.Read(event.data())) | 292 if (!drop_data.Read(event.data())) |
205 return ui::DragDropTypes::DRAG_NONE; | 293 return ui::DragDropTypes::DRAG_NONE; |
206 | 294 |
207 if (drop_data.index() < owner_->VisibleBrowserActions()) | 295 if (drop_data.index() < browser_actions_container_->VisibleBrowserActions()) |
208 return ui::DragDropTypes::DRAG_NONE; | 296 return ui::DragDropTypes::DRAG_NONE; |
209 } | 297 } |
210 | 298 |
211 return ui::DragDropTypes::DRAG_MOVE; | 299 return ui::DragDropTypes::DRAG_MOVE; |
212 } | 300 } |
213 | 301 |
214 int BrowserActionOverflowMenuController::OnPerformDrop( | 302 int ChevronMenuButton::MenuController::OnPerformDrop( |
215 views::MenuItemView* menu, | 303 views::MenuItemView* menu, |
216 DropPosition position, | 304 DropPosition position, |
217 const ui::DropTargetEvent& event) { | 305 const ui::DropTargetEvent& event) { |
218 BrowserActionDragData drop_data; | 306 BrowserActionDragData drop_data; |
219 if (!drop_data.Read(event.data())) | 307 if (!drop_data.Read(event.data())) |
220 return ui::DragDropTypes::DRAG_NONE; | 308 return ui::DragDropTypes::DRAG_NONE; |
221 | 309 |
222 size_t drop_index = IndexForId(menu->GetCommand()); | 310 size_t drop_index = IndexForId(menu->GetCommand()); |
223 | 311 |
224 // When not dragging within the overflow menu (dragging an icon into the menu) | 312 // When not dragging within the overflow menu (dragging an icon into the menu) |
225 // subtract one to get the right index. | 313 // subtract one to get the right index. |
226 if (position == DROP_BEFORE && | 314 if (position == DROP_BEFORE && |
227 drop_data.index() < owner_->VisibleBrowserActions()) | 315 drop_data.index() < browser_actions_container_->VisibleBrowserActions()) |
228 --drop_index; | 316 --drop_index; |
229 | 317 |
318 Profile* profile = browser_actions_container_->profile(); | |
230 // Move the extension in the model. | 319 // Move the extension in the model. |
231 const extensions::Extension* extension = | 320 const extensions::Extension* extension = |
232 extensions::ExtensionRegistry::Get(browser_->profile())-> | 321 extensions::ExtensionRegistry::Get(profile)-> |
233 enabled_extensions().GetByID(drop_data.id()); | 322 enabled_extensions().GetByID(drop_data.id()); |
234 extensions::ExtensionToolbarModel* toolbar_model = | 323 extensions::ExtensionToolbarModel* toolbar_model = |
235 extensions::ExtensionToolbarModel::Get(browser_->profile()); | 324 extensions::ExtensionToolbarModel::Get(profile); |
236 if (browser_->profile()->IsOffTheRecord()) | 325 if (profile->IsOffTheRecord()) |
237 drop_index = toolbar_model->IncognitoIndexToOriginal(drop_index); | 326 drop_index = toolbar_model->IncognitoIndexToOriginal(drop_index); |
238 toolbar_model->MoveExtensionIcon(extension, drop_index); | 327 toolbar_model->MoveExtensionIcon(extension, drop_index); |
239 | 328 |
240 // If the extension was moved to the overflow menu from the main bar, notify | 329 // If the extension was moved to the overflow menu from the main bar, notify |
241 // the owner. | 330 // the owner. |
242 if (drop_data.index() < owner_->VisibleBrowserActions()) | 331 if (drop_data.index() < browser_actions_container_->VisibleBrowserActions()) |
243 owner_->NotifyActionMovedToOverflow(); | 332 browser_actions_container_->NotifyActionMovedToOverflow(); |
244 | 333 |
245 if (for_drop_) | 334 if (for_drop_) |
246 delete this; | 335 owner_->MenuDone(); |
247 return ui::DragDropTypes::DRAG_MOVE; | 336 return ui::DragDropTypes::DRAG_MOVE; |
248 } | 337 } |
249 | 338 |
250 bool BrowserActionOverflowMenuController::CanDrag(views::MenuItemView* menu) { | 339 bool ChevronMenuButton::MenuController::CanDrag(views::MenuItemView* menu) { |
251 return true; | 340 return true; |
252 } | 341 } |
253 | 342 |
254 void BrowserActionOverflowMenuController::WriteDragData( | 343 void ChevronMenuButton::MenuController::WriteDragData( |
255 views::MenuItemView* sender, OSExchangeData* data) { | 344 views::MenuItemView* sender, OSExchangeData* data) { |
256 size_t drag_index = IndexForId(sender->GetCommand()); | 345 size_t drag_index = IndexForId(sender->GetCommand()); |
257 const extensions::Extension* extension = views_[drag_index]->extension(); | 346 const extensions::Extension* extension = |
347 browser_actions_container_->GetBrowserActionViewAt(drag_index)-> | |
348 extension(); | |
258 BrowserActionDragData drag_data(extension->id(), drag_index); | 349 BrowserActionDragData drag_data(extension->id(), drag_index); |
259 drag_data.Write(owner_->profile(), data); | 350 drag_data.Write(browser_actions_container_->profile(), data); |
260 } | 351 } |
261 | 352 |
262 int BrowserActionOverflowMenuController::GetDragOperations( | 353 int ChevronMenuButton::MenuController::GetDragOperations( |
263 views::MenuItemView* sender) { | 354 views::MenuItemView* sender) { |
264 return ui::DragDropTypes::DRAG_MOVE; | 355 return ui::DragDropTypes::DRAG_MOVE; |
265 } | 356 } |
266 | 357 |
267 size_t BrowserActionOverflowMenuController::IndexForId(int id) const { | 358 size_t ChevronMenuButton::MenuController::IndexForId(int id) const { |
268 // The index of the view being dragged (GetCommand gives a 1-based index into | 359 // The index of the view being dragged (GetCommand gives a 1-based index into |
269 // the overflow menu). | 360 // the overflow menu). |
270 DCHECK_GT(owner_->VisibleBrowserActions() + id, 0u); | 361 DCHECK_GT(browser_actions_container_->VisibleBrowserActions() + id, 0u); |
271 return owner_->VisibleBrowserActions() + id - 1; | 362 return browser_actions_container_->VisibleBrowserActions() + id - 1; |
272 } | 363 } |
364 | |
365 ChevronMenuButton::ChevronMenuButton( | |
366 BrowserActionsContainer* browser_actions_container) | |
367 : views::MenuButton(NULL, base::string16(), this, false), | |
368 browser_actions_container_(browser_actions_container), | |
369 weak_factory_(this) { | |
370 } | |
371 | |
372 ChevronMenuButton::~ChevronMenuButton() { | |
373 } | |
374 | |
375 void ChevronMenuButton::CloseMenu() { | |
376 if (menu_controller_.get()) | |
377 menu_controller_->CloseMenu(); | |
378 } | |
379 | |
380 scoped_ptr<views::LabelButtonBorder> ChevronMenuButton::CreateDefaultBorder() | |
381 const { | |
382 // The chevron resource was designed to not have any insets. | |
383 scoped_ptr<views::LabelButtonBorder> border = | |
384 views::MenuButton::CreateDefaultBorder(); | |
385 border->set_insets(gfx::Insets()); | |
386 return border.Pass(); | |
387 } | |
388 | |
389 bool ChevronMenuButton::GetDropFormats( | |
390 int* formats, | |
391 std::set<OSExchangeData::CustomFormat>* custom_formats) { | |
392 return BrowserActionDragData::GetDropFormats(custom_formats); | |
393 } | |
394 | |
395 bool ChevronMenuButton::AreDropTypesRequired() { | |
396 return BrowserActionDragData::AreDropTypesRequired(); | |
397 } | |
398 | |
399 bool ChevronMenuButton::CanDrop(const OSExchangeData& data) { | |
400 return BrowserActionDragData::CanDrop( | |
401 data, browser_actions_container_->profile()); | |
402 } | |
403 | |
404 void ChevronMenuButton::OnDragEntered(const ui::DropTargetEvent& event) { | |
405 DCHECK(!weak_factory_.HasWeakPtrs()); | |
406 base::MessageLoop::current()->PostDelayedTask( | |
407 FROM_HERE, | |
408 base::Bind(&ChevronMenuButton::ShowOverflowMenu, | |
409 weak_factory_.GetWeakPtr(), | |
410 true), | |
411 base::TimeDelta::FromMilliseconds(views::GetMenuShowDelay())); | |
412 } | |
413 | |
414 int ChevronMenuButton::OnDragUpdated(const ui::DropTargetEvent& event) { | |
415 return ui::DragDropTypes::DRAG_MOVE; | |
416 } | |
417 | |
418 void ChevronMenuButton::OnDragExited() { | |
419 weak_factory_.InvalidateWeakPtrs(); | |
420 } | |
421 | |
422 int ChevronMenuButton::OnPerformDrop(const ui::DropTargetEvent& event) { | |
423 return ui::DragDropTypes::DRAG_MOVE; | |
424 } | |
425 | |
426 void ChevronMenuButton::OnMenuButtonClicked(views::View* source, | |
427 const gfx::Point& point) { | |
428 DCHECK_EQ(this, source); | |
429 ShowOverflowMenu(false); | |
430 } | |
431 | |
432 void ChevronMenuButton::ShowOverflowMenu(bool for_drop) { | |
433 DCHECK(!menu_controller_.get()); | |
434 menu_controller_.reset(new MenuController( | |
435 this, browser_actions_container_, for_drop)); | |
436 menu_controller_->RunMenu(GetWidget()); | |
437 } | |
438 | |
439 void ChevronMenuButton::MenuDone() { | |
440 menu_controller_.reset(); | |
441 } | |
OLD | NEW |