1 // Copyright (c) 2011 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/chromeos/login/message_bubble.h"
6
7 #include "base/logging.h"
8 #include "chrome/browser/chromeos/login/helper.h"
9 #include "grit/generated_resources.h"
10 #include "grit/theme_resources.h"
11 #include "ui/base/resource/resource_bundle.h"
12 #include "views/controls/button/image_button.h"
13 #include "views/controls/image_view.h"
14 #include "views/controls/label.h"
15 #include "views/layout/grid_layout.h"
16 #include "views/widget/widget.h"
17
18 namespace chromeos {
19
20 static const int kBorderSize = 4;
21 static const int kMaxLabelWidth = 250;
22
MessageBubble(views::WidgetGtk::Type type,views::Widget * parent,SkBitmap * image,const std::wstring & text,const std::wstring & help,bool grab_enabled,MessageBubbleDelegate * delegate)23 MessageBubble::MessageBubble(views::WidgetGtk::Type type,
24 views::Widget* parent,
25 SkBitmap* image,
26 const std::wstring& text,
27 const std::wstring& help,
28 bool grab_enabled,
29 MessageBubbleDelegate* delegate)
30 : Bubble(type, false), // don't show while screen is locked
31 parent_(parent),
32 help_link_(NULL),
33 message_delegate_(delegate),
34 grab_enabled_(grab_enabled) {
35 using views::GridLayout;
36
37 views::View* control_view = new views::View();
38 GridLayout* layout = new GridLayout(control_view);
39 control_view->SetLayoutManager(layout);
40 views::ColumnSet* column_set = layout->AddColumnSet(0);
41 column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
42 GridLayout::USE_PREF, 0, 0);
43 column_set->AddPaddingColumn(0, kBorderSize);
44 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
45 GridLayout::USE_PREF, 0, 0);
46 column_set->AddPaddingColumn(0, kBorderSize);
47 column_set->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
48 GridLayout::USE_PREF, 0, 0);
49 if (!help.empty()) {
50 column_set = layout->AddColumnSet(1);
51 column_set->AddPaddingColumn(0, kBorderSize + image->width());
52 column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 1,
53 GridLayout::USE_PREF, 0, 0);
54 }
55
56 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
57
58 layout->StartRow(0, 0);
59 icon_ = new views::ImageView();
60 icon_->SetImage(*image);
61 layout->AddView(icon_);
62
63 text_ = new views::Label(text);
64 text_->SetMultiLine(true);
65 text_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
66 text_->SizeToFit(kMaxLabelWidth);
67 layout->AddView(text_);
68
69 close_button_ = new views::ImageButton(this);
70 close_button_->SetImage(views::CustomButton::BS_NORMAL,
71 rb.GetBitmapNamed(IDR_CLOSE_BAR));
72 close_button_->SetImage(views::CustomButton::BS_HOT,
73 rb.GetBitmapNamed(IDR_CLOSE_BAR_H));
74 close_button_->SetImage(views::CustomButton::BS_PUSHED,
75 rb.GetBitmapNamed(IDR_CLOSE_BAR_P));
76 layout->AddView(close_button_);
77
78 if (!help.empty()) {
79 layout->StartRowWithPadding(0, 1, 0, kBorderSize);
80 help_link_ = new views::Link(help);
81 help_link_->SetController(this);
82 help_link_->SetNormalColor(login::kLinkColor);
83 help_link_->SetHighlightedColor(login::kLinkColor);
84 layout->AddView(help_link_);
85 }
86 }
87
ButtonPressed(views::Button * sender,const views::Event & event)88 void MessageBubble::ButtonPressed(views::Button* sender,
89 const views::Event& event) {
90 if (sender == close_button_) {
91 Close();
92 } else {
93 NOTREACHED() << "Unknown view";
94 }
95 }
96
LinkActivated(views::Link * source,int event_flags)97 void MessageBubble::LinkActivated(views::Link* source, int event_flags) {
98 if (source == help_link_) {
99 if (message_delegate_)
100 message_delegate_->OnHelpLinkActivated();
101 } else {
102 NOTREACHED() << "Unknown view";
103 }
104 }
105
106 // static
Show(views::Widget * parent,const gfx::Rect & position_relative_to,BubbleBorder::ArrowLocation arrow_location,SkBitmap * image,const std::wstring & text,const std::wstring & help,MessageBubbleDelegate * delegate)107 MessageBubble* MessageBubble::Show(views::Widget* parent,
108 const gfx::Rect& position_relative_to,
109 BubbleBorder::ArrowLocation arrow_location,
110 SkBitmap* image,
111 const std::wstring& text,
112 const std::wstring& help,
113 MessageBubbleDelegate* delegate) {
114 // The bubble will be destroyed when it is closed.
115 MessageBubble* bubble = new MessageBubble(
116 views::WidgetGtk::TYPE_WINDOW, parent, image, text, help, true, delegate);
117 bubble->InitBubble(parent, position_relative_to, arrow_location,
118 bubble->text_->parent(), delegate);
119 return bubble;
120 }
121
122 // static
ShowNoGrab(views::Widget * parent,const gfx::Rect & position_relative_to,BubbleBorder::ArrowLocation arrow_location,SkBitmap * image,const std::wstring & text,const std::wstring & help,MessageBubbleDelegate * delegate)123 MessageBubble* MessageBubble::ShowNoGrab(
124 views::Widget* parent,
125 const gfx::Rect& position_relative_to,
126 BubbleBorder::ArrowLocation arrow_location,
127 SkBitmap* image,
128 const std::wstring& text,
129 const std::wstring& help,
130 MessageBubbleDelegate* delegate) {
131 // The bubble will be destroyed when it is closed.
132 MessageBubble* bubble = new MessageBubble(
133 views::WidgetGtk::TYPE_CHILD, parent, image, text, help, false, delegate);
134 bubble->InitBubble(parent, position_relative_to, arrow_location,
135 bubble->text_->parent(), delegate);
136 return bubble;
137 }
138
IsActiveChanged()139 void MessageBubble::IsActiveChanged() {
140 // Active parent instead.
141 if (parent_ && IsActive()) {
142 gtk_window_present_with_time(
143 GTK_WINDOW(static_cast<WidgetGtk*>(parent_)->GetNativeView()),
144 gtk_get_current_event_time());
145 }
146 }
147
SetMouseCapture()148 void MessageBubble::SetMouseCapture() {
149 if (grab_enabled_)
150 WidgetGtk::SetMouseCapture();
151 }
152
Close()153 void MessageBubble::Close() {
154 parent_ = NULL;
155 Bubble::Close();
156 }
157
158 } // namespace chromeos
159