| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 "ash/system/network/tray_network.h" | |
| 6 | |
| 7 #include "ash/shell.h" | |
| 8 #include "ash/shell_window_ids.h" | |
| 9 #include "ash/system/tray/system_tray.h" | |
| 10 #include "ash/system/tray/system_tray_delegate.h" | |
| 11 #include "ash/system/tray/tray_constants.h" | |
| 12 #include "ash/system/tray/tray_details_view.h" | |
| 13 #include "ash/system/tray/tray_item_more.h" | |
| 14 #include "ash/system/tray/tray_item_view.h" | |
| 15 #include "ash/system/tray/tray_notification_view.h" | |
| 16 #include "ash/system/tray/tray_views.h" | |
| 17 #include "base/utf_string_conversions.h" | |
| 18 #include "grit/ash_resources.h" | |
| 19 #include "grit/ash_strings.h" | |
| 20 #include "third_party/skia/include/core/SkColor.h" | |
| 21 #include "ui/aura/window.h" | |
| 22 #include "ui/base/l10n/l10n_util.h" | |
| 23 #include "ui/base/resource/resource_bundle.h" | |
| 24 #include "ui/gfx/canvas.h" | |
| 25 #include "ui/gfx/font.h" | |
| 26 #include "ui/gfx/image/image.h" | |
| 27 #include "ui/gfx/skia_util.h" | |
| 28 #include "ui/views/bubble/bubble_border.h" | |
| 29 #include "ui/views/bubble/bubble_delegate.h" | |
| 30 #include "ui/views/controls/button/button.h" | |
| 31 #include "ui/views/controls/button/image_button.h" | |
| 32 #include "ui/views/controls/image_view.h" | |
| 33 #include "ui/views/controls/label.h" | |
| 34 #include "ui/views/controls/link.h" | |
| 35 #include "ui/views/controls/link_listener.h" | |
| 36 #include "ui/views/controls/scroll_view.h" | |
| 37 #include "ui/views/layout/box_layout.h" | |
| 38 #include "ui/views/layout/fill_layout.h" | |
| 39 #include "ui/views/view.h" | |
| 40 #include "ui/views/widget/widget.h" | |
| 41 | |
| 42 namespace { | |
| 43 | |
| 44 // Height of the list of networks in the popup. | |
| 45 const int kNetworkListHeight = 203; | |
| 46 | |
| 47 // Create a label with the font size and color used in the network info bubble. | |
| 48 views::Label* CreateInfoBubbleLabel(const string16& text) { | |
| 49 const SkColor text_color = SkColorSetARGB(127, 0, 0, 0); | |
| 50 views::Label* label = new views::Label(text); | |
| 51 label->SetFont(label->font().DeriveFont(-1)); | |
| 52 label->SetEnabledColor(text_color); | |
| 53 return label; | |
| 54 } | |
| 55 | |
| 56 // Create a row of labels for the network info bubble. | |
| 57 views::View* CreateInfoBubbleLine(const string16& text_label, | |
| 58 const std::string& text_string) { | |
| 59 views::View* view = new views::View; | |
| 60 view->SetLayoutManager( | |
| 61 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 1)); | |
| 62 view->AddChildView(CreateInfoBubbleLabel(text_label)); | |
| 63 view->AddChildView(CreateInfoBubbleLabel(UTF8ToUTF16(": "))); | |
| 64 view->AddChildView(CreateInfoBubbleLabel(UTF8ToUTF16(text_string))); | |
| 65 return view; | |
| 66 } | |
| 67 | |
| 68 // A bubble that cannot be activated. | |
| 69 class NonActivatableSettingsBubble : public views::BubbleDelegateView { | |
| 70 public: | |
| 71 NonActivatableSettingsBubble(views::View* anchor, views::View* content) | |
| 72 : views::BubbleDelegateView(anchor, views::BubbleBorder::TOP_RIGHT) { | |
| 73 set_use_focusless(true); | |
| 74 set_parent_window(ash::Shell::GetContainer( | |
| 75 anchor->GetWidget()->GetNativeWindow()->GetRootWindow(), | |
| 76 ash::internal::kShellWindowId_SettingBubbleContainer)); | |
| 77 SetLayoutManager(new views::FillLayout()); | |
| 78 AddChildView(content); | |
| 79 } | |
| 80 | |
| 81 virtual ~NonActivatableSettingsBubble() {} | |
| 82 | |
| 83 virtual bool CanActivate() const OVERRIDE { | |
| 84 return false; | |
| 85 } | |
| 86 | |
| 87 private: | |
| 88 DISALLOW_COPY_AND_ASSIGN(NonActivatableSettingsBubble); | |
| 89 }; | |
| 90 | |
| 91 using ash::internal::TrayNetwork; | |
| 92 | |
| 93 int GetMessageIcon(TrayNetwork::MessageType message_type) { | |
| 94 switch(message_type) { | |
| 95 case TrayNetwork::ERROR_CONNECT_FAILED: | |
| 96 return IDR_AURA_UBER_TRAY_NETWORK_FAILED; | |
| 97 case TrayNetwork::MESSAGE_DATA_LOW: | |
| 98 return IDR_AURA_UBER_TRAY_NETWORK_DATA_LOW; | |
| 99 case TrayNetwork::MESSAGE_DATA_NONE: | |
| 100 return IDR_AURA_UBER_TRAY_NETWORK_DATA_NONE; | |
| 101 case TrayNetwork::MESSAGE_DATA_PROMO: | |
| 102 return IDR_AURA_UBER_TRAY_NOTIFICATION_3G; | |
| 103 } | |
| 104 NOTREACHED(); | |
| 105 return 0; | |
| 106 } | |
| 107 | |
| 108 } // namespace | |
| 109 | |
| 110 namespace ash { | |
| 111 namespace internal { | |
| 112 | |
| 113 namespace tray { | |
| 114 | |
| 115 enum ColorTheme { | |
| 116 LIGHT, | |
| 117 DARK, | |
| 118 }; | |
| 119 | |
| 120 class NetworkMessages { | |
| 121 public: | |
| 122 struct Message { | |
| 123 Message() : delegate(NULL) {} | |
| 124 Message(NetworkTrayDelegate* in_delegate, | |
| 125 const string16& in_title, | |
| 126 const string16& in_message, | |
| 127 const std::vector<string16>& in_links) : | |
| 128 delegate(in_delegate), | |
| 129 title(in_title), | |
| 130 message(in_message), | |
| 131 links(in_links) {} | |
| 132 NetworkTrayDelegate* delegate; | |
| 133 string16 title; | |
| 134 string16 message; | |
| 135 std::vector<string16> links; | |
| 136 }; | |
| 137 typedef std::map<TrayNetwork::MessageType, Message> MessageMap; | |
| 138 | |
| 139 MessageMap& messages() { return messages_; } | |
| 140 const MessageMap& messages() const { return messages_; } | |
| 141 | |
| 142 private: | |
| 143 MessageMap messages_; | |
| 144 }; | |
| 145 | |
| 146 class NetworkTrayView : public TrayItemView { | |
| 147 public: | |
| 148 NetworkTrayView(ColorTheme size, bool tray_icon) | |
| 149 : color_theme_(size), tray_icon_(tray_icon) { | |
| 150 SetLayoutManager( | |
| 151 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0)); | |
| 152 | |
| 153 image_view_ = color_theme_ == DARK ? | |
| 154 new FixedSizedImageView(0, kTrayPopupItemHeight) : | |
| 155 new views::ImageView; | |
| 156 AddChildView(image_view_); | |
| 157 | |
| 158 NetworkIconInfo info; | |
| 159 Shell::GetInstance()->tray_delegate()-> | |
| 160 GetMostRelevantNetworkIcon(&info, false); | |
| 161 Update(info); | |
| 162 } | |
| 163 | |
| 164 virtual ~NetworkTrayView() {} | |
| 165 | |
| 166 void Update(const NetworkIconInfo& info) { | |
| 167 image_view_->SetImage(info.image); | |
| 168 if (tray_icon_) | |
| 169 SetVisible(info.tray_icon_visible); | |
| 170 SchedulePaint(); | |
| 171 } | |
| 172 | |
| 173 private: | |
| 174 views::ImageView* image_view_; | |
| 175 ColorTheme color_theme_; | |
| 176 bool tray_icon_; | |
| 177 | |
| 178 DISALLOW_COPY_AND_ASSIGN(NetworkTrayView); | |
| 179 }; | |
| 180 | |
| 181 class NetworkDefaultView : public TrayItemMore { | |
| 182 public: | |
| 183 explicit NetworkDefaultView(SystemTrayItem* owner) | |
| 184 : TrayItemMore(owner) { | |
| 185 Update(); | |
| 186 } | |
| 187 | |
| 188 virtual ~NetworkDefaultView() {} | |
| 189 | |
| 190 void Update() { | |
| 191 NetworkIconInfo info; | |
| 192 Shell::GetInstance()->tray_delegate()-> | |
| 193 GetMostRelevantNetworkIcon(&info, true); | |
| 194 SetImage(&info.image); | |
| 195 SetLabel(info.description); | |
| 196 SetAccessibleName(info.description); | |
| 197 } | |
| 198 | |
| 199 private: | |
| 200 DISALLOW_COPY_AND_ASSIGN(NetworkDefaultView); | |
| 201 }; | |
| 202 | |
| 203 class NetworkDetailedView : public TrayDetailsView { | |
| 204 public: | |
| 205 NetworkDetailedView() {} | |
| 206 | |
| 207 virtual ~NetworkDetailedView() {} | |
| 208 | |
| 209 virtual TrayNetwork::DetailedViewType GetViewType() const = 0; | |
| 210 | |
| 211 virtual void Update() = 0; | |
| 212 }; | |
| 213 | |
| 214 class NetworkListDetailedView : public NetworkDetailedView, | |
| 215 public views::ButtonListener, | |
| 216 public ViewClickListener { | |
| 217 public: | |
| 218 NetworkListDetailedView(user::LoginStatus login) | |
| 219 : login_(login), | |
| 220 airplane_(NULL), | |
| 221 info_icon_(NULL), | |
| 222 button_wifi_(NULL), | |
| 223 button_mobile_(NULL), | |
| 224 view_mobile_account_(NULL), | |
| 225 setup_mobile_account_(NULL), | |
| 226 other_wifi_(NULL), | |
| 227 turn_on_wifi_(NULL), | |
| 228 other_mobile_(NULL), | |
| 229 settings_(NULL), | |
| 230 proxy_settings_(NULL), | |
| 231 info_bubble_(NULL) { | |
| 232 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate(); | |
| 233 delegate->RequestNetworkScan(); | |
| 234 CreateItems(); | |
| 235 Update(); | |
| 236 } | |
| 237 | |
| 238 virtual ~NetworkListDetailedView() { | |
| 239 if (info_bubble_) | |
| 240 info_bubble_->GetWidget()->CloseNow(); | |
| 241 } | |
| 242 | |
| 243 void CreateItems() { | |
| 244 RemoveAllChildViews(true); | |
| 245 | |
| 246 airplane_ = NULL; | |
| 247 info_icon_ = NULL; | |
| 248 button_wifi_ = NULL; | |
| 249 button_mobile_ = NULL; | |
| 250 view_mobile_account_ = NULL; | |
| 251 setup_mobile_account_ = NULL; | |
| 252 other_wifi_ = NULL; | |
| 253 turn_on_wifi_ = NULL; | |
| 254 other_mobile_ = NULL; | |
| 255 settings_ = NULL; | |
| 256 proxy_settings_ = NULL; | |
| 257 | |
| 258 AppendNetworkEntries(); | |
| 259 AppendNetworkExtra(); | |
| 260 AppendHeaderEntry(); | |
| 261 AppendHeaderButtons(); | |
| 262 | |
| 263 Update(); | |
| 264 } | |
| 265 | |
| 266 // Overridden from NetworkDetailedView: | |
| 267 virtual TrayNetwork::DetailedViewType GetViewType() const OVERRIDE { | |
| 268 return TrayNetwork::LIST_VIEW; | |
| 269 } | |
| 270 | |
| 271 virtual void Update() OVERRIDE { | |
| 272 UpdateAvailableNetworkList(); | |
| 273 UpdateHeaderButtons(); | |
| 274 UpdateNetworkEntries(); | |
| 275 UpdateNetworkExtra(); | |
| 276 | |
| 277 Layout(); | |
| 278 } | |
| 279 | |
| 280 private: | |
| 281 void AppendHeaderEntry() { | |
| 282 CreateSpecialRow(IDS_ASH_STATUS_TRAY_NETWORK, this); | |
| 283 } | |
| 284 | |
| 285 void AppendHeaderButtons() { | |
| 286 button_wifi_ = new TrayPopupHeaderButton(this, | |
| 287 IDR_AURA_UBER_TRAY_WIFI_ENABLED, | |
| 288 IDR_AURA_UBER_TRAY_WIFI_DISABLED, | |
| 289 IDR_AURA_UBER_TRAY_WIFI_ENABLED_HOVER, | |
| 290 IDR_AURA_UBER_TRAY_WIFI_DISABLED_HOVER, | |
| 291 IDS_ASH_STATUS_TRAY_WIFI); | |
| 292 button_wifi_->SetTooltipText( | |
| 293 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISABLE_WIFI)); | |
| 294 button_wifi_->SetToggledTooltipText( | |
| 295 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ENABLE_WIFI)); | |
| 296 footer()->AddButton(button_wifi_); | |
| 297 | |
| 298 button_mobile_ = new TrayPopupHeaderButton(this, | |
| 299 IDR_AURA_UBER_TRAY_CELLULAR_ENABLED, | |
| 300 IDR_AURA_UBER_TRAY_CELLULAR_DISABLED, | |
| 301 IDR_AURA_UBER_TRAY_CELLULAR_ENABLED_HOVER, | |
| 302 IDR_AURA_UBER_TRAY_CELLULAR_DISABLED_HOVER, | |
| 303 IDS_ASH_STATUS_TRAY_CELLULAR); | |
| 304 button_mobile_->SetTooltipText( | |
| 305 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISABLE_MOBILE)); | |
| 306 button_mobile_->SetToggledTooltipText( | |
| 307 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ENABLE_MOBILE)); | |
| 308 footer()->AddButton(button_mobile_); | |
| 309 | |
| 310 info_icon_ = new TrayPopupHeaderButton(this, | |
| 311 IDR_AURA_UBER_TRAY_NETWORK_INFO, | |
| 312 IDR_AURA_UBER_TRAY_NETWORK_INFO, | |
| 313 IDR_AURA_UBER_TRAY_NETWORK_INFO_HOVER, | |
| 314 IDR_AURA_UBER_TRAY_NETWORK_INFO_HOVER, | |
| 315 IDS_ASH_STATUS_TRAY_NETWORK_INFO); | |
| 316 info_icon_->SetTooltipText( | |
| 317 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_INFO)); | |
| 318 footer()->AddButton(info_icon_); | |
| 319 } | |
| 320 | |
| 321 void UpdateHeaderButtons() { | |
| 322 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate(); | |
| 323 button_wifi_->SetToggled(!delegate->GetWifiEnabled()); | |
| 324 button_mobile_->SetToggled(!delegate->GetMobileEnabled()); | |
| 325 button_mobile_->SetVisible(delegate->GetMobileAvailable()); | |
| 326 if (proxy_settings_) | |
| 327 proxy_settings_->SetEnabled(delegate->IsNetworkConnected()); | |
| 328 } | |
| 329 | |
| 330 void AppendNetworkEntries() { | |
| 331 CreateScrollableList(); | |
| 332 | |
| 333 HoverHighlightView* container = new HoverHighlightView(this); | |
| 334 container->set_fixed_height(kTrayPopupItemHeight); | |
| 335 container->AddLabel(ui::ResourceBundle::GetSharedInstance(). | |
| 336 GetLocalizedString(IDS_ASH_STATUS_TRAY_MOBILE_VIEW_ACCOUNT), | |
| 337 gfx::Font::NORMAL); | |
| 338 AddChildView(container); | |
| 339 view_mobile_account_ = container; | |
| 340 | |
| 341 container = new HoverHighlightView(this); | |
| 342 container->set_fixed_height(kTrayPopupItemHeight); | |
| 343 container->AddLabel(ui::ResourceBundle::GetSharedInstance(). | |
| 344 GetLocalizedString(IDS_ASH_STATUS_TRAY_SETUP_MOBILE), | |
| 345 gfx::Font::NORMAL); | |
| 346 AddChildView(container); | |
| 347 setup_mobile_account_ = container; | |
| 348 } | |
| 349 | |
| 350 void UpdateAvailableNetworkList() { | |
| 351 network_list_.clear(); | |
| 352 Shell::GetInstance()->tray_delegate()->GetAvailableNetworks(&network_list_); | |
| 353 } | |
| 354 | |
| 355 void RefreshNetworkScrollWithUpdatedNetworkList() { | |
| 356 network_map_.clear(); | |
| 357 std::set<std::string> new_service_paths; | |
| 358 | |
| 359 bool needs_relayout = false; | |
| 360 views::View* highlighted_view = NULL; | |
| 361 | |
| 362 if (service_path_map_.empty()) | |
| 363 scroll_content()->RemoveAllChildViews(true); | |
| 364 | |
| 365 for (size_t i = 0; i < network_list_.size(); ++i) { | |
| 366 std::map<std::string, HoverHighlightView*>::const_iterator it = | |
| 367 service_path_map_.find(network_list_[i].service_path); | |
| 368 HoverHighlightView* container = NULL; | |
| 369 if (it == service_path_map_.end()) { | |
| 370 // Create a new view. | |
| 371 container = new HoverHighlightView(this); | |
| 372 container->set_fixed_height(kTrayPopupItemHeight); | |
| 373 container->AddIconAndLabel(network_list_[i].image, | |
| 374 network_list_[i].description.empty() ? | |
| 375 network_list_[i].name : network_list_[i].description, | |
| 376 network_list_[i].highlight ? | |
| 377 gfx::Font::BOLD : gfx::Font::NORMAL); | |
| 378 scroll_content()->AddChildViewAt(container, i); | |
| 379 container->set_border(views::Border::CreateEmptyBorder(0, | |
| 380 kTrayPopupPaddingHorizontal, 0, 0)); | |
| 381 needs_relayout = true; | |
| 382 } else { | |
| 383 container = it->second; | |
| 384 container->RemoveAllChildViews(true); | |
| 385 container->AddIconAndLabel(network_list_[i].image, | |
| 386 network_list_[i].description.empty() ? | |
| 387 network_list_[i].name : network_list_[i].description, | |
| 388 network_list_[i].highlight ? gfx::Font::BOLD : gfx::Font::NORMAL); | |
| 389 container->Layout(); | |
| 390 container->SchedulePaint(); | |
| 391 | |
| 392 // Reordering the view if necessary. | |
| 393 views::View* child = scroll_content()->child_at(i); | |
| 394 if (child != container) { | |
| 395 scroll_content()->ReorderChildView(container, i); | |
| 396 needs_relayout = true; | |
| 397 } | |
| 398 } | |
| 399 | |
| 400 if (network_list_[i].highlight) | |
| 401 highlighted_view = container; | |
| 402 network_map_[container] = network_list_[i].service_path; | |
| 403 service_path_map_[network_list_[i].service_path] = container; | |
| 404 new_service_paths.insert(network_list_[i].service_path); | |
| 405 } | |
| 406 | |
| 407 std::set<std::string> remove_service_paths; | |
| 408 for (std::map<std::string, HoverHighlightView*>::const_iterator it = | |
| 409 service_path_map_.begin(); it != service_path_map_.end(); ++it) { | |
| 410 if (new_service_paths.find(it->first) == new_service_paths.end()) { | |
| 411 remove_service_paths.insert(it->first); | |
| 412 scroll_content()->RemoveChildView(it->second); | |
| 413 needs_relayout = true; | |
| 414 } | |
| 415 } | |
| 416 | |
| 417 for (std::set<std::string>::const_iterator remove_it = | |
| 418 remove_service_paths.begin(); | |
| 419 remove_it != remove_service_paths.end(); ++remove_it) { | |
| 420 service_path_map_.erase(*remove_it); | |
| 421 } | |
| 422 | |
| 423 if (needs_relayout) { | |
| 424 scroll_content()->SizeToPreferredSize(); | |
| 425 static_cast<views::View*>(scroller())->Layout(); | |
| 426 if (highlighted_view) | |
| 427 scroll_content()->ScrollRectToVisible(highlighted_view->bounds()); | |
| 428 } | |
| 429 } | |
| 430 | |
| 431 void RefreshNetworkScrollWithEmptyNetworkList() { | |
| 432 service_path_map_.clear(); | |
| 433 network_map_.clear(); | |
| 434 scroll_content()->RemoveAllChildViews(true); | |
| 435 HoverHighlightView* container = new HoverHighlightView(this); | |
| 436 container->set_fixed_height(kTrayPopupItemHeight); | |
| 437 | |
| 438 if (Shell::GetInstance()->tray_delegate()->GetWifiEnabled()) { | |
| 439 NetworkIconInfo info; | |
| 440 Shell::GetInstance()->tray_delegate()-> | |
| 441 GetMostRelevantNetworkIcon(&info, true); | |
| 442 container->AddIconAndLabel(info.image, | |
| 443 info.description, | |
| 444 gfx::Font::NORMAL); | |
| 445 container->set_border(views::Border::CreateEmptyBorder(0, | |
| 446 kTrayPopupPaddingHorizontal, 0, 0)); | |
| 447 | |
| 448 } else { | |
| 449 container->AddLabel(ui::ResourceBundle::GetSharedInstance(). | |
| 450 GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED), | |
| 451 gfx::Font::NORMAL); | |
| 452 } | |
| 453 | |
| 454 scroll_content()->AddChildViewAt(container, 0); | |
| 455 scroll_content()->SizeToPreferredSize(); | |
| 456 static_cast<views::View*>(scroller())->Layout(); | |
| 457 } | |
| 458 | |
| 459 void UpdateNetworkEntries() { | |
| 460 if (network_list_.size() > 0 ) | |
| 461 RefreshNetworkScrollWithUpdatedNetworkList(); | |
| 462 else | |
| 463 RefreshNetworkScrollWithEmptyNetworkList(); | |
| 464 | |
| 465 view_mobile_account_->SetVisible(false); | |
| 466 setup_mobile_account_->SetVisible(false); | |
| 467 | |
| 468 if (login_ == user::LOGGED_IN_NONE) | |
| 469 return; | |
| 470 | |
| 471 std::string carrier_id, topup_url, setup_url; | |
| 472 if (Shell::GetInstance()->tray_delegate()-> | |
| 473 GetCellularCarrierInfo(&carrier_id, | |
| 474 &topup_url, | |
| 475 &setup_url)) { | |
| 476 if (carrier_id != carrier_id_) { | |
| 477 carrier_id_ = carrier_id; | |
| 478 if (!topup_url.empty()) | |
| 479 topup_url_ = topup_url; | |
| 480 } | |
| 481 | |
| 482 if (!setup_url.empty()) | |
| 483 setup_url_ = setup_url; | |
| 484 | |
| 485 if (!topup_url_.empty()) | |
| 486 view_mobile_account_->SetVisible(true); | |
| 487 if (!setup_url_.empty()) | |
| 488 setup_mobile_account_->SetVisible(true); | |
| 489 } | |
| 490 } | |
| 491 | |
| 492 void AppendNetworkExtra() { | |
| 493 if (login_ == user::LOGGED_IN_LOCKED) | |
| 494 return; | |
| 495 | |
| 496 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 497 | |
| 498 TrayPopupTextButtonContainer* bottom_row = | |
| 499 new TrayPopupTextButtonContainer; | |
| 500 | |
| 501 other_wifi_ = new TrayPopupTextButton(this, | |
| 502 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_OTHER_WIFI)); | |
| 503 bottom_row->AddTextButton(other_wifi_); | |
| 504 | |
| 505 turn_on_wifi_ = new TrayPopupTextButton(this, | |
| 506 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_TURN_ON_WIFI)); | |
| 507 bottom_row->AddTextButton(turn_on_wifi_); | |
| 508 | |
| 509 other_mobile_ = new TrayPopupTextButton(this, | |
| 510 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_OTHER_MOBILE)); | |
| 511 bottom_row->AddTextButton(other_mobile_); | |
| 512 | |
| 513 CreateSettingsEntry(); | |
| 514 DCHECK(settings_ || proxy_settings_); | |
| 515 bottom_row->AddTextButton(settings_ ? settings_ : proxy_settings_); | |
| 516 | |
| 517 AddChildView(bottom_row); | |
| 518 } | |
| 519 | |
| 520 void UpdateNetworkExtra() { | |
| 521 if (login_ == user::LOGGED_IN_LOCKED) | |
| 522 return; | |
| 523 | |
| 524 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate(); | |
| 525 if (network_list_.size() == 0 && !delegate->GetWifiEnabled()) { | |
| 526 turn_on_wifi_->SetVisible(true); | |
| 527 other_wifi_->SetVisible(false); | |
| 528 } else { | |
| 529 turn_on_wifi_->SetVisible(false); | |
| 530 other_wifi_->SetVisible(true); | |
| 531 other_wifi_->SetEnabled(delegate->GetWifiEnabled()); | |
| 532 } | |
| 533 other_mobile_->SetVisible(delegate->GetMobileAvailable() && | |
| 534 delegate->GetMobileScanSupported()); | |
| 535 if (other_mobile_->visible()) | |
| 536 other_mobile_->SetEnabled(delegate->GetMobileEnabled()); | |
| 537 | |
| 538 turn_on_wifi_->parent()->Layout(); | |
| 539 } | |
| 540 | |
| 541 // Adds a settings entry when logged in, and an entry for changing proxy | |
| 542 // settings otherwise. | |
| 543 void CreateSettingsEntry() { | |
| 544 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 545 if (login_ != user::LOGGED_IN_NONE) { | |
| 546 // Settings, only if logged in. | |
| 547 settings_ = new TrayPopupTextButton(this, | |
| 548 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS)); | |
| 549 } else { | |
| 550 proxy_settings_ = new TrayPopupTextButton(this, | |
| 551 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_PROXY_SETTINGS)); | |
| 552 } | |
| 553 } | |
| 554 | |
| 555 views::View* CreateNetworkInfoView() { | |
| 556 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | |
| 557 std::string ip_address, ethernet_address, wifi_address; | |
| 558 Shell::GetInstance()->tray_delegate()->GetNetworkAddresses(&ip_address, | |
| 559 ðernet_address, &wifi_address); | |
| 560 | |
| 561 views::View* container = new views::View; | |
| 562 container->SetLayoutManager(new | |
| 563 views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); | |
| 564 container->set_border(views::Border::CreateEmptyBorder(0, 5, 0, 5)); | |
| 565 | |
| 566 // GetNetworkAddresses returns empty strings if no information is available. | |
| 567 if (!ip_address.empty()) { | |
| 568 container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString( | |
| 569 IDS_ASH_STATUS_TRAY_IP), ip_address)); | |
| 570 } | |
| 571 if (!ethernet_address.empty()) { | |
| 572 container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString( | |
| 573 IDS_ASH_STATUS_TRAY_ETHERNET), ethernet_address)); | |
| 574 } | |
| 575 if (!wifi_address.empty()) { | |
| 576 container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString( | |
| 577 IDS_ASH_STATUS_TRAY_WIFI), wifi_address)); | |
| 578 } | |
| 579 | |
| 580 // Avoid an empty bubble in the unlikely event that there is no network | |
| 581 // information at all. | |
| 582 if (!container->has_children()) { | |
| 583 container->AddChildView(CreateInfoBubbleLabel(bundle.GetLocalizedString( | |
| 584 IDS_ASH_STATUS_TRAY_NO_NETWORKS))); | |
| 585 } | |
| 586 | |
| 587 return container; | |
| 588 } | |
| 589 | |
| 590 void ToggleInfoBubble() { | |
| 591 if (ResetInfoBubble()) | |
| 592 return; | |
| 593 | |
| 594 info_bubble_ = new NonActivatableSettingsBubble( | |
| 595 info_icon_, CreateNetworkInfoView()); | |
| 596 views::BubbleDelegateView::CreateBubble(info_bubble_); | |
| 597 info_bubble_->Show(); | |
| 598 } | |
| 599 | |
| 600 // Returns whether an existing info-bubble was closed. | |
| 601 bool ResetInfoBubble() { | |
| 602 if (!info_bubble_) | |
| 603 return false; | |
| 604 info_bubble_->GetWidget()->Close(); | |
| 605 info_bubble_ = NULL; | |
| 606 return true; | |
| 607 } | |
| 608 | |
| 609 // Overridden from ButtonListener. | |
| 610 virtual void ButtonPressed(views::Button* sender, | |
| 611 const ui::Event& event) OVERRIDE { | |
| 612 ash::SystemTrayDelegate* delegate = | |
| 613 ash::Shell::GetInstance()->tray_delegate(); | |
| 614 if (sender == info_icon_) { | |
| 615 ToggleInfoBubble(); | |
| 616 return; | |
| 617 } | |
| 618 | |
| 619 // If the info bubble was visible, close it when some other item is clicked | |
| 620 // on. | |
| 621 ResetInfoBubble(); | |
| 622 if (sender == button_wifi_) | |
| 623 delegate->ToggleWifi(); | |
| 624 else if (sender == button_mobile_) | |
| 625 delegate->ToggleMobile(); | |
| 626 else if (sender == settings_) | |
| 627 delegate->ShowNetworkSettings(); | |
| 628 else if (sender == proxy_settings_) | |
| 629 delegate->ChangeProxySettings(); | |
| 630 else if (sender == other_mobile_) | |
| 631 delegate->ShowOtherCellular(); | |
| 632 else if (sender == other_wifi_) | |
| 633 delegate->ShowOtherWifi(); | |
| 634 else if (sender == turn_on_wifi_) | |
| 635 delegate->ToggleWifi(); | |
| 636 else | |
| 637 NOTREACHED(); | |
| 638 } | |
| 639 | |
| 640 // Overridden from ViewClickListener. | |
| 641 virtual void ClickedOn(views::View* sender) OVERRIDE { | |
| 642 ash::SystemTrayDelegate* delegate = | |
| 643 ash::Shell::GetInstance()->tray_delegate(); | |
| 644 // If the info bubble was visible, close it when some other item is clicked | |
| 645 // on. | |
| 646 ResetInfoBubble(); | |
| 647 | |
| 648 if (sender == footer()->content()) { | |
| 649 Shell::GetInstance()->system_tray()->ShowDefaultView(BUBBLE_USE_EXISTING); | |
| 650 return; | |
| 651 } | |
| 652 | |
| 653 if (login_ == user::LOGGED_IN_LOCKED) | |
| 654 return; | |
| 655 | |
| 656 if (sender == view_mobile_account_) { | |
| 657 delegate->ShowCellularURL(topup_url_); | |
| 658 } else if (sender == setup_mobile_account_) { | |
| 659 delegate->ShowCellularURL(setup_url_); | |
| 660 } else if (sender == airplane_) { | |
| 661 delegate->ToggleAirplaneMode(); | |
| 662 } else { | |
| 663 std::map<views::View*, std::string>::iterator find; | |
| 664 find = network_map_.find(sender); | |
| 665 if (find != network_map_.end()) { | |
| 666 std::string network_id = find->second; | |
| 667 delegate->ConnectToNetwork(network_id); | |
| 668 } | |
| 669 } | |
| 670 } | |
| 671 | |
| 672 std::string carrier_id_; | |
| 673 std::string topup_url_; | |
| 674 std::string setup_url_; | |
| 675 | |
| 676 user::LoginStatus login_; | |
| 677 std::map<views::View*, std::string> network_map_; | |
| 678 std::map<std::string, HoverHighlightView*> service_path_map_; | |
| 679 std::vector<NetworkIconInfo> network_list_; | |
| 680 views::View* airplane_; | |
| 681 TrayPopupHeaderButton* info_icon_; | |
| 682 TrayPopupHeaderButton* button_wifi_; | |
| 683 TrayPopupHeaderButton* button_mobile_; | |
| 684 views::View* view_mobile_account_; | |
| 685 views::View* setup_mobile_account_; | |
| 686 TrayPopupTextButton* other_wifi_; | |
| 687 TrayPopupTextButton* turn_on_wifi_; | |
| 688 TrayPopupTextButton* other_mobile_; | |
| 689 TrayPopupTextButton* settings_; | |
| 690 TrayPopupTextButton* proxy_settings_; | |
| 691 | |
| 692 views::BubbleDelegateView* info_bubble_; | |
| 693 | |
| 694 DISALLOW_COPY_AND_ASSIGN(NetworkListDetailedView); | |
| 695 }; | |
| 696 | |
| 697 class NetworkWifiDetailedView : public NetworkDetailedView { | |
| 698 public: | |
| 699 explicit NetworkWifiDetailedView(bool wifi_enabled) { | |
| 700 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, | |
| 701 kTrayPopupPaddingHorizontal, | |
| 702 10, | |
| 703 kTrayPopupPaddingBetweenItems)); | |
| 704 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | |
| 705 views::ImageView* image = new views::ImageView; | |
| 706 const int image_id = wifi_enabled ? | |
| 707 IDR_AURA_UBER_TRAY_WIFI_ENABLED : IDR_AURA_UBER_TRAY_WIFI_DISABLED; | |
| 708 image->SetImage(bundle.GetImageNamed(image_id).ToImageSkia()); | |
| 709 AddChildView(image); | |
| 710 | |
| 711 const int string_id = wifi_enabled ? | |
| 712 IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED: | |
| 713 IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED; | |
| 714 views::Label* label = | |
| 715 new views::Label(bundle.GetLocalizedString(string_id)); | |
| 716 label->SetMultiLine(true); | |
| 717 label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
| 718 AddChildView(label); | |
| 719 } | |
| 720 | |
| 721 virtual ~NetworkWifiDetailedView() {} | |
| 722 | |
| 723 // Overridden from NetworkDetailedView: | |
| 724 virtual TrayNetwork::DetailedViewType GetViewType() const OVERRIDE { | |
| 725 return TrayNetwork::WIFI_VIEW; | |
| 726 } | |
| 727 | |
| 728 virtual void Update() OVERRIDE {} | |
| 729 | |
| 730 private: | |
| 731 DISALLOW_COPY_AND_ASSIGN(NetworkWifiDetailedView); | |
| 732 }; | |
| 733 | |
| 734 class NetworkMessageView : public views::View, | |
| 735 public views::LinkListener { | |
| 736 public: | |
| 737 NetworkMessageView(TrayNetwork* tray, | |
| 738 TrayNetwork::MessageType message_type, | |
| 739 const NetworkMessages::Message& network_msg) | |
| 740 : tray_(tray), | |
| 741 message_type_(message_type) { | |
| 742 SetLayoutManager( | |
| 743 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); | |
| 744 | |
| 745 if (!network_msg.title.empty()) { | |
| 746 views::Label* title = new views::Label(network_msg.title); | |
| 747 title->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
| 748 title->SetFont(title->font().DeriveFont(0, gfx::Font::BOLD)); | |
| 749 AddChildView(title); | |
| 750 } | |
| 751 | |
| 752 if (!network_msg.message.empty()) { | |
| 753 views::Label* message = new views::Label(network_msg.message); | |
| 754 message->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
| 755 message->SetMultiLine(true); | |
| 756 message->SizeToFit(kTrayNotificationContentsWidth); | |
| 757 AddChildView(message); | |
| 758 } | |
| 759 | |
| 760 if (!network_msg.links.empty()) { | |
| 761 for (size_t i = 0; i < network_msg.links.size(); ++i) { | |
| 762 views::Link* link = new views::Link(network_msg.links[i]); | |
| 763 link->set_id(i); | |
| 764 link->set_listener(this); | |
| 765 link->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
| 766 link->SetMultiLine(true); | |
| 767 link->SizeToFit(kTrayNotificationContentsWidth); | |
| 768 AddChildView(link); | |
| 769 } | |
| 770 } | |
| 771 } | |
| 772 | |
| 773 virtual ~NetworkMessageView() { | |
| 774 } | |
| 775 | |
| 776 // Overridden from views::LinkListener. | |
| 777 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE { | |
| 778 tray_->LinkClicked(message_type_, source->id()); | |
| 779 } | |
| 780 | |
| 781 TrayNetwork::MessageType message_type() const { return message_type_; } | |
| 782 | |
| 783 private: | |
| 784 TrayNetwork* tray_; | |
| 785 TrayNetwork::MessageType message_type_; | |
| 786 | |
| 787 DISALLOW_COPY_AND_ASSIGN(NetworkMessageView); | |
| 788 }; | |
| 789 | |
| 790 class NetworkNotificationView : public TrayNotificationView { | |
| 791 public: | |
| 792 explicit NetworkNotificationView(TrayNetwork* tray) | |
| 793 : TrayNotificationView(tray, 0) { | |
| 794 CreateMessageView(); | |
| 795 InitView(network_message_view_); | |
| 796 SetIconImage(*ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 797 GetMessageIcon(network_message_view_->message_type()))); | |
| 798 } | |
| 799 | |
| 800 // Overridden from TrayNotificationView. | |
| 801 virtual void OnClose() OVERRIDE { | |
| 802 tray_network()->ClearNetworkMessage(network_message_view_->message_type()); | |
| 803 } | |
| 804 | |
| 805 virtual void OnClickAction() OVERRIDE { | |
| 806 if (network_message_view_->message_type() != | |
| 807 TrayNetwork::MESSAGE_DATA_PROMO) | |
| 808 tray()->PopupDetailedView(0, true); | |
| 809 } | |
| 810 | |
| 811 void Update() { | |
| 812 CreateMessageView(); | |
| 813 UpdateViewAndImage(network_message_view_, | |
| 814 *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 815 GetMessageIcon(network_message_view_->message_type()))); | |
| 816 } | |
| 817 | |
| 818 private: | |
| 819 TrayNetwork* tray_network() { | |
| 820 return static_cast<TrayNetwork*>(tray()); | |
| 821 } | |
| 822 | |
| 823 void CreateMessageView() { | |
| 824 // Display the first (highest priority) message. | |
| 825 CHECK(!tray_network()->messages()->messages().empty()); | |
| 826 NetworkMessages::MessageMap::const_iterator iter = | |
| 827 tray_network()->messages()->messages().begin(); | |
| 828 network_message_view_ = | |
| 829 new NetworkMessageView(tray_network(), iter->first, iter->second); | |
| 830 } | |
| 831 | |
| 832 tray::NetworkMessageView* network_message_view_; | |
| 833 | |
| 834 DISALLOW_COPY_AND_ASSIGN(NetworkNotificationView); | |
| 835 }; | |
| 836 | |
| 837 } // namespace tray | |
| 838 | |
| 839 TrayNetwork::TrayNetwork() | |
| 840 : tray_(NULL), | |
| 841 default_(NULL), | |
| 842 detailed_(NULL), | |
| 843 notification_(NULL), | |
| 844 messages_(new tray::NetworkMessages()), | |
| 845 request_wifi_view_(false) { | |
| 846 } | |
| 847 | |
| 848 TrayNetwork::~TrayNetwork() { | |
| 849 } | |
| 850 | |
| 851 views::View* TrayNetwork::CreateTrayView(user::LoginStatus status) { | |
| 852 CHECK(tray_ == NULL); | |
| 853 tray_ = new tray::NetworkTrayView(tray::LIGHT, true /*tray_icon*/); | |
| 854 return tray_; | |
| 855 } | |
| 856 | |
| 857 views::View* TrayNetwork::CreateDefaultView(user::LoginStatus status) { | |
| 858 CHECK(default_ == NULL); | |
| 859 default_ = new tray::NetworkDefaultView(this); | |
| 860 return default_; | |
| 861 } | |
| 862 | |
| 863 views::View* TrayNetwork::CreateDetailedView(user::LoginStatus status) { | |
| 864 CHECK(detailed_ == NULL); | |
| 865 // Clear any notifications when showing the detailed view. | |
| 866 messages_->messages().clear(); | |
| 867 HideNotificationView(); | |
| 868 if (request_wifi_view_) { | |
| 869 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate(); | |
| 870 // The Wi-Fi state is not toggled yet at this point. | |
| 871 detailed_ = new tray::NetworkWifiDetailedView(!delegate->GetWifiEnabled()); | |
| 872 request_wifi_view_ = false; | |
| 873 } else { | |
| 874 detailed_ = new tray::NetworkListDetailedView(status); | |
| 875 } | |
| 876 return detailed_; | |
| 877 } | |
| 878 | |
| 879 views::View* TrayNetwork::CreateNotificationView(user::LoginStatus status) { | |
| 880 CHECK(notification_ == NULL); | |
| 881 if (messages_->messages().empty()) | |
| 882 return NULL; // Message has already been cleared. | |
| 883 notification_ = new tray::NetworkNotificationView(this); | |
| 884 return notification_; | |
| 885 } | |
| 886 | |
| 887 void TrayNetwork::DestroyTrayView() { | |
| 888 tray_ = NULL; | |
| 889 } | |
| 890 | |
| 891 void TrayNetwork::DestroyDefaultView() { | |
| 892 default_ = NULL; | |
| 893 } | |
| 894 | |
| 895 void TrayNetwork::DestroyDetailedView() { | |
| 896 detailed_ = NULL; | |
| 897 } | |
| 898 | |
| 899 void TrayNetwork::DestroyNotificationView() { | |
| 900 notification_ = NULL; | |
| 901 } | |
| 902 | |
| 903 void TrayNetwork::UpdateAfterLoginStatusChange(user::LoginStatus status) { | |
| 904 } | |
| 905 | |
| 906 void TrayNetwork::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) { | |
| 907 SetTrayImageItemBorder(tray_, alignment); | |
| 908 } | |
| 909 | |
| 910 void TrayNetwork::OnNetworkRefresh(const NetworkIconInfo& info) { | |
| 911 if (tray_) | |
| 912 tray_->Update(info); | |
| 913 if (default_) | |
| 914 default_->Update(); | |
| 915 if (detailed_) | |
| 916 detailed_->Update(); | |
| 917 } | |
| 918 | |
| 919 void TrayNetwork::SetNetworkMessage(NetworkTrayDelegate* delegate, | |
| 920 MessageType message_type, | |
| 921 const string16& title, | |
| 922 const string16& message, | |
| 923 const std::vector<string16>& links) { | |
| 924 messages_->messages()[message_type] = | |
| 925 tray::NetworkMessages::Message(delegate, title, message, links); | |
| 926 if (notification_) | |
| 927 notification_->Update(); | |
| 928 else | |
| 929 ShowNotificationView(); | |
| 930 } | |
| 931 | |
| 932 void TrayNetwork::ClearNetworkMessage(MessageType message_type) { | |
| 933 messages_->messages().erase(message_type); | |
| 934 if (messages_->messages().empty()) { | |
| 935 HideNotificationView(); | |
| 936 return; | |
| 937 } | |
| 938 if (notification_) | |
| 939 notification_->Update(); | |
| 940 else | |
| 941 ShowNotificationView(); | |
| 942 } | |
| 943 | |
| 944 void TrayNetwork::OnWillToggleWifi() { | |
| 945 if (!detailed_ || detailed_->GetViewType() == WIFI_VIEW) { | |
| 946 request_wifi_view_ = true; | |
| 947 PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false); | |
| 948 } | |
| 949 } | |
| 950 | |
| 951 void TrayNetwork::LinkClicked(MessageType message_type, int link_id) { | |
| 952 tray::NetworkMessages::MessageMap::const_iterator iter = | |
| 953 messages()->messages().find(message_type); | |
| 954 if (iter != messages()->messages().end() && iter->second.delegate) | |
| 955 iter->second.delegate->NotificationLinkClicked(link_id); | |
| 956 } | |
| 957 | |
| 958 } // namespace internal | |
| 959 } // namespace ash | |
| OLD | NEW |