OLD | NEW |
| (Empty) |
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 | |
OLD | NEW |