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 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 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 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 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 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 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 148 void MessageBubble::SetMouseCapture() { 149 if (grab_enabled_) 150 WidgetGtk::SetMouseCapture(); 151 } 152 153 void MessageBubble::Close() { 154 parent_ = NULL; 155 Bubble::Close(); 156 } 157 158 } // namespace chromeos 159