Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / validation_message_bubble_gtk.cc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/validation_message_bubble.h"
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/ui/gtk/bubble/bubble_gtk.h"
10 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
11 #include "chrome/browser/ui/gtk/gtk_util.h"
12 #include "content/public/browser/render_view_host.h"
13 #include "content/public/browser/render_widget_host_view.h"
14 #include "content/public/browser/web_contents.h"
15 #include "grit/theme_resources.h"
16 #include "ui/base/resource/resource_bundle.h"
17 #include "ui/gfx/gtk_util.h"
18 #include "ui/gfx/image/image_skia.h"
19 #include "ui/gfx/rect.h"
20
21 namespace {
22
23 const int kPadding = 4;
24 const int kIconTextMargin = 8;
25 const int kTextMargin = 4;
26 const int kTextMaxWidth = 256;
27
28 // A GTK implementation of ValidationMessageBubble.
29 class ValidationMessageBubbleGtk : public chrome::ValidationMessageBubble,
30                                    public BubbleDelegateGtk {
31  public:
32   ValidationMessageBubbleGtk(content::RenderWidgetHost* widget_host,
33                              const gfx::Rect& anchor_in_screen,
34                              const base::string16& main_text,
35                              const base::string16& sub_text);
36   virtual ~ValidationMessageBubbleGtk();
37   virtual void SetPositionRelativeToAnchor(
38       content::RenderWidgetHost* widget_host,
39       const gfx::Rect& anchor_in_root_view) OVERRIDE;
40
41   // BubbleDelegateGtk override:
42   virtual void BubbleClosing(BubbleGtk*, bool) OVERRIDE;
43
44  private:
45   static GtkWidget* ConstructContent(const base::string16& main_text,
46                                      const base::string16& sub_text);
47
48   BubbleGtk* bubble_;
49 };
50
51 ValidationMessageBubbleGtk::ValidationMessageBubbleGtk(
52     content::RenderWidgetHost* widget_host,
53     const gfx::Rect& anchor_in_root_view,
54     const base::string16& main_text,
55     const base::string16& sub_text)
56     : bubble_(NULL) {
57   if (!widget_host->IsRenderView())
58     return;
59   Profile* profile = Profile::FromBrowserContext(
60       content::WebContents::FromRenderViewHost(
61           content::RenderViewHost::From(widget_host))->GetBrowserContext());
62   bubble_ = BubbleGtk::Show(widget_host->GetView()->GetNativeView(),
63                             &anchor_in_root_view,
64                             ConstructContent(main_text, sub_text),
65                             BubbleGtk::ANCHOR_TOP_LEFT,
66                             BubbleGtk::POPUP_WINDOW,
67                             GtkThemeService::GetFrom(profile),
68                             this);
69 }
70
71 ValidationMessageBubbleGtk::~ValidationMessageBubbleGtk() {
72   if (bubble_)
73     bubble_->Close();
74 }
75
76 void ValidationMessageBubbleGtk::SetPositionRelativeToAnchor(
77     content::RenderWidgetHost* widget_host,
78     const gfx::Rect& anchor_in_root_view) {
79   if (bubble_)
80     bubble_->SetPositionRelativeToAnchor(&anchor_in_root_view);
81 }
82
83 void ValidationMessageBubbleGtk::BubbleClosing(BubbleGtk*, bool) {
84   bubble_ = NULL;
85 }
86
87 // static
88 GtkWidget* ValidationMessageBubbleGtk::ConstructContent(
89       const base::string16& main_text, const base::string16& sub_text) {
90   GtkWidget* icon = gtk_image_new();
91   gtk_misc_set_alignment(GTK_MISC(icon), 0.5, 0);
92   gtk_misc_set_padding(GTK_MISC(icon), kPadding, kPadding);
93   ResourceBundle& bundle = ResourceBundle::GetSharedInstance();
94   GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(
95       *bundle.GetImageSkiaNamed(IDR_INPUT_ALERT)->bitmap());
96   gtk_image_set_from_pixbuf(GTK_IMAGE(icon), pixbuf);
97   g_object_unref(pixbuf);
98   GtkWidget* icon_text_box = gtk_hbox_new(FALSE, kIconTextMargin);
99   gtk_container_add(GTK_CONTAINER(icon_text_box), icon);
100
101   GtkWidget* text_box = gtk_vbox_new(FALSE, kTextMargin);
102   GtkWidget* label = gtk_label_new(base::UTF16ToUTF8(main_text).c_str());
103   const gfx::Font& main_font = bundle.GetFont(ResourceBundle::MediumFont);
104   gtk_util::ForceFontSizePixels(label, main_font.GetHeight());
105   gtk_box_pack_start(
106       GTK_BOX(text_box), gtk_util::LeftAlignMisc(label), TRUE, TRUE, 0);
107
108   if (!sub_text.empty()) {
109     GtkWidget* sub_label = gtk_label_new(base::UTF16ToUTF8(sub_text).c_str());
110     const gfx::Font& sub_font = bundle.GetFont(ResourceBundle::BaseFont);
111     gtk_util::ForceFontSizePixels(sub_label, sub_font.GetHeight());
112     int max_characters = kTextMaxWidth / sub_font.GetExpectedTextWidth(1);
113     if (sub_text.length() > static_cast<size_t>(max_characters))
114       gtk_util::SetLabelWidth(sub_label, kTextMaxWidth);
115     gtk_box_pack_start(
116         GTK_BOX(text_box), gtk_util::LeftAlignMisc(sub_label), TRUE, TRUE, 0);
117   }
118   gtk_container_add(GTK_CONTAINER(icon_text_box), text_box);
119
120   GtkWidget* content = gtk_alignment_new(0, 0, 0, 0);
121   gtk_alignment_set_padding(
122       GTK_ALIGNMENT(content), kPadding, kPadding, kPadding, kPadding);
123   gtk_container_add(GTK_CONTAINER(content), icon_text_box);
124   return content;
125 }
126
127 }  // namespace
128
129 namespace chrome {
130
131 scoped_ptr<ValidationMessageBubble> ValidationMessageBubble::CreateAndShow(
132     content::RenderWidgetHost* widget_host,
133     const gfx::Rect& anchor_in_root_view,
134     const base::string16& main_text,
135     const base::string16& sub_text) {
136   return scoped_ptr<ValidationMessageBubble>(new ValidationMessageBubbleGtk(
137       widget_host, anchor_in_root_view, main_text, sub_text)).Pass();
138 }
139
140 }  // namespace chrome