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