| Index: chrome/browser/gtk/infobar_gtk.cc
|
| ===================================================================
|
| --- chrome/browser/gtk/infobar_gtk.cc (revision 71352)
|
| +++ chrome/browser/gtk/infobar_gtk.cc (working copy)
|
| @@ -1,453 +0,0 @@
|
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/gtk/infobar_gtk.h"
|
| -
|
| -#include <gtk/gtk.h>
|
| -
|
| -#include "base/utf_string_conversions.h"
|
| -#include "chrome/browser/gtk/browser_window_gtk.h"
|
| -#include "chrome/browser/gtk/custom_button.h"
|
| -#include "chrome/browser/gtk/gtk_chrome_link_button.h"
|
| -#include "chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h"
|
| -#include "chrome/browser/gtk/gtk_theme_provider.h"
|
| -#include "chrome/browser/gtk/gtk_util.h"
|
| -#include "chrome/browser/gtk/infobar_container_gtk.h"
|
| -#include "chrome/browser/platform_util.h"
|
| -#include "chrome/common/notification_service.h"
|
| -#include "gfx/gtk_util.h"
|
| -
|
| -extern const int InfoBar::kInfoBarHeight = 37;
|
| -
|
| -namespace {
|
| -
|
| -// Spacing after message (and before buttons).
|
| -const int kEndOfLabelSpacing = 6;
|
| -// Spacing between buttons.
|
| -const int kButtonButtonSpacing = 3;
|
| -
|
| -// Pixels between infobar elements.
|
| -const int kElementPadding = 5;
|
| -
|
| -// Extra padding on either end of info bar.
|
| -const int kLeftPadding = 5;
|
| -const int kRightPadding = 5;
|
| -
|
| -} // namespace
|
| -
|
| -InfoBar::InfoBar(InfoBarDelegate* delegate)
|
| - : container_(NULL),
|
| - delegate_(delegate),
|
| - theme_provider_(NULL),
|
| - arrow_model_(this) {
|
| - // Create |hbox_| and pad the sides.
|
| - hbox_ = gtk_hbox_new(FALSE, kElementPadding);
|
| -
|
| - // Make the whole infor bar horizontally shrinkable.
|
| - gtk_widget_set_size_request(hbox_, 0, -1);
|
| -
|
| - GtkWidget* padding = gtk_alignment_new(0, 0, 1, 1);
|
| - gtk_alignment_set_padding(GTK_ALIGNMENT(padding),
|
| - 0, 0, kLeftPadding, kRightPadding);
|
| -
|
| - bg_box_ = gtk_event_box_new();
|
| - gtk_widget_set_app_paintable(bg_box_, TRUE);
|
| - g_signal_connect(bg_box_, "expose-event",
|
| - G_CALLBACK(OnBackgroundExposeThunk), this);
|
| - gtk_container_add(GTK_CONTAINER(padding), hbox_);
|
| - gtk_container_add(GTK_CONTAINER(bg_box_), padding);
|
| - gtk_widget_set_size_request(bg_box_, -1, kInfoBarHeight);
|
| -
|
| - // Add the icon on the left, if any.
|
| - SkBitmap* icon = delegate->GetIcon();
|
| - if (icon) {
|
| - 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);
|
| - }
|
| -
|
| - close_button_.reset(CustomDrawButton::CloseButton(NULL));
|
| - gtk_util::CenterWidgetInHBox(hbox_, close_button_->widget(), true, 0);
|
| - g_signal_connect(close_button_->widget(), "clicked",
|
| - G_CALLBACK(OnCloseButtonThunk), this);
|
| -
|
| - slide_widget_.reset(new SlideAnimatorGtk(bg_box_,
|
| - SlideAnimatorGtk::DOWN,
|
| - 0, true, true, this));
|
| - // We store a pointer back to |this| so we can refer to it from the infobar
|
| - // container.
|
| - g_object_set_data(G_OBJECT(slide_widget_->widget()), "info-bar", this);
|
| -}
|
| -
|
| -InfoBar::~InfoBar() {
|
| -}
|
| -
|
| -GtkWidget* InfoBar::widget() {
|
| - return slide_widget_->widget();
|
| -}
|
| -
|
| -void InfoBar::AnimateOpen() {
|
| - slide_widget_->Open();
|
| -
|
| - gtk_widget_show_all(bg_box_);
|
| - if (bg_box_->window)
|
| - gdk_window_lower(bg_box_->window);
|
| -}
|
| -
|
| -void InfoBar::Open() {
|
| - slide_widget_->OpenWithoutAnimation();
|
| -
|
| - gtk_widget_show_all(bg_box_);
|
| - if (bg_box_->window)
|
| - gdk_window_lower(bg_box_->window);
|
| -}
|
| -
|
| -void InfoBar::AnimateClose() {
|
| - slide_widget_->Close();
|
| -}
|
| -
|
| -void InfoBar::Close() {
|
| - if (delegate_) {
|
| - delegate_->InfoBarClosed();
|
| - delegate_ = NULL;
|
| - }
|
| - delete this;
|
| -}
|
| -
|
| -bool InfoBar::IsAnimating() {
|
| - return slide_widget_->IsAnimating();
|
| -}
|
| -
|
| -bool InfoBar::IsClosing() {
|
| - return slide_widget_->IsClosing();
|
| -}
|
| -
|
| -void InfoBar::ShowArrowFor(InfoBar* other, bool animate) {
|
| - arrow_model_.ShowArrowFor(other, animate);
|
| -}
|
| -
|
| -void InfoBar::PaintStateChanged() {
|
| - gtk_widget_queue_draw(widget());
|
| -}
|
| -
|
| -void InfoBar::RemoveInfoBar() const {
|
| - container_->RemoveDelegate(delegate_);
|
| -}
|
| -
|
| -void InfoBar::Closed() {
|
| - Close();
|
| -}
|
| -
|
| -void InfoBar::SetThemeProvider(GtkThemeProvider* theme_provider) {
|
| - if (theme_provider_) {
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| -
|
| - theme_provider_ = theme_provider;
|
| - registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
|
| - NotificationService::AllSources());
|
| - UpdateBorderColor();
|
| -}
|
| -
|
| -void InfoBar::Observe(NotificationType type,
|
| - const NotificationSource& source,
|
| - const NotificationDetails& details) {
|
| - UpdateBorderColor();
|
| -}
|
| -
|
| -void InfoBar::AddLabelWithInlineLink(const string16& display_text,
|
| - const string16& link_text,
|
| - size_t link_offset,
|
| - GCallback callback) {
|
| - GtkWidget* link_button = gtk_chrome_link_button_new(
|
| - UTF16ToUTF8(link_text).c_str());
|
| - gtk_chrome_link_button_set_use_gtk_theme(
|
| - GTK_CHROME_LINK_BUTTON(link_button), FALSE);
|
| - gtk_util::ForceFontSizePixels(
|
| - GTK_CHROME_LINK_BUTTON(link_button)->label, 13.4);
|
| - DCHECK(callback);
|
| - g_signal_connect(link_button, "clicked", callback, this);
|
| - gtk_util::SetButtonTriggersNavigation(link_button);
|
| -
|
| - GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
|
| - // We want the link to be horizontally shrinkable, so that the Chrome
|
| - // window can be resized freely even with a very long link.
|
| - gtk_widget_set_size_request(hbox, 0, -1);
|
| - gtk_box_pack_start(GTK_BOX(hbox_), hbox, TRUE, TRUE, 0);
|
| -
|
| - // Need to insert the link inside the display text.
|
| - GtkWidget* initial_label = gtk_label_new(
|
| - UTF16ToUTF8(display_text.substr(0, link_offset)).c_str());
|
| - GtkWidget* trailing_label = gtk_label_new(
|
| - UTF16ToUTF8(display_text.substr(link_offset)).c_str());
|
| -
|
| - gtk_util::ForceFontSizePixels(initial_label, 13.4);
|
| - gtk_util::ForceFontSizePixels(trailing_label, 13.4);
|
| -
|
| - // TODO(joth): Unlike the AddLabelAndLink below, none of the label widgets
|
| - // are set as shrinkable here, meaning the text will run under the close
|
| - // button etc. when the width is restricted, rather than eliding.
|
| - gtk_widget_modify_fg(initial_label, GTK_STATE_NORMAL, >k_util::kGdkBlack);
|
| - gtk_widget_modify_fg(trailing_label, GTK_STATE_NORMAL, >k_util::kGdkBlack);
|
| -
|
| - // We don't want any spacing between the elements, so we pack them into
|
| - // this hbox that doesn't use kElementPadding.
|
| - gtk_box_pack_start(GTK_BOX(hbox), initial_label, FALSE, FALSE, 0);
|
| - gtk_util::CenterWidgetInHBox(hbox, link_button, false, 0);
|
| - gtk_box_pack_start(GTK_BOX(hbox), trailing_label, FALSE, FALSE, 0);
|
| -}
|
| -
|
| -// TODO(joth): This method factors out some common functionality between the
|
| -// various derived infobar classes, however the class hierarchy itself could
|
| -// use refactoring to reduce this duplication. http://crbug.com/38924
|
| -void InfoBar::AddLabelAndLink(const string16& display_text,
|
| - const string16& link_text,
|
| - GCallback callback) {
|
| - GtkWidget* link_button = NULL;
|
| - if (!link_text.empty()) {
|
| - // If we have some link text, create the link button.
|
| - link_button = gtk_chrome_link_button_new(UTF16ToUTF8(link_text).c_str());
|
| - gtk_chrome_link_button_set_use_gtk_theme(
|
| - GTK_CHROME_LINK_BUTTON(link_button), FALSE);
|
| - DCHECK(callback);
|
| - g_signal_connect(link_button, "clicked", callback, this);
|
| - gtk_util::SetButtonTriggersNavigation(link_button);
|
| - }
|
| -
|
| - GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
|
| - // We want the link to be horizontally shrinkable, so that the Chrome
|
| - // window can be resized freely even with a very long link.
|
| - gtk_widget_set_size_request(hbox, 0, -1);
|
| - gtk_box_pack_start(GTK_BOX(hbox_), hbox, TRUE, TRUE, 0);
|
| -
|
| - if (link_button)
|
| - gtk_box_pack_end(GTK_BOX(hbox), link_button, FALSE, FALSE, 0);
|
| - GtkWidget* label = gtk_label_new(UTF16ToUTF8(display_text).c_str());
|
| - gtk_util::ForceFontSizePixels(label, 13.4);
|
| - // In order to avoid the link_button and the label overlapping with each
|
| - // other, we make the label shrinkable.
|
| - gtk_widget_set_size_request(label, 0, -1);
|
| - gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
|
| - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
|
| - gtk_widget_modify_fg(label, GTK_STATE_NORMAL, >k_util::kGdkBlack);
|
| - gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
|
| -}
|
| -
|
| -void InfoBar::GetTopColor(InfoBarDelegate::Type type,
|
| - double* r, double* g, double *b) {
|
| - // These constants are copied from corresponding skia constants from
|
| - // browser/ui/views/infobars/infobars.cc, and then changed into 0-1 ranged
|
| - // values for cairo.
|
| - switch (type) {
|
| - case InfoBarDelegate::WARNING_TYPE:
|
| - *r = 255.0 / 255.0;
|
| - *g = 242.0 / 255.0;
|
| - *b = 183.0 / 255.0;
|
| - break;
|
| - case InfoBarDelegate::PAGE_ACTION_TYPE:
|
| - *r = 218.0 / 255.0;
|
| - *g = 231.0 / 255.0;
|
| - *b = 249.0 / 255.0;
|
| - break;
|
| - }
|
| -}
|
| -
|
| -void InfoBar::GetBottomColor(InfoBarDelegate::Type type,
|
| - double* r, double* g, double *b) {
|
| - switch (type) {
|
| - case InfoBarDelegate::WARNING_TYPE:
|
| - *r = 250.0 / 255.0;
|
| - *g = 230.0 / 255.0;
|
| - *b = 145.0 / 255.0;
|
| - break;
|
| - case InfoBarDelegate::PAGE_ACTION_TYPE:
|
| - *r = 179.0 / 255.0;
|
| - *g = 202.0 / 255.0;
|
| - *b = 231.0 / 255.0;
|
| - break;
|
| - }
|
| -}
|
| -
|
| -void InfoBar::UpdateBorderColor() {
|
| - gtk_widget_queue_draw(widget());
|
| -}
|
| -
|
| -void InfoBar::OnCloseButton(GtkWidget* button) {
|
| - if (delegate_)
|
| - delegate_->InfoBarDismissed();
|
| - RemoveInfoBar();
|
| -}
|
| -
|
| -gboolean InfoBar::OnBackgroundExpose(GtkWidget* sender,
|
| - GdkEventExpose* event) {
|
| - const int height = sender->allocation.height;
|
| -
|
| - cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(sender->window));
|
| - gdk_cairo_rectangle(cr, &event->area);
|
| - cairo_clip(cr);
|
| -
|
| - cairo_pattern_t* pattern = cairo_pattern_create_linear(0, 0, 0, height);
|
| -
|
| - double top_r, top_g, top_b;
|
| - GetTopColor(delegate_->GetInfoBarType(), &top_r, &top_g, &top_b);
|
| - cairo_pattern_add_color_stop_rgb(pattern, 0.0, top_r, top_g, top_b);
|
| -
|
| - double bottom_r, bottom_g, bottom_b;
|
| - GetBottomColor(delegate_->GetInfoBarType(), &bottom_r, &bottom_g, &bottom_b);
|
| - cairo_pattern_add_color_stop_rgb(
|
| - pattern, 1.0, bottom_r, bottom_g, bottom_b);
|
| - cairo_set_source(cr, pattern);
|
| - cairo_paint(cr);
|
| - cairo_pattern_destroy(pattern);
|
| -
|
| - // Draw the bottom border.
|
| - GdkColor border_color = theme_provider_->GetBorderColor();
|
| - cairo_set_source_rgb(cr, border_color.red / 65535.0,
|
| - border_color.green / 65535.0,
|
| - border_color.blue / 65535.0);
|
| - cairo_set_line_width(cr, 1.0);
|
| - int y = sender->allocation.height;
|
| - cairo_move_to(cr, 0, y - 0.5);
|
| - cairo_rel_line_to(cr, sender->allocation.width, 0);
|
| - cairo_stroke(cr);
|
| -
|
| - cairo_destroy(cr);
|
| -
|
| - if (!arrow_model_.NeedToDrawInfoBarArrow())
|
| - return FALSE;
|
| -
|
| - GtkWindow* parent = platform_util::GetTopLevel(widget());
|
| - BrowserWindowGtk* browser_window =
|
| - BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent);
|
| - int x = browser_window ?
|
| - browser_window->GetXPositionOfLocationIcon(sender) : 0;
|
| -
|
| - arrow_model_.Paint(sender, event, gfx::Point(x, y), border_color);
|
| -
|
| - return FALSE;
|
| -}
|
| -
|
| -// AlertInfoBar ----------------------------------------------------------------
|
| -
|
| -class AlertInfoBar : public InfoBar {
|
| - public:
|
| - explicit AlertInfoBar(AlertInfoBarDelegate* delegate)
|
| - : InfoBar(delegate) {
|
| - AddLabelAndLink(delegate->GetMessageText(), string16(), NULL);
|
| - }
|
| -};
|
| -
|
| -// LinkInfoBar -----------------------------------------------------------------
|
| -
|
| -class LinkInfoBar : public InfoBar {
|
| - public:
|
| - explicit LinkInfoBar(LinkInfoBarDelegate* delegate)
|
| - : InfoBar(delegate) {
|
| - size_t link_offset;
|
| - string16 display_text = delegate->GetMessageTextWithOffset(&link_offset);
|
| - string16 link_text = delegate->GetLinkText();
|
| - AddLabelWithInlineLink(display_text, link_text, link_offset,
|
| - G_CALLBACK(OnLinkClick));
|
| - }
|
| -
|
| - private:
|
| - static void OnLinkClick(GtkWidget* button, LinkInfoBar* link_info_bar) {
|
| - if (link_info_bar->delegate_->AsLinkInfoBarDelegate()->
|
| - LinkClicked(gtk_util::DispositionForCurrentButtonPressEvent())) {
|
| - link_info_bar->RemoveInfoBar();
|
| - }
|
| - }
|
| -};
|
| -
|
| -// ConfirmInfoBar --------------------------------------------------------------
|
| -
|
| -class ConfirmInfoBar : public InfoBar {
|
| - public:
|
| - explicit ConfirmInfoBar(ConfirmInfoBarDelegate* delegate);
|
| -
|
| - 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 AddButton(ConfirmInfoBarDelegate::InfoBarButton type);
|
| -
|
| - CHROMEGTK_CALLBACK_0(ConfirmInfoBar, void, OnOkButton);
|
| - CHROMEGTK_CALLBACK_0(ConfirmInfoBar, void, OnCancelButton);
|
| - CHROMEGTK_CALLBACK_0(ConfirmInfoBar, void, OnLinkClicked);
|
| -
|
| - GtkWidget* confirm_hbox_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ConfirmInfoBar);
|
| -};
|
| -
|
| -ConfirmInfoBar::ConfirmInfoBar(ConfirmInfoBarDelegate* delegate)
|
| - : InfoBar(delegate) {
|
| - confirm_hbox_ = gtk_chrome_shrinkable_hbox_new(FALSE, FALSE, 0);
|
| - gtk_box_pack_start(GTK_BOX(hbox_), confirm_hbox_, TRUE, TRUE, 0);
|
| - gtk_widget_set_size_request(confirm_hbox_, 0, -1);
|
| -
|
| - std::string label_text = UTF16ToUTF8(delegate->GetMessageText());
|
| - GtkWidget* label = gtk_label_new(label_text.c_str());
|
| - gtk_util::ForceFontSizePixels(label, 13.4);
|
| - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
|
| - gtk_util::CenterWidgetInHBox(confirm_hbox_, label, false, kEndOfLabelSpacing);
|
| - gtk_widget_modify_fg(label, GTK_STATE_NORMAL, >k_util::kGdkBlack);
|
| - g_signal_connect(label, "map",
|
| - G_CALLBACK(gtk_util::InitLabelSizeRequestAndEllipsizeMode),
|
| - NULL);
|
| -
|
| - AddButton(ConfirmInfoBarDelegate::BUTTON_CANCEL);
|
| - AddButton(ConfirmInfoBarDelegate::BUTTON_OK);
|
| -
|
| - std::string link_text = UTF16ToUTF8(delegate->GetLinkText());
|
| - GtkWidget* link = gtk_chrome_link_button_new(link_text.c_str());
|
| - gtk_misc_set_alignment(GTK_MISC(GTK_CHROME_LINK_BUTTON(link)->label), 0, 0.5);
|
| - g_signal_connect(link, "clicked", G_CALLBACK(OnLinkClickedThunk), this);
|
| - gtk_util::SetButtonTriggersNavigation(link);
|
| - // Until we switch to vector graphics, force the font size.
|
| - // 13.4px == 10pt @ 96dpi
|
| - gtk_util::ForceFontSizePixels(GTK_CHROME_LINK_BUTTON(link)->label, 13.4);
|
| - gtk_util::CenterWidgetInHBox(hbox_, link, true, kEndOfLabelSpacing);
|
| -}
|
| -
|
| -void ConfirmInfoBar::AddButton(ConfirmInfoBarDelegate::InfoBarButton type) {
|
| - if (delegate_->AsConfirmInfoBarDelegate()->GetButtons() & type) {
|
| - GtkWidget* button = gtk_button_new_with_label(UTF16ToUTF8(
|
| - delegate_->AsConfirmInfoBarDelegate()->GetButtonLabel(type)).c_str());
|
| - gtk_util::CenterWidgetInHBox(confirm_hbox_, button, false,
|
| - kButtonButtonSpacing);
|
| - g_signal_connect(button, "clicked",
|
| - G_CALLBACK(type == ConfirmInfoBarDelegate::BUTTON_OK ?
|
| - OnOkButtonThunk : OnCancelButtonThunk),
|
| - this);
|
| - }
|
| -}
|
| -
|
| -void ConfirmInfoBar::OnCancelButton(GtkWidget* widget) {
|
| - if (delegate_->AsConfirmInfoBarDelegate()->Cancel())
|
| - RemoveInfoBar();
|
| -}
|
| -
|
| -void ConfirmInfoBar::OnOkButton(GtkWidget* widget) {
|
| - if (delegate_->AsConfirmInfoBarDelegate()->Accept())
|
| - RemoveInfoBar();
|
| -}
|
| -
|
| -void ConfirmInfoBar::OnLinkClicked(GtkWidget* widget) {
|
| - if (delegate_->AsConfirmInfoBarDelegate()->LinkClicked(
|
| - gtk_util::DispositionForCurrentButtonPressEvent())) {
|
| - RemoveInfoBar();
|
| - }
|
| -}
|
| -
|
| -InfoBar* AlertInfoBarDelegate::CreateInfoBar() {
|
| - return new AlertInfoBar(this);
|
| -}
|
| -InfoBar* LinkInfoBarDelegate::CreateInfoBar() {
|
| - return new LinkInfoBar(this);
|
| -}
|
| -InfoBar* ConfirmInfoBarDelegate::CreateInfoBar() {
|
| - return new ConfirmInfoBar(this);
|
| -}
|
|
|