diff options
author | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-16 18:19:17 +0000 |
---|---|---|
committer | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-16 18:19:17 +0000 |
commit | 2b2d1697cd3cd6303b372949565bb8ac87741589 (patch) | |
tree | 2c4ca63f7e4854c1be423d74896ec71d4c80a858 /chrome | |
parent | 54e1d52455272e0af32b4c6080f1914f6f2c4f95 (diff) | |
download | chromium_src-2b2d1697cd3cd6303b372949565bb8ac87741589.zip chromium_src-2b2d1697cd3cd6303b372949565bb8ac87741589.tar.gz chromium_src-2b2d1697cd3cd6303b372949565bb8ac87741589.tar.bz2 |
Recommit previous change with GYP files fixed.
Implement BookmarkContextMenuGtk and hook it up to most bookmark bar elements.
Also:
- Fixes window dispositions (shift-click works on bookmark bar items).
- Reorganizes gtk_utils
Original Review URL: http://codereview.chromium.org/76002
Review URL: http://codereview.chromium.org/67223
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13857 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/gtk/bookmark_bar_gtk.cc | 79 | ||||
-rw-r--r-- | chrome/browser/gtk/bookmark_bar_gtk.h | 11 | ||||
-rw-r--r-- | chrome/browser/gtk/bookmark_context_menu_gtk.cc | 353 | ||||
-rw-r--r-- | chrome/browser/gtk/bookmark_context_menu_gtk.h | 116 | ||||
-rw-r--r-- | chrome/browser/gtk/find_bar_gtk.cc | 1 | ||||
-rw-r--r-- | chrome/browser/gtk/infobar_container_gtk.cc | 2 | ||||
-rw-r--r-- | chrome/browser/gtk/infobar_gtk.cc | 1 | ||||
-rw-r--r-- | chrome/browser/gtk/location_bar_view_gtk.cc | 1 | ||||
-rw-r--r-- | chrome/browser/gtk/menu_gtk.cc | 49 | ||||
-rw-r--r-- | chrome/browser/gtk/menu_gtk.h | 5 | ||||
-rw-r--r-- | chrome/browser/tab_contents/web_contents_view_gtk.cc | 2 | ||||
-rw-r--r-- | chrome/chrome.gyp | 8 | ||||
-rw-r--r-- | chrome/common/gtk_util.cc | 81 | ||||
-rw-r--r-- | chrome/common/gtk_util.h | 41 | ||||
-rw-r--r-- | chrome/common/resource_bundle_linux.cc | 1 |
15 files changed, 700 insertions, 51 deletions
diff --git a/chrome/browser/gtk/bookmark_bar_gtk.cc b/chrome/browser/gtk/bookmark_bar_gtk.cc index 4c8abea..7819ad4 100644 --- a/chrome/browser/gtk/bookmark_bar_gtk.cc +++ b/chrome/browser/gtk/bookmark_bar_gtk.cc @@ -5,12 +5,15 @@ #include "chrome/browser/gtk/bookmark_bar_gtk.h" #include "base/gfx/gtk_util.h" +#include "chrome/browser/bookmarks/bookmark_utils.h" #include "chrome/browser/browser.h" +#include "chrome/browser/gtk/bookmark_context_menu_gtk.h" #include "chrome/browser/gtk/custom_button.h" #include "chrome/browser/gtk/gtk_chrome_button.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/profile.h" #include "chrome/common/gfx/text_elider.h" +#include "chrome/common/gtk_util.h" #include "chrome/common/l10n_util.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" @@ -115,16 +118,20 @@ void BookmarkBarGtk::Init(Profile* profile) { G_CALLBACK(&OnToolbarDragLeave), this); g_signal_connect(bookmark_toolbar_.get(), "drag-drop", G_CALLBACK(&OnToolbarDragDrop), this); + g_signal_connect(bookmark_toolbar_.get(), "button-press-event", + G_CALLBACK(&OnButtonPressed), this); gtk_box_pack_start(GTK_BOX(bookmark_hbox_), gtk_vseparator_new(), FALSE, FALSE, 0); other_bookmarks_button_ = gtk_chrome_button_new(); + g_signal_connect(other_bookmarks_button_, "button-press-event", + G_CALLBACK(&OnButtonPressed), this); gtk_button_set_label(GTK_BUTTON(other_bookmarks_button_), "Other bookmarks"); gtk_button_set_image(GTK_BUTTON(other_bookmarks_button_), gtk_image_new_from_pixbuf(folder_icon)); - // TODO(erg): Hook up a popup menu to |other_bookmarks_button_|. + gtk_box_pack_start(GTK_BOX(bookmark_hbox_), other_bookmarks_button_, FALSE, FALSE, 0); } @@ -343,8 +350,16 @@ std::string BookmarkBarGtk::BuildTooltip(BookmarkNode* node) { return node->GetURL().possibly_invalid_spec(); } -BookmarkNode* BookmarkBarGtk::GetNodeForToolButton(GtkWidget* button) { - GtkWidget* item_to_find = gtk_widget_get_parent(button); +BookmarkNode* BookmarkBarGtk::GetNodeForToolButton(GtkWidget* widget) { + // First check to see if |button| is the special cased. + if (widget == other_bookmarks_button_) + return model_->other_node(); + else if (widget == bookmark_toolbar_.get()) + return model_->GetBookmarkBarNode(); + + // Search the contents of |bookmark_toolbar_| for the corresponding widget + // and find its index. + GtkWidget* item_to_find = gtk_widget_get_parent(widget); int index_to_use = -1; int index = 0; GList* children = gtk_container_get_children( @@ -363,20 +378,49 @@ BookmarkNode* BookmarkBarGtk::GetNodeForToolButton(GtkWidget* button) { return NULL; } -void BookmarkBarGtk::PopupMenuForNode(BookmarkNode* node, +void BookmarkBarGtk::PopupMenuForNode(GtkWidget* sender, BookmarkNode* node, GdkEventButton* event) { - GtkWidget* menu = gtk_menu_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), - gtk_menu_item_new_with_label("TODO(erg): Write menus")); - gtk_widget_show_all(menu); - gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, - event->time); + if (!model_->IsLoaded()) { + // Don't do anything if the model isn't loaded. + return; + } + + BookmarkNode* parent = NULL; + std::vector<BookmarkNode*> nodes; + if (sender == other_bookmarks_button_) { + parent = model_->GetBookmarkBarNode(); + nodes.push_back(parent); + } else if (sender != bookmark_toolbar_.get()) { + nodes.push_back(node); + parent = node->GetParent(); + } else { + parent = model_->GetBookmarkBarNode(); + nodes.push_back(parent); + } + + current_context_menu_.reset(new BookmarkContextMenuGtk( + GTK_WINDOW(gtk_widget_get_toplevel(sender)), + profile_, browser_, page_navigator_, + parent, nodes, + BookmarkContextMenuGtk::BOOKMARK_BAR)); + current_context_menu_->PopupAsContext(event->time); } +// static gboolean BookmarkBarGtk::OnButtonPressed(GtkWidget* sender, GdkEventButton* event, BookmarkBarGtk* bar) { - bar->ignore_button_release_ = false; + if (sender != bar->other_bookmarks_button_ && + sender != bar->bookmark_toolbar_.get()) + bar->ignore_button_release_ = false; + + if (event->button == 3) { + BookmarkNode* node = bar->GetNodeForToolButton(sender); + DCHECK(node); + DCHECK(bar->page_navigator_); + bar->PopupMenuForNode(sender, node, event); + } + return FALSE; } @@ -393,19 +437,16 @@ gboolean BookmarkBarGtk::OnButtonReleased(GtkWidget* sender, DCHECK(node); DCHECK(bar->page_navigator_); - if (event->button == 3) { - bar->PopupMenuForNode(node, event); - return FALSE; - } - if (node->is_url()) { bar->page_navigator_->OpenURL( node->GetURL(), GURL(), - // TODO(erg): Detect the disposition based on the click type. - CURRENT_TAB, + event_utils::DispositionFromEventFlags(event->state), PageTransition::AUTO_BOOKMARK); } else { - // TODO(erg): Handle folders and extensions. + bookmark_utils::OpenAll( + GTK_WINDOW(gtk_widget_get_toplevel(sender)), bar->profile_, + bar->page_navigator_, node, + event_utils::DispositionFromEventFlags(event->state)); } UserMetrics::RecordAction(L"ClickedBookmarkBarURLButton", bar->profile_); diff --git a/chrome/browser/gtk/bookmark_bar_gtk.h b/chrome/browser/gtk/bookmark_bar_gtk.h index d45fcdbb..930a26f 100644 --- a/chrome/browser/gtk/bookmark_bar_gtk.h +++ b/chrome/browser/gtk/bookmark_bar_gtk.h @@ -13,6 +13,7 @@ #include "chrome/common/owned_widget_gtk.h" #include "chrome/browser/bookmarks/bookmark_model.h" +class BookmarkContextMenuGtk; class Browser; class CustomContainerButton; class PageNavigator; @@ -111,13 +112,15 @@ class BookmarkBarGtk : public BookmarkModelObserver { BookmarkNode* GetNodeForToolButton(GtkWidget* button); // Creates and displays a popup menu for BookmarkNode |node|. - void PopupMenuForNode(BookmarkNode* node, GdkEventButton* event); + void PopupMenuForNode(GtkWidget* sender, BookmarkNode* node, + GdkEventButton* event); // GtkButton callbacks static gboolean OnButtonPressed(GtkWidget* sender, GdkEventButton* event, BookmarkBarGtk* bar); - static gboolean OnButtonReleased(GtkWidget* sender, GdkEventButton* event, + static gboolean OnButtonReleased(GtkWidget* sender, + GdkEventButton* event, BookmarkBarGtk* bar); static gboolean OnButtonExpose(GtkWidget* widget, GdkEventExpose* e, BookmarkBarGtk* button); @@ -188,6 +191,10 @@ class BookmarkBarGtk : public BookmarkModelObserver { // Whether we should show the instructional text in the bookmark bar. bool show_instructions_; + + // The last displayed right click menu, or NULL if no menus have been + // displayed yet. + scoped_ptr<BookmarkContextMenuGtk> current_context_menu_; }; #endif // CHROME_BROWSER_GTK_BOOKMARK_BAR_GTK_H_ diff --git a/chrome/browser/gtk/bookmark_context_menu_gtk.cc b/chrome/browser/gtk/bookmark_context_menu_gtk.cc new file mode 100644 index 0000000..f6fc56f --- /dev/null +++ b/chrome/browser/gtk/bookmark_context_menu_gtk.cc @@ -0,0 +1,353 @@ +// 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/gtk/bookmark_context_menu_gtk.h" + +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/bookmarks/bookmark_utils.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/metrics/user_metrics.h" +#include "chrome/browser/profile.h" +#include "chrome/common/l10n_util.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" + +namespace { + +// Returns true if the specified node is of type URL, or has a descendant +// of type URL. +bool NodeHasURLs(BookmarkNode* node) { + if (node->is_url()) + return true; + + for (int i = 0; i < node->GetChildCount(); ++i) { + if (NodeHasURLs(node->GetChild(i))) + return true; + } + return false; +} + +} // namespace + +BookmarkContextMenuGtk::BookmarkContextMenuGtk( + GtkWindow* window, + Profile* profile, + Browser* browser, + PageNavigator* navigator, + BookmarkNode* parent, + const std::vector<BookmarkNode*>& selection, + ConfigurationType configuration) + : window_(window), + profile_(profile), + browser_(browser), + navigator_(navigator), + parent_(parent), + selection_(selection), + model_(profile->GetBookmarkModel()), + configuration_(configuration), + menu_(new MenuGtk(this, false)) { + if (configuration != BOOKMARK_MANAGER_ORGANIZE_MENU) { + if (selection.size() == 1 && selection[0]->is_url()) { + AppendItem(IDS_BOOMARK_BAR_OPEN_ALL, IDS_BOOMARK_BAR_OPEN_IN_NEW_TAB); + AppendItem(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW, + IDS_BOOMARK_BAR_OPEN_IN_NEW_WINDOW); + AppendItem(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO, + IDS_BOOMARK_BAR_OPEN_INCOGNITO); + } else { + AppendItem(IDS_BOOMARK_BAR_OPEN_ALL, IDS_BOOMARK_BAR_OPEN_ALL); + AppendItem(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW, + IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW); + AppendItem(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO, + IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO); + } + AppendSeparator(); + } + + if (selection.size() == 1 && selection[0]->is_folder()) { + AppendItem(IDS_BOOKMARK_BAR_RENAME_FOLDER); + } else { + AppendItem(IDS_BOOKMARK_BAR_EDIT); + } + AppendItem(IDS_BOOKMARK_BAR_REMOVE); + + if (configuration == BOOKMARK_MANAGER_TABLE || + configuration == BOOKMARK_MANAGER_TABLE_OTHER || + configuration == BOOKMARK_MANAGER_ORGANIZE_MENU || + configuration == BOOKMARK_MANAGER_ORGANIZE_MENU_OTHER) { + AppendItem(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER); + } + + if (configuration == BOOKMARK_MANAGER_TABLE || + configuration == BOOKMARK_MANAGER_TABLE_OTHER || + configuration == BOOKMARK_MANAGER_TREE || + configuration == BOOKMARK_MANAGER_ORGANIZE_MENU || + configuration == BOOKMARK_MANAGER_ORGANIZE_MENU_OTHER) { + AppendSeparator(); + AppendItem(IDS_CUT); + AppendItem(IDS_COPY); + AppendItem(IDS_PASTE); + } + + if (configuration == BOOKMARK_MANAGER_ORGANIZE_MENU) { + AppendSeparator(); + AppendItem(IDS_BOOKMARK_MANAGER_SORT); + } + + AppendSeparator(); + + AppendItem(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK); + AppendItem(IDS_BOOMARK_BAR_NEW_FOLDER); + + if (configuration == BOOKMARK_BAR) { + AppendSeparator(); + AppendItem(IDS_BOOKMARK_MANAGER); + AppendItem(IDS_BOOMARK_BAR_ALWAYS_SHOW); + } + + model_->AddObserver(this); +} + +BookmarkContextMenuGtk::~BookmarkContextMenuGtk() { + if (model_) + model_->RemoveObserver(this); +} + +void BookmarkContextMenuGtk::PopupAsContext(guint32 event_time) { + menu_->PopupAsContext(event_time); +} + +bool BookmarkContextMenuGtk::IsCommandEnabled(int index) const { + bool is_root_node = + (selection_.size() == 1 && + selection_[0]->GetParent() == model_->root_node()); + switch (index) { + case IDS_BOOMARK_BAR_OPEN_INCOGNITO: + return !profile_->IsOffTheRecord(); + + case IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO: + return HasURLs() && !profile_->IsOffTheRecord(); + + case IDS_BOOMARK_BAR_OPEN_ALL: + case IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW: + return HasURLs(); + + case IDS_BOOKMARK_BAR_RENAME_FOLDER: + case IDS_BOOKMARK_BAR_EDIT: + return selection_.size() == 1 && !is_root_node; + + case IDS_BOOKMARK_BAR_REMOVE: + return !selection_.empty() && !is_root_node; + + case IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER: + return (configuration_ == BOOKMARK_MANAGER_TABLE_OTHER || + configuration_ == BOOKMARK_MANAGER_ORGANIZE_MENU_OTHER) && + selection_.size() == 1; + + case IDS_BOOKMARK_MANAGER_SORT: + return parent_ && parent_ != model_->root_node(); + + case IDS_BOOMARK_BAR_NEW_FOLDER: + case IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK: + return GetParentForNewNodes() != NULL; + + case IDS_COPY: + case IDS_CUT: + return selection_.size() > 0 && !is_root_node; + + // TODO(erg): Port boomark_utils::CanPasteFromClipboard + // case IDS_PASTE: + // // Always paste to parent. + // return bookmark_utils::CanPasteFromClipboard(parent_); + } + return true; +} + +void BookmarkContextMenuGtk::ExecuteCommand(int index) { + switch (index) { + case IDS_BOOMARK_BAR_OPEN_ALL: + case IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO: + case IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW: { + PageNavigator* navigator = browser_ ? + browser_->GetSelectedTabContents() : navigator_; + WindowOpenDisposition initial_disposition; + if (index == IDS_BOOMARK_BAR_OPEN_ALL) { + initial_disposition = NEW_FOREGROUND_TAB; + UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_OpenAll", + profile_); + } else if (index == IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW) { + initial_disposition = NEW_WINDOW; + UserMetrics::RecordAction( + L"BookmarkBar_ContextMenu_OpenAllInNewWindow", profile_); + } else { + initial_disposition = OFF_THE_RECORD; + UserMetrics::RecordAction( + L"BookmarkBar_ContextMenu_OpenAllIncognito", profile_); + } + + bookmark_utils::OpenAll(window_, profile_, navigator, + selection_, initial_disposition); + break; + } + + case IDS_BOOKMARK_BAR_RENAME_FOLDER: + case IDS_BOOKMARK_BAR_EDIT: { + UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Edit", profile_); + + if (selection_.size() != 1) { + NOTREACHED(); + return; + } + + if (selection_[0]->is_url()) { + NOTIMPLEMENTED() << "Bookmark editor not implemented"; + } else { + NOTIMPLEMENTED() << "Folder editor not implemented"; + } + break; + } + + case IDS_BOOKMARK_BAR_REMOVE: { + UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Remove", profile_); + BookmarkModel* model = RemoveModelObserver(); + + for (size_t i = 0; i < selection_.size(); ++i) { + model->Remove(selection_[i]->GetParent(), + selection_[i]->GetParent()->IndexOfChild(selection_[i])); + } + selection_.clear(); + break; + } + + case IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK: { + UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Add", profile_); + NOTIMPLEMENTED() << "Adding new bookmark not implemented"; + break; + } + + case IDS_BOOMARK_BAR_NEW_FOLDER: { + UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_NewFolder", + profile_); + + NOTIMPLEMENTED() << "EditFolderController not implemented"; + break; + } + + case IDS_BOOMARK_BAR_ALWAYS_SHOW: { + bookmark_utils::ToggleWhenVisible(profile_); + break; + } + + case IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER: { + UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_ShowInFolder", + profile_); + + if (selection_.size() != 1) { + NOTREACHED(); + return; + } + + NOTIMPLEMENTED() << "Bookmark Manager not implemented"; + break; + } + + case IDS_BOOKMARK_MANAGER: { + UserMetrics::RecordAction(L"ShowBookmarkManager", profile_); + NOTIMPLEMENTED() << "Bookmark Manager not implemented"; + break; + } + + case IDS_BOOKMARK_MANAGER_SORT: { + UserMetrics::RecordAction(L"BookmarkManager_Sort", profile_); + model_->SortChildren(parent_); + break; + } + + case IDS_COPY: + case IDS_CUT: + case IDS_PASTE: { + NOTIMPLEMENTED() << "Cut/Copy/Paste not implemented"; + break; + } + + default: + NOTREACHED(); + } +} + +void BookmarkContextMenuGtk::AppendItem(int id) { + menu_->AppendMenuItemWithLabel( + id, + MenuGtk::ConvertAcceleratorsFromWindowsStyle( + l10n_util::GetStringUTF8(id))); +} + +void BookmarkContextMenuGtk::AppendItem(int id, int localization_id) { + menu_->AppendMenuItemWithLabel( + id, + MenuGtk::ConvertAcceleratorsFromWindowsStyle( + l10n_util::GetStringUTF8(localization_id))); +} + +void BookmarkContextMenuGtk::AppendSeparator() { + menu_->AppendSeparator(); +} + +void BookmarkContextMenuGtk::BookmarkModelBeingDeleted(BookmarkModel* model) { + ModelChanged(); +} + +void BookmarkContextMenuGtk::BookmarkNodeMoved(BookmarkModel* model, + BookmarkNode* old_parent, + int old_index, + BookmarkNode* new_parent, + int new_index) { + ModelChanged(); +} + +void BookmarkContextMenuGtk::BookmarkNodeAdded(BookmarkModel* model, + BookmarkNode* parent, + int index) { + ModelChanged(); +} + +void BookmarkContextMenuGtk::BookmarkNodeRemoved(BookmarkModel* model, + BookmarkNode* parent, + int index, + BookmarkNode* node) { + ModelChanged(); +} + +void BookmarkContextMenuGtk::BookmarkNodeChanged(BookmarkModel* model, + BookmarkNode* node) { + ModelChanged(); +} + +void BookmarkContextMenuGtk::BookmarkNodeChildrenReordered(BookmarkModel* model, + BookmarkNode* node) { + ModelChanged(); +} + +void BookmarkContextMenuGtk::ModelChanged() { + menu_->Cancel(); +} + +BookmarkModel* BookmarkContextMenuGtk::RemoveModelObserver() { + BookmarkModel* model = model_; + model_->RemoveObserver(this); + model_ = NULL; + return model; +} + +bool BookmarkContextMenuGtk::HasURLs() const { + for (size_t i = 0; i < selection_.size(); ++i) { + if (NodeHasURLs(selection_[i])) + return true; + } + return false; +} + +BookmarkNode* BookmarkContextMenuGtk::GetParentForNewNodes() const { + return (selection_.size() == 1 && selection_[0]->is_folder()) ? + selection_[0] : parent_; +} diff --git a/chrome/browser/gtk/bookmark_context_menu_gtk.h b/chrome/browser/gtk/bookmark_context_menu_gtk.h new file mode 100644 index 0000000..26ecee1a --- /dev/null +++ b/chrome/browser/gtk/bookmark_context_menu_gtk.h @@ -0,0 +1,116 @@ +// 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. + +#ifndef CHROME_BROWSER_GTK_BOOKMARK_CONTEXT_MENU_GTK_H_ +#define CHROME_BROWSER_GTK_BOOKMARK_CONTEXT_MENU_GTK_H_ + +#include <vector> + +#include "base/gfx/native_widget_types.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/gtk/menu_gtk.h" + +class Profile; +class Browser; +class PageNavigator; + +typedef struct _GtkWindow GtkWindow; + +// The context menu that opens or modifies bookmarks. (This is not the menu +// that displays folders contents.) +// +// TODO(erg): This is a copy of +// ./browser/bookmarks/bookmark_context_menu.{cc,h} and should be merged with +// that file once it is sufficiently de-views-ed. +class BookmarkContextMenuGtk : public MenuGtk::Delegate, + public BookmarkModelObserver { + public: + // Used to configure what the context menu shows. + enum ConfigurationType { + BOOKMARK_BAR, + BOOKMARK_MANAGER_TABLE, + // Used when the source is the table in the bookmark manager and the table + // is showing recently bookmarked or searched. + BOOKMARK_MANAGER_TABLE_OTHER, + BOOKMARK_MANAGER_TREE, + BOOKMARK_MANAGER_ORGANIZE_MENU, + // Used when the source is the bookmark manager and the table is showing + // recently bookmarked or searched. + BOOKMARK_MANAGER_ORGANIZE_MENU_OTHER + }; + + BookmarkContextMenuGtk(GtkWindow* window, + Profile* profile, + Browser* browser, + PageNavigator* navigator, + BookmarkNode* parent, + const std::vector<BookmarkNode*>& selection, + ConfigurationType configuration); + virtual ~BookmarkContextMenuGtk(); + + // Pops up this menu. + void PopupAsContext(guint32 event_time); + + // Overridden from MenuGtk::Delegate: + virtual bool IsCommandEnabled(int index) const; + virtual void ExecuteCommand(int index); + + private: + // BookmarkModelObserver method. Any change to the model results in closing + // the menu. + virtual void Loaded(BookmarkModel* model) {} + virtual void BookmarkModelBeingDeleted(BookmarkModel* model); + virtual void BookmarkNodeMoved(BookmarkModel* model, + BookmarkNode* old_parent, + int old_index, + BookmarkNode* new_parent, + int new_index); + virtual void BookmarkNodeAdded(BookmarkModel* model, + BookmarkNode* parent, + int index); + virtual void BookmarkNodeRemoved(BookmarkModel* model, + BookmarkNode* parent, + int index, + BookmarkNode* node); + virtual void BookmarkNodeChanged(BookmarkModel* model, + BookmarkNode* node); + virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model, + BookmarkNode* node) {} + virtual void BookmarkNodeChildrenReordered(BookmarkModel* model, + BookmarkNode* node); + + // Adds a IDS_* style command to the menu. + void AppendItem(int id); + // Adds a IDS_* style command to the menu with a different localized string. + void AppendItem(int id, int localization_id); + // Adds a separator to the menu. + void AppendSeparator(); + + // Invoked from the various bookmark model observer methods. Closes the menu. + void ModelChanged(); + + // Removes the observer from the model and NULLs out model_. + BookmarkModel* RemoveModelObserver(); + + // Returns true if selection_ has at least one bookmark of type url. + bool HasURLs() const; + + // Returns the parent for newly created folders/bookmarks. If selection_ + // has one element and it is a folder, selection_[0] is returned, otherwise + // parent_ is returned. + BookmarkNode* GetParentForNewNodes() const; + + gfx::NativeWindow window_; + Profile* profile_; + Browser* browser_; + PageNavigator* navigator_; + BookmarkNode* parent_; + std::vector<BookmarkNode*> selection_; + BookmarkModel* model_; + ConfigurationType configuration_; + + scoped_ptr<MenuGtk> menu_; +}; + +#endif // CHROME_BROWSER_GTK_BOOKMARK_CONTEXT_MENU_GTK_H_ diff --git a/chrome/browser/gtk/find_bar_gtk.cc b/chrome/browser/gtk/find_bar_gtk.cc index b7c7845..e30da63 100644 --- a/chrome/browser/gtk/find_bar_gtk.cc +++ b/chrome/browser/gtk/find_bar_gtk.cc @@ -13,6 +13,7 @@ #include "chrome/browser/gtk/custom_button.h" #include "chrome/browser/gtk/tab_contents_container_gtk.h" #include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/common/gtk_util.h" #include "chrome/common/l10n_util.h" #include "grit/generated_resources.h" diff --git a/chrome/browser/gtk/infobar_container_gtk.cc b/chrome/browser/gtk/infobar_container_gtk.cc index cc8543d..b30333e 100644 --- a/chrome/browser/gtk/infobar_container_gtk.cc +++ b/chrome/browser/gtk/infobar_container_gtk.cc @@ -6,11 +6,11 @@ #include <gtk/gtk.h> -#include "base/gfx/gtk_util.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/gtk/infobar_gtk.h" #include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/gtk_util.h" #include "chrome/common/notification_service.h" namespace { diff --git a/chrome/browser/gtk/infobar_gtk.cc b/chrome/browser/gtk/infobar_gtk.cc index a8456b7..06dd38b 100644 --- a/chrome/browser/gtk/infobar_gtk.cc +++ b/chrome/browser/gtk/infobar_gtk.cc @@ -11,6 +11,7 @@ #include "chrome/browser/gtk/custom_button.h" #include "chrome/browser/gtk/infobar_container_gtk.h" #include "chrome/browser/gtk/link_button_gtk.h" +#include "chrome/common/gtk_util.h" namespace { diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc index 845b7dd..8c858e4 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.cc +++ b/chrome/browser/gtk/location_bar_view_gtk.cc @@ -15,6 +15,7 @@ #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/gtk_util.h" #include "chrome/common/page_transition_types.h" #include "skia/include/SkBitmap.h" #include "webkit/glue/window_open_disposition.h" diff --git a/chrome/browser/gtk/menu_gtk.cc b/chrome/browser/gtk/menu_gtk.cc index 059755a..0b2bda0 100644 --- a/chrome/browser/gtk/menu_gtk.cc +++ b/chrome/browser/gtk/menu_gtk.cc @@ -4,36 +4,12 @@ #include "chrome/browser/gtk/menu_gtk.h" -#include "base/gfx/gtk_util.h" #include "base/logging.h" #include "base/string_util.h" +#include "chrome/common/gtk_util.h" #include "chrome/common/l10n_util.h" #include "skia/include/SkBitmap.h" -namespace { - -// GTK uses _ for accelerators. Windows uses & with && as an escape for &. -std::string ConvertAcceleratorsFromWindowsStyle(const std::string& label) { - std::string ret; - ret.reserve(label.length()); - for (size_t i = 0; i < label.length(); ++i) { - if ('&' == label[i]) { - if (i + 1 < label.length() && '&' == label[i + 1]) { - ret.push_back(label[i]); - ++i; - } else { - ret.push_back('_'); - } - } else { - ret.push_back(label[i]); - } - } - - return ret; -} - -} // namespace - MenuGtk::MenuGtk(MenuGtk::Delegate* delegate, const MenuCreateMaterial* menu_data, GtkAccelGroup* accel_group) @@ -103,7 +79,28 @@ void MenuGtk::PopupAsContext(guint32 event_time) { } void MenuGtk::Cancel() { - gtk_menu_detach(GTK_MENU(menu_.get())); + gtk_menu_popdown(GTK_MENU(menu_.get())); +} + +// static +std::string MenuGtk::ConvertAcceleratorsFromWindowsStyle( + const std::string& label) { + std::string ret; + ret.reserve(label.length()); + for (size_t i = 0; i < label.length(); ++i) { + if ('&' == label[i]) { + if (i + 1 < label.length() && '&' == label[i + 1]) { + ret.push_back(label[i]); + ++i; + } else { + ret.push_back('_'); + } + } else { + ret.push_back(label[i]); + } + } + + return ret; } void MenuGtk::BuildMenuIn(GtkWidget* menu, diff --git a/chrome/browser/gtk/menu_gtk.h b/chrome/browser/gtk/menu_gtk.h index 9b9a724..371ed58 100644 --- a/chrome/browser/gtk/menu_gtk.h +++ b/chrome/browser/gtk/menu_gtk.h @@ -67,6 +67,11 @@ class MenuGtk { // Closes the menu. void Cancel(); + // Change windows accelerator style to GTK style. (GTK uses _ for + // accelerators. Windows uses & with && as an escape for &.) + static std::string ConvertAcceleratorsFromWindowsStyle( + const std::string& label); + private: // A recursive function that transforms a MenuCreateMaterial tree into a set // of GtkMenuItems. diff --git a/chrome/browser/tab_contents/web_contents_view_gtk.cc b/chrome/browser/tab_contents/web_contents_view_gtk.cc index 4187c38..96c95f3 100644 --- a/chrome/browser/tab_contents/web_contents_view_gtk.cc +++ b/chrome/browser/tab_contents/web_contents_view_gtk.cc @@ -8,7 +8,6 @@ #include <gtk/gtk.h> #include "base/string_util.h" -#include "base/gfx/gtk_util.h" #include "base/gfx/point.h" #include "base/gfx/rect.h" #include "chrome/browser/gtk/browser_window_gtk.h" @@ -18,6 +17,7 @@ #include "chrome/browser/tab_contents/render_view_context_menu_gtk.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/common/gtk_util.h" namespace { diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 4f20c80..350d84f 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -13,13 +13,13 @@ 'sources/': [ ['exclude', '/(cocoa|gtk|win)/'], ['exclude', '_(cocoa|gtk|linux|mac|posix|skia|win|x)\\.(cc|mm?)$'], - ['exclude', '/(win|x11)_[^/]*\\.cc$'], + ['exclude', '/(gtk|win|x11)_[^/]*\\.cc$'], ], 'conditions': [ ['OS=="linux"', {'sources/': [ ['include', '/gtk/'], ['include', '_(gtk|linux|posix|skia|x)\\.cc$'], - ['include', '/x11_[^/]*\\.cc$'], + ['include', '/(gtk|x11)_[^/]*\\.cc$'], ]}], ['OS=="mac"', {'sources/': [ ['include', '/cocoa/'], @@ -125,6 +125,8 @@ 'common/gfx/text_elider.cc', 'common/gfx/text_elider.h', 'common/gfx/utils.h', + 'common/gtk_util.cc', + 'common/gtk_util.h', 'common/net/cookie_monster_sqlite.cc', 'common/net/cookie_monster_sqlite.h', 'common/net/dns.h', @@ -710,6 +712,8 @@ 'browser/gtk/back_forward_menu_model_gtk.h', 'browser/gtk/bookmark_bar_gtk.cc', 'browser/gtk/bookmark_bar_gtk.h', + 'browser/gtk/bookmark_context_menu_gtk.cc', + 'browser/gtk/bookmark_context_menu_gtk.h', 'browser/gtk/browser_toolbar_gtk.cc', 'browser/gtk/browser_toolbar_gtk.h', 'browser/gtk/browser_window_factory_gtk.cc', diff --git a/chrome/common/gtk_util.cc b/chrome/common/gtk_util.cc new file mode 100644 index 0000000..0576c0c --- /dev/null +++ b/chrome/common/gtk_util.cc @@ -0,0 +1,81 @@ +// 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/common/gtk_util.h" + +#include <gtk/gtk.h> + +#include "base/gfx/gtk_util.h" +#include "skia/include/SkBitmap.h" + +namespace { + +// Callback used in RemoveAllChildren. +void RemoveWidget(GtkWidget* widget, gpointer container) { + gtk_container_remove(GTK_CONTAINER(container), widget); +} + +void FreePixels(guchar* pixels, gpointer data) { + free(data); +} + +} // namespace + +namespace event_utils { + +WindowOpenDisposition DispositionFromEventFlags(guint event_flags) { + if ((event_flags & GDK_BUTTON2_MASK) || (event_flags & GDK_CONTROL_MASK)) { + return (event_flags & GDK_SHIFT_MASK) ? + NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB; + } + + if (event_flags & GDK_SHIFT_MASK) + return NEW_WINDOW; + return false /*event.IsAltDown()*/ ? SAVE_TO_DISK : CURRENT_TAB; +} + +} // namespace event_utils + +namespace gfx { + +GdkPixbuf* GdkPixbufFromSkBitmap(const SkBitmap* bitmap) { + bitmap->lockPixels(); + int width = bitmap->width(); + int height = bitmap->height(); + int stride = bitmap->rowBytes(); + const guchar* orig_data = static_cast<guchar*>(bitmap->getPixels()); + guchar* data = BGRAToRGBA(orig_data, width, height, stride); + + // This pixbuf takes ownership of our malloc()ed data and will + // free it for us when it is destroyed. + GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( + data, + GDK_COLORSPACE_RGB, // The only colorspace gtk supports. + true, // There is an alpha channel. + 8, + width, height, stride, &FreePixels, data); + + bitmap->unlockPixels(); + return pixbuf; +} + +GtkWidget* CreateGtkBorderBin(GtkWidget* child, const GdkColor* color, + int top, int bottom, int left, int right) { + // Use a GtkEventBox to get the background painted. However, we can't just + // use a container border, since it won't paint there. Use an alignment + // inside to get the sizes exactly of how we want the border painted. + GtkWidget* ebox = gtk_event_box_new(); + gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, color); + GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); + gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), top, bottom, left, right); + gtk_container_add(GTK_CONTAINER(alignment), child); + gtk_container_add(GTK_CONTAINER(ebox), alignment); + return ebox; +} + +void RemoveAllChildren(GtkWidget* container) { + gtk_container_foreach(GTK_CONTAINER(container), RemoveWidget, container); +} + +} // namespace gfx diff --git a/chrome/common/gtk_util.h b/chrome/common/gtk_util.h new file mode 100644 index 0000000..ff3dc5c --- /dev/null +++ b/chrome/common/gtk_util.h @@ -0,0 +1,41 @@ +// 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. + +#ifndef CHROME_COMMON_GTK_UTIL_H_ +#define CHROME_COMMON_GTK_UTIL_H_ + +#include <gtk/gtk.h> + +#include "webkit/glue/window_open_disposition.h" + +typedef struct _GdkPixbuf GdkPixbuf; +typedef struct _GtkWidget GtkWidget; +class SkBitmap; + +namespace event_utils { + +// Translates event flags into what kind of disposition they represent. +// For example, a middle click would mean to open a background tab. +// event_flags are the state in the GdkEvent structure. +WindowOpenDisposition DispositionFromEventFlags(guint state); + +} // namespace event_utils + +namespace gfx { + +// Convert and copy a SkBitmap to a GdkPixbuf. NOTE: this uses BGRAToRGBA, so +// it is an expensive operation. +GdkPixbuf* GdkPixbufFromSkBitmap(const SkBitmap* bitmap); + +// Create a GtkBin with |child| as its child widget. This bin will paint a +// border of color |color| with the sizes specified in pixels. +GtkWidget* CreateGtkBorderBin(GtkWidget* child, const GdkColor* color, + int top, int bottom, int left, int right); + +// Remove all children from this container. +void RemoveAllChildren(GtkWidget* container); + +} // namespace gfx + +#endif // CHROME_COMMON_GTK_UTIL_H_ diff --git a/chrome/common/resource_bundle_linux.cc b/chrome/common/resource_bundle_linux.cc index 57cce50..2fe2a31 100644 --- a/chrome/common/resource_bundle_linux.cc +++ b/chrome/common/resource_bundle_linux.cc @@ -19,6 +19,7 @@ #include "base/string_util.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/gfx/chrome_font.h" +#include "chrome/common/gtk_util.h" #include "chrome/common/l10n_util.h" #include "SkBitmap.h" |