Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(298)

Side by Side Diff: chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc

Issue 7054020: Refactors code for showing bookmark menus so that it can be used by (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/bookmarks/bookmark_menu_controller_views.h" 5 #include "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h"
6 6
7 #include "base/stl_util-inl.h" 7 #include "base/stl_util-inl.h"
8 #include "base/utf_string_conversions.h" 8 #include "base/utf_string_conversions.h"
9 #include "chrome/browser/bookmarks/bookmark_model.h" 9 #include "chrome/browser/bookmarks/bookmark_model.h"
10 #include "chrome/browser/bookmarks/bookmark_node_data.h" 10 #include "chrome/browser/bookmarks/bookmark_node_data.h"
11 #include "chrome/browser/bookmarks/bookmark_utils.h" 11 #include "chrome/browser/bookmarks/bookmark_utils.h"
12 #include "chrome/browser/prefs/pref_service.h" 12 #include "chrome/browser/prefs/pref_service.h"
13 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h" 14 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
16 #include "chrome/browser/ui/views/event_utils.h" 15 #include "chrome/browser/ui/views/event_utils.h"
17 #include "chrome/common/pref_names.h" 16 #include "chrome/common/pref_names.h"
18 #include "content/browser/tab_contents/page_navigator.h" 17 #include "content/browser/tab_contents/page_navigator.h"
19 #include "content/browser/user_metrics.h" 18 #include "content/browser/user_metrics.h"
20 #include "content/common/page_transition_types.h" 19 #include "content/common/page_transition_types.h"
21 #include "grit/app_resources.h" 20 #include "grit/app_resources.h"
22 #include "grit/generated_resources.h" 21 #include "grit/generated_resources.h"
23 #include "grit/theme_resources.h" 22 #include "grit/theme_resources.h"
24 #include "ui/base/dragdrop/os_exchange_data.h" 23 #include "ui/base/dragdrop/os_exchange_data.h"
24 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/base/resource/resource_bundle.h" 25 #include "ui/base/resource/resource_bundle.h"
26 #include "views/controls/button/menu_button.h" 26 #include "views/controls/button/menu_button.h"
27 #include "views/controls/menu/menu_item_view.h"
27 28
28 using views::MenuItemView; 29 using views::MenuItemView;
29 30
30 // Max width of a menu. There does not appear to be an OS value for this, yet 31 // Max width of a menu. There does not appear to be an OS value for this, yet
31 // both IE and FF restrict the max width of a menu. 32 // both IE and FF restrict the max width of a menu.
32 static const int kMaxMenuWidth = 400; 33 static const int kMaxMenuWidth = 400;
33 34
34 BookmarkMenuController::BookmarkMenuController(Browser* browser, 35 BookmarkMenuDelegate::BookmarkMenuDelegate(Profile* profile,
35 Profile* profile, 36 PageNavigator* navigator,
36 PageNavigator* navigator, 37 gfx::NativeWindow parent,
37 gfx::NativeWindow parent, 38 int first_menu_id)
38 const BookmarkNode* node, 39 : profile_(profile),
39 int start_child_index)
40 : browser_(browser),
41 profile_(profile),
42 page_navigator_(navigator), 40 page_navigator_(navigator),
43 parent_(parent), 41 parent_(parent),
44 node_(node),
45 menu_(NULL), 42 menu_(NULL),
46 observer_(NULL),
47 for_drop_(false), 43 for_drop_(false),
48 bookmark_bar_(NULL), 44 next_menu_id_(first_menu_id),
49 next_menu_id_(1) { 45 real_delegate_(NULL),
50 menu_ = CreateMenu(node, start_child_index); 46 is_mutating_model_(false) {
51 } 47 }
52 48
53 void BookmarkMenuController::RunMenuAt(BookmarkBarView* bookmark_bar, 49 BookmarkMenuDelegate::~BookmarkMenuDelegate() {
54 bool for_drop) { 50 profile_->GetBookmarkModel()->RemoveObserver(this);
55 bookmark_bar_ = bookmark_bar; 51 STLDeleteValues(&node_to_menu_map_);
56 views::MenuButton* menu_button = bookmark_bar_->GetMenuButtonForNode(node_);
57 DCHECK(menu_button);
58 MenuItemView::AnchorPosition anchor;
59 int start_index;
60 bookmark_bar_->GetAnchorPositionAndStartIndexForButton(
61 menu_button, &anchor, &start_index);
62 RunMenuAt(menu_button, anchor, for_drop);
63 } 52 }
64 53
65 void BookmarkMenuController::RunMenuAt( 54 void BookmarkMenuDelegate::Init(views::MenuDelegate* real_delegate,
66 views::MenuButton* button, 55 MenuItemView* parent,
67 MenuItemView::AnchorPosition position, 56 const BookmarkNode* node,
68 bool for_drop) { 57 int start_child_index,
69 gfx::Point screen_loc; 58 ShowOptions show_options) {
70 views::View::ConvertPointToScreen(button, &screen_loc);
71 // Subtract 1 from the height to make the popup flush with the button border.
72 gfx::Rect bounds(screen_loc.x(), screen_loc.y(), button->width(),
73 button->height() - 1);
74 for_drop_ = for_drop;
75 profile_->GetBookmarkModel()->AddObserver(this); 59 profile_->GetBookmarkModel()->AddObserver(this);
76 // The constructor creates the initial menu and that is all we should have 60 real_delegate_ = real_delegate;
77 // at this point. 61 if (parent) {
78 DCHECK(node_to_menu_map_.size() == 1); 62 BuildMenu(node, start_child_index, parent, &next_menu_id_);
79 if (for_drop) { 63 if (show_options == SHOW_OTHER_FOLDER)
80 menu_->RunMenuForDropAt(parent_, bounds, position); 64 BuildOtherFolderMenu(parent, &next_menu_id_);
81 } else { 65 } else {
82 menu_->RunMenuAt(parent_, button, bounds, position, false); 66 menu_ = CreateMenu(node, start_child_index, show_options);
83 delete this;
84 } 67 }
85 } 68 }
86 69
87 void BookmarkMenuController::Cancel() { 70 void BookmarkMenuDelegate::SetActiveMenu(const BookmarkNode* node,
88 menu_->Cancel(); 71 int start_index) {
72 if (!node_to_menu_map_[node])
73 CreateMenu(node, start_index, HIDE_OTHER_FOLDER);
74 menu_ = node_to_menu_map_[node];
89 } 75 }
90 76
91 std::wstring BookmarkMenuController::GetTooltipText( 77 std::wstring BookmarkMenuDelegate::GetTooltipText(
92 int id, const gfx::Point& screen_loc) { 78 int id,
79 const gfx::Point& screen_loc) {
93 DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end()); 80 DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end());
94 81
95 const BookmarkNode* node = menu_id_to_node_map_[id]; 82 const BookmarkNode* node = menu_id_to_node_map_[id];
96 if (node->type() == BookmarkNode::URL) 83 if (node->type() == BookmarkNode::URL)
97 return BookmarkBarView::CreateToolTipForURLAndTitle( 84 return BookmarkBarView::CreateToolTipForURLAndTitle(
98 screen_loc, node->GetURL(), UTF16ToWide(node->GetTitle()), profile_); 85 screen_loc, node->GetURL(), UTF16ToWide(node->GetTitle()), profile_);
99 return std::wstring(); 86 return std::wstring();
100 } 87 }
101 88
102 bool BookmarkMenuController::IsTriggerableEvent(MenuItemView* view, 89 bool BookmarkMenuDelegate::IsTriggerableEvent(views::MenuItemView* menu,
103 const views::MouseEvent& e) { 90 const views::MouseEvent& e) {
104 return event_utils::IsPossibleDispositionEvent(e); 91 return event_utils::IsPossibleDispositionEvent(e);
105 } 92 }
106 93
107 void BookmarkMenuController::ExecuteCommand(int id, int mouse_event_flags) { 94 void BookmarkMenuDelegate::ExecuteCommand(int id, int mouse_event_flags) {
108 DCHECK(page_navigator_);
109 DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end()); 95 DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end());
110 96
111 const BookmarkNode* node = menu_id_to_node_map_[id]; 97 const BookmarkNode* node = menu_id_to_node_map_[id];
112 std::vector<const BookmarkNode*> selection; 98 std::vector<const BookmarkNode*> selection;
113 selection.push_back(node); 99 selection.push_back(node);
114 100
115 WindowOpenDisposition initial_disposition = 101 WindowOpenDisposition initial_disposition =
116 event_utils::DispositionFromEventFlags(mouse_event_flags); 102 event_utils::DispositionFromEventFlags(mouse_event_flags);
117 103
118 bookmark_utils::OpenAll(parent_, profile_, page_navigator_, selection, 104 bookmark_utils::OpenAll(parent_, profile_, page_navigator_, selection,
119 initial_disposition); 105 initial_disposition);
120 } 106 }
121 107
122 bool BookmarkMenuController::GetDropFormats( 108 bool BookmarkMenuDelegate::GetDropFormats(
123 MenuItemView* menu, 109 MenuItemView* menu,
124 int* formats, 110 int* formats,
125 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { 111 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) {
126 *formats = ui::OSExchangeData::URL; 112 *formats = ui::OSExchangeData::URL;
127 custom_formats->insert(BookmarkNodeData::GetBookmarkCustomFormat()); 113 custom_formats->insert(BookmarkNodeData::GetBookmarkCustomFormat());
128 return true; 114 return true;
129 } 115 }
130 116
131 bool BookmarkMenuController::AreDropTypesRequired(MenuItemView* menu) { 117 bool BookmarkMenuDelegate::AreDropTypesRequired(MenuItemView* menu) {
132 return true; 118 return true;
133 } 119 }
134 120
135 bool BookmarkMenuController::CanDrop(MenuItemView* menu, 121 bool BookmarkMenuDelegate::CanDrop(MenuItemView* menu,
136 const ui::OSExchangeData& data) { 122 const ui::OSExchangeData& data) {
137 // Only accept drops of 1 node, which is the case for all data dragged from 123 // Only accept drops of 1 node, which is the case for all data dragged from
138 // bookmark bar and menus. 124 // bookmark bar and menus.
139 125
140 if (!drop_data_.Read(data) || drop_data_.elements.size() != 1 || 126 if (!drop_data_.Read(data) || drop_data_.elements.size() != 1 ||
141 !profile_->GetPrefs()->GetBoolean(prefs::kEditBookmarksEnabled)) 127 !profile_->GetPrefs()->GetBoolean(prefs::kEditBookmarksEnabled))
142 return false; 128 return false;
143 129
144 if (drop_data_.has_single_url()) 130 if (drop_data_.has_single_url())
145 return true; 131 return true;
146 132
147 const BookmarkNode* drag_node = drop_data_.GetFirstNode(profile_); 133 const BookmarkNode* drag_node = drop_data_.GetFirstNode(profile_);
148 if (!drag_node) { 134 if (!drag_node) {
149 // Dragging a folder from another profile, always accept. 135 // Dragging a folder from another profile, always accept.
150 return true; 136 return true;
151 } 137 }
152 138
153 // Drag originated from same profile and is not a URL. Only accept it if 139 // Drag originated from same profile and is not a URL. Only accept it if
154 // the dragged node is not a parent of the node menu represents. 140 // the dragged node is not a parent of the node menu represents.
141 if (menu_id_to_node_map_.find(menu->GetCommand()) ==
142 menu_id_to_node_map_.end()) {
143 // If we don't know the menu assume its because we're embedded. We'll
144 // figure out the real operation when GetDropOperation is invoked.
145 return true;
146 }
155 const BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()]; 147 const BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()];
156 DCHECK(drop_node); 148 DCHECK(drop_node);
157 while (drop_node && drop_node != drag_node) 149 while (drop_node && drop_node != drag_node)
158 drop_node = drop_node->parent(); 150 drop_node = drop_node->parent();
159 return (drop_node == NULL); 151 return (drop_node == NULL);
160 } 152 }
161 153
162 int BookmarkMenuController::GetDropOperation( 154 int BookmarkMenuDelegate::GetDropOperation(
163 MenuItemView* item, 155 MenuItemView* item,
164 const views::DropTargetEvent& event, 156 const views::DropTargetEvent& event,
165 DropPosition* position) { 157 views::MenuDelegate::DropPosition* position) {
166 // Should only get here if we have drop data. 158 // Should only get here if we have drop data.
167 DCHECK(drop_data_.is_valid()); 159 DCHECK(drop_data_.is_valid());
168 160
169 const BookmarkNode* node = menu_id_to_node_map_[item->GetCommand()]; 161 const BookmarkNode* node = menu_id_to_node_map_[item->GetCommand()];
170 const BookmarkNode* drop_parent = node->parent(); 162 const BookmarkNode* drop_parent = node->parent();
171 int index_to_drop_at = drop_parent->GetIndexOf(node); 163 int index_to_drop_at = drop_parent->GetIndexOf(node);
172 if (*position == DROP_AFTER) { 164 if (*position == views::MenuDelegate::DROP_AFTER) {
165 if (node == profile_->GetBookmarkModel()->other_node()) {
166 // The other folder is shown after all bookmarks on the bookmark bar.
167 // Dropping after the other folder makes no sense.
168 *position = views::MenuDelegate::DROP_NONE;
169 }
173 index_to_drop_at++; 170 index_to_drop_at++;
174 } else if (*position == DROP_ON) { 171 } else if (*position == views::MenuDelegate::DROP_ON) {
175 drop_parent = node; 172 drop_parent = node;
176 index_to_drop_at = node->child_count(); 173 index_to_drop_at = node->child_count();
177 } 174 }
178 DCHECK(drop_parent); 175 DCHECK(drop_parent);
179 return bookmark_utils::BookmarkDropOperation( 176 return bookmark_utils::BookmarkDropOperation(
180 profile_, event, drop_data_, drop_parent, index_to_drop_at); 177 profile_, event, drop_data_, drop_parent, index_to_drop_at);
181 } 178 }
182 179
183 int BookmarkMenuController::OnPerformDrop(MenuItemView* menu, 180 int BookmarkMenuDelegate::OnPerformDrop(
184 DropPosition position, 181 MenuItemView* menu,
185 const views::DropTargetEvent& event) { 182 views::MenuDelegate::DropPosition position,
183 const views::DropTargetEvent& event) {
186 const BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()]; 184 const BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()];
187 DCHECK(drop_node); 185 DCHECK(drop_node);
188 BookmarkModel* model = profile_->GetBookmarkModel(); 186 BookmarkModel* model = profile_->GetBookmarkModel();
189 DCHECK(model); 187 DCHECK(model);
190 const BookmarkNode* drop_parent = drop_node->parent(); 188 const BookmarkNode* drop_parent = drop_node->parent();
191 DCHECK(drop_parent); 189 DCHECK(drop_parent);
192 int index_to_drop_at = drop_parent->GetIndexOf(drop_node); 190 int index_to_drop_at = drop_parent->GetIndexOf(drop_node);
193 if (position == DROP_AFTER) { 191 switch (position) {
194 index_to_drop_at++; 192 case views::MenuDelegate::DROP_AFTER:
195 } else if (position == DROP_ON) { 193 index_to_drop_at++;
196 DCHECK(drop_node->is_folder()); 194 break;
197 drop_parent = drop_node; 195
198 index_to_drop_at = drop_node->child_count(); 196 case views::MenuDelegate::DROP_ON:
197 DCHECK(drop_node->is_folder());
198 drop_parent = drop_node;
199 index_to_drop_at = drop_node->child_count();
200 break;
201
202 case views::MenuDelegate::DROP_BEFORE:
203 if (drop_node == model->other_node()) {
204 // This can happen with SHOW_OTHER_FOLDER.
205 drop_parent = model->GetBookmarkBarNode();
206 index_to_drop_at = drop_parent->child_count();
207 }
208 break;
209
210 default:
211 break;
199 } 212 }
200 213
201 int result = bookmark_utils::PerformBookmarkDrop( 214 int result = bookmark_utils::PerformBookmarkDrop(
202 profile_, drop_data_, drop_parent, index_to_drop_at); 215 profile_, drop_data_, drop_parent, index_to_drop_at);
203 if (for_drop_)
204 delete this;
205 return result; 216 return result;
206 } 217 }
207 218
208 bool BookmarkMenuController::ShowContextMenu(MenuItemView* source, 219 bool BookmarkMenuDelegate::ShowContextMenu(MenuItemView* source,
209 int id, 220 int id,
210 const gfx::Point& p, 221 const gfx::Point& p,
211 bool is_mouse_gesture) { 222 bool is_mouse_gesture) {
212 DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end()); 223 DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end());
213 std::vector<const BookmarkNode*> nodes; 224 std::vector<const BookmarkNode*> nodes;
214 nodes.push_back(menu_id_to_node_map_[id]); 225 nodes.push_back(menu_id_to_node_map_[id]);
215 context_menu_.reset( 226 context_menu_.reset(
216 new BookmarkContextMenu( 227 new BookmarkContextMenu(
217 parent_, 228 parent_,
218 profile_, 229 profile_,
219 page_navigator_, 230 page_navigator_,
220 nodes[0]->parent(), 231 nodes[0]->parent(),
221 nodes)); 232 nodes));
222 context_menu_->set_observer(this); 233 context_menu_->set_observer(this);
223 context_menu_->RunMenuAt(p); 234 context_menu_->RunMenuAt(p);
224 context_menu_.reset(NULL); 235 context_menu_.reset(NULL);
225 return true; 236 return true;
226 } 237 }
227 238
228 void BookmarkMenuController::DropMenuClosed(MenuItemView* menu) { 239 bool BookmarkMenuDelegate::CanDrag(MenuItemView* menu) {
229 delete this; 240 const BookmarkNode* node = menu_id_to_node_map_[menu->GetCommand()];
241 // Don't let users drag the other folder.
242 return node->parent() != profile_->GetBookmarkModel()->root_node();
230 } 243 }
231 244
232 bool BookmarkMenuController::CanDrag(MenuItemView* menu) { 245 void BookmarkMenuDelegate::WriteDragData(MenuItemView* sender,
233 return true; 246 ui::OSExchangeData* data) {
234 }
235
236 void BookmarkMenuController::WriteDragData(MenuItemView* sender,
237 ui::OSExchangeData* data) {
238 DCHECK(sender && data); 247 DCHECK(sender && data);
239 248
240 UserMetrics::RecordAction(UserMetricsAction("BookmarkBar_DragFromFolder")); 249 UserMetrics::RecordAction(UserMetricsAction("BookmarkBar_DragFromFolder"));
241 250
242 BookmarkNodeData drag_data(menu_id_to_node_map_[sender->GetCommand()]); 251 BookmarkNodeData drag_data(menu_id_to_node_map_[sender->GetCommand()]);
243 drag_data.Write(profile_, data); 252 drag_data.Write(profile_, data);
244 } 253 }
245 254
246 int BookmarkMenuController::GetDragOperations(MenuItemView* sender) { 255 int BookmarkMenuDelegate::GetDragOperations(MenuItemView* sender) {
247 return bookmark_utils::BookmarkDragOperation(profile_, 256 return bookmark_utils::BookmarkDragOperation(
248 menu_id_to_node_map_[sender->GetCommand()]); 257 profile_, menu_id_to_node_map_[sender->GetCommand()]);
249 } 258 }
250 259
251 views::MenuItemView* BookmarkMenuController::GetSiblingMenu( 260 int BookmarkMenuDelegate::GetMaxWidthForMenu(MenuItemView* menu) {
252 views::MenuItemView* menu,
253 const gfx::Point& screen_point,
254 views::MenuItemView::AnchorPosition* anchor,
255 bool* has_mnemonics,
256 views::MenuButton** button) {
257 if (!bookmark_bar_ || for_drop_)
258 return NULL;
259 gfx::Point bookmark_bar_loc(screen_point);
260 views::View::ConvertPointToView(NULL, bookmark_bar_, &bookmark_bar_loc);
261 int start_index;
262 const BookmarkNode* node =
263 bookmark_bar_->GetNodeForButtonAt(bookmark_bar_loc, &start_index);
264 if (!node || !node->is_folder())
265 return NULL;
266
267 MenuItemView* alt_menu = node_to_menu_map_[node];
268 if (!alt_menu)
269 alt_menu = CreateMenu(node, start_index);
270
271 menu_ = alt_menu;
272
273 *button = bookmark_bar_->GetMenuButtonForNode(node);
274 bookmark_bar_->GetAnchorPositionAndStartIndexForButton(
275 *button, anchor, &start_index);
276 *has_mnemonics = false;
277 return alt_menu;
278 }
279
280 int BookmarkMenuController::GetMaxWidthForMenu(MenuItemView* view) {
281 return kMaxMenuWidth; 261 return kMaxMenuWidth;
282 } 262 }
283 263
284 void BookmarkMenuController::BookmarkModelChanged() { 264 void BookmarkMenuDelegate::BookmarkModelChanged() {
285 menu_->Cancel();
286 } 265 }
287 266
288 void BookmarkMenuController::BookmarkNodeFaviconLoaded( 267 void BookmarkMenuDelegate::BookmarkNodeFaviconLoaded(
289 BookmarkModel* model, const BookmarkNode* node) { 268 BookmarkModel* model, const BookmarkNode* node) {
290 NodeToMenuIDMap::iterator menu_pair = node_to_menu_id_map_.find(node); 269 NodeToMenuIDMap::iterator menu_pair = node_to_menu_id_map_.find(node);
291 if (menu_pair == node_to_menu_id_map_.end()) 270 if (menu_pair == node_to_menu_id_map_.end())
292 return; // We're not showing a menu item for the node. 271 return; // We're not showing a menu item for the node.
293 272
294 // Iterate through the menus looking for the menu containing node. 273 // Iterate through the menus looking for the menu containing node.
295 for (NodeToMenuMap::iterator i = node_to_menu_map_.begin(); 274 for (NodeToMenuMap::iterator i = node_to_menu_map_.begin();
296 i != node_to_menu_map_.end(); ++i) { 275 i != node_to_menu_map_.end(); ++i) {
297 MenuItemView* menu_item = i->second->GetMenuItemByID(menu_pair->second); 276 MenuItemView* menu_item = i->second->GetMenuItemByID(menu_pair->second);
298 if (menu_item) { 277 if (menu_item) {
299 menu_item->SetIcon(model->GetFavicon(node)); 278 menu_item->SetIcon(model->GetFavicon(node));
300 return; 279 return;
301 } 280 }
302 } 281 }
303 } 282 }
304 283
305 void BookmarkMenuController::WillRemoveBookmarks( 284 void BookmarkMenuDelegate::WillRemoveBookmarks(
306 const std::vector<const BookmarkNode*>& bookmarks) { 285 const std::vector<const BookmarkNode*>& bookmarks) {
286 DCHECK(!is_mutating_model_);
287 is_mutating_model_ = true;
307 std::set<MenuItemView*> removed_menus; 288 std::set<MenuItemView*> removed_menus;
308
309 WillRemoveBookmarksImpl(bookmarks, &removed_menus); 289 WillRemoveBookmarksImpl(bookmarks, &removed_menus);
310
311 STLDeleteElements(&removed_menus); 290 STLDeleteElements(&removed_menus);
312 } 291 }
313 292
314 void BookmarkMenuController::DidRemoveBookmarks() { 293 void BookmarkMenuDelegate::DidRemoveBookmarks() {
294 // Balances remove in WillRemoveBookmarksImpl.
315 profile_->GetBookmarkModel()->AddObserver(this); 295 profile_->GetBookmarkModel()->AddObserver(this);
296 DCHECK(is_mutating_model_);
297 is_mutating_model_ = false;
316 } 298 }
317 299
318 MenuItemView* BookmarkMenuController::CreateMenu(const BookmarkNode* parent, 300 MenuItemView* BookmarkMenuDelegate::CreateMenu(const BookmarkNode* parent,
319 int start_child_index) { 301 int start_child_index,
320 MenuItemView* menu = new MenuItemView(this); 302 ShowOptions show_options) {
303 MenuItemView* menu = new MenuItemView(real_delegate_);
321 menu->SetCommand(next_menu_id_++); 304 menu->SetCommand(next_menu_id_++);
322 menu_id_to_node_map_[menu->GetCommand()] = parent; 305 menu_id_to_node_map_[menu->GetCommand()] = parent;
323 menu->set_has_icons(true); 306 menu->set_has_icons(true);
324 BuildMenu(parent, start_child_index, menu, &next_menu_id_); 307 BuildMenu(parent, start_child_index, menu, &next_menu_id_);
308 if (show_options == SHOW_OTHER_FOLDER)
309 BuildOtherFolderMenu(menu, &next_menu_id_);
325 node_to_menu_map_[parent] = menu; 310 node_to_menu_map_[parent] = menu;
326 return menu; 311 return menu;
327 } 312 }
328 313
329 void BookmarkMenuController::BuildMenu(const BookmarkNode* parent, 314 void BookmarkMenuDelegate::BuildOtherFolderMenu(
330 int start_child_index, 315 MenuItemView* menu, int* next_menu_id) {
331 MenuItemView* menu, 316 const BookmarkNode* other_folder = profile_->GetBookmarkModel()->other_node();
332 int* next_menu_id) { 317 int id = *next_menu_id;
318 (*next_menu_id)++;
319 SkBitmap* folder_icon = ResourceBundle::GetSharedInstance().
320 GetBitmapNamed(IDR_BOOKMARK_BAR_FOLDER);
321 MenuItemView* submenu = menu->AppendSubMenuWithIcon(
322 id, UTF16ToWide(
323 l10n_util::GetStringUTF16(IDS_BOOMARK_BAR_OTHER_BOOKMARKED)),
324 *folder_icon);
325 BuildMenu(other_folder, 0, submenu, next_menu_id);
326 menu_id_to_node_map_[id] = other_folder;
327 }
328
329 void BookmarkMenuDelegate::BuildMenu(const BookmarkNode* parent,
330 int start_child_index,
331 MenuItemView* menu,
332 int* next_menu_id) {
333 DCHECK(!parent->child_count() || 333 DCHECK(!parent->child_count() ||
334 start_child_index < parent->child_count()); 334 start_child_index < parent->child_count());
335 for (int i = start_child_index; i < parent->child_count(); ++i) { 335 for (int i = start_child_index; i < parent->child_count(); ++i) {
336 const BookmarkNode* node = parent->GetChild(i); 336 const BookmarkNode* node = parent->GetChild(i);
337 int id = *next_menu_id; 337 int id = *next_menu_id;
338 338
339 (*next_menu_id)++; 339 (*next_menu_id)++;
340 if (node->is_url()) { 340 if (node->is_url()) {
341 SkBitmap icon = profile_->GetBookmarkModel()->GetFavicon(node); 341 SkBitmap icon = profile_->GetBookmarkModel()->GetFavicon(node);
342 if (icon.width() == 0) { 342 if (icon.width() == 0) {
343 icon = *ResourceBundle::GetSharedInstance(). 343 icon = *ResourceBundle::GetSharedInstance().
344 GetBitmapNamed(IDR_DEFAULT_FAVICON); 344 GetBitmapNamed(IDR_DEFAULT_FAVICON);
345 } 345 }
346 menu->AppendMenuItemWithIcon(id, UTF16ToWide(node->GetTitle()), icon); 346 menu->AppendMenuItemWithIcon(id, UTF16ToWide(node->GetTitle()), icon);
347 node_to_menu_id_map_[node] = id; 347 node_to_menu_id_map_[node] = id;
348 } else if (node->is_folder()) { 348 } else if (node->is_folder()) {
349 SkBitmap* folder_icon = ResourceBundle::GetSharedInstance(). 349 SkBitmap* folder_icon = ResourceBundle::GetSharedInstance().
350 GetBitmapNamed(IDR_BOOKMARK_BAR_FOLDER); 350 GetBitmapNamed(IDR_BOOKMARK_BAR_FOLDER);
351 MenuItemView* submenu = menu->AppendSubMenuWithIcon(id, 351 MenuItemView* submenu = menu->AppendSubMenuWithIcon(
352 UTF16ToWide(node->GetTitle()), *folder_icon); 352 id, UTF16ToWide(node->GetTitle()), *folder_icon);
353 node_to_menu_id_map_[node] = id; 353 node_to_menu_id_map_[node] = id;
354 BuildMenu(node, 0, submenu, next_menu_id); 354 BuildMenu(node, 0, submenu, next_menu_id);
355 } else { 355 } else {
356 NOTREACHED(); 356 NOTREACHED();
357 } 357 }
358 menu_id_to_node_map_[id] = node; 358 menu_id_to_node_map_[id] = node;
359 } 359 }
360 } 360 }
361 361
362 BookmarkMenuController::~BookmarkMenuController() { 362 MenuItemView* BookmarkMenuDelegate::GetMenuByID(int id) {
363 profile_->GetBookmarkModel()->RemoveObserver(this);
364 if (observer_)
365 observer_->BookmarkMenuDeleted(this);
366 STLDeleteValues(&node_to_menu_map_);
367 }
368
369 MenuItemView* BookmarkMenuController::GetMenuByID(int id) {
370 for (NodeToMenuMap::const_iterator i = node_to_menu_map_.begin(); 363 for (NodeToMenuMap::const_iterator i = node_to_menu_map_.begin();
371 i != node_to_menu_map_.end(); ++i) { 364 i != node_to_menu_map_.end(); ++i) {
372 MenuItemView* menu = i->second->GetMenuItemByID(id); 365 MenuItemView* menu = i->second->GetMenuItemByID(id);
373 if (menu) 366 if (menu)
374 return menu; 367 return menu;
375 } 368 }
376 return NULL; 369 return NULL;
377 } 370 }
378 371
379 void BookmarkMenuController::WillRemoveBookmarksImpl( 372 void BookmarkMenuDelegate::WillRemoveBookmarksImpl(
380 const std::vector<const BookmarkNode*>& bookmarks, 373 const std::vector<const BookmarkNode*>& bookmarks,
381 std::set<views::MenuItemView*>* removed_menus) { 374 std::set<views::MenuItemView*>* removed_menus) {
382 // Remove the observer so that when the remove happens we don't prematurely 375 // Remove the observer so that when the remove happens we don't prematurely
383 // cancel the menu. 376 // cancel the menu. The observer ias added back in DidRemoveBookmarks.
384 profile_->GetBookmarkModel()->RemoveObserver(this); 377 profile_->GetBookmarkModel()->RemoveObserver(this);
385 378
386 // Remove the menu items. 379 // Remove the menu items.
387 std::set<MenuItemView*> changed_parent_menus; 380 std::set<MenuItemView*> changed_parent_menus;
388 for (std::vector<const BookmarkNode*>::const_iterator i = bookmarks.begin(); 381 for (std::vector<const BookmarkNode*>::const_iterator i = bookmarks.begin();
389 i != bookmarks.end(); ++i) { 382 i != bookmarks.end(); ++i) {
390 NodeToMenuIDMap::iterator node_to_menu = node_to_menu_id_map_.find(*i); 383 NodeToMenuIDMap::iterator node_to_menu = node_to_menu_id_map_.find(*i);
391 if (node_to_menu != node_to_menu_id_map_.end()) { 384 if (node_to_menu != node_to_menu_id_map_.end()) {
392 MenuItemView* menu = GetMenuByID(node_to_menu->second); 385 MenuItemView* menu = GetMenuByID(node_to_menu->second);
393 DCHECK(menu); // If there an entry in node_to_menu_id_map_, there should 386 DCHECK(menu); // If there an entry in node_to_menu_id_map_, there should
394 // be a menu. 387 // be a menu.
395 removed_menus->insert(menu); 388 removed_menus->insert(menu);
396 changed_parent_menus.insert(menu->GetParentMenuItem()); 389 changed_parent_menus.insert(menu->GetParentMenuItem());
397 menu->parent()->RemoveChildView(menu); 390 menu->parent()->RemoveChildView(menu);
398 node_to_menu_id_map_.erase(node_to_menu); 391 node_to_menu_id_map_.erase(node_to_menu);
399 } 392 }
400 } 393 }
401 394
402 // All the bookmarks in |bookmarks| should have the same parent. It's possible 395 // All the bookmarks in |bookmarks| should have the same parent. It's possible
403 // to support different parents, but this would need to prune any nodes whose 396 // to support different parents, but this would need to prune any nodes whose
404 // parent has been removed. As all nodes currently have the same parent, there 397 // parent has been removed. As all nodes currently have the same parent, there
(...skipping 16 matching lines...) Expand all
421 break; 414 break;
422 } 415 }
423 } 416 }
424 if (ancestor_removed) { 417 if (ancestor_removed) {
425 node_to_menu_id_map_.erase(i++); 418 node_to_menu_id_map_.erase(i++);
426 } else { 419 } else {
427 ++i; 420 ++i;
428 } 421 }
429 } 422 }
430 } 423 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h ('k') | chrome/browser/ui/views/wrench_menu.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698