summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h
blob: 5e5b56f8f8c2fccad538df0c4e3763be7f12c1e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_VIEWS_BOOKMARKS_BOOKMARK_MENU_DELEGATE_H_
#define CHROME_BROWSER_UI_VIEWS_BOOKMARKS_BOOKMARK_MENU_DELEGATE_H_
#pragma once

#include <map>
#include <set>

#include "base/compiler_specific.h"
#include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
#include "chrome/browser/bookmarks/bookmark_node_data.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/ui/views/bookmarks/bookmark_context_menu.h"
#include "ui/views/controls/menu/menu_delegate.h"

class BookmarkNode;
class Profile;

namespace content {
class PageNavigator;
}

namespace ui {
class OSExchangeData;
}

namespace views {
class MenuItemView;
class Widget;
}

// BookmarkMenuDelegate acts as the (informal) views::MenuDelegate for showing
// bookmarks in a MenuItemView. BookmarkMenuDelegate informally implements
// MenuDelegate as its assumed another class is going to forward the appropriate
// methods to this class. Doing so allows this class to be used for both menus
// on the bookmark bar and the bookmarks in the wrench menu.
class BookmarkMenuDelegate : public BaseBookmarkModelObserver,
                             public BookmarkContextMenuObserver {
 public:
  enum ShowOptions {
    // Indicates a menu should be added containing the permanent folders (other
    // than then bookmark bar folder). This only makes sense when showing the
    // contents of the bookmark bar folder.
    SHOW_PERMANENT_FOLDERS,

    // Don't show any additional folders.
    HIDE_PERMANENT_FOLDERS
  };

  BookmarkMenuDelegate(Profile* profile,
                       content::PageNavigator* navigator,
                       views::Widget* parent,
                       int first_menu_id);
  virtual ~BookmarkMenuDelegate();

  // Creates the menus from the model.
  void Init(views::MenuDelegate* real_delegate,
            views::MenuItemView* parent,
            const BookmarkNode* node,
            int start_child_index,
            ShowOptions show_options,
            bookmark_utils::BookmarkLaunchLocation);

  // Sets the PageNavigator.
  void SetPageNavigator(content::PageNavigator* navigator);

  // Returns the id given to the next menu.
  int next_menu_id() const { return next_menu_id_; }

  // Makes the menu for |node| the active menu. |start_index| is the index of
  // the first child of |node| to show in the menu.
  void SetActiveMenu(const BookmarkNode* node, int start_index);

  // Returns the menu.
  views::MenuItemView* menu() const { return menu_; }

  // Returns the context menu, or NULL if the context menu isn't showing.
  views::MenuItemView* context_menu() const {
    return context_menu_.get() ? context_menu_->menu() : NULL;
  }

  Profile* profile() { return profile_; }

  views::Widget* parent() { return parent_; }

  // Returns true if we're in the process of mutating the model. This happens
  // when the user deletes menu items using the context menu.
  bool is_mutating_model() const { return is_mutating_model_; }

  // MenuDelegate like methods (see class description for details).
  string16 GetTooltipText(int id, const gfx::Point& p) const;
  bool IsTriggerableEvent(views::MenuItemView* menu,
                          const views::Event& e);
  void ExecuteCommand(int id, int mouse_event_flags);
  bool GetDropFormats(
      views::MenuItemView* menu,
      int* formats,
      std::set<ui::OSExchangeData::CustomFormat>* custom_formats);
  bool AreDropTypesRequired(views::MenuItemView* menu);
  bool CanDrop(views::MenuItemView* menu, const ui::OSExchangeData& data);
  int GetDropOperation(views::MenuItemView* item,
                       const views::DropTargetEvent& event,
                       views::MenuDelegate::DropPosition* position);
  int OnPerformDrop(views::MenuItemView* menu,
                    views::MenuDelegate::DropPosition position,
                    const views::DropTargetEvent& event);
  bool ShowContextMenu(views::MenuItemView* source,
                       int id,
                       const gfx::Point& p,
                       bool is_mouse_gesture);
  bool CanDrag(views::MenuItemView* menu);
  void WriteDragData(views::MenuItemView* sender, ui::OSExchangeData* data);
  int GetDragOperations(views::MenuItemView* sender);
  int GetMaxWidthForMenu(views::MenuItemView* menu);

  // BookmarkModelObserver methods.
  virtual void BookmarkModelChanged() OVERRIDE;
  virtual void BookmarkNodeFaviconChanged(BookmarkModel* model,
                                          const BookmarkNode* node) OVERRIDE;

  // BookmarkContextMenu::Observer methods.
  virtual void WillRemoveBookmarks(
      const std::vector<const BookmarkNode*>& bookmarks) OVERRIDE;
  virtual void DidRemoveBookmarks() OVERRIDE;

 private:
  typedef std::map<int, const BookmarkNode*> MenuIDToNodeMap;
  typedef std::map<const BookmarkNode*, int> NodeToMenuIDMap;
  typedef std::map<const BookmarkNode*, views::MenuItemView*> NodeToMenuMap;

  // Creates a menu and adds it to node_to_menu_id_map_. This uses
  // BuildMenu to recursively populate the menu.
  views::MenuItemView* CreateMenu(const BookmarkNode* parent,
                                  int start_child_index,
                                  ShowOptions show_options);

  // Invokes BuildMenuForPermanentNode() for the permanent nodes (excluding
  // 'other bookmarks' folder).
  void BuildMenusForPermanentNodes(views::MenuItemView* menu,
                                   int* next_menu_id);

  // If |node| has children a new menu is created and added to |menu| to
  // represent it. If |node| is not empty and |added_separator| is false, a
  // separator is added before the new menu items and |added_separator| is set
  // to true.
  void BuildMenuForPermanentNode(const BookmarkNode* node,
                                 views::MenuItemView* menu,
                                 int* next_menu_id,
                                 bool* added_separator);

  // Creates an entry in menu for each child node of |parent| starting at
  // |start_child_index|.
  void BuildMenu(const BookmarkNode* parent,
                 int start_child_index,
                 views::MenuItemView* menu,
                 int* next_menu_id);

  // Returns the menu whose id is |id|.
  views::MenuItemView* GetMenuByID(int id);

  Profile* profile_;

  content::PageNavigator* page_navigator_;

  // Parent of menus.
  views::Widget* parent_;

  // Maps from menu id to BookmarkNode.
  MenuIDToNodeMap menu_id_to_node_map_;

  // Mapping from node to menu id. This only contains entries for nodes of type
  // URL.
  NodeToMenuIDMap node_to_menu_id_map_;

  // Current menu.
  views::MenuItemView* menu_;

  // Data for the drop.
  BookmarkNodeData drop_data_;

  // Used when a context menu is shown.
  scoped_ptr<BookmarkContextMenu> context_menu_;

  // Is the menu being shown for a drop?
  bool for_drop_;

  // If non-NULL this is the |parent| passed to Init and is NOT owned by us.
  views::MenuItemView* parent_menu_item_;

  // Maps from node to menu. This is used if a NULL parent is passed to Init().
  NodeToMenuMap node_to_menu_map_;

  // ID of the next menu item.
  int next_menu_id_;

  views::MenuDelegate* real_delegate_;

  // Is the model being changed?
  bool is_mutating_model_;

  // The location where this bookmark menu will be displayed (for UMA).
  bookmark_utils::BookmarkLaunchLocation location_;

  DISALLOW_COPY_AND_ASSIGN(BookmarkMenuDelegate);
};

#endif  // CHROME_BROWSER_UI_VIEWS_BOOKMARKS_BOOKMARK_MENU_DELEGATE_H_