| Index: chrome/browser/gtk/infobar_gtk.cc
|
| ===================================================================
|
| --- chrome/browser/gtk/infobar_gtk.cc (revision 23543)
|
| +++ chrome/browser/gtk/infobar_gtk.cc (working copy)
|
| @@ -10,7 +10,10 @@
|
| #include "base/string_util.h"
|
| #include "chrome/browser/gtk/custom_button.h"
|
| #include "chrome/browser/gtk/gtk_chrome_link_button.h"
|
| +#include "chrome/browser/gtk/gtk_skinny_button.h"
|
| #include "chrome/browser/gtk/infobar_container_gtk.h"
|
| +#include "chrome/browser/tab_contents/customize_geoloc_infobar_delegate.h"
|
| +#include "chrome/browser/tab_contents/geoloc_infobar_delegate.h"
|
| #include "chrome/browser/tab_contents/infobar_delegate.h"
|
| #include "chrome/common/gtk_util.h"
|
|
|
| @@ -35,7 +38,8 @@
|
| const int kRightPadding = 5;
|
|
|
| static gboolean OnBackgroundExpose(GtkWidget* widget, GdkEventExpose* event,
|
| - gpointer unused) {
|
| + InfoBarStyle *style) {
|
| + CHECK(style);
|
| const int height = widget->allocation.height;
|
|
|
| cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
|
| @@ -46,11 +50,13 @@
|
| cairo_pattern_t* pattern = cairo_pattern_create_linear(0, 0, 0, height);
|
| cairo_pattern_add_color_stop_rgb(
|
| pattern, 0.0,
|
| - kBackgroundColorTop[0], kBackgroundColorTop[1], kBackgroundColorTop[2]);
|
| + style->gradient_top_[0], style->gradient_top_[1],
|
| + style->gradient_top_[2]);
|
| cairo_pattern_add_color_stop_rgb(
|
| pattern, 1.0,
|
| - kBackgroundColorBottom[0], kBackgroundColorBottom[1],
|
| - kBackgroundColorBottom[2]);
|
| + style->gradient_bottom_[0], style->gradient_bottom_[1],
|
| + style->gradient_bottom_[2]);
|
| +
|
| cairo_set_source(cr, pattern);
|
| cairo_paint(cr);
|
| cairo_pattern_destroy(pattern);
|
| @@ -61,10 +67,39 @@
|
| }
|
|
|
| } // namespace
|
| +InfoBarStyle::InfoBarStyle(const double top[3],
|
| + const double bottom[3],
|
| + int height,
|
| + GdkColor text_color,
|
| + bool even)
|
| + : height_(height),
|
| + text_color_(text_color),
|
| + even_(even) {
|
| + memcpy(gradient_top_, top, sizeof(gradient_top_));
|
| + memcpy(gradient_bottom_, bottom, sizeof(gradient_bottom_));
|
| +}
|
| +InfoBarStyle::InfoBarStyle() : height_(0), even_(true) {
|
| + memset(gradient_top_, 0, sizeof(gradient_top_));
|
| + memset(gradient_bottom_, 0, sizeof(gradient_bottom_));
|
| +}
|
|
|
| InfoBar::InfoBar(InfoBarDelegate* delegate)
|
| : container_(NULL),
|
| delegate_(delegate) {
|
| + GtkWidget* outer_hbox = gtk_hbox_new(FALSE, kElementPadding);
|
| +
|
| + if (!delegate->GetStyle()) {
|
| + InfoBarStyle def(kBackgroundColorTop,
|
| + kBackgroundColorBottom,
|
| + kInfoBarHeight,
|
| + gfx::kGdkBlack,
|
| + true);
|
| + style_ = def;
|
| + } else {
|
| + style_ = *(delegate->GetStyle());
|
| + }
|
| +
|
| + vbox_ = gtk_vbox_new(style_.even_, 0);
|
| // Create |hbox_| and pad the sides.
|
| hbox_ = gtk_hbox_new(FALSE, kElementPadding);
|
| GtkWidget* padding = gtk_alignment_new(0, 0, 1, 1);
|
| @@ -74,11 +109,11 @@
|
| GtkWidget* bg_box = gtk_event_box_new();
|
| gtk_widget_set_app_paintable(bg_box, TRUE);
|
| g_signal_connect(bg_box, "expose-event",
|
| - G_CALLBACK(OnBackgroundExpose), NULL);
|
| - gtk_container_add(GTK_CONTAINER(padding), hbox_);
|
| + G_CALLBACK(OnBackgroundExpose), &style_);
|
| + gtk_container_add(GTK_CONTAINER(padding), outer_hbox);
|
| gtk_container_add(GTK_CONTAINER(bg_box), padding);
|
| // The -1 on the kInfoBarHeight is to account for the border.
|
| - gtk_widget_set_size_request(bg_box, -1, kInfoBarHeight - 1);
|
| + gtk_widget_set_size_request(bg_box, -1, style_.height_ - 1);
|
|
|
| border_bin_.Own(gtk_util::CreateGtkBorderBin(bg_box, &kBorderColor,
|
| 0, 1, 0, 0));
|
| @@ -89,9 +124,12 @@
|
| GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(icon);
|
| GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
|
| g_object_unref(pixbuf);
|
| - gtk_box_pack_start(GTK_BOX(hbox_), image, FALSE, FALSE, 0);
|
| + gtk_box_pack_start(GTK_BOX(outer_hbox), image, FALSE, FALSE, 0);
|
| }
|
|
|
| + gtk_box_pack_start(GTK_BOX(outer_hbox), vbox_, true, true, 0);
|
| + gtk_box_pack_start(GTK_BOX(vbox_), hbox_, false, false, style_.even_ ? 0 : kElementPadding);
|
| +
|
| // TODO(erg): GTK theme the info bar.
|
| close_button_.reset(CustomDrawButton::CloseButton(NULL));
|
| gtk_util::CenterWidgetInHBox(hbox_, close_button_->widget(), true, 0);
|
| @@ -162,12 +200,16 @@
|
| AlertInfoBar(AlertInfoBarDelegate* delegate)
|
| : InfoBar(delegate) {
|
| std::wstring text = delegate->GetMessageText();
|
| - GtkWidget* label = gtk_label_new(WideToUTF8(text).c_str());
|
| - gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &gfx::kGdkBlack);
|
| - gtk_box_pack_start(GTK_BOX(hbox_), label, FALSE, FALSE, 0);
|
| + label_ = gtk_label_new(WideToUTF8(text).c_str());
|
| + gtk_widget_modify_fg(label_, GTK_STATE_NORMAL, &(style_.text_color_));
|
| + //gtk_box_pack_start(GTK_BOX(hbox_), label_, FALSE, FALSE, 0);
|
| + gtk_util::CenterWidgetInHBox(hbox_, label_, false, 0);
|
|
|
| gtk_widget_show_all(border_bin_.get());
|
| }
|
| + protected:
|
| + // The label for the alert.
|
| + GtkWidget* label_;
|
| };
|
|
|
| // LinkInfoBar -----------------------------------------------------------------
|
| @@ -195,7 +237,7 @@
|
| if (link_offset == std::wstring::npos) {
|
| gtk_box_pack_end(GTK_BOX(hbox_), link_button, FALSE, FALSE, 0);
|
| GtkWidget* label = gtk_label_new(WideToUTF8(display_text).c_str());
|
| - gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &gfx::kGdkBlack);
|
| + gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &(style_.text_color_));
|
| gtk_box_pack_start(GTK_BOX(hbox_), label, FALSE, FALSE, 0);
|
| } else {
|
| GtkWidget* initial_label = gtk_label_new(
|
| @@ -203,8 +245,12 @@
|
| GtkWidget* trailing_label = gtk_label_new(
|
| WideToUTF8(display_text.substr(link_offset)).c_str());
|
|
|
| - gtk_widget_modify_fg(initial_label, GTK_STATE_NORMAL, &gfx::kGdkBlack);
|
| - gtk_widget_modify_fg(trailing_label, GTK_STATE_NORMAL, &gfx::kGdkBlack);
|
| + gtk_widget_modify_fg(initial_label,
|
| + GTK_STATE_NORMAL,
|
| + &(style_.text_color_));
|
| + gtk_widget_modify_fg(trailing_label,
|
| + GTK_STATE_NORMAL,
|
| + &(style_.text_color_));
|
|
|
| // We don't want any spacing between the elements, so we pack them into
|
| // this hbox that doesn't use kElementPadding.
|
| @@ -259,6 +305,7 @@
|
| G_CALLBACK(type == ConfirmInfoBarDelegate::BUTTON_OK ?
|
| OnOkButton : OnCancelButton),
|
| this);
|
| + gtk_container_set_border_width(GTK_CONTAINER(button), 0);
|
| }
|
| }
|
|
|
| @@ -273,6 +320,223 @@
|
| }
|
| };
|
|
|
| +// GeolocInfoBar ---------------------------------------------------------------
|
| +
|
| +class GeolocInfoBar : public AlertInfoBar {
|
| + public:
|
| + GeolocInfoBar(GeolocInfoBarDelegate* delegate)
|
| + : AlertInfoBar(delegate) {
|
| + button_box_ = gtk_hbox_new(FALSE, kElementPadding);
|
| + AddConfirmButton(ConfirmInfoBarDelegate::BUTTON_OK);
|
| + AddConfirmButton(ConfirmInfoBarDelegate::BUTTON_CANCEL);
|
| + gtk_box_pack_start(GTK_BOX(vbox_), button_box_, FALSE, FALSE, 0);
|
| +
|
| + std::wstring text = delegate->GetMessageText();
|
| + gtk_label_set_markup(GTK_LABEL(label_), WideToUTF8(text).c_str());
|
| +
|
| + GtkWidget* linkbox = CreateLinkButtons(delegate);
|
| + GtkWidget* checkbox = CreateRememberCheckbox(delegate);
|
| +
|
| + gtk_box_pack_start(GTK_BOX(button_box_), checkbox, FALSE, FALSE, 0);
|
| + gtk_box_pack_end(GTK_BOX(button_box_), linkbox, FALSE, FALSE, 0);
|
| +
|
| + gtk_widget_show_all(border_bin_.get());
|
| + }
|
| +
|
| + private:
|
| + GtkWidget* CreateLinkButtons(GeolocInfoBarDelegate* delegate) {
|
| + std::wstring customize_text = delegate->GetCustomizeText();
|
| + std::wstring learn_more_text = delegate->GetLearnMoreText();
|
| +
|
| + GtkWidget* linkbox = gtk_hbox_new(FALSE, kElementPadding);
|
| + GtkWidget* customize_link = gtk_chrome_link_button_new_with_markup(
|
| + WideToUTF8(customize_text).c_str());
|
| + GtkWidget* learn_more_link = gtk_chrome_link_button_new_with_markup(
|
| + WideToUTF8(learn_more_text).c_str());
|
| +
|
| + g_signal_connect(customize_link, "clicked",
|
| + G_CALLBACK(OnCustomizeClick), this);
|
| + g_signal_connect(learn_more_link, "clicked",
|
| + G_CALLBACK(OnLearnMoreClick), this);
|
| +
|
| + gtk_box_pack_end(GTK_BOX(linkbox), customize_link, FALSE, FALSE, 0);
|
| + gtk_box_pack_end(GTK_BOX(linkbox), learn_more_link, FALSE, FALSE, 0);
|
| + return linkbox;
|
| + }
|
| +
|
| + GtkWidget* CreateRememberCheckbox(GeolocInfoBarDelegate* delegate) {
|
| + GtkWidget* checkbox = gtk_hbox_new(FALSE, kElementPadding);
|
| + GtkWidget* check_button = gtk_check_button_new();
|
| + GtkWidget* remember = gtk_label_new("Remember for this site");
|
| + gtk_box_pack_start(GTK_BOX(checkbox), check_button, FALSE, FALSE, 0);
|
| + gtk_box_pack_start(GTK_BOX(checkbox), remember, FALSE, FALSE, 0);
|
| + gtk_widget_modify_fg(remember, GTK_STATE_NORMAL, &(style_.text_color_));
|
| + return checkbox;
|
| + }
|
| +
|
| + // Adds a button to the info bar by type. It will do nothing if the delegate
|
| + // doesn't specify a button of the given type.
|
| + void AddConfirmButton(ConfirmInfoBarDelegate::InfoBarButton type) {
|
| + GeolocInfoBarDelegate *delegate = delegate_->AsGeolocInfoBarDelegate();
|
| + if (delegate->GetButtons() & type) {
|
| + GtkWidget* button = gtk_skinny_button_new_with_label(WideToUTF8(
|
| + delegate->GetButtonLabel(type)).c_str());
|
| + gtk_util::CenterWidgetInHBox(button_box_, button, false, 0);
|
| + g_signal_connect(button, "clicked",
|
| + G_CALLBACK(type == ConfirmInfoBarDelegate::BUTTON_OK ?
|
| + OnOkButton : OnCancelButton),
|
| + this);
|
| + }
|
| + }
|
| +
|
| + static void OnCancelButton(GtkWidget* button, GeolocInfoBar* info_bar) {
|
| + if (info_bar->delegate_->AsGeolocInfoBarDelegate()->Cancel())
|
| + info_bar->RemoveInfoBar();
|
| + }
|
| +
|
| + static void OnOkButton(GtkWidget* button, GeolocInfoBar* info_bar) {
|
| + if (info_bar->delegate_->AsGeolocInfoBarDelegate()->Accept())
|
| + info_bar->RemoveInfoBar();
|
| + }
|
| +
|
| +
|
| +
|
| + private:
|
| + static WindowOpenDisposition GetDisposition(GtkWidget* button) {
|
| + const GdkEventButton* button_click_event =
|
| + reinterpret_cast<GdkEventButton*>(gtk_get_current_event());
|
| + WindowOpenDisposition disposition = CURRENT_TAB;
|
| + if (button_click_event) {
|
| + disposition = event_utils::DispositionFromEventFlags(
|
| + button_click_event->state);
|
| + }
|
| + return disposition;
|
| + }
|
| + static void OnCustomizeClick(GtkWidget* button, GeolocInfoBar* info_bar) {
|
| + WindowOpenDisposition disposition = GetDisposition(button);
|
| + if (info_bar->delegate_->AsGeolocInfoBarDelegate()->
|
| + CustomizeClicked(disposition)) {
|
| + info_bar->RemoveInfoBar();
|
| + }
|
| + }
|
| + static void OnLearnMoreClick(GtkWidget* button, GeolocInfoBar* info_bar) {
|
| + WindowOpenDisposition disposition = GetDisposition(button);
|
| + if (info_bar->delegate_->AsGeolocInfoBarDelegate()->
|
| + LearnMoreClicked(disposition)) {
|
| + info_bar->RemoveInfoBar();
|
| + }
|
| + }
|
| +
|
| + // The hbox that holds the buttons.
|
| + GtkWidget* button_box_;
|
| +};
|
| +
|
| +class CustomizeGeolocInfoBar : public AlertInfoBar {
|
| + public:
|
| + CustomizeGeolocInfoBar(CustomizeGeolocInfoBarDelegate* delegate)
|
| + : AlertInfoBar(delegate) {
|
| + std::wstring text = delegate->GetMessageText();
|
| + gtk_label_set_markup(GTK_LABEL(label_), WideToUTF8(text).c_str());
|
| +
|
| +
|
| + GtkWidget *hbox = gtk_hbox_new(FALSE, kElementPadding);
|
| + text = delegate->GetAuxiliaryText();
|
| + GtkWidget *label = gtk_label_new(WideToUTF8(text).c_str());
|
| + gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &(style_.text_color_));
|
| + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
|
| + gtk_box_pack_start(GTK_BOX(vbox_), hbox, false, false, 0);
|
| +
|
| + button_box_ = gtk_hbox_new(FALSE, kElementPadding);
|
| + AddCustomizeButton(CustomizeGeolocInfoBarDelegate::BUTTON_BEST);
|
| + AddCustomizeButton(CustomizeGeolocInfoBarDelegate::BUTTON_CITY);
|
| + AddCustomizeButton(CustomizeGeolocInfoBarDelegate::BUTTON_NONE);
|
| +
|
| + gtk_box_pack_start(GTK_BOX(vbox_), button_box_, FALSE, FALSE, kElementPadding*2);
|
| +
|
| + GtkWidget* checkbox = CreateRememberCheckbox(delegate);
|
| + gtk_box_pack_start(GTK_BOX(hbox), checkbox, FALSE, FALSE, 0);
|
| +
|
| + gtk_widget_show_all(border_bin_.get());
|
| + }
|
| +
|
| + private:
|
| + // Adds a button to the info bar by type. It will do nothing if the delegate
|
| + // doesn't specify a button of the given type.
|
| + void AddCustomizeButton(CustomizeGeolocInfoBarDelegate::GeolocButton type) {
|
| + GtkWidget* box = gtk_vbox_new(FALSE, kElementPadding);
|
| +
|
| + CustomizeGeolocInfoBarDelegate *delegate =
|
| + delegate_->AsCustomizeGeolocInfoBarDelegate();
|
| + GtkWidget* button = gtk_button_new();
|
| + GtkWidget* label = gtk_label_new(WideToUTF8(
|
| + delegate->GetGeolocButtonLabel(type)).c_str());
|
| + gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &(style_.text_color_));
|
| +
|
| + SkBitmap* icon = delegate->GetGeolocButtonImage(type);
|
| + if (icon) {
|
| + GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(icon);
|
| + gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_pixbuf(pixbuf));
|
| + g_object_unref(pixbuf);
|
| + }
|
| + gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
|
| + gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
|
| +
|
| + gtk_box_pack_start(GTK_BOX(button_box_), box, true, FALSE, 0);
|
| + ConnectButton(button, type);
|
| + gtk_container_set_border_width(GTK_CONTAINER(button), 0);
|
| + }
|
| +
|
| + GtkWidget* CreateRememberCheckbox(CustomizeGeolocInfoBarDelegate* delegate) {
|
| + GtkWidget* checkbox = gtk_hbox_new(FALSE, kElementPadding);
|
| + GtkWidget* check_button = gtk_check_button_new();
|
| + GtkWidget* remember = gtk_label_new("Remember for this site");
|
| + gtk_box_pack_start(GTK_BOX(checkbox), check_button, FALSE, FALSE, 0);
|
| + gtk_box_pack_start(GTK_BOX(checkbox), remember, FALSE, FALSE, 0);
|
| + gtk_widget_modify_fg(remember, GTK_STATE_NORMAL, &(style_.text_color_));
|
| + return checkbox;
|
| + }
|
| +
|
| + void ConnectButton(GtkWidget *button,
|
| + CustomizeGeolocInfoBarDelegate::GeolocButton type) {
|
| + switch(type) {
|
| + case CustomizeGeolocInfoBarDelegate::BUTTON_BEST:
|
| + g_signal_connect(button, "clicked", G_CALLBACK(OnBestClick), this);
|
| + break;
|
| + case CustomizeGeolocInfoBarDelegate::BUTTON_CITY:
|
| + g_signal_connect(button, "clicked", G_CALLBACK(OnCityClick), this);
|
| + break;
|
| + case CustomizeGeolocInfoBarDelegate::BUTTON_NONE:
|
| + g_signal_connect(button, "clicked", G_CALLBACK(OnNoneClick), this);
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| + }
|
| +
|
| + static void OnBestClick(GtkWidget* button, CustomizeGeolocInfoBar* info_bar) {
|
| + if (info_bar->delegate_->AsCustomizeGeolocInfoBarDelegate()
|
| + ->OnGeolocButtonClick(CustomizeGeolocInfoBarDelegate::BUTTON_BEST))
|
| + info_bar->RemoveInfoBar();
|
| + }
|
| +
|
| + static void OnCityClick(GtkWidget* button, CustomizeGeolocInfoBar* info_bar) {
|
| + if (info_bar->delegate_->AsCustomizeGeolocInfoBarDelegate()
|
| + ->OnGeolocButtonClick(CustomizeGeolocInfoBarDelegate::BUTTON_CITY))
|
| + info_bar->RemoveInfoBar();
|
| + }
|
| +
|
| + static void OnNoneClick(GtkWidget* button, CustomizeGeolocInfoBar* info_bar) {
|
| + if (info_bar->delegate_->AsCustomizeGeolocInfoBarDelegate()
|
| + ->OnGeolocButtonClick(CustomizeGeolocInfoBarDelegate::BUTTON_NONE))
|
| + info_bar->RemoveInfoBar();
|
| + }
|
| +
|
| + // The hbox that holds the buttons.
|
| + GtkWidget* button_box_;
|
| +
|
| +};
|
| +
|
| // AlertInfoBarDelegate, InfoBarDelegate overrides: ----------------------------
|
|
|
| InfoBar* AlertInfoBarDelegate::CreateInfoBar() {
|
| @@ -290,3 +554,15 @@
|
| InfoBar* ConfirmInfoBarDelegate::CreateInfoBar() {
|
| return new ConfirmInfoBar(this);
|
| }
|
| +
|
| +// GeolocInfoBarDelegate, InfoBarDelegate overrides: --------------------_------
|
| +
|
| +InfoBar* GeolocInfoBarDelegate::CreateInfoBar() {
|
| + return new GeolocInfoBar(this);
|
| +}
|
| +
|
| +// CustomizeGeolocInfoBarDelegate, InfoBarDelegate overrides: ------------------
|
| +
|
| +InfoBar* CustomizeGeolocInfoBarDelegate::CreateInfoBar() {
|
| + return new CustomizeGeolocInfoBar(this);
|
| +}
|
|
|