| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/login/message_bubble.h" | 5 #include "chrome/browser/chromeos/login/message_bubble.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/utf_string_conversions.h" | |
| 11 #include "chrome/browser/chromeos/login/helper.h" | 10 #include "chrome/browser/chromeos/login/helper.h" |
| 12 #include "grit/generated_resources.h" | 11 #include "grit/generated_resources.h" |
| 13 #include "grit/theme_resources_standard.h" | 12 #include "grit/theme_resources_standard.h" |
| 14 #include "ui/base/resource/resource_bundle.h" | 13 #include "ui/base/resource/resource_bundle.h" |
| 15 #include "ui/views/controls/button/image_button.h" | 14 #include "ui/views/controls/button/image_button.h" |
| 16 #include "ui/views/controls/image_view.h" | 15 #include "ui/views/controls/image_view.h" |
| 17 #include "ui/views/controls/label.h" | 16 #include "ui/views/controls/label.h" |
| 18 #include "ui/views/controls/link.h" | 17 #include "ui/views/controls/link.h" |
| 19 #include "ui/views/layout/grid_layout.h" | 18 #include "ui/views/layout/grid_layout.h" |
| 20 #include "ui/views/widget/widget.h" | 19 #include "ui/views/widget/widget.h" |
| 21 | 20 |
| 21 namespace { |
| 22 |
| 23 const int kBorderSize = 4; |
| 24 const int kMaxLabelWidth = 250; |
| 25 |
| 26 } // namespace |
| 27 |
| 22 namespace chromeos { | 28 namespace chromeos { |
| 23 | 29 |
| 24 static const int kBorderSize = 4; | 30 MessageBubble::MessageBubble(views::View* anchor_view, |
| 25 static const int kMaxLabelWidth = 250; | 31 views::BubbleBorder::ArrowLocation arrow_location, |
| 32 SkBitmap* image, |
| 33 const string16& text, |
| 34 const std::vector<string16>& links) |
| 35 : BubbleDelegateView(anchor_view, arrow_location, kBackgroundColor), |
| 36 image_(image), |
| 37 text_(text), |
| 38 close_button_(NULL), |
| 39 link_listener_(NULL) { |
| 40 set_use_focusless(true); |
| 41 for (size_t i = 0; i < links.size(); ++i) |
| 42 help_links_.push_back(new views::Link(links[i])); |
| 43 } |
| 26 | 44 |
| 27 MessageBubble::MessageBubble(views::Widget::InitParams::Type type, | 45 MessageBubble::~MessageBubble() { |
| 28 views::Widget* parent, | 46 } |
| 29 SkBitmap* image, | 47 |
| 30 const std::wstring& text, | 48 void MessageBubble::Init() { |
| 31 const std::vector<std::wstring>& links, | |
| 32 bool grab_enabled, | |
| 33 MessageBubbleDelegate* delegate) | |
| 34 : Bubble(type, false), // don't show while screen is locked | |
| 35 parent_(parent), | |
| 36 message_delegate_(delegate), | |
| 37 grab_enabled_(grab_enabled) { | |
| 38 using views::GridLayout; | 49 using views::GridLayout; |
| 39 | 50 |
| 40 views::View* control_view = new views::View(); | 51 views::View* control_view = new views::View(); |
| 41 GridLayout* layout = new GridLayout(control_view); | 52 GridLayout* layout = new GridLayout(control_view); |
| 42 control_view->SetLayoutManager(layout); | 53 control_view->SetLayoutManager(layout); |
| 43 views::ColumnSet* column_set = layout->AddColumnSet(0); | 54 views::ColumnSet* column_set = layout->AddColumnSet(0); |
| 44 column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0, | 55 column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0, |
| 45 GridLayout::USE_PREF, 0, 0); | 56 GridLayout::USE_PREF, 0, 0); |
| 46 column_set->AddPaddingColumn(0, kBorderSize); | 57 column_set->AddPaddingColumn(0, kBorderSize); |
| 47 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, | 58 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, |
| 48 GridLayout::USE_PREF, 0, 0); | 59 GridLayout::USE_PREF, 0, 0); |
| 49 column_set->AddPaddingColumn(0, kBorderSize); | 60 column_set->AddPaddingColumn(0, kBorderSize); |
| 50 column_set->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0, | 61 column_set->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0, |
| 51 GridLayout::USE_PREF, 0, 0); | 62 GridLayout::USE_PREF, 0, 0); |
| 52 if (!links.empty()) { | 63 if (!help_links_.empty()) { |
| 53 column_set = layout->AddColumnSet(1); | 64 column_set = layout->AddColumnSet(1); |
| 54 column_set->AddPaddingColumn(0, kBorderSize + image->width()); | 65 column_set->AddPaddingColumn(0, kBorderSize + image_->width()); |
| 55 column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 1, | 66 column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 1, |
| 56 GridLayout::USE_PREF, 0, 0); | 67 GridLayout::USE_PREF, 0, 0); |
| 57 } | 68 } |
| 58 | 69 |
| 59 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 70 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 60 | 71 |
| 61 layout->StartRow(0, 0); | 72 layout->StartRow(0, 0); |
| 62 icon_ = new views::ImageView(); | 73 views::ImageView* icon = new views::ImageView(); |
| 63 icon_->SetImage(*image); | 74 icon->SetImage(*image_); |
| 64 layout->AddView(icon_); | 75 layout->AddView(icon); |
| 65 | 76 |
| 66 text_ = new views::Label(WideToUTF16Hack(text)); | 77 views::Label* label = new views::Label(text_); |
| 67 text_->SetMultiLine(true); | 78 label->SetMultiLine(true); |
| 68 text_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | 79 label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 69 text_->SetBackgroundColor(Bubble::kBackgroundColor); | 80 label->SizeToFit(kMaxLabelWidth); |
| 70 text_->SizeToFit(kMaxLabelWidth); | 81 layout->AddView(label); |
| 71 layout->AddView(text_); | |
| 72 | 82 |
| 73 close_button_ = new views::ImageButton(this); | 83 close_button_ = new views::ImageButton(this); |
| 74 close_button_->SetImage(views::CustomButton::BS_NORMAL, | 84 close_button_->SetImage(views::CustomButton::BS_NORMAL, |
| 75 rb.GetBitmapNamed(IDR_CLOSE_BAR)); | 85 rb.GetBitmapNamed(IDR_CLOSE_BAR)); |
| 76 close_button_->SetImage(views::CustomButton::BS_HOT, | 86 close_button_->SetImage(views::CustomButton::BS_HOT, |
| 77 rb.GetBitmapNamed(IDR_CLOSE_BAR_H)); | 87 rb.GetBitmapNamed(IDR_CLOSE_BAR_H)); |
| 78 close_button_->SetImage(views::CustomButton::BS_PUSHED, | 88 close_button_->SetImage(views::CustomButton::BS_PUSHED, |
| 79 rb.GetBitmapNamed(IDR_CLOSE_BAR_P)); | 89 rb.GetBitmapNamed(IDR_CLOSE_BAR_P)); |
| 80 layout->AddView(close_button_); | 90 layout->AddView(close_button_); |
| 81 | 91 |
| 82 for (size_t i = 0; i < links.size(); ++i) { | 92 for (size_t i = 0; i < help_links_.size(); ++i) { |
| 83 layout->StartRowWithPadding(0, 1, 0, kBorderSize); | 93 layout->StartRowWithPadding(0, 1, 0, kBorderSize); |
| 84 views::Link* help_link_ = new views::Link(WideToUTF16Hack(links[i])); | 94 views::Link* help_link = help_links_[i]; |
| 85 help_links_.push_back(help_link_); | 95 help_link->set_listener(this); |
| 86 help_link_->set_listener(this); | 96 help_link->SetEnabledColor(login::kLinkColor); |
| 87 help_link_->SetBackgroundColor(Bubble::kBackgroundColor); | 97 help_link->SetPressedColor(login::kLinkColor); |
| 88 help_link_->SetEnabledColor(login::kLinkColor); | 98 layout->AddView(help_link); |
| 89 help_link_->SetPressedColor(login::kLinkColor); | |
| 90 layout->AddView(help_link_); | |
| 91 } | 99 } |
| 92 } | 100 } |
| 93 | 101 |
| 94 MessageBubble::~MessageBubble() { | |
| 95 } | |
| 96 | |
| 97 void MessageBubble::ButtonPressed(views::Button* sender, | 102 void MessageBubble::ButtonPressed(views::Button* sender, |
| 98 const views::Event& event) { | 103 const views::Event& event) { |
| 99 if (sender == close_button_) { | 104 if (sender == close_button_) { |
| 100 Close(); | 105 GetWidget()->Close(); |
| 101 } else { | 106 } else { |
| 102 NOTREACHED() << "Unknown view"; | 107 NOTREACHED() << "Unknown view"; |
| 103 } | 108 } |
| 104 } | 109 } |
| 105 | 110 |
| 106 void MessageBubble::LinkClicked(views::Link* source, int event_flags) { | 111 void MessageBubble::LinkClicked(views::Link* source, int event_flags) { |
| 107 if (!message_delegate_) | 112 if (!link_listener_) |
| 108 return; | 113 return; |
| 109 for (size_t i = 0; i < help_links_.size(); ++i) { | 114 for (size_t i = 0; i < help_links_.size(); ++i) { |
| 110 if (source == help_links_[i]) { | 115 if (source == help_links_[i]) { |
| 111 message_delegate_->OnLinkActivated(i); | 116 link_listener_->OnLinkActivated(i); |
| 112 return; | 117 return; |
| 113 } | 118 } |
| 114 } | 119 } |
| 115 NOTREACHED() << "Unknown view"; | 120 NOTREACHED() << "Unknown view"; |
| 116 } | 121 } |
| 117 | 122 |
| 118 // static | |
| 119 MessageBubble* MessageBubble::Show( | |
| 120 views::Widget* parent, | |
| 121 const gfx::Rect& position_relative_to, | |
| 122 views::BubbleBorder::ArrowLocation arrow_location, | |
| 123 SkBitmap* image, | |
| 124 const std::wstring& text, | |
| 125 const std::wstring& help, | |
| 126 MessageBubbleDelegate* delegate) { | |
| 127 std::vector<std::wstring> links; | |
| 128 if (!help.empty()) | |
| 129 links.push_back(help); | |
| 130 return MessageBubble::ShowWithLinks(parent, | |
| 131 position_relative_to, | |
| 132 arrow_location, | |
| 133 image, | |
| 134 text, | |
| 135 links, | |
| 136 delegate); | |
| 137 } | |
| 138 | |
| 139 // static | |
| 140 MessageBubble* MessageBubble::ShowWithLinks( | |
| 141 views::Widget* parent, | |
| 142 const gfx::Rect& position_relative_to, | |
| 143 views::BubbleBorder::ArrowLocation arrow_location, | |
| 144 SkBitmap* image, | |
| 145 const std::wstring& text, | |
| 146 const std::vector<std::wstring>& links, | |
| 147 MessageBubbleDelegate* delegate) { | |
| 148 // The bubble will be destroyed when it is closed. | |
| 149 MessageBubble* bubble = new MessageBubble( | |
| 150 views::Widget::InitParams::TYPE_POPUP, parent, image, text, links, | |
| 151 true, delegate); | |
| 152 bubble->InitBubble(parent, position_relative_to, arrow_location, | |
| 153 views::BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, | |
| 154 bubble->text_->parent(), delegate); | |
| 155 return bubble; | |
| 156 } | |
| 157 | |
| 158 // static | |
| 159 MessageBubble* MessageBubble::ShowNoGrab( | |
| 160 views::Widget* parent, | |
| 161 const gfx::Rect& position_relative_to, | |
| 162 views::BubbleBorder::ArrowLocation arrow_location, | |
| 163 SkBitmap* image, | |
| 164 const std::wstring& text, | |
| 165 const std::wstring& help, | |
| 166 MessageBubbleDelegate* delegate) { | |
| 167 std::vector<std::wstring> links; | |
| 168 if (!help.empty()) | |
| 169 links.push_back(help); | |
| 170 // The bubble will be destroyed when it is closed. | |
| 171 MessageBubble* bubble = new MessageBubble( | |
| 172 views::Widget::InitParams::TYPE_CONTROL, parent, image, text, links, | |
| 173 false, delegate); | |
| 174 bubble->InitBubble(parent, position_relative_to, arrow_location, | |
| 175 views::BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, | |
| 176 bubble->text_->parent(), delegate); | |
| 177 return bubble; | |
| 178 } | |
| 179 | |
| 180 #if defined(TOOLKIT_USES_GTK) | |
| 181 // TODO(saintlou): Unclear if we need this for the !gtk case. | |
| 182 void MessageBubble::OnActiveChanged() { | |
| 183 if (parent_ && IsActive()) { | |
| 184 // Show the parent. | |
| 185 gtk_window_present_with_time(parent_->GetNativeWindow(), | |
| 186 gtk_get_current_event_time()); | |
| 187 } | |
| 188 } | |
| 189 | |
| 190 void MessageBubble::SetMouseCapture() { | |
| 191 if (grab_enabled_) | |
| 192 NativeWidgetGtk::SetMouseCapture(); | |
| 193 } | |
| 194 #endif | |
| 195 | |
| 196 void MessageBubble::Close() { | |
| 197 parent_ = NULL; | |
| 198 Bubble::Close(); | |
| 199 } | |
| 200 | |
| 201 #if defined(TOOLKIT_USES_GTK) | |
| 202 gboolean MessageBubble::OnButtonPress(GtkWidget* widget, | |
| 203 GdkEventButton* event) { | |
| 204 NativeWidgetGtk::OnButtonPress(widget, event); | |
| 205 // Never propagate event to parent. | |
| 206 return true; | |
| 207 } | |
| 208 #endif | |
| 209 | |
| 210 } // namespace chromeos | 123 } // namespace chromeos |
| OLD | NEW |