OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/gtk/avatar_menu_item_gtk.h" | 5 #include "chrome/browser/ui/gtk/avatar_menu_item_gtk.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
10 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h" | 10 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h" |
11 #include "chrome/browser/ui/gtk/gtk_theme_service.h" | 11 #include "chrome/browser/ui/gtk/gtk_theme_service.h" |
12 #include "chrome/browser/ui/gtk/gtk_util.h" | 12 #include "chrome/browser/ui/gtk/gtk_util.h" |
| 13 #include "chrome/common/chrome_notification_types.h" |
| 14 #include "content/public/browser/notification_source.h" |
13 #include "grit/generated_resources.h" | 15 #include "grit/generated_resources.h" |
14 #include "grit/theme_resources.h" | 16 #include "grit/theme_resources.h" |
15 #include "grit/theme_resources_standard.h" | 17 #include "grit/theme_resources_standard.h" |
16 #include "third_party/skia/include/core/SkBitmap.h" | 18 #include "third_party/skia/include/core/SkBitmap.h" |
17 #include "ui/base/gtk/gtk_hig_constants.h" | 19 #include "ui/base/gtk/gtk_hig_constants.h" |
18 #include "ui/base/l10n/l10n_util.h" | 20 #include "ui/base/l10n/l10n_util.h" |
19 #include "ui/base/resource/resource_bundle.h" | 21 #include "ui/base/resource/resource_bundle.h" |
20 #include "ui/base/text/text_elider.h" | 22 #include "ui/base/text/text_elider.h" |
21 #include "ui/gfx/canvas_skia.h" | 23 #include "ui/gfx/canvas_skia.h" |
22 #include "ui/gfx/gtk_util.h" | 24 #include "ui/gfx/gtk_util.h" |
23 #include "ui/gfx/image/image.h" | 25 #include "ui/gfx/image/image.h" |
24 | 26 |
25 namespace { | 27 namespace { |
26 | 28 |
27 // A checkmark is drawn in the lower-right corner of the active avatar image. | 29 // A checkmark is drawn in the lower-right corner of the active avatar image. |
28 // This value is the x offset, in pixels, from that position. | 30 // This value is the x offset, in pixels, from that position. |
29 const int kCheckMarkXOffset = 2; | 31 const int kCheckMarkXOffset = 2; |
30 | 32 |
31 // The maximum width of a user name in pixels. Anything longer than this will be | 33 // The maximum width of a user name in pixels. Anything longer than this will be |
32 // elided. | 34 // elided. |
33 const int kUserNameMaxWidth = 200; | 35 const int kUserNameMaxWidth = 200; |
34 | 36 |
| 37 // The color of the item highlight when we're in chrome-theme mode. |
| 38 const GdkColor kHighlightColor = GDK_COLOR_RGB(0xe3, 0xed, 0xf6); |
| 39 |
| 40 // The color of the background when we're in chrome-theme mode. |
| 41 const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xff, 0xff, 0xff); |
| 42 |
35 } // namespace | 43 } // namespace |
36 | 44 |
37 AvatarMenuItemGtk::AvatarMenuItemGtk(Delegate* delegate, | 45 AvatarMenuItemGtk::AvatarMenuItemGtk(Delegate* delegate, |
38 const AvatarMenuModel::Item& item, | 46 const AvatarMenuModel::Item& item, |
39 size_t item_index, | 47 size_t item_index, |
40 GtkThemeService* theme_service) | 48 GtkThemeService* theme_service) |
41 : delegate_(delegate), | 49 : delegate_(delegate), |
42 item_(item), | 50 item_(item), |
43 item_index_(item_index), | 51 item_index_(item_index), |
| 52 theme_service_(theme_service), |
44 status_label_(NULL), | 53 status_label_(NULL), |
45 link_alignment_(NULL), | 54 link_alignment_(NULL), |
| 55 edit_profile_link_(NULL), |
46 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | 56 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
47 Init(theme_service); | 57 Init(theme_service_); |
| 58 |
| 59 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, |
| 60 content::Source<ThemeService>(theme_service_)); |
| 61 theme_service_->InitThemesFor(this); |
48 } | 62 } |
49 | 63 |
50 AvatarMenuItemGtk::~AvatarMenuItemGtk() { | 64 AvatarMenuItemGtk::~AvatarMenuItemGtk() { |
51 widget_.Destroy(); | 65 widget_.Destroy(); |
52 } | 66 } |
53 | 67 |
54 void AvatarMenuItemGtk::OpenProfile() { | 68 void AvatarMenuItemGtk::OpenProfile() { |
55 delegate_->OpenProfile(item_index_); | 69 delegate_->OpenProfile(item_index_); |
56 } | 70 } |
57 | 71 |
58 gboolean AvatarMenuItemGtk::OnProfileClick(GtkWidget* widget, | 72 gboolean AvatarMenuItemGtk::OnProfileClick(GtkWidget* widget, |
59 GdkEventButton* event) { | 73 GdkEventButton* event) { |
60 // delegate_->EditProfile() will close the avatar bubble which in turn | 74 // delegate_->EditProfile() will close the avatar bubble which in turn |
61 // try to destroy this AvatarMenuItemGtk. | 75 // try to destroy this AvatarMenuItemGtk. |
62 // This is not OK to do this from the signal handler, so we'll | 76 // This is not OK to do this from the signal handler, so we'll |
63 // defer it. | 77 // defer it. |
64 MessageLoop::current()->PostTask( | 78 MessageLoop::current()->PostTask( |
65 FROM_HERE, | 79 FROM_HERE, |
66 base::Bind(&AvatarMenuItemGtk::OpenProfile, | 80 base::Bind(&AvatarMenuItemGtk::OpenProfile, |
67 weak_factory_.GetWeakPtr())); | 81 weak_factory_.GetWeakPtr())); |
68 return FALSE; | 82 return FALSE; |
69 } | 83 } |
70 | 84 |
71 gboolean AvatarMenuItemGtk::OnProfileEnter(GtkWidget* widget, | 85 gboolean AvatarMenuItemGtk::OnProfileEnter(GtkWidget* widget, |
72 GdkEventCrossing* event) { | 86 GdkEventCrossing* event) { |
73 if (event->detail == GDK_NOTIFY_INFERIOR) | 87 if (event->detail == GDK_NOTIFY_INFERIOR) |
74 return FALSE; | 88 return FALSE; |
75 | 89 |
76 GtkStyle* style = gtk_rc_get_style(widget); | 90 gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &highlighted_color_); |
77 GdkColor highlight_color = style->bg[GTK_STATE_SELECTED]; | |
78 gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &highlight_color); | |
79 if (item_.active) { | 91 if (item_.active) { |
80 gtk_widget_hide(status_label_); | 92 gtk_widget_hide(status_label_); |
81 gtk_widget_show(link_alignment_); | 93 gtk_widget_show(link_alignment_); |
82 } | 94 } |
83 | 95 |
84 return FALSE; | 96 return FALSE; |
85 } | 97 } |
86 | 98 |
87 gboolean AvatarMenuItemGtk::OnProfileLeave(GtkWidget* widget, | 99 gboolean AvatarMenuItemGtk::OnProfileLeave(GtkWidget* widget, |
88 GdkEventCrossing* event) { | 100 GdkEventCrossing* event) { |
89 if (event->detail == GDK_NOTIFY_INFERIOR) | 101 if (event->detail == GDK_NOTIFY_INFERIOR) |
90 return FALSE; | 102 return FALSE; |
91 | 103 |
92 gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, NULL); | 104 gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, unhighlighted_color_); |
93 if (item_.active) { | 105 if (item_.active) { |
94 gtk_widget_show(status_label_); | 106 gtk_widget_show(status_label_); |
95 gtk_widget_hide(link_alignment_); | 107 gtk_widget_hide(link_alignment_); |
96 } | 108 } |
97 | 109 |
98 return FALSE; | 110 return FALSE; |
99 } | 111 } |
100 | 112 |
101 void AvatarMenuItemGtk::EditProfile() { | 113 void AvatarMenuItemGtk::EditProfile() { |
102 delegate_->EditProfile(item_index_); | 114 delegate_->EditProfile(item_index_); |
103 } | 115 } |
104 | 116 |
| 117 void AvatarMenuItemGtk::Observe(int type, |
| 118 const content::NotificationSource& source, |
| 119 const content::NotificationDetails& details) { |
| 120 DCHECK_EQ(type, chrome::NOTIFICATION_BROWSER_THEME_CHANGED); |
| 121 bool using_native = theme_service_->UsingNativeTheme(); |
| 122 |
| 123 if (using_native) { |
| 124 GtkStyle* style = gtk_rc_get_style(widget_.get()); |
| 125 highlighted_color_ = style->bg[GTK_STATE_SELECTED]; |
| 126 unhighlighted_color_ = NULL; |
| 127 } else { |
| 128 highlighted_color_ = kHighlightColor; |
| 129 unhighlighted_color_ = &kBackgroundColor; |
| 130 } |
| 131 |
| 132 // Assume that the widget isn't highlighted since theme changes will almost |
| 133 // never happen while we're up. |
| 134 gtk_widget_modify_bg(widget_.get(), GTK_STATE_NORMAL, unhighlighted_color_); |
| 135 |
| 136 if (edit_profile_link_) { |
| 137 gtk_chrome_link_button_set_use_gtk_theme( |
| 138 GTK_CHROME_LINK_BUTTON(edit_profile_link_), |
| 139 using_native); |
| 140 } |
| 141 } |
| 142 |
105 void AvatarMenuItemGtk::OnEditProfileLinkClicked(GtkWidget* link) { | 143 void AvatarMenuItemGtk::OnEditProfileLinkClicked(GtkWidget* link) { |
106 // delegate_->EditProfile() will close the avatar bubble which in turn | 144 // delegate_->EditProfile() will close the avatar bubble which in turn |
107 // try to destroy this AvatarMenuItemGtk. | 145 // try to destroy this AvatarMenuItemGtk. |
108 // This is not OK to do this from the signal handler, so we'll | 146 // This is not OK to do this from the signal handler, so we'll |
109 // defer it. | 147 // defer it. |
110 MessageLoop::current()->PostTask( | 148 MessageLoop::current()->PostTask( |
111 FROM_HERE, | 149 FROM_HERE, |
112 base::Bind(&AvatarMenuItemGtk::EditProfile, | 150 base::Bind(&AvatarMenuItemGtk::EditProfile, |
113 weak_factory_.GetWeakPtr())); | 151 weak_factory_.GetWeakPtr())); |
114 } | 152 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 "<span size='small'>%s</span>", UTF16ToUTF8(item_.sync_state).c_str()); | 213 "<span size='small'>%s</span>", UTF16ToUTF8(item_.sync_state).c_str()); |
176 gtk_label_set_markup(GTK_LABEL(status_label_), markup); | 214 gtk_label_set_markup(GTK_LABEL(status_label_), markup); |
177 g_free(markup); | 215 g_free(markup); |
178 gtk_misc_set_alignment(GTK_MISC(status_label_), 0, 0); | 216 gtk_misc_set_alignment(GTK_MISC(status_label_), 0, 0); |
179 gtk_widget_set_no_show_all(status_label_, TRUE); | 217 gtk_widget_set_no_show_all(status_label_, TRUE); |
180 gtk_box_pack_start(GTK_BOX(item_vbox), status_label_, FALSE, FALSE, 0); | 218 gtk_box_pack_start(GTK_BOX(item_vbox), status_label_, FALSE, FALSE, 0); |
181 gtk_widget_show(status_label_); | 219 gtk_widget_show(status_label_); |
182 | 220 |
183 if (item_.active) { | 221 if (item_.active) { |
184 // The "edit your profile" link. | 222 // The "edit your profile" link. |
185 GtkWidget* edit_profile_link = gtk_chrome_link_button_new( | 223 edit_profile_link_ = gtk_chrome_link_button_new( |
186 l10n_util::GetStringUTF8(IDS_PROFILES_EDIT_PROFILE_LINK).c_str()); | 224 l10n_util::GetStringUTF8(IDS_PROFILES_EDIT_PROFILE_LINK).c_str()); |
187 | 225 |
188 link_alignment_ = gtk_alignment_new(0, 0, 0, 0); | 226 link_alignment_ = gtk_alignment_new(0, 0, 0, 0); |
189 gtk_container_add(GTK_CONTAINER(link_alignment_), edit_profile_link); | 227 gtk_container_add(GTK_CONTAINER(link_alignment_), edit_profile_link_); |
190 | 228 |
191 // The chrome link button contains a label that won't be shown if the button | 229 // The chrome link button contains a label that won't be shown if the button |
192 // is set to "no show all", so show all first. | 230 // is set to "no show all", so show all first. |
193 gtk_widget_show_all(link_alignment_); | 231 gtk_widget_show_all(link_alignment_); |
194 gtk_widget_set_no_show_all(link_alignment_, TRUE); | 232 gtk_widget_set_no_show_all(link_alignment_, TRUE); |
195 gtk_widget_hide(link_alignment_); | 233 gtk_widget_hide(link_alignment_); |
196 | 234 |
197 gtk_box_pack_start(GTK_BOX(item_vbox), link_alignment_, FALSE, FALSE, 0); | 235 gtk_box_pack_start(GTK_BOX(item_vbox), link_alignment_, FALSE, FALSE, 0); |
198 | 236 |
199 g_signal_connect(edit_profile_link, "clicked", | 237 g_signal_connect(edit_profile_link_, "clicked", |
200 G_CALLBACK(OnEditProfileLinkClickedThunk), this); | 238 G_CALLBACK(OnEditProfileLinkClickedThunk), this); |
201 | 239 |
202 GtkSizeGroup* size_group = gtk_size_group_new(GTK_SIZE_GROUP_BOTH); | 240 GtkSizeGroup* size_group = gtk_size_group_new(GTK_SIZE_GROUP_BOTH); |
203 gtk_size_group_add_widget(size_group, status_label_); | 241 gtk_size_group_add_widget(size_group, status_label_); |
204 gtk_size_group_add_widget(size_group, link_alignment_); | 242 gtk_size_group_add_widget(size_group, link_alignment_); |
205 g_object_unref(size_group); | 243 g_object_unref(size_group); |
206 } | 244 } |
207 | 245 |
208 gtk_box_pack_start(GTK_BOX(item_hbox), item_vbox, TRUE, TRUE, 0); | 246 gtk_box_pack_start(GTK_BOX(item_hbox), item_vbox, TRUE, TRUE, 0); |
209 gtk_container_add(GTK_CONTAINER(widget_.get()), item_hbox); | 247 gtk_container_add(GTK_CONTAINER(widget_.get()), item_hbox); |
210 } | 248 } |
OLD | NEW |