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/helper.h" 6 7 #include "base/file_util.h" 8 #include "chrome/browser/chromeos/cros/network_library.h" 9 #include "chrome/browser/chromeos/system_access.h" 10 #include "chrome/browser/google/google_util.h" 11 #include "googleurl/src/gurl.h" 12 #include "grit/generated_resources.h" 13 #include "grit/theme_resources.h" 14 #include "third_party/skia/include/effects/SkGradientShader.h" 15 #include "ui/base/l10n/l10n_util.h" 16 #include "ui/base/resource/resource_bundle.h" 17 #include "ui/gfx/canvas_skia.h" 18 #include "views/controls/button/menu_button.h" 19 #include "views/controls/button/native_button.h" 20 #include "views/controls/label.h" 21 #include "views/controls/textfield/textfield.h" 22 #include "views/controls/throbber.h" 23 #include "views/painter.h" 24 #include "views/screen.h" 25 #include "views/widget/widget.h" 26 #include "views/widget/widget_gtk.h" 27 28 namespace chromeos { 29 30 namespace { 31 32 // Time in ms per throbber frame. 33 const int kThrobberFrameMs = 60; 34 35 // Time in ms before smoothed throbber is shown. 36 const int kThrobberStartDelayMs = 500; 37 38 const SkColor kBackgroundCenterColor = SkColorSetRGB(41, 50, 67); 39 const SkColor kBackgroundEdgeColor = SK_ColorBLACK; 40 41 const char kAccountRecoveryHelpUrl[] = 42 "https://www.google.com/support/accounts/bin/answer.py?answer=48598"; 43 44 class BackgroundPainter : public views::Painter { 45 public: 46 BackgroundPainter() {} 47 48 virtual void Paint(int w, int h, gfx::Canvas* canvas) { 49 SkRect rect; 50 rect.set(SkIntToScalar(0), 51 SkIntToScalar(0), 52 SkIntToScalar(w), 53 SkIntToScalar(h)); 54 SkPaint paint; 55 paint.setStyle(SkPaint::kFill_Style); 56 paint.setFlags(SkPaint::kAntiAlias_Flag); 57 SkColor colors[2] = { kBackgroundCenterColor, kBackgroundEdgeColor }; 58 SkShader* s = SkGradientShader::CreateRadial( 59 SkPoint::Make(SkIntToScalar(w / 2), SkIntToScalar(h / 2)), 60 SkIntToScalar(w / 2), 61 colors, 62 NULL, 63 2, 64 SkShader::kClamp_TileMode, 65 NULL); 66 paint.setShader(s); 67 s->unref(); 68 canvas->AsCanvasSkia()->drawRect(rect, paint); 69 } 70 71 private: 72 DISALLOW_COPY_AND_ASSIGN(BackgroundPainter); 73 }; 74 75 } // namespace 76 77 ThrobberHostView::ThrobberHostView() 78 : host_view_(this), 79 throbber_widget_(NULL) { 80 } 81 82 ThrobberHostView::~ThrobberHostView() { 83 StopThrobber(); 84 } 85 86 void ThrobberHostView::StartThrobber() { 87 StopThrobber(); 88 89 views::Widget* host_widget = host_view_->GetWidget(); 90 if (!host_widget) { 91 LOG(WARNING) << "Failed to start the throbber: no Widget"; 92 return; 93 } 94 95 GtkWidget* host_gtk_window = host_widget->GetNativeView(); 96 while (host_gtk_window && !GTK_IS_WINDOW(host_gtk_window)) 97 host_gtk_window = gtk_widget_get_parent(host_gtk_window); 98 if (!host_gtk_window) { 99 LOG(WARNING) << "Failed to start the throbber: no GtkWindow"; 100 return; 101 } 102 103 views::SmoothedThrobber* throbber = CreateDefaultSmoothedThrobber(); 104 throbber->set_stop_delay_ms(0); 105 gfx::Rect throbber_bounds = CalculateThrobberBounds(throbber); 106 107 views::Widget::CreateParams params(views::Widget::CreateParams::TYPE_POPUP); 108 params.transparent = true; 109 throbber_widget_ = views::Widget::CreateWidget(params); 110 static_cast<views::WidgetGtk*>(throbber_widget_)->make_transient_to_parent(); 111 112 throbber_bounds.Offset(host_view_->GetScreenBounds().origin()); 113 throbber_widget_->Init(host_gtk_window, throbber_bounds); 114 throbber_widget_->SetContentsView(throbber); 115 // This keeps the window from flashing at startup. 116 gdk_window_set_back_pixmap( 117 throbber_widget_->GetNativeView()->window, NULL, false); 118 throbber_widget_->Show(); 119 // WM can ignore bounds before widget is shown. 120 throbber_widget_->SetBounds(throbber_bounds); 121 throbber->Start(); 122 } 123 124 void ThrobberHostView::StopThrobber() { 125 if (throbber_widget_) { 126 throbber_widget_->Close(); 127 throbber_widget_ = NULL; 128 } 129 } 130 131 gfx::Rect ThrobberHostView::CalculateThrobberBounds(views::Throbber* throbber) { 132 gfx::Rect bounds(throbber->GetPreferredSize()); 133 bounds.set_x( 134 host_view_->width() - login::kThrobberRightMargin - bounds.width()); 135 bounds.set_y((host_view_->height() - bounds.height()) / 2); 136 return bounds; 137 } 138 139 views::SmoothedThrobber* CreateDefaultSmoothedThrobber() { 140 views::SmoothedThrobber* throbber = 141 new views::SmoothedThrobber(kThrobberFrameMs); 142 throbber->SetFrames( 143 ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_SPINNER)); 144 throbber->set_start_delay_ms(kThrobberStartDelayMs); 145 return throbber; 146 } 147 148 views::Throbber* CreateDefaultThrobber() { 149 views::Throbber* throbber = new views::Throbber(kThrobberFrameMs, false); 150 throbber->SetFrames( 151 ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_SPINNER)); 152 return throbber; 153 } 154 155 views::Painter* CreateBackgroundPainter() { 156 return new BackgroundPainter(); 157 } 158 159 gfx::Rect CalculateScreenBounds(const gfx::Size& size) { 160 gfx::Rect bounds(views::Screen::GetMonitorWorkAreaNearestWindow(NULL)); 161 if (!size.IsEmpty()) { 162 int horizontal_diff = bounds.width() - size.width(); 163 int vertical_diff = bounds.height() - size.height(); 164 bounds.Inset(horizontal_diff / 2, vertical_diff / 2); 165 } 166 return bounds; 167 } 168 169 void CorrectLabelFontSize(views::Label* label) { 170 if (label) 171 label->SetFont(label->font().DeriveFont(kFontSizeCorrectionDelta)); 172 } 173 174 void CorrectMenuButtonFontSize(views::MenuButton* button) { 175 if (button) 176 button->SetFont(button->font().DeriveFont(kFontSizeCorrectionDelta)); 177 } 178 179 void CorrectNativeButtonFontSize(views::NativeButton* button) { 180 if (button) 181 button->set_font(button->font().DeriveFont(kFontSizeCorrectionDelta)); 182 } 183 184 void CorrectTextfieldFontSize(views::Textfield* textfield) { 185 if (textfield) 186 textfield->SetFont(textfield->font().DeriveFont(kFontSizeCorrectionDelta)); 187 } 188 189 void SetAndCorrectTextfieldFont(views::Textfield* textfield, 190 const gfx::Font& font) { 191 if (textfield) 192 textfield->SetFont(font.DeriveFont(kFontSizeCorrectionDelta)); 193 } 194 195 GURL GetAccountRecoveryHelpUrl() { 196 return google_util::AppendGoogleLocaleParam(GURL(kAccountRecoveryHelpUrl)); 197 } 198 199 string16 GetCurrentNetworkName(NetworkLibrary* network_library) { 200 if (!network_library) 201 return string16(); 202 203 if (network_library->ethernet_connected()) { 204 return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET); 205 } else if (network_library->wifi_connected()) { 206 return UTF8ToUTF16(network_library->wifi_network()->name()); 207 } else if (network_library->cellular_connected()) { 208 return UTF8ToUTF16(network_library->cellular_network()->name()); 209 } else if (network_library->ethernet_connecting()) { 210 return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET); 211 } else if (network_library->wifi_connecting()) { 212 return UTF8ToUTF16(network_library->wifi_network()->name()); 213 } else if (network_library->cellular_connecting()) { 214 return UTF8ToUTF16(network_library->cellular_network()->name()); 215 } else { 216 return string16(); 217 } 218 } 219 220 namespace login { 221 222 gfx::Size WideButton::GetPreferredSize() { 223 gfx::Size preferred_size = NativeButton::GetPreferredSize(); 224 // Set minimal width. 225 if (preferred_size.width() < kButtonMinWidth) 226 preferred_size.set_width(kButtonMinWidth); 227 return preferred_size; 228 } 229 230 } // namespace login 231 232 } // namespace chromeos 233