diff --git a/chrome/browser/gtk/bookmark_editor_gtk.cc b/chrome/browser/gtk/bookmark_editor_gtk.cc index 5aafc6c73609a2f6f1f46e0564502f71fc2d146f..f7cf7610cbedff42088e74fa834d25123cfa3fa7 100644 --- a/chrome/browser/gtk/bookmark_editor_gtk.cc +++ b/chrome/browser/gtk/bookmark_editor_gtk.cc @@ -7,6 +7,7 @@ #include <gtk/gtk.h> #include "app/l10n_util.h" +#include "app/menus/simple_menu_model.h" #include "base/basictypes.h" #include "base/logging.h" #include "base/string_util.h" @@ -17,6 +18,7 @@ #include "chrome/browser/gtk/bookmark_utils_gtk.h" #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/gtk_util.h" +#include "chrome/browser/gtk/menu_gtk.h" #include "chrome/browser/history/history.h" #include "chrome/browser/net/url_fixer_upper.h" #include "chrome/browser/profile.h" @@ -37,6 +39,127 @@ static const int kTreeHeight = 150; } // namespace +class BookmarkEditorGtk::ContextMenuController + : public menus::SimpleMenuModel::Delegate { + public: + explicit ContextMenuController(BookmarkEditorGtk* editor) + : editor_(editor), + running_menu_for_root_(false) { + menu_model_.reset(new menus::SimpleMenuModel(this)); + menu_model_->AddItemWithStringId(COMMAND_EDIT, IDS_EDIT); + menu_model_->AddItemWithStringId( + COMMAND_NEW_FOLDER, + IDS_BOOMARK_EDITOR_NEW_FOLDER_MENU_ITEM); + menu_.reset(new MenuGtk(NULL, menu_model_.get())); + } + virtual ~ContextMenuController() {} + + void RunMenu() { + const BookmarkNode* selected_node = GetSelectedNode(); + if (selected_node) + running_menu_for_root_ = selected_node->GetParent()->IsRoot(); + menu_->PopupAsContext(gtk_get_current_event_time()); + } + + void Cancel() { + editor_ = NULL; + menu_->Cancel(); + } + + private: + enum ContextMenuCommand { + COMMAND_EDIT, + COMMAND_NEW_FOLDER + }; + + // Overridden from menus::SimpleMenuModel::Delegate: + virtual bool IsCommandIdEnabled(int command_id) const { + return !(command_id == COMMAND_EDIT && running_menu_for_root_) && + (editor_ != NULL); + } + + virtual bool IsCommandIdChecked(int command_id) const { + return false; + } + + virtual bool GetAcceleratorForCommandId(int command_id, + menus::Accelerator* accelerator) { + return false; + } + + virtual void ExecuteCommand(int command_id) { + if (!editor_) + return; + + switch (command_id) { + case COMMAND_EDIT: { + GtkTreeIter iter; + if (!gtk_tree_selection_get_selected(editor_->tree_selection_, + NULL, + &iter)) { + return; + } + + GtkTreePath* path = gtk_tree_model_get_path( + GTK_TREE_MODEL(editor_->tree_store_), &iter); + gtk_tree_view_expand_to_path(GTK_TREE_VIEW(editor_->tree_view_), path); + + // Make the folder name editable. + gtk_tree_view_set_cursor(GTK_TREE_VIEW(editor_->tree_view_), path, + gtk_tree_view_get_column(GTK_TREE_VIEW(editor_->tree_view_), 0), + TRUE); + + gtk_tree_path_free(path); + break; + } + case COMMAND_NEW_FOLDER: + editor_->NewFolder(); + break; + default: + NOTREACHED(); + break; + } + } + + int64 GetRowIdAt(GtkTreeModel* model, GtkTreeIter* iter) { + GValue value = { 0, }; + gtk_tree_model_get_value(model, iter, bookmark_utils::ITEM_ID, &value); + int64 id = g_value_get_int64(&value); + g_value_unset(&value); + return id; + } + + const BookmarkNode* GetNodeAt(GtkTreeModel* model, GtkTreeIter* iter) { + int64 id = GetRowIdAt(model, iter); + return (id > 0) ? editor_->bb_model_->GetNodeByID(id) : NULL; + } + + const BookmarkNode* GetSelectedNode() { + GtkTreeModel* model; + GtkTreeIter iter; + if (!gtk_tree_selection_get_selected(editor_->tree_selection_, + &model, + &iter)) { + return NULL; + } + + return GetNodeAt(model, &iter); + } + + // The model and view for the right click context menu. + scoped_ptr<menus::SimpleMenuModel> menu_model_; + scoped_ptr<MenuGtk> menu_; + + // The context menu was brought up for. Set to NULL when the menu is canceled. + BookmarkEditorGtk* editor_; + + // If true, we're running the menu for the bookmark bar or other bookmarks + // nodes. + bool running_menu_for_root_; + + DISALLOW_COPY_AND_ASSIGN(ContextMenuController); +}; + // static void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd, Profile* profile, @@ -181,6 +304,8 @@ void BookmarkEditorGtk::Init(GtkWindow* parent_window) { tree_view_ = bookmark_utils::MakeTreeViewForStore(tree_store_); gtk_widget_set_size_request(tree_view_, kTreeWidth, kTreeHeight); tree_selection_ = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_)); + g_signal_connect(tree_view_, "button-press-event", + G_CALLBACK(OnTreeViewButtonPressEventThunk), this); GtkTreePath* path = NULL; if (selected_id) { @@ -396,6 +521,25 @@ void BookmarkEditorGtk::OnEntryChanged(GtkWidget* entry) { } void BookmarkEditorGtk::OnNewFolderClicked(GtkWidget* button) { + NewFolder(); +} + +gboolean BookmarkEditorGtk::OnTreeViewButtonPressEvent(GtkWidget* widget, + GdkEventButton* event) { + if (event->button == 3) + ShowContextMenu(); + + return FALSE; +} + +void BookmarkEditorGtk::ShowContextMenu() { + if (!menu_controller_.get()) + menu_controller_.reset(new ContextMenuController(this)); + + menu_controller_->RunMenu(); +} + +void BookmarkEditorGtk::NewFolder() { GtkTreeIter iter; if (!gtk_tree_selection_get_selected(tree_selection_, NULL, diff --git a/chrome/browser/gtk/bookmark_editor_gtk.h b/chrome/browser/gtk/bookmark_editor_gtk.h index fda876910a31a31dcc632c6d247db27367547780..debec747b63fb3985c875e6a29274a541b87f987 100644 --- a/chrome/browser/gtk/bookmark_editor_gtk.h +++ b/chrome/browser/gtk/bookmark_editor_gtk.h @@ -9,6 +9,7 @@ #include "app/gtk_integers.h" #include "app/gtk_signal.h" #include "base/gtest_prod_util.h" +#include "base/scoped_ptr.h" #include "base/string16.h" #include "chrome/browser/bookmarks/bookmark_editor.h" #include "chrome/browser/bookmarks/bookmark_model_observer.h" @@ -16,6 +17,7 @@ class GURL; typedef union _GdkEvent GdkEvent; +typedef struct _GdkEventButton GdkEventButton; typedef struct _GtkTreeIter GtkTreeIter; typedef struct _GtkTreeSelection GtkTreeSelection; typedef struct _GtkTreeStore GtkTreeStore; @@ -47,6 +49,9 @@ class BookmarkEditorGtk : public BookmarkEditor, void Close(); private: + class ContextMenuController; + friend class ContextMenuController; + void Init(GtkWindow* parent_window); // BookmarkModel observer methods. Any structural change results in @@ -104,6 +109,13 @@ class BookmarkEditorGtk : public BookmarkEditor, CHROMEGTK_CALLBACK_0(BookmarkEditorGtk, void, OnNewFolderClicked); + CHROMEGTK_CALLBACK_1(BookmarkEditorGtk, gboolean, OnTreeViewButtonPressEvent, + GdkEventButton*); + + void ShowContextMenu(); + + void NewFolder(); + // Profile the entry is from. Profile* profile_; @@ -141,6 +153,9 @@ class BookmarkEditorGtk : public BookmarkEditor, // Is the tree shown? bool show_tree_; + // The context menu controller. + scoped_ptr<ContextMenuController> menu_controller_; + DISALLOW_COPY_AND_ASSIGN(BookmarkEditorGtk); };