| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/infobars/infobar_gtk.h" | 5 #include "chrome/browser/ui/gtk/infobars/infobar_gtk.h" |
| 6 | 6 |
| 7 #include "base/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
| 8 #include "base/utf_string_conversions.h" | 8 #include "base/utf_string_conversions.h" |
| 9 #include "chrome/browser/infobars/infobar_service.h" | 9 #include "chrome/browser/infobars/infobar_service.h" |
| 10 #include "chrome/browser/profiles/profile.h" | 10 #include "chrome/browser/profiles/profile.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 const int InfoBar::kMaximumArrowTargetHeight = 24; | 45 const int InfoBar::kMaximumArrowTargetHeight = 24; |
| 46 const int InfoBar::kDefaultArrowTargetHalfWidth = kDefaultArrowTargetHeight; | 46 const int InfoBar::kDefaultArrowTargetHalfWidth = kDefaultArrowTargetHeight; |
| 47 const int InfoBar::kMaximumArrowTargetHalfWidth = 14; | 47 const int InfoBar::kMaximumArrowTargetHalfWidth = 14; |
| 48 const int InfoBar::kDefaultBarTargetHeight = 36; | 48 const int InfoBar::kDefaultBarTargetHeight = 36; |
| 49 | 49 |
| 50 // static | 50 // static |
| 51 const int InfoBarGtk::kEndOfLabelSpacing = 6; | 51 const int InfoBarGtk::kEndOfLabelSpacing = 6; |
| 52 | 52 |
| 53 InfoBarGtk::InfoBarGtk(InfoBarService* owner, InfoBarDelegate* delegate) | 53 InfoBarGtk::InfoBarGtk(InfoBarService* owner, InfoBarDelegate* delegate) |
| 54 : InfoBar(owner, delegate), | 54 : InfoBar(owner, delegate), |
| 55 theme_service_(GtkThemeService::GetFrom(Profile::FromBrowserContext( | 55 bg_box_(NULL), |
| 56 owner->GetWebContents()->GetBrowserContext()))), | 56 hbox_(NULL), |
| 57 theme_service_(NULL), |
| 57 signals_(new ui::GtkSignalRegistrar) { | 58 signals_(new ui::GtkSignalRegistrar) { |
| 58 DCHECK(delegate); | |
| 59 // Create |hbox_| and pad the sides. | |
| 60 hbox_ = gtk_hbox_new(FALSE, kElementPadding); | |
| 61 | |
| 62 // Make the whole infor bar horizontally shrinkable. | |
| 63 gtk_widget_set_size_request(hbox_, 0, -1); | |
| 64 | |
| 65 GtkWidget* padding = gtk_alignment_new(0, 0, 1, 1); | |
| 66 gtk_alignment_set_padding(GTK_ALIGNMENT(padding), | |
| 67 0, 0, kLeftPadding, kRightPadding); | |
| 68 | |
| 69 bg_box_ = gtk_event_box_new(); | |
| 70 gtk_widget_set_app_paintable(bg_box_, TRUE); | |
| 71 g_signal_connect(bg_box_, "expose-event", | |
| 72 G_CALLBACK(OnBackgroundExposeThunk), this); | |
| 73 gtk_container_add(GTK_CONTAINER(padding), hbox_); | |
| 74 gtk_container_add(GTK_CONTAINER(bg_box_), padding); | |
| 75 | |
| 76 // Add the icon on the left, if any. | |
| 77 gfx::Image* icon = delegate->GetIcon(); | |
| 78 if (icon) { | |
| 79 GtkWidget* image = gtk_image_new_from_pixbuf(icon->ToGdkPixbuf()); | |
| 80 | |
| 81 gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.5); | |
| 82 | |
| 83 gtk_box_pack_start(GTK_BOX(hbox_), image, FALSE, FALSE, 0); | |
| 84 } | |
| 85 | |
| 86 close_button_.reset(CustomDrawButton::CloseButtonBar(theme_service_)); | |
| 87 gtk_util::CenterWidgetInHBox(hbox_, close_button_->widget(), true, 0); | |
| 88 signals_->Connect(close_button_->widget(), "clicked", | |
| 89 G_CALLBACK(OnCloseButtonThunk), this); | |
| 90 | |
| 91 widget_.Own(gtk_expanded_container_new()); | |
| 92 gtk_container_add(GTK_CONTAINER(widget_.get()), bg_box_); | |
| 93 gtk_widget_set_size_request(widget_.get(), -1, 0); | |
| 94 | |
| 95 g_signal_connect(widget_.get(), "child-size-request", | |
| 96 G_CALLBACK(OnChildSizeRequestThunk), | |
| 97 this); | |
| 98 | |
| 99 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, | |
| 100 content::Source<ThemeService>(theme_service_)); | |
| 101 UpdateBorderColor(); | |
| 102 } | 59 } |
| 103 | 60 |
| 104 InfoBarGtk::~InfoBarGtk() { | 61 InfoBarGtk::~InfoBarGtk() { |
| 105 } | 62 } |
| 106 | 63 |
| 107 GtkWidget* InfoBarGtk::widget() { | 64 GtkWidget* InfoBarGtk::widget() { |
| 108 return widget_.get(); | 65 return widget_.get(); |
| 109 } | 66 } |
| 110 | 67 |
| 111 GdkColor InfoBarGtk::GetBorderColor() const { | 68 GdkColor InfoBarGtk::GetBorderColor() const { |
| 69 DCHECK(theme_service_); |
| 112 return theme_service_->GetBorderColor(); | 70 return theme_service_->GetBorderColor(); |
| 113 } | 71 } |
| 114 | 72 |
| 115 int InfoBarGtk::AnimatingHeight() const { | 73 int InfoBarGtk::AnimatingHeight() const { |
| 116 return animation().is_animating() ? bar_target_height() : 0; | 74 return animation().is_animating() ? bar_target_height() : 0; |
| 117 } | 75 } |
| 118 | 76 |
| 119 ui::GtkSignalRegistrar* InfoBarGtk::Signals() { | 77 ui::GtkSignalRegistrar* InfoBarGtk::Signals() { |
| 120 return signals_.get(); | 78 return signals_.get(); |
| 121 } | 79 } |
| 122 | 80 |
| 123 GtkWidget* InfoBarGtk::CreateLabel(const std::string& text) { | 81 GtkWidget* InfoBarGtk::CreateLabel(const std::string& text) { |
| 82 DCHECK(theme_service_); |
| 124 return theme_service_->BuildLabel(text, ui::kGdkBlack); | 83 return theme_service_->BuildLabel(text, ui::kGdkBlack); |
| 125 } | 84 } |
| 126 | 85 |
| 127 GtkWidget* InfoBarGtk::CreateLinkButton(const std::string& text) { | 86 GtkWidget* InfoBarGtk::CreateLinkButton(const std::string& text) { |
| 87 DCHECK(theme_service_); |
| 128 return theme_service_->BuildChromeLinkButton(text); | 88 return theme_service_->BuildChromeLinkButton(text); |
| 129 } | 89 } |
| 130 | 90 |
| 131 // static | 91 // static |
| 132 GtkWidget* InfoBarGtk::CreateMenuButton(const std::string& text) { | 92 GtkWidget* InfoBarGtk::CreateMenuButton(const std::string& text) { |
| 133 GtkWidget* button = gtk_button_new(); | 93 GtkWidget* button = gtk_button_new(); |
| 134 GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button)); | 94 GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button)); |
| 135 if (former_child) | 95 if (former_child) |
| 136 gtk_container_remove(GTK_CONTAINER(button), former_child); | 96 gtk_container_remove(GTK_CONTAINER(button), former_child); |
| 137 | 97 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 151 SkColor InfoBarGtk::ConvertGetColor(ColorGetter getter) { | 111 SkColor InfoBarGtk::ConvertGetColor(ColorGetter getter) { |
| 152 double r, g, b; | 112 double r, g, b; |
| 153 (this->*getter)(delegate()->GetInfoBarType(), &r, &g, &b); | 113 (this->*getter)(delegate()->GetInfoBarType(), &r, &g, &b); |
| 154 return SkColorSetARGB(255, 255 * r, 255 * g, 255 * b); | 114 return SkColorSetARGB(255, 255 * r, 255 * g, 255 * b); |
| 155 } | 115 } |
| 156 | 116 |
| 157 void InfoBarGtk::AddLabelWithInlineLink(const string16& display_text, | 117 void InfoBarGtk::AddLabelWithInlineLink(const string16& display_text, |
| 158 const string16& link_text, | 118 const string16& link_text, |
| 159 size_t link_offset, | 119 size_t link_offset, |
| 160 GCallback callback) { | 120 GCallback callback) { |
| 121 DCHECK(hbox_); |
| 161 GtkWidget* link_button = CreateLinkButton(UTF16ToUTF8(link_text)); | 122 GtkWidget* link_button = CreateLinkButton(UTF16ToUTF8(link_text)); |
| 162 gtk_util::ForceFontSizePixels( | 123 gtk_util::ForceFontSizePixels( |
| 163 GTK_CHROME_LINK_BUTTON(link_button)->label, 13.4); | 124 GTK_CHROME_LINK_BUTTON(link_button)->label, 13.4); |
| 164 DCHECK(callback); | 125 DCHECK(callback); |
| 165 signals_->Connect(link_button, "clicked", callback, this); | 126 signals_->Connect(link_button, "clicked", callback, this); |
| 166 gtk_util::SetButtonTriggersNavigation(link_button); | 127 gtk_util::SetButtonTriggersNavigation(link_button); |
| 167 | 128 |
| 168 GtkWidget* hbox = gtk_hbox_new(FALSE, 0); | 129 GtkWidget* hbox = gtk_hbox_new(FALSE, 0); |
| 169 // We want the link to be horizontally shrinkable, so that the Chrome | 130 // We want the link to be horizontally shrinkable, so that the Chrome |
| 170 // window can be resized freely even with a very long link. | 131 // window can be resized freely even with a very long link. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 193 | 154 |
| 194 void InfoBarGtk::ShowMenuWithModel(GtkWidget* sender, | 155 void InfoBarGtk::ShowMenuWithModel(GtkWidget* sender, |
| 195 MenuGtk::Delegate* delegate, | 156 MenuGtk::Delegate* delegate, |
| 196 ui::MenuModel* model) { | 157 ui::MenuModel* model) { |
| 197 menu_.reset(new MenuGtk(delegate, model)); | 158 menu_.reset(new MenuGtk(delegate, model)); |
| 198 menu_->PopupForWidget(sender, 1, gtk_get_current_event_time()); | 159 menu_->PopupForWidget(sender, 1, gtk_get_current_event_time()); |
| 199 } | 160 } |
| 200 | 161 |
| 201 void InfoBarGtk::GetTopColor(InfoBarDelegate::Type type, | 162 void InfoBarGtk::GetTopColor(InfoBarDelegate::Type type, |
| 202 double* r, double* g, double* b) { | 163 double* r, double* g, double* b) { |
| 164 DCHECK(theme_service_); |
| 203 SkColor color = theme_service_->UsingNativeTheme() ? | 165 SkColor color = theme_service_->UsingNativeTheme() ? |
| 204 theme_service_->GetColor(ThemeProperties::COLOR_TOOLBAR) : | 166 theme_service_->GetColor(ThemeProperties::COLOR_TOOLBAR) : |
| 205 GetInfoBarTopColor(type); | 167 GetInfoBarTopColor(type); |
| 206 *r = SkColorGetR(color) / 255.0; | 168 *r = SkColorGetR(color) / 255.0; |
| 207 *g = SkColorGetG(color) / 255.0; | 169 *g = SkColorGetG(color) / 255.0; |
| 208 *b = SkColorGetB(color) / 255.0; | 170 *b = SkColorGetB(color) / 255.0; |
| 209 } | 171 } |
| 210 | 172 |
| 211 void InfoBarGtk::GetBottomColor(InfoBarDelegate::Type type, | 173 void InfoBarGtk::GetBottomColor(InfoBarDelegate::Type type, |
| 212 double* r, double* g, double* b) { | 174 double* r, double* g, double* b) { |
| 175 DCHECK(theme_service_); |
| 213 SkColor color = theme_service_->UsingNativeTheme() ? | 176 SkColor color = theme_service_->UsingNativeTheme() ? |
| 214 theme_service_->GetColor(ThemeProperties::COLOR_TOOLBAR) : | 177 theme_service_->GetColor(ThemeProperties::COLOR_TOOLBAR) : |
| 215 GetInfoBarBottomColor(type); | 178 GetInfoBarBottomColor(type); |
| 216 *r = SkColorGetR(color) / 255.0; | 179 *r = SkColorGetR(color) / 255.0; |
| 217 *g = SkColorGetG(color) / 255.0; | 180 *g = SkColorGetG(color) / 255.0; |
| 218 *b = SkColorGetB(color) / 255.0; | 181 *b = SkColorGetB(color) / 255.0; |
| 219 } | 182 } |
| 220 | 183 |
| 221 void InfoBarGtk::UpdateBorderColor() { | 184 void InfoBarGtk::UpdateBorderColor() { |
| 185 DCHECK(widget()); |
| 222 gtk_widget_queue_draw(widget()); | 186 gtk_widget_queue_draw(widget()); |
| 223 } | 187 } |
| 224 | 188 |
| 225 void InfoBarGtk::OnCloseButton(GtkWidget* button) { | 189 void InfoBarGtk::OnCloseButton(GtkWidget* button) { |
| 226 // If we're not owned, we're already closing, so don't call | 190 // If we're not owned, we're already closing, so don't call |
| 227 // InfoBarDismissed(), since this can lead to us double-recording dismissals. | 191 // InfoBarDismissed(), since this can lead to us double-recording dismissals. |
| 228 if (delegate() && owned()) | 192 if (delegate() && owner()) |
| 229 delegate()->InfoBarDismissed(); | 193 delegate()->InfoBarDismissed(); |
| 230 RemoveSelf(); | 194 RemoveSelf(); |
| 231 } | 195 } |
| 232 | 196 |
| 233 gboolean InfoBarGtk::OnBackgroundExpose(GtkWidget* sender, | 197 gboolean InfoBarGtk::OnBackgroundExpose(GtkWidget* sender, |
| 234 GdkEventExpose* event) { | 198 GdkEventExpose* event) { |
| 235 TRACE_EVENT0("ui::gtk", "InfoBarGtk::OnBackgroundExpose"); | 199 TRACE_EVENT0("ui::gtk", "InfoBarGtk::OnBackgroundExpose"); |
| 200 DCHECK(theme_service_); |
| 236 | 201 |
| 237 GtkAllocation allocation; | 202 GtkAllocation allocation; |
| 238 gtk_widget_get_allocation(sender, &allocation); | 203 gtk_widget_get_allocation(sender, &allocation); |
| 239 const int height = allocation.height; | 204 const int height = allocation.height; |
| 240 | 205 |
| 241 cairo_t* cr = gdk_cairo_create(gtk_widget_get_window(sender)); | 206 cairo_t* cr = gdk_cairo_create(gtk_widget_get_window(sender)); |
| 242 gdk_cairo_rectangle(cr, &event->area); | 207 gdk_cairo_rectangle(cr, &event->area); |
| 243 cairo_clip(cr); | 208 cairo_clip(cr); |
| 244 | 209 |
| 245 cairo_pattern_t* pattern = cairo_pattern_create_linear(0, 0, 0, height); | 210 cairo_pattern_t* pattern = cairo_pattern_create_linear(0, 0, 0, height); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 270 | 235 |
| 271 if (container()) { | 236 if (container()) { |
| 272 static_cast<InfoBarContainerGtk*>(container())-> | 237 static_cast<InfoBarContainerGtk*>(container())-> |
| 273 PaintInfobarBitsOn(sender, event, this); | 238 PaintInfobarBitsOn(sender, event, this); |
| 274 } | 239 } |
| 275 | 240 |
| 276 return FALSE; | 241 return FALSE; |
| 277 } | 242 } |
| 278 | 243 |
| 279 void InfoBarGtk::PlatformSpecificShow(bool animate) { | 244 void InfoBarGtk::PlatformSpecificShow(bool animate) { |
| 245 if (!theme_service_) |
| 246 InitWidgets(); |
| 247 DCHECK(bg_box_); |
| 248 |
| 249 DCHECK(widget()); |
| 280 gtk_widget_show_all(widget_.get()); | 250 gtk_widget_show_all(widget_.get()); |
| 281 gtk_widget_set_size_request(widget_.get(), -1, bar_height()); | 251 gtk_widget_set_size_request(widget_.get(), -1, bar_height()); |
| 282 | 252 |
| 283 GdkWindow* gdk_window = gtk_widget_get_window(bg_box_); | 253 GdkWindow* gdk_window = gtk_widget_get_window(bg_box_); |
| 284 if (gdk_window) | 254 if (gdk_window) |
| 285 gdk_window_lower(gdk_window); | 255 gdk_window_lower(gdk_window); |
| 286 } | 256 } |
| 287 | 257 |
| 288 void InfoBarGtk::PlatformSpecificOnCloseSoon() { | 258 void InfoBarGtk::PlatformSpecificOnCloseSoon() { |
| 289 // We must close all menus and prevent any signals from being emitted while | 259 // We must close all menus and prevent any signals from being emitted while |
| 290 // we are animating the info bar closed. | 260 // we are animating the info bar closed. |
| 291 menu_.reset(); | 261 menu_.reset(); |
| 292 signals_.reset(); | 262 signals_.reset(); |
| 293 } | 263 } |
| 294 | 264 |
| 295 void InfoBarGtk::PlatformSpecificOnHeightsRecalculated() { | 265 void InfoBarGtk::PlatformSpecificOnHeightsRecalculated() { |
| 266 DCHECK(bg_box_); |
| 267 DCHECK(widget()); |
| 296 gtk_widget_set_size_request(bg_box_, -1, bar_target_height()); | 268 gtk_widget_set_size_request(bg_box_, -1, bar_target_height()); |
| 297 gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(widget_.get()), | 269 gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(widget_.get()), |
| 298 bg_box_, 0, | 270 bg_box_, 0, |
| 299 bar_height() - bar_target_height()); | 271 bar_height() - bar_target_height()); |
| 300 | 272 |
| 301 gtk_widget_set_size_request(widget_.get(), -1, bar_height()); | 273 gtk_widget_set_size_request(widget_.get(), -1, bar_height()); |
| 302 gtk_widget_queue_draw(widget_.get()); | 274 gtk_widget_queue_draw(widget_.get()); |
| 303 } | 275 } |
| 304 | 276 |
| 305 void InfoBarGtk::Observe(int type, | 277 void InfoBarGtk::Observe(int type, |
| 306 const content::NotificationSource& source, | 278 const content::NotificationSource& source, |
| 307 const content::NotificationDetails& details) { | 279 const content::NotificationDetails& details) { |
| 280 DCHECK(widget()); |
| 308 UpdateBorderColor(); | 281 UpdateBorderColor(); |
| 309 } | 282 } |
| 310 | 283 |
| 284 void InfoBarGtk::InitWidgets() { |
| 285 theme_service_ = GtkThemeService::GetFrom(Profile::FromBrowserContext( |
| 286 owner()->GetWebContents()->GetBrowserContext())); |
| 287 |
| 288 // Create |hbox_| and pad the sides. |
| 289 hbox_ = gtk_hbox_new(FALSE, kElementPadding); |
| 290 |
| 291 // Make the whole infor bar horizontally shrinkable. |
| 292 gtk_widget_set_size_request(hbox_, 0, -1); |
| 293 |
| 294 GtkWidget* padding = gtk_alignment_new(0, 0, 1, 1); |
| 295 gtk_alignment_set_padding(GTK_ALIGNMENT(padding), |
| 296 0, 0, kLeftPadding, kRightPadding); |
| 297 |
| 298 bg_box_ = gtk_event_box_new(); |
| 299 gtk_widget_set_app_paintable(bg_box_, TRUE); |
| 300 g_signal_connect(bg_box_, "expose-event", |
| 301 G_CALLBACK(OnBackgroundExposeThunk), this); |
| 302 gtk_container_add(GTK_CONTAINER(padding), hbox_); |
| 303 gtk_container_add(GTK_CONTAINER(bg_box_), padding); |
| 304 |
| 305 // Add the icon on the left, if any. |
| 306 gfx::Image* icon = delegate()->GetIcon(); |
| 307 if (icon) { |
| 308 GtkWidget* image = gtk_image_new_from_pixbuf(icon->ToGdkPixbuf()); |
| 309 |
| 310 gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.5); |
| 311 |
| 312 gtk_box_pack_start(GTK_BOX(hbox_), image, FALSE, FALSE, 0); |
| 313 } |
| 314 |
| 315 close_button_.reset(CustomDrawButton::CloseButtonBar(theme_service_)); |
| 316 gtk_util::CenterWidgetInHBox(hbox_, close_button_->widget(), true, 0); |
| 317 signals_->Connect(close_button_->widget(), "clicked", |
| 318 G_CALLBACK(OnCloseButtonThunk), this); |
| 319 |
| 320 widget_.Own(gtk_expanded_container_new()); |
| 321 gtk_container_add(GTK_CONTAINER(widget_.get()), bg_box_); |
| 322 gtk_widget_set_size_request(widget_.get(), -1, 0); |
| 323 |
| 324 g_signal_connect(widget_.get(), "child-size-request", |
| 325 G_CALLBACK(OnChildSizeRequestThunk), |
| 326 this); |
| 327 |
| 328 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, |
| 329 content::Source<ThemeService>(theme_service_)); |
| 330 UpdateBorderColor(); |
| 331 } |
| 332 |
| 311 void InfoBarGtk::OnChildSizeRequest(GtkWidget* expanded, | 333 void InfoBarGtk::OnChildSizeRequest(GtkWidget* expanded, |
| 312 GtkWidget* child, | 334 GtkWidget* child, |
| 313 GtkRequisition* requisition) { | 335 GtkRequisition* requisition) { |
| 314 requisition->height = -1; | 336 requisition->height = -1; |
| 315 } | 337 } |
| OLD | NEW |