diff options
-rw-r--r-- | chrome/browser/gtk/bookmark_bubble_gtk.cc | 155 | ||||
-rw-r--r-- | chrome/browser/gtk/bookmark_bubble_gtk.h | 44 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_toolbar_gtk.cc | 2 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_toolbar_gtk.h | 1 | ||||
-rw-r--r-- | chrome/browser/gtk/toolbar_star_toggle_gtk.cc | 8 | ||||
-rw-r--r-- | chrome/browser/gtk/toolbar_star_toggle_gtk.h | 6 |
6 files changed, 171 insertions, 45 deletions
diff --git a/chrome/browser/gtk/bookmark_bubble_gtk.cc b/chrome/browser/gtk/bookmark_bubble_gtk.cc index 310f00b..040a8f8 100644 --- a/chrome/browser/gtk/bookmark_bubble_gtk.cc +++ b/chrome/browser/gtk/bookmark_bubble_gtk.cc @@ -10,8 +10,13 @@ #include "app/resource_bundle.h" #include "base/basictypes.h" #include "base/logging.h" +#include "chrome/browser/bookmarks/bookmark_editor.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/bookmarks/bookmark_utils.h" #include "chrome/browser/gtk/gtk_chrome_link_button.h" #include "chrome/browser/gtk/info_bubble_gtk.h" +#include "chrome/browser/metrics/user_metrics.h" +#include "chrome/browser/profile.h" #include "grit/generated_resources.h" namespace { @@ -20,16 +25,6 @@ namespace { // keeps track of the currently open bubble, or NULL if none is open. BookmarkBubbleGtk* g_bubble = NULL; -// TODO(deanm): Just a temporary state to keep track of the last entry in the -// combo box. This makes sure we are catching the closing events right and -// saving the state. -gint g_last_active = 0; - -void HandleCloseButton(GtkWidget* widget, - gpointer user_data) { - reinterpret_cast<InfoBubbleGtk*>(user_data)->Close(); -} - } // namespace // static @@ -50,8 +45,6 @@ void BookmarkBubbleGtk::Show(GtkWindow* transient_toplevel, void BookmarkBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble, bool closed_by_escape) { - // Possibly commit any bookmark changes here... - g_last_active = gtk_combo_box_get_active(GTK_COMBO_BOX(combo_)); } BookmarkBubbleGtk::BookmarkBubbleGtk(GtkWindow* transient_toplevel, @@ -59,10 +52,15 @@ BookmarkBubbleGtk::BookmarkBubbleGtk(GtkWindow* transient_toplevel, Profile* profile, const GURL& url, bool newly_bookmarked) - : profile_(profile), - newly_bookmarked_(newly_bookmarked), + : url_(url), + profile_(profile), content_(NULL), - combo_(NULL) { + name_entry_(NULL), + folder_combo_(NULL), + bubble_(NULL), + newly_bookmarked_(newly_bookmarked), + apply_edits_(true), + remove_bookmark_(false) { GtkWidget* label = gtk_label_new(l10n_util::GetStringUTF8( newly_bookmarked_ ? IDS_BOOMARK_BUBBLE_PAGE_BOOKMARKED : IDS_BOOMARK_BUBBLE_PAGE_BOOKMARK).c_str()); @@ -77,6 +75,10 @@ BookmarkBubbleGtk::BookmarkBubbleGtk(GtkWindow* transient_toplevel, GtkWidget* close_button = gtk_button_new_with_label( l10n_util::GetStringUTF8(IDS_CLOSE).c_str()); + // Our content is arrange in 3 rows. |top| contains a left justified + // message, and a right justified remove link button. |table| is the middle + // portion with the name entry and the folder combo. |bottom| is the final + // row with a spacer, and the edit... and close buttons on the right. GtkWidget* content = gtk_vbox_new(FALSE, 5); GtkWidget* top = gtk_hbox_new(FALSE, 0); @@ -86,16 +88,23 @@ BookmarkBubbleGtk::BookmarkBubbleGtk(GtkWindow* transient_toplevel, gtk_box_pack_start(GTK_BOX(top), remove_button, FALSE, FALSE, 0); - // Use a combo box just to make sure popup windows work in the bubble content - // and we're not fighting with the bubble for the grab. - combo_ = gtk_combo_box_new_text(); - gtk_combo_box_append_text(GTK_COMBO_BOX(combo_), "entry 1"); - gtk_combo_box_append_text(GTK_COMBO_BOX(combo_), "entry 2"); - gtk_combo_box_append_text(GTK_COMBO_BOX(combo_), "entry 3"); - gtk_combo_box_set_active(GTK_COMBO_BOX(combo_), g_last_active); - - GtkWidget* name_entry = gtk_entry_new(); - + // TODO(deanm): We should show the bookmark bar folder along with the top + // other choices and an entry to go into the bookmark editor. Since we don't + // have the editor up yet on Linux, just show the bookmark bar for now. + BookmarkModel* model = profile_->GetBookmarkModel(); + BookmarkNode* bookmark_bar = model->GetBookmarkBarNode(); + folder_combo_ = gtk_combo_box_new_text(); + gtk_combo_box_append_text(GTK_COMBO_BOX(folder_combo_), + WideToUTF8(bookmark_bar->GetTitle()).c_str()); + // We default to the bookmark bar, so make it the active selection. + gtk_combo_box_set_active(GTK_COMBO_BOX(folder_combo_), 0); + + // Create the edit entry for updating the bookmark name / title. + name_entry_ = gtk_entry_new(); + gtk_entry_set_text(GTK_ENTRY(name_entry_), GetTitle().c_str()); + + // We use a table to allow the labels to line up with each other, along + // with the entry and folder combo lining up. GtkWidget* table = gtk_table_new(2, 2, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 10); @@ -103,16 +112,18 @@ BookmarkBubbleGtk::BookmarkBubbleGtk(GtkWindow* transient_toplevel, name_label, 0, 1, 0, 1); gtk_table_attach_defaults(GTK_TABLE(table), - name_entry, + name_entry_, 1, 2, 0, 1); gtk_table_attach_defaults(GTK_TABLE(table), folder_label, 0, 1, 1, 2); gtk_table_attach_defaults(GTK_TABLE(table), - combo_, + folder_combo_, 1, 2, 1, 2); GtkWidget* bottom = gtk_hbox_new(FALSE, 0); + // We want the buttons on the right, so just use an expanding label to fill + // all of the extra space on the right. gtk_box_pack_start(GTK_BOX(bottom), gtk_label_new(""), TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(bottom), edit_button, @@ -126,19 +137,21 @@ BookmarkBubbleGtk::BookmarkBubbleGtk(GtkWindow* transient_toplevel, // We want the focus to start on the entry, not on the remove button. gtk_container_set_focus_child(GTK_CONTAINER(content), table); - g_signal_connect(content, "destroy", - G_CALLBACK(&HandleDestroyThunk), this); - - // TODO(deanm): In the future we might want to hang on to the returned - // InfoBubble so that we can call Close() on it. - InfoBubbleGtk* bubble = InfoBubbleGtk::Show(transient_toplevel, - rect, content, this); - if (!bubble) { + bubble_ = InfoBubbleGtk::Show(transient_toplevel, + rect, content, this); + if (!bubble_) { NOTREACHED(); + return; } + g_signal_connect(content, "destroy", + G_CALLBACK(&HandleDestroyThunk), this); + g_signal_connect(name_entry_, "activate", + G_CALLBACK(&HandleNameActivateThunk), this); g_signal_connect(close_button, "clicked", - G_CALLBACK(&HandleCloseButton), bubble); + G_CALLBACK(&HandleCloseButtonThunk), this); + g_signal_connect(remove_button, "clicked", + G_CALLBACK(&HandleRemoveButtonThunk), this); } BookmarkBubbleGtk::~BookmarkBubbleGtk() { @@ -146,6 +159,15 @@ BookmarkBubbleGtk::~BookmarkBubbleGtk() { DCHECK(g_bubble); g_bubble = NULL; + + if (apply_edits_) { + ApplyEdits(); + } else if (remove_bookmark_) { + BookmarkModel* model = profile_->GetBookmarkModel(); + BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url_); + if (node) + model->Remove(node->GetParent(), node->GetParent()->IndexOfChild(node)); + } } gboolean BookmarkBubbleGtk::HandleDestroy() { @@ -155,3 +177,64 @@ gboolean BookmarkBubbleGtk::HandleDestroy() { delete this; return FALSE; // Propagate. } + +void BookmarkBubbleGtk::HandleNameActivate() { + bubble_->Close(); +} + +void BookmarkBubbleGtk::HandleCloseButton() { + bubble_->Close(); +} + +void BookmarkBubbleGtk::HandleRemoveButton() { + UserMetrics::RecordAction(L"BookmarkBubble_Unstar", profile_); + + apply_edits_ = false; + remove_bookmark_ = true; + bubble_->Close(); +} + +void BookmarkBubbleGtk::ApplyEdits() { + // Set this to make sure we don't attempt to apply edits again. + apply_edits_ = false; + + BookmarkModel* model = profile_->GetBookmarkModel(); + BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url_); + if (node) { + // NOTE: Would be nice to save a strlen and use gtk_entry_get_text_length, + // but it is fairly new and not always in our GTK version. + const std::wstring new_title( + UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(name_entry_)))); + + if (new_title != node->GetTitle()) { + model->SetTitle(node, new_title); + UserMetrics::RecordAction(L"BookmarkBubble_ChangeTitleInBubble", + profile_); + } + +// TODO(deanm): We need to get the Bookmark editor running on Linux. +#if 0 + // Last index means 'Choose another folder...' + if (parent_combobox_->selected_item() < + parent_model_.GetItemCount(parent_combobox_) - 1) { + BookmarkNode* new_parent = + parent_model_.GetNodeAt(parent_combobox_->selected_item()); + if (new_parent != node->GetParent()) { + UserMetrics::RecordAction(L"BookmarkBubble_ChangeParent", profile_); + model->Move(node, new_parent, new_parent->GetChildCount()); + } + } +#endif + } +} + +std::string BookmarkBubbleGtk::GetTitle() { + BookmarkModel* bookmark_model= profile_->GetBookmarkModel(); + BookmarkNode* node = bookmark_model->GetMostRecentlyAddedNodeForURL(url_); + if (!node) { + NOTREACHED(); + return std::string(); + } + + return WideToUTF8(node->GetTitle()); +} diff --git a/chrome/browser/gtk/bookmark_bubble_gtk.h b/chrome/browser/gtk/bookmark_bubble_gtk.h index 5192413..3dd0291 100644 --- a/chrome/browser/gtk/bookmark_bubble_gtk.h +++ b/chrome/browser/gtk/bookmark_bubble_gtk.h @@ -53,20 +53,56 @@ class BookmarkBubbleGtk : public InfoBubbleGtkDelegate { } // Notified when |content_| is destroyed so we can delete our instance. gboolean HandleDestroy(); - + + static void HandleNameActivateThunk(GtkWidget* widget, + gpointer user_data) { + return reinterpret_cast<BookmarkBubbleGtk*>(user_data)-> + HandleNameActivate(); + } + void HandleNameActivate(); + + static void HandleCloseButtonThunk(GtkWidget* widget, + gpointer user_data) { + return reinterpret_cast<BookmarkBubbleGtk*>(user_data)-> + HandleCloseButton(); + } + void HandleCloseButton(); + + static void HandleRemoveButtonThunk(GtkWidget* widget, + gpointer user_data) { + return reinterpret_cast<BookmarkBubbleGtk*>(user_data)-> + HandleRemoveButton(); + } + void HandleRemoveButton(); + + // Update the bookmark with any edits that have been made. + void ApplyEdits(); + + // Return the UTF8 encoded title for the current |url_|. + std::string GetTitle(); + // The URL of the bookmark. GURL url_; // Our current profile (used to access the bookmark system). Profile* profile_; - // Whether the bubble is creating or editing an existing bookmark. - bool newly_bookmarked_; // We let the InfoBubble own our content, and then we delete ourself // when the widget is destroyed (when the InfoBubble is destroyed). GtkWidget* content_; + // The GtkEntry for editing the bookmark name / title. + GtkWidget* name_entry_; + // The combo box for selecting the bookmark folder. - GtkWidget* combo_; + GtkWidget* folder_combo_; + + InfoBubbleGtk* bubble_; + + // Whether the bubble is creating or editing an existing bookmark. + bool newly_bookmarked_; + // When closing the window, whether we should update or remove the bookmark. + bool apply_edits_; + bool remove_bookmark_; DISALLOW_COPY_AND_ASSIGN(BookmarkBubbleGtk); }; diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc index e9eeded..8d53112 100644 --- a/chrome/browser/gtk/browser_toolbar_gtk.cc +++ b/chrome/browser/gtk/browser_toolbar_gtk.cc @@ -292,7 +292,7 @@ CustomDrawButton* BrowserToolbarGtk::BuildToolbarButton( ToolbarStarToggleGtk* BrowserToolbarGtk::BuildStarButton( const std::string& localized_tooltip) { - ToolbarStarToggleGtk* button = new ToolbarStarToggleGtk; + ToolbarStarToggleGtk* button = new ToolbarStarToggleGtk(this); gtk_widget_set_tooltip_text(button->widget(), localized_tooltip.c_str()); diff --git a/chrome/browser/gtk/browser_toolbar_gtk.h b/chrome/browser/gtk/browser_toolbar_gtk.h index 6a2a3aa..8f7542d 100644 --- a/chrome/browser/gtk/browser_toolbar_gtk.h +++ b/chrome/browser/gtk/browser_toolbar_gtk.h @@ -64,6 +64,7 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver, const NotificationSource& source, const NotificationDetails& details); + Profile* profile() { return profile_; } void SetProfile(Profile* profile); // Message that we should react to a state change. diff --git a/chrome/browser/gtk/toolbar_star_toggle_gtk.cc b/chrome/browser/gtk/toolbar_star_toggle_gtk.cc index 4e03454..77c5732 100644 --- a/chrome/browser/gtk/toolbar_star_toggle_gtk.cc +++ b/chrome/browser/gtk/toolbar_star_toggle_gtk.cc @@ -7,10 +7,12 @@ #include "app/resource_bundle.h" #include "base/gfx/rect.h" #include "chrome/browser/gtk/bookmark_bubble_gtk.h" +#include "chrome/browser/gtk/browser_toolbar_gtk.h" #include "grit/theme_resources.h" -ToolbarStarToggleGtk::ToolbarStarToggleGtk() - : widget_(gtk_button_new()), +ToolbarStarToggleGtk::ToolbarStarToggleGtk(BrowserToolbarGtk* host) + : host_(host), + widget_(gtk_button_new()), is_starred_(false), unstarred_(IDR_STAR, IDR_STAR_P, IDR_STAR_H, IDR_STAR_D), starred_(IDR_STARRED, IDR_STARRED_P, IDR_STARRED_H, 0) { @@ -42,7 +44,7 @@ void ToolbarStarToggleGtk::ShowStarBubble(const GURL& url, BookmarkBubbleGtk::Show(GTK_WINDOW(gtk_widget_get_toplevel(widget)), gfx::Rect(x, y, width, height), - NULL, + host_->profile(), url, newly_bookmarked); } diff --git a/chrome/browser/gtk/toolbar_star_toggle_gtk.h b/chrome/browser/gtk/toolbar_star_toggle_gtk.h index dec5cd9..afa61a3 100644 --- a/chrome/browser/gtk/toolbar_star_toggle_gtk.h +++ b/chrome/browser/gtk/toolbar_star_toggle_gtk.h @@ -11,12 +11,13 @@ #include "chrome/browser/gtk/custom_button.h" #include "chrome/common/owned_widget_gtk.h" +class BrowserToolbarGtk; class GURL; // Displays the bookmark star button, which toggles between two images. class ToolbarStarToggleGtk { public: - ToolbarStarToggleGtk(); + ToolbarStarToggleGtk(BrowserToolbarGtk* host); ~ToolbarStarToggleGtk(); // If the bubble isn't showing, shows it above the star button. @@ -31,6 +32,9 @@ class ToolbarStarToggleGtk { static gboolean OnExpose(GtkWidget* widget, GdkEventExpose* e, ToolbarStarToggleGtk* obj); + // The browser toolbar hosting this widget, for getting the current profile. + BrowserToolbarGtk* host_; + // The actual button widget. OwnedWidgetGtk widget_; |