GTK: Fix profile selection bubble to match the chrome-theme when selected.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/8402005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107495 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.cc b/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.cc
index 732d983..c92a7902 100644
--- a/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.cc
+++ b/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.cc
@@ -16,6 +16,8 @@
#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
#include "chrome/browser/ui/gtk/gtk_theme_service.h"
#include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/notification_source.h"
#include "grit/generated_resources.h"
#include "ui/base/gtk/gtk_hig_constants.h"
#include "ui/base/l10n/l10n_util.h"
@@ -37,6 +39,7 @@
const gfx::Rect* rect)
: contents_(NULL),
theme_service_(GtkThemeService::GetFrom(browser->profile())),
+ new_profile_link_(NULL),
minimum_width_(kBubbleMinWidth) {
avatar_menu_model_.reset(new AvatarMenuModel(
&g_browser_process->profile_manager()->GetProfileInfoCache(),
@@ -56,6 +59,10 @@
this); // |delegate|
g_signal_connect(contents_, "destroy",
G_CALLBACK(&OnDestroyThunk), this);
+
+ registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
+ content::Source<ThemeService>(theme_service_));
+ theme_service_->InitThemesFor(this);
}
AvatarMenuBubbleGtk::~AvatarMenuBubbleGtk() {
@@ -91,6 +98,15 @@
bubble_->Close();
}
+void AvatarMenuBubbleGtk::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ DCHECK_EQ(type, chrome::NOTIFICATION_BROWSER_THEME_CHANGED);
+ gtk_chrome_link_button_set_use_gtk_theme(
+ GTK_CHROME_LINK_BUTTON(new_profile_link_),
+ theme_service_->UsingNativeTheme());
+}
+
void AvatarMenuBubbleGtk::OnSizeRequest(GtkWidget* widget,
GtkRequisition* req) {
// Always use the maximum width ever requested.
@@ -129,15 +145,15 @@
gtk_box_pack_start(GTK_BOX(contents_), gtk_hseparator_new(), TRUE, TRUE, 0);
// The new profile link.
- GtkWidget* new_profile_link = gtk_chrome_link_button_new(
+ new_profile_link_ = gtk_chrome_link_button_new(
l10n_util::GetStringUTF8(IDS_PROFILES_CREATE_NEW_PROFILE_LINK).c_str());
- g_signal_connect(new_profile_link, "clicked",
+ g_signal_connect(new_profile_link_, "clicked",
G_CALLBACK(OnNewProfileLinkClickedThunk), this);
GtkWidget* link_align = gtk_alignment_new(0, 0, 0, 0);
gtk_alignment_set_padding(GTK_ALIGNMENT(link_align),
0, 0, kNewProfileLinkLeftPadding, 0);
- gtk_container_add(GTK_CONTAINER(link_align), new_profile_link);
+ gtk_container_add(GTK_CONTAINER(link_align), new_profile_link_);
gtk_box_pack_start(GTK_BOX(contents_), link_align, FALSE, FALSE, 0);
}
diff --git a/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h b/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h
index a31addc..22e59823 100644
--- a/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h
+++ b/chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h
@@ -16,6 +16,8 @@
#include "chrome/browser/profiles/avatar_menu_model_observer.h"
#include "chrome/browser/ui/gtk/avatar_menu_item_gtk.h"
#include "chrome/browser/ui/gtk/bubble/bubble_gtk.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
#include "ui/base/gtk/gtk_signal.h"
class AvatarMenuModel;
@@ -26,7 +28,8 @@
// It displays a list of profiles and allows users to switch between profiles.
class AvatarMenuBubbleGtk : public BubbleDelegateGtk,
public AvatarMenuModelObserver,
- public AvatarMenuItemGtk::Delegate {
+ public AvatarMenuItemGtk::Delegate,
+ public content::NotificationObserver {
public:
AvatarMenuBubbleGtk(Browser* browser,
GtkWidget* anchor,
@@ -43,9 +46,13 @@
AvatarMenuModel* avatar_menu_model) OVERRIDE;
// AvatarMenuItemGtk::Delegate implementation.
- virtual void OpenProfile(size_t profile_index);
+ virtual void OpenProfile(size_t profile_index) OVERRIDE;
+ virtual void EditProfile(size_t profile_index) OVERRIDE;
- virtual void EditProfile(size_t profile_index);
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
private:
// Notified when |contents_| is destroyed so we can delete our instance.
@@ -69,6 +76,10 @@
// A weak pointer to the theme service.
GtkThemeService* theme_service_;
+ // A weak pointer to the new proifle link to keep its theme information
+ // updated.
+ GtkWidget* new_profile_link_;
+
// A vector of all profile items in the menu.
std::vector<AvatarMenuItemGtk*> items_;
@@ -76,6 +87,8 @@
// from automatically reducing its size when hovering over a profile item.
int minimum_width_;
+ content::NotificationRegistrar registrar_;
+
DISALLOW_COPY_AND_ASSIGN(AvatarMenuBubbleGtk);
};
diff --git a/chrome/browser/ui/gtk/avatar_menu_item_gtk.cc b/chrome/browser/ui/gtk/avatar_menu_item_gtk.cc
index b0bb3eaa..fd6ee9f 100644
--- a/chrome/browser/ui/gtk/avatar_menu_item_gtk.cc
+++ b/chrome/browser/ui/gtk/avatar_menu_item_gtk.cc
@@ -10,6 +10,8 @@
#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
#include "chrome/browser/ui/gtk/gtk_theme_service.h"
#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/notification_source.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "grit/theme_resources_standard.h"
@@ -32,6 +34,12 @@
// elided.
const int kUserNameMaxWidth = 200;
+// The color of the item highlight when we're in chrome-theme mode.
+const GdkColor kHighlightColor = GDK_COLOR_RGB(0xe3, 0xed, 0xf6);
+
+// The color of the background when we're in chrome-theme mode.
+const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xff, 0xff, 0xff);
+
} // namespace
AvatarMenuItemGtk::AvatarMenuItemGtk(Delegate* delegate,
@@ -41,10 +49,16 @@
: delegate_(delegate),
item_(item),
item_index_(item_index),
+ theme_service_(theme_service),
status_label_(NULL),
link_alignment_(NULL),
+ edit_profile_link_(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
- Init(theme_service);
+ Init(theme_service_);
+
+ registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
+ content::Source<ThemeService>(theme_service_));
+ theme_service_->InitThemesFor(this);
}
AvatarMenuItemGtk::~AvatarMenuItemGtk() {
@@ -73,9 +87,7 @@
if (event->detail == GDK_NOTIFY_INFERIOR)
return FALSE;
- GtkStyle* style = gtk_rc_get_style(widget);
- GdkColor highlight_color = style->bg[GTK_STATE_SELECTED];
- gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &highlight_color);
+ gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &highlighted_color_);
if (item_.active) {
gtk_widget_hide(status_label_);
gtk_widget_show(link_alignment_);
@@ -89,7 +101,7 @@
if (event->detail == GDK_NOTIFY_INFERIOR)
return FALSE;
- gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, NULL);
+ gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, unhighlighted_color_);
if (item_.active) {
gtk_widget_show(status_label_);
gtk_widget_hide(link_alignment_);
@@ -102,6 +114,32 @@
delegate_->EditProfile(item_index_);
}
+void AvatarMenuItemGtk::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ DCHECK_EQ(type, chrome::NOTIFICATION_BROWSER_THEME_CHANGED);
+ bool using_native = theme_service_->UsingNativeTheme();
+
+ if (using_native) {
+ GtkStyle* style = gtk_rc_get_style(widget_.get());
+ highlighted_color_ = style->bg[GTK_STATE_SELECTED];
+ unhighlighted_color_ = NULL;
+ } else {
+ highlighted_color_ = kHighlightColor;
+ unhighlighted_color_ = &kBackgroundColor;
+ }
+
+ // Assume that the widget isn't highlighted since theme changes will almost
+ // never happen while we're up.
+ gtk_widget_modify_bg(widget_.get(), GTK_STATE_NORMAL, unhighlighted_color_);
+
+ if (edit_profile_link_) {
+ gtk_chrome_link_button_set_use_gtk_theme(
+ GTK_CHROME_LINK_BUTTON(edit_profile_link_),
+ using_native);
+ }
+}
+
void AvatarMenuItemGtk::OnEditProfileLinkClicked(GtkWidget* link) {
// delegate_->EditProfile() will close the avatar bubble which in turn
// try to destroy this AvatarMenuItemGtk.
@@ -182,11 +220,11 @@
if (item_.active) {
// The "edit your profile" link.
- GtkWidget* edit_profile_link = gtk_chrome_link_button_new(
+ edit_profile_link_ = gtk_chrome_link_button_new(
l10n_util::GetStringUTF8(IDS_PROFILES_EDIT_PROFILE_LINK).c_str());
link_alignment_ = gtk_alignment_new(0, 0, 0, 0);
- gtk_container_add(GTK_CONTAINER(link_alignment_), edit_profile_link);
+ gtk_container_add(GTK_CONTAINER(link_alignment_), edit_profile_link_);
// The chrome link button contains a label that won't be shown if the button
// is set to "no show all", so show all first.
@@ -196,7 +234,7 @@
gtk_box_pack_start(GTK_BOX(item_vbox), link_alignment_, FALSE, FALSE, 0);
- g_signal_connect(edit_profile_link, "clicked",
+ g_signal_connect(edit_profile_link_, "clicked",
G_CALLBACK(OnEditProfileLinkClickedThunk), this);
GtkSizeGroup* size_group = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
diff --git a/chrome/browser/ui/gtk/avatar_menu_item_gtk.h b/chrome/browser/ui/gtk/avatar_menu_item_gtk.h
index 62ff3782..6cfef4904 100644
--- a/chrome/browser/ui/gtk/avatar_menu_item_gtk.h
+++ b/chrome/browser/ui/gtk/avatar_menu_item_gtk.h
@@ -10,6 +10,8 @@
#include "base/memory/weak_ptr.h"
#include "chrome/browser/profiles/avatar_menu_model.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
#include "ui/base/gtk/gtk_signal.h"
#include "ui/base/gtk/owned_widget_gtk.h"
@@ -19,7 +21,7 @@
// to be displayed in the AvatarMenuBubble. Clicking the profile will open a new
// browser window, and when the user hovers over an active profile item, a link
// is displayed that will allow editing the profile.
-class AvatarMenuItemGtk {
+class AvatarMenuItemGtk : public content::NotificationObserver {
public:
// Delegates opening or editing a profile.
class Delegate {
@@ -43,6 +45,11 @@
// Returns the root widget for this menu item.
GtkWidget* widget() { return widget_.get(); }
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
private:
CHROMEGTK_CALLBACK_1(AvatarMenuItemGtk, gboolean, OnProfileClick,
GdkEventButton*);
@@ -68,6 +75,9 @@
// The root widget for this menu item.
ui::OwnedWidgetGtk widget_;
+ // Provides colors.
+ GtkThemeService* theme_service_;
+
// A weak pointer to a label that displays the sync status. It is not shown
// when the user is hovering over the item if the profile is the active
// profile.
@@ -77,7 +87,23 @@
// when the user is hovering over the active profile.
GtkWidget* link_alignment_;
+ // A weak pointer to a GtkChromeLinkButton so we can keep the use_gtk_theme
+ // property up to date.
+ GtkWidget* edit_profile_link_;
+
+ // The highlighted color. Depending on the theme, this is either |widget|'s
+ // bg[GTK_STATE_SELECTED] or a static highlight.
+ GdkColor highlighted_color_;
+
+ // The unhighlighted color. Depending on the theme, this is either NULL or a
+ // pointer to static data.
+ const GdkColor* unhighlighted_color_;
+
base::WeakPtrFactory<AvatarMenuItemGtk> weak_factory_;
+
+ content::NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(AvatarMenuItemGtk);
};
#endif // CHROME_BROWSER_UI_GTK_AVATAR_MENU_ITEM_GTK_H_