bookmark_menu_controller_views.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.h"
6
7#include "base/prefs/pref_service.h"
8#include "base/stl_util.h"
9#include "base/strings/utf_string_conversions.h"
10#include "chrome/browser/bookmarks/bookmark_stats.h"
11#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
12#include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_observer.h"
13#include "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h"
14#include "chrome/common/pref_names.h"
15#include "components/bookmarks/browser/bookmark_model.h"
16#include "content/public/browser/page_navigator.h"
17#include "content/public/browser/user_metrics.h"
18#include "ui/base/dragdrop/os_exchange_data.h"
19#include "ui/views/controls/button/menu_button.h"
20#include "ui/views/controls/menu/menu_item_view.h"
21#include "ui/views/controls/menu/menu_runner.h"
22#include "ui/views/widget/widget.h"
23
24using base::UserMetricsAction;
25using content::PageNavigator;
26using views::MenuItemView;
27
28BookmarkMenuController::BookmarkMenuController(Browser* browser,
29                                               PageNavigator* page_navigator,
30                                               views::Widget* parent,
31                                               const BookmarkNode* node,
32                                               int start_child_index,
33                                               bool for_drop)
34    : menu_delegate_(
35        new BookmarkMenuDelegate(browser, page_navigator, parent, 1,
36                                 kint32max)),
37      node_(node),
38      observer_(NULL),
39      for_drop_(for_drop),
40      bookmark_bar_(NULL) {
41  menu_delegate_->Init(this, NULL, node, start_child_index,
42                       BookmarkMenuDelegate::HIDE_PERMANENT_FOLDERS,
43                       BOOKMARK_LAUNCH_LOCATION_BAR_SUBFOLDER);
44  menu_runner_.reset(new views::MenuRunner(
45      menu_delegate_->menu(), for_drop ? views::MenuRunner::FOR_DROP : 0));
46}
47
48void BookmarkMenuController::RunMenuAt(BookmarkBarView* bookmark_bar) {
49  bookmark_bar_ = bookmark_bar;
50  views::MenuButton* menu_button = bookmark_bar_->GetMenuButtonForNode(node_);
51  DCHECK(menu_button);
52  views::MenuAnchorPosition anchor;
53  bookmark_bar_->GetAnchorPositionForButton(menu_button, &anchor);
54  gfx::Point screen_loc;
55  views::View::ConvertPointToScreen(menu_button, &screen_loc);
56  // Subtract 1 from the height to make the popup flush with the button border.
57  gfx::Rect bounds(screen_loc.x(), screen_loc.y(), menu_button->width(),
58                   menu_button->height() - 1);
59  menu_delegate_->GetBookmarkModel()->AddObserver(this);
60  // We only delete ourself after the menu completes, so we can safely ignore
61  // the return value.
62  ignore_result(menu_runner_->RunMenuAt(menu_delegate_->parent(),
63                                        menu_button,
64                                        bounds,
65                                        anchor,
66                                        ui::MENU_SOURCE_NONE));
67  if (!for_drop_)
68    delete this;
69}
70
71void BookmarkMenuController::Cancel() {
72  menu_delegate_->menu()->Cancel();
73}
74
75MenuItemView* BookmarkMenuController::menu() const {
76  return menu_delegate_->menu();
77}
78
79MenuItemView* BookmarkMenuController::context_menu() const {
80  return menu_delegate_->context_menu();
81}
82
83void BookmarkMenuController::SetPageNavigator(PageNavigator* navigator) {
84  menu_delegate_->SetPageNavigator(navigator);
85}
86
87base::string16 BookmarkMenuController::GetTooltipText(int id,
88                                                const gfx::Point& p) const {
89  return menu_delegate_->GetTooltipText(id, p);
90}
91
92bool BookmarkMenuController::IsTriggerableEvent(views::MenuItemView* menu,
93                                                const ui::Event& e) {
94  return menu_delegate_->IsTriggerableEvent(menu, e);
95}
96
97void BookmarkMenuController::ExecuteCommand(int id, int mouse_event_flags) {
98  menu_delegate_->ExecuteCommand(id, mouse_event_flags);
99}
100
101bool BookmarkMenuController::ShouldExecuteCommandWithoutClosingMenu(
102      int id, const ui::Event& e) {
103  return menu_delegate_->ShouldExecuteCommandWithoutClosingMenu(id, e);
104}
105
106bool BookmarkMenuController::GetDropFormats(
107      MenuItemView* menu,
108      int* formats,
109      std::set<ui::OSExchangeData::CustomFormat>* custom_formats) {
110  return menu_delegate_->GetDropFormats(menu, formats, custom_formats);
111}
112
113bool BookmarkMenuController::AreDropTypesRequired(MenuItemView* menu) {
114  return menu_delegate_->AreDropTypesRequired(menu);
115}
116
117bool BookmarkMenuController::CanDrop(MenuItemView* menu,
118                                     const ui::OSExchangeData& data) {
119  return menu_delegate_->CanDrop(menu, data);
120}
121
122int BookmarkMenuController::GetDropOperation(
123    MenuItemView* item,
124    const ui::DropTargetEvent& event,
125    DropPosition* position) {
126  return menu_delegate_->GetDropOperation(item, event, position);
127}
128
129int BookmarkMenuController::OnPerformDrop(MenuItemView* menu,
130                                          DropPosition position,
131                                          const ui::DropTargetEvent& event) {
132  int result = menu_delegate_->OnPerformDrop(menu, position, event);
133  if (for_drop_)
134    delete this;
135  return result;
136}
137
138bool BookmarkMenuController::ShowContextMenu(MenuItemView* source,
139                                             int id,
140                                             const gfx::Point& p,
141                                             ui::MenuSourceType source_type) {
142  return menu_delegate_->ShowContextMenu(source, id, p, source_type);
143}
144
145void BookmarkMenuController::DropMenuClosed(MenuItemView* menu) {
146  delete this;
147}
148
149bool BookmarkMenuController::CanDrag(MenuItemView* menu) {
150  return menu_delegate_->CanDrag(menu);
151}
152
153void BookmarkMenuController::WriteDragData(MenuItemView* sender,
154                                           ui::OSExchangeData* data) {
155  return menu_delegate_->WriteDragData(sender, data);
156}
157
158int BookmarkMenuController::GetDragOperations(MenuItemView* sender) {
159  return menu_delegate_->GetDragOperations(sender);
160}
161
162views::MenuItemView* BookmarkMenuController::GetSiblingMenu(
163    views::MenuItemView* menu,
164    const gfx::Point& screen_point,
165    views::MenuAnchorPosition* anchor,
166    bool* has_mnemonics,
167    views::MenuButton** button) {
168  if (!bookmark_bar_ || for_drop_)
169    return NULL;
170  gfx::Point bookmark_bar_loc(screen_point);
171  views::View::ConvertPointFromScreen(bookmark_bar_, &bookmark_bar_loc);
172  int start_index;
173  const BookmarkNode* node = bookmark_bar_->GetNodeForButtonAtModelIndex(
174      bookmark_bar_loc, &start_index);
175  if (!node || !node->is_folder())
176    return NULL;
177
178  menu_delegate_->SetActiveMenu(node, start_index);
179  *button = bookmark_bar_->GetMenuButtonForNode(node);
180  bookmark_bar_->GetAnchorPositionForButton(*button, anchor);
181  *has_mnemonics = false;
182  return this->menu();
183}
184
185int BookmarkMenuController::GetMaxWidthForMenu(MenuItemView* view) {
186  return menu_delegate_->GetMaxWidthForMenu(view);
187}
188
189void BookmarkMenuController::BookmarkModelChanged() {
190  if (!menu_delegate_->is_mutating_model())
191    menu()->Cancel();
192}
193
194BookmarkMenuController::~BookmarkMenuController() {
195  menu_delegate_->GetBookmarkModel()->RemoveObserver(this);
196  if (observer_)
197    observer_->BookmarkMenuControllerDeleted(this);
198}
199