| // Copyright (c) 2013 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/ui/validation_message_bubble.h" |
| |
| #include "base/strings/utf_string_conversions.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/gtk/bubble/bubble_gtk.h" |
| #include "chrome/browser/ui/gtk/gtk_theme_service.h" |
| #include "chrome/browser/ui/gtk/gtk_util.h" |
| #include "content/public/browser/render_view_host.h" |
| #include "content/public/browser/render_widget_host_view.h" |
| #include "content/public/browser/web_contents.h" |
| #include "grit/theme_resources.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #include "ui/gfx/gtk_util.h" |
| #include "ui/gfx/image/image_skia.h" |
| #include "ui/gfx/rect.h" |
| |
| namespace { |
| |
| const int kPadding = 4; |
| const int kIconTextMargin = 8; |
| const int kTextMargin = 4; |
| const int kTextMaxWidth = 256; |
| |
| // A GTK implementation of ValidationMessageBubble. |
| class ValidationMessageBubbleGtk : public chrome::ValidationMessageBubble, |
| public BubbleDelegateGtk { |
| public: |
| ValidationMessageBubbleGtk(content::RenderWidgetHost* widget_host, |
| const gfx::Rect& anchor_in_screen, |
| const string16& main_text, |
| const string16& sub_text); |
| virtual ~ValidationMessageBubbleGtk(); |
| virtual void SetPositionRelativeToAnchor( |
| content::RenderWidgetHost* widget_host, |
| const gfx::Rect& anchor_in_root_view) OVERRIDE; |
| |
| // BubbleDelegateGtk override: |
| virtual void BubbleClosing(BubbleGtk*, bool) OVERRIDE; |
| |
| private: |
| static GtkWidget* ConstructContent(const string16& main_text, |
| const string16& sub_text); |
| |
| BubbleGtk* bubble_; |
| }; |
| |
| ValidationMessageBubbleGtk::ValidationMessageBubbleGtk( |
| content::RenderWidgetHost* widget_host, |
| const gfx::Rect& anchor_in_root_view, |
| const string16& main_text, |
| const string16& sub_text) |
| : bubble_(NULL) { |
| if (!widget_host->IsRenderView()) |
| return; |
| Profile* profile = Profile::FromBrowserContext( |
| content::WebContents::FromRenderViewHost( |
| content::RenderViewHost::From(widget_host))->GetBrowserContext()); |
| bubble_ = BubbleGtk::Show(widget_host->GetView()->GetNativeView(), |
| &anchor_in_root_view, |
| ConstructContent(main_text, sub_text), |
| BubbleGtk::ANCHOR_TOP_LEFT, |
| BubbleGtk::POPUP_WINDOW, |
| GtkThemeService::GetFrom(profile), |
| this); |
| } |
| |
| ValidationMessageBubbleGtk::~ValidationMessageBubbleGtk() { |
| if (bubble_) |
| bubble_->Close(); |
| } |
| |
| void ValidationMessageBubbleGtk::SetPositionRelativeToAnchor( |
| content::RenderWidgetHost* widget_host, |
| const gfx::Rect& anchor_in_root_view) { |
| if (bubble_) |
| bubble_->SetPositionRelativeToAnchor(&anchor_in_root_view); |
| } |
| |
| void ValidationMessageBubbleGtk::BubbleClosing(BubbleGtk*, bool) { |
| bubble_ = NULL; |
| } |
| |
| // static |
| GtkWidget* ValidationMessageBubbleGtk::ConstructContent( |
| const string16& main_text, const string16& sub_text) { |
| GtkWidget* icon = gtk_image_new(); |
| gtk_misc_set_alignment(GTK_MISC(icon), 0.5, 0); |
| gtk_misc_set_padding(GTK_MISC(icon), kPadding, kPadding); |
| ResourceBundle& bundle = ResourceBundle::GetSharedInstance(); |
| GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap( |
| *bundle.GetImageSkiaNamed(IDR_INPUT_ALERT)->bitmap()); |
| gtk_image_set_from_pixbuf(GTK_IMAGE(icon), pixbuf); |
| g_object_unref(pixbuf); |
| GtkWidget* icon_text_box = gtk_hbox_new(FALSE, kIconTextMargin); |
| gtk_container_add(GTK_CONTAINER(icon_text_box), icon); |
| |
| GtkWidget* text_box = gtk_vbox_new(FALSE, kTextMargin); |
| GtkWidget* label = gtk_label_new(UTF16ToUTF8(main_text).c_str()); |
| const gfx::Font& main_font = bundle.GetFont(ResourceBundle::MediumFont); |
| gtk_util::ForceFontSizePixels(label, main_font.GetHeight()); |
| gtk_box_pack_start( |
| GTK_BOX(text_box), gtk_util::LeftAlignMisc(label), TRUE, TRUE, 0); |
| |
| if (!sub_text.empty()) { |
| GtkWidget* sub_label = gtk_label_new(UTF16ToUTF8(sub_text).c_str()); |
| const gfx::Font& sub_font = bundle.GetFont(ResourceBundle::BaseFont); |
| gtk_util::ForceFontSizePixels(sub_label, sub_font.GetHeight()); |
| int max_characters = kTextMaxWidth / sub_font.GetAverageCharacterWidth(); |
| if (sub_text.length() > static_cast<size_t>(max_characters)) |
| gtk_util::SetLabelWidth(sub_label, kTextMaxWidth); |
| gtk_box_pack_start( |
| GTK_BOX(text_box), gtk_util::LeftAlignMisc(sub_label), TRUE, TRUE, 0); |
| } |
| gtk_container_add(GTK_CONTAINER(icon_text_box), text_box); |
| |
| GtkWidget* content = gtk_alignment_new(0, 0, 0, 0); |
| gtk_alignment_set_padding( |
| GTK_ALIGNMENT(content), kPadding, kPadding, kPadding, kPadding); |
| gtk_container_add(GTK_CONTAINER(content), icon_text_box); |
| return content; |
| } |
| |
| } // namespace |
| |
| namespace chrome { |
| |
| scoped_ptr<ValidationMessageBubble> ValidationMessageBubble::CreateAndShow( |
| content::RenderWidgetHost* widget_host, |
| const gfx::Rect& anchor_in_root_view, |
| const string16& main_text, |
| const string16& sub_text) { |
| return scoped_ptr<ValidationMessageBubble>(new ValidationMessageBubbleGtk( |
| widget_host, anchor_in_root_view, main_text, sub_text)).Pass(); |
| } |
| |
| } // namespace chrome |