// Copyright (c) 2009 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. #include "chrome/browser/views/bookmark_menu_button.h" #include "build/build_config.h" #if defined(OS_GTK) #include #endif #include "app/os_exchange_data.h" #include "app/resource_bundle.h" #include "app/theme_provider.h" #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/bookmarks/bookmark_utils.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/view_ids.h" #include "grit/theme_resources.h" #include "views/window/window.h" BookmarkMenuButton::BookmarkMenuButton(Browser* browser) : views::MenuButton(NULL, std::wstring(), NULL, false), browser_(browser), bookmark_drop_menu_(NULL), drop_operation_(0) { // TODO(sky): if we keep this code, we need real icons, a11y support, and a // tooltip. set_menu_delegate(this); SetID(VIEW_ID_BOOKMARK_MENU); ThemeProvider* tp = browser_->profile()->GetThemeProvider(); SetIcon(*tp->GetBitmapNamed(IDR_MENU_BOOKMARK)); } BookmarkMenuButton::~BookmarkMenuButton() { if (bookmark_drop_menu_) bookmark_drop_menu_->set_observer(NULL); } bool BookmarkMenuButton::GetDropFormats( int* formats, std::set* custom_formats) { BookmarkModel* bookmark_model = GetBookmarkModel(); if (!bookmark_model || !bookmark_model->IsLoaded()) return false; *formats = OSExchangeData::URL; custom_formats->insert(BookmarkDragData::GetBookmarkCustomFormat()); return true; } bool BookmarkMenuButton::AreDropTypesRequired() { return true; } bool BookmarkMenuButton::CanDrop(const OSExchangeData& data) { BookmarkModel* bookmark_model = GetBookmarkModel(); if (!bookmark_model || !bookmark_model->IsLoaded()) return false; drag_data_ = BookmarkDragData(); // Only accept drops of 1 node, which is the case for all data dragged from // bookmark bar and menus. return drag_data_.Read(data) && drag_data_.has_single_url(); } int BookmarkMenuButton::OnDragUpdated(const views::DropTargetEvent& event) { if (!drag_data_.is_valid()) return 0; BookmarkModel* bookmark_model = GetBookmarkModel(); drop_operation_ = bookmark_utils::BookmarkDropOperation( browser_->profile(), event, drag_data_, bookmark_model->GetBookmarkBarNode(), bookmark_model->GetBookmarkBarNode()->GetChildCount()); if (drop_operation_ != 0) StartShowFolderDropMenuTimer(); else StopShowFolderDropMenuTimer(); return drop_operation_; } void BookmarkMenuButton::OnDragExited() { StopShowFolderDropMenuTimer(); drag_data_ = BookmarkDragData(); } int BookmarkMenuButton::OnPerformDrop(const views::DropTargetEvent& event) { StopShowFolderDropMenuTimer(); if (bookmark_drop_menu_) bookmark_drop_menu_->Cancel(); // Reset the drag data to take as little memory as needed. BookmarkDragData data = drag_data_; drag_data_ = BookmarkDragData(); if (!drop_operation_) return DragDropTypes::DRAG_NONE; BookmarkModel* model = GetBookmarkModel(); if (!model) return DragDropTypes::DRAG_NONE; const BookmarkNode* parent = model->GetBookmarkBarNode(); return bookmark_utils::PerformBookmarkDrop( browser_->profile(), data, parent, parent->GetChildCount()); } void BookmarkMenuButton::BookmarkMenuDeleted( BookmarkMenuController* controller) { bookmark_drop_menu_ = NULL; } void BookmarkMenuButton::RunMenu(views::View* source, const gfx::Point& pt) { RunMenu(source, pt, GetWindow()->GetNativeWindow(), false); } void BookmarkMenuButton::RunMenu(views::View* source, const gfx::Point& pt, gfx::NativeWindow hwnd, bool for_drop) { Profile* profile = browser_->profile(); UserMetrics::RecordAction(UserMetricsAction("BookmarkMenu_clicked"), profile); BookmarkMenuController* menu = new BookmarkMenuController( browser_, profile, browser_->GetSelectedTabContents(), hwnd, GetBookmarkModel()->GetBookmarkBarNode(), 0, true); views::MenuItemView::AnchorPosition anchor = views::MenuItemView::TOPRIGHT; if (UILayoutIsRightToLeft()) anchor = views::MenuItemView::TOPLEFT; if (for_drop) { bookmark_drop_menu_ = menu; bookmark_drop_menu_->set_observer(this); } menu->RunMenuAt(this, views::MenuItemView::TOPRIGHT, for_drop); } BookmarkModel* BookmarkMenuButton::GetBookmarkModel() { return browser_->profile()->GetBookmarkModel(); } void BookmarkMenuButton::StartShowFolderDropMenuTimer() { if (show_drop_menu_timer_.IsRunning()) return; #if defined(OS_WIN) static DWORD delay = 0; if (!delay && !SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &delay, 0)) delay = 400; #else static int delay = 400; #endif show_drop_menu_timer_.Start(base::TimeDelta::FromMilliseconds(delay), this, &BookmarkMenuButton::ShowDropMenu); } void BookmarkMenuButton::StopShowFolderDropMenuTimer() { show_drop_menu_timer_.Stop(); } void BookmarkMenuButton::ShowDropMenu() { RunMenu(NULL, gfx::Point(), GetWindow()->GetNativeWindow(), true); }