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