diff options
Diffstat (limited to 'chrome/browser/views/bookmark_bar_view.cc')
-rw-r--r-- | chrome/browser/views/bookmark_bar_view.cc | 259 |
1 files changed, 256 insertions, 3 deletions
diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc index dbfb38f..6a1c2e6 100644 --- a/chrome/browser/views/bookmark_bar_view.cc +++ b/chrome/browser/views/bookmark_bar_view.cc @@ -358,6 +358,254 @@ struct DropInfo { BookmarkDragData data; }; +<<<<<<< .mine +// MenuRunner ----------------------------------------------------------------- + +// MenuRunner manages creation and showing of a menu containing BookmarkNodes. +// MenuRunner is used to show the contents of bookmark folders on the +// bookmark bar, other folder, or overflow bookmarks. +// +class MenuRunner : public views::MenuDelegate, + public BookmarkBarView::ModelChangedListener { + public: + // start_child_index is the index of the first child in node to add to the + // menu. + MenuRunner(BookmarkBarView* view, BookmarkNode* node, int start_child_index) + : view_(view), + node_(node), + menu_(this) { + int next_menu_id = 1; + menu_id_to_node_map_[menu_.GetCommand()] = node; + menu_.set_has_icons(true); + BuildMenu(node, start_child_index, &menu_, &next_menu_id); + } + + // Returns the node the menu is being run for. + BookmarkNode* GetNode() { + return node_; + } + + void RunMenuAt(HWND hwnd, + const gfx::Rect& bounds, + MenuItemView::AnchorPosition position, + bool for_drop) { + view_->SetModelChangedListener(this); + if (for_drop) + menu_.RunMenuForDropAt(hwnd, bounds, position); + else + menu_.RunMenuAt(hwnd, bounds, position, false); + view_->ClearModelChangedListenerIfEquals(this); + } + + // Notification that the favicon has finished loading. Reset the icon + // of the menu item. + void FavIconLoaded(BookmarkNode* node) { + if (node_to_menu_id_map_.find(node) != + node_to_menu_id_map_.end()) { + menu_.SetIcon(node->GetFavIcon(), node_to_menu_id_map_[node]); + } + } + + virtual void ModelChanged() { + menu_.Cancel(); + } + + MenuItemView* menu() { return &menu_; } + + MenuItemView* context_menu() { + return context_menu_.get() ? context_menu_->menu() : NULL; + } + + private: + // Creates an entry in menu for each child node of parent starting at + // start_child_index, recursively invoking this for any star groups. + void BuildMenu(BookmarkNode* parent, + int start_child_index, + MenuItemView* menu, + int* next_menu_id) { + DCHECK(!parent->GetChildCount() || + + start_child_index < parent->GetChildCount()); + for (int i = start_child_index; i < parent->GetChildCount(); ++i) { + BookmarkNode* node = parent->GetChild(i); + int id = *next_menu_id; + + (*next_menu_id)++; + if (node->GetType() == history::StarredEntry::URL) { + SkBitmap icon = node->GetFavIcon(); + if (icon.width() == 0) + icon = *kDefaultFavIcon; + menu->AppendMenuItemWithIcon(id, node->GetTitle(), icon); + node_to_menu_id_map_[node] = id; + } else { + SkBitmap* folder_icon = + ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_BOOKMARK_BAR_FOLDER); + MenuItemView* submenu = menu->AppendSubMenuWithIcon( + id, node->GetTitle(), *folder_icon); + BuildMenu(node, 0, submenu, next_menu_id); + } + menu_id_to_node_map_[id] = node; + } + } + + // ViewMenuDelegate method. Overridden to forward to the PageNavigator so + // that we accept any events that may trigger opening a url. + virtual bool IsTriggerableEvent(const views::MouseEvent& e) { + return event_utils::IsPossibleDispositionEvent(e); + } + + // Invoked when a menu item is selected. Uses the PageNavigator set on + // the BookmarkBarView to open the URL. + virtual void ExecuteCommand(int id, int mouse_event_flags) { + DCHECK(view_->GetPageNavigator()); + GURL url; + DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end()); + url = menu_id_to_node_map_[id]->GetURL(); + view_->GetPageNavigator()->OpenURL( + url, GURL(), event_utils::DispositionFromEventFlags(mouse_event_flags), + PageTransition::AUTO_BOOKMARK); + } + + virtual bool CanDrop(MenuItemView* menu, const OSExchangeData& data) { + // Only accept drops of 1 node, which is the case for all data dragged from + // bookmark bar and menus. + if (!drop_data_.Read(data) || drop_data_.elements.size() != 1) + return false; + + if (drop_data_.has_single_url()) + return true; + + BookmarkNode* drag_node = drop_data_.GetFirstNode(view_->GetProfile()); + if (!drag_node) { + // Dragging a group from another profile, always accept. + return true; + } + // Drag originated from same profile and is not a URL. Only accept it if + // the dragged node is not a parent of the node menu represents. + BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()]; + DCHECK(drop_node); + BookmarkNode* node = drop_node; + while (drop_node && drop_node != drag_node) + drop_node = drop_node->GetParent(); + return (drop_node == NULL); + } + + virtual int GetDropOperation(MenuItemView* item, + const views::DropTargetEvent& event, + DropPosition* position) { + DCHECK(drop_data_.is_valid()); + BookmarkNode* node = menu_id_to_node_map_[item->GetCommand()]; + BookmarkNode* drop_parent = node->GetParent(); + int index_to_drop_at = drop_parent->IndexOfChild(node); + if (*position == DROP_AFTER) { + index_to_drop_at++; + } else if (*position == DROP_ON) { + drop_parent = node; + index_to_drop_at = node->GetChildCount(); + } + DCHECK(drop_parent); + return view_->CalculateDropOperation(event, drop_data_, drop_parent, + index_to_drop_at); + } + + virtual int OnPerformDrop(MenuItemView* menu, + DropPosition position, + const DropTargetEvent& event) { + BookmarkNode* drop_node = menu_id_to_node_map_[menu->GetCommand()]; + DCHECK(drop_node); + BookmarkModel* model = view_->GetModel(); + DCHECK(model); + BookmarkNode* drop_parent = drop_node->GetParent(); + DCHECK(drop_parent); + int index_to_drop_at = drop_parent->IndexOfChild(drop_node); + if (position == DROP_AFTER) { + index_to_drop_at++; + } else if (position == DROP_ON) { + DCHECK(drop_node->GetType() != history::StarredEntry::URL); + drop_parent = drop_node; + index_to_drop_at = drop_node->GetChildCount(); + } + + const int result = view_->PerformDropImpl(drop_data_, drop_parent, + index_to_drop_at); + if (view_->drop_menu_runner_.get() == this) + view_->drop_menu_runner_.reset(); + // WARNING: we've been deleted! + return result; + } + + virtual bool ShowContextMenu(MenuItemView* source, + int id, + int x, + int y, + bool is_mouse_gesture) { + DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end()); + std::vector<BookmarkNode*> nodes; + nodes.push_back(menu_id_to_node_map_[id]); + context_menu_.reset( + new BookmarkContextMenu(view_->GetWidget()->GetNativeView(), + view_->GetProfile(), + view_->browser(), + view_->GetPageNavigator(), + nodes[0]->GetParent(), + nodes, + BookmarkContextMenu::BOOKMARK_BAR)); + context_menu_->RunMenuAt(x, y); + context_menu_.reset(NULL); + return true; + } + + virtual void DropMenuClosed(MenuItemView* menu) { + if (view_->drop_menu_runner_.get() == this) + view_->drop_menu_runner_.reset(); + } + + virtual bool CanDrag(MenuItemView* menu) { + DCHECK(menu); + return true; + } + + virtual void WriteDragData(MenuItemView* sender, OSExchangeData* data) { + DCHECK(sender && data); + + UserMetrics::RecordAction(L"BookmarkBar_DragFromFolder", + view_->GetProfile()); + + view_->WriteDragData(menu_id_to_node_map_[sender->GetCommand()], data); + } + + virtual int GetDragOperations(MenuItemView* sender) { + return GetDragOperationsForNode( + menu_id_to_node_map_[sender->GetCommand()]); + } + + // The node we're showing the contents of. + BookmarkNode* node_; + + // The view that created us. + BookmarkBarView* view_; + + // The menu. + MenuItemView menu_; + + // Mapping from menu id to the BookmarkNode. + std::map<int, BookmarkNode*> menu_id_to_node_map_; + + // Mapping from node to menu id. This only contains entries for nodes of type + // URL. + std::map<BookmarkNode*, int> node_to_menu_id_map_; + + // Data for the drop. + BookmarkDragData drop_data_; + + scoped_ptr<BookmarkContextMenu> context_menu_; + + DISALLOW_COPY_AND_ASSIGN(MenuRunner); +}; + +======= +>>>>>>> .r11559 // ButtonSeparatorView -------------------------------------------------------- class ButtonSeparatorView : public views::View { @@ -1224,7 +1472,7 @@ void BookmarkBarView::RunMenu(views::View* view, gfx::Point screen_loc(x, 0); View::ConvertPointToScreen(this, &screen_loc); bookmark_menu_ = new BookmarkMenuController( - browser_, profile_, page_navigator_, GetWidget()->GetHWND(), + browser_, profile_, page_navigator_, GetWidget()->GetNativeView(), node, start_index); bookmark_menu_->set_observer(this); bookmark_menu_->RunMenuAt(gfx::Rect(screen_loc.x(), screen_loc.y(), @@ -1249,7 +1497,7 @@ void BookmarkBarView::ButtonPressed(views::BaseButton* sender) { PageTransition::AUTO_BOOKMARK); } else { bookmark_utils::OpenAll( - GetWidget()->GetHWND(), profile_, GetPageNavigator(), node, + GetWidget()->GetNativeView(), profile_, GetPageNavigator(), node, event_utils::DispositionFromEventFlags(sender->mouse_event_flags())); } UserMetrics::RecordAction(L"ClickedBookmarkBarURLButton", profile_); @@ -1285,7 +1533,7 @@ void BookmarkBarView::ShowContextMenu(View* source, parent = model_->GetBookmarkBarNode(); nodes.push_back(parent); } - BookmarkContextMenu controller(GetWidget()->GetHWND(), + BookmarkContextMenu controller(GetWidget()->GetNativeView(), GetProfile(), browser(), GetPageNavigator(), parent, nodes, BookmarkContextMenu::BOOKMARK_BAR); @@ -1454,7 +1702,12 @@ void BookmarkBarView::ShowDropFolderForNode(BookmarkNode* node) { bookmark_drop_menu_->set_observer(this); gfx::Point screen_loc; View::ConvertPointToScreen(view_to_position_menu_from, &screen_loc); +<<<<<<< .mine + drop_menu_runner_->RunMenuAt( + GetWidget()->GetNativeView(), +======= bookmark_drop_menu_->RunMenuAt( +>>>>>>> .r11559 gfx::Rect(screen_loc.x(), screen_loc.y(), view_to_position_menu_from->width(), view_to_position_menu_from->height()), |