OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "ash/system/network/tray_network.h" | 5 #include "ash/system/network/tray_network.h" |
6 | 6 |
7 #include "ash/shell.h" | 7 #include "ash/shell.h" |
8 #include "ash/shell_window_ids.h" | 8 #include "ash/shell_window_ids.h" |
9 #include "ash/system/tray/system_tray.h" | 9 #include "ash/system/tray/system_tray.h" |
10 #include "ash/system/tray/system_tray_delegate.h" | 10 #include "ash/system/tray/system_tray_delegate.h" |
11 #include "ash/system/tray/tray_constants.h" | 11 #include "ash/system/tray/tray_constants.h" |
12 #include "ash/system/tray/tray_details_view.h" | 12 #include "ash/system/tray/tray_details_view.h" |
13 #include "ash/system/tray/tray_item_more.h" | 13 #include "ash/system/tray/tray_item_more.h" |
14 #include "ash/system/tray/tray_item_view.h" | 14 #include "ash/system/tray/tray_item_view.h" |
15 #include "ash/system/tray/tray_views.h" | 15 #include "ash/system/tray/tray_views.h" |
16 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
17 #include "grit/ash_strings.h" | 17 #include "grit/ash_strings.h" |
18 #include "grit/ui_resources.h" | 18 #include "grit/ui_resources.h" |
19 #include "third_party/skia/include/core/SkColor.h" | 19 #include "third_party/skia/include/core/SkColor.h" |
20 #include "ui/aura/window.h" | 20 #include "ui/aura/window.h" |
21 #include "ui/base/resource/resource_bundle.h" | 21 #include "ui/base/resource/resource_bundle.h" |
22 #include "ui/gfx/canvas.h" | 22 #include "ui/gfx/canvas.h" |
23 #include "ui/gfx/font.h" | 23 #include "ui/gfx/font.h" |
24 #include "ui/gfx/image/image.h" | 24 #include "ui/gfx/image/image.h" |
25 #include "ui/gfx/skia_util.h" | 25 #include "ui/gfx/skia_util.h" |
| 26 #include "ui/views/bubble/bubble_border.h" |
| 27 #include "ui/views/bubble/bubble_delegate.h" |
26 #include "ui/views/controls/button/button.h" | 28 #include "ui/views/controls/button/button.h" |
27 #include "ui/views/controls/button/image_button.h" | 29 #include "ui/views/controls/button/image_button.h" |
28 #include "ui/views/controls/image_view.h" | 30 #include "ui/views/controls/image_view.h" |
29 #include "ui/views/controls/label.h" | 31 #include "ui/views/controls/label.h" |
| 32 #include "ui/views/controls/link.h" |
| 33 #include "ui/views/controls/link_listener.h" |
30 #include "ui/views/controls/scroll_view.h" | 34 #include "ui/views/controls/scroll_view.h" |
| 35 #include "ui/views/layout/box_layout.h" |
31 #include "ui/views/layout/fill_layout.h" | 36 #include "ui/views/layout/fill_layout.h" |
32 #include "ui/views/layout/box_layout.h" | 37 #include "ui/views/layout/grid_layout.h" |
33 #include "ui/views/view.h" | 38 #include "ui/views/view.h" |
34 #include "ui/views/bubble/bubble_border.h" | |
35 #include "ui/views/bubble/bubble_delegate.h" | |
36 #include "ui/views/widget/widget.h" | 39 #include "ui/views/widget/widget.h" |
37 | 40 |
38 namespace { | 41 namespace { |
39 | 42 |
40 // Height of the list of networks in the popup. | 43 // Height of the list of networks in the popup. |
41 const int kNetworkListHeight = 203; | 44 const int kNetworkListHeight = 203; |
42 | 45 |
43 // Create a label with the font size and color used in the network info bubble. | 46 // Create a label with the font size and color used in the network info bubble. |
44 views::Label* CreateInfoBubbleLabel(const string16& text) { | 47 views::Label* CreateInfoBubbleLabel(const string16& text) { |
45 const SkColor text_color = SkColorSetARGB(127, 0, 0, 0); | 48 const SkColor text_color = SkColorSetARGB(127, 0, 0, 0); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 namespace ash { | 91 namespace ash { |
89 namespace internal { | 92 namespace internal { |
90 | 93 |
91 namespace tray { | 94 namespace tray { |
92 | 95 |
93 enum ColorTheme { | 96 enum ColorTheme { |
94 LIGHT, | 97 LIGHT, |
95 DARK, | 98 DARK, |
96 }; | 99 }; |
97 | 100 |
| 101 class NetworkErrors { |
| 102 public: |
| 103 struct Message { |
| 104 Message() : delegate(NULL) {} |
| 105 Message(NetworkTrayDelegate* in_delegate, |
| 106 const string16& in_title, |
| 107 const string16& in_message, |
| 108 const string16& in_link_text) : |
| 109 delegate(in_delegate), |
| 110 title(in_title), |
| 111 message(in_message), |
| 112 link_text(in_link_text) {} |
| 113 NetworkTrayDelegate* delegate; |
| 114 string16 title; |
| 115 string16 message; |
| 116 string16 link_text; |
| 117 }; |
| 118 typedef std::map<TrayNetwork::ErrorType, Message> ErrorMap; |
| 119 |
| 120 ErrorMap& messages() { return messages_; } |
| 121 const ErrorMap& messages() const { return messages_; } |
| 122 |
| 123 private: |
| 124 ErrorMap messages_; |
| 125 }; |
| 126 |
98 class NetworkTrayView : public TrayItemView { | 127 class NetworkTrayView : public TrayItemView { |
99 public: | 128 public: |
100 NetworkTrayView(ColorTheme size, bool tray_icon) | 129 NetworkTrayView(ColorTheme size, bool tray_icon) |
101 : color_theme_(size), tray_icon_(tray_icon) { | 130 : color_theme_(size), tray_icon_(tray_icon) { |
102 SetLayoutManager(new views::FillLayout()); | 131 SetLayoutManager(new views::FillLayout()); |
103 | 132 |
104 image_view_ = color_theme_ == DARK ? | 133 image_view_ = color_theme_ == DARK ? |
105 new FixedSizedImageView(0, kTrayPopupItemHeight) : | 134 new FixedSizedImageView(0, kTrayPopupItemHeight) : |
106 new views::ImageView; | 135 new views::ImageView; |
107 AddChildView(image_view_); | 136 AddChildView(image_view_); |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 TrayPopupTextButton* other_wifi_; | 539 TrayPopupTextButton* other_wifi_; |
511 TrayPopupTextButton* other_mobile_; | 540 TrayPopupTextButton* other_mobile_; |
512 TrayPopupTextButton* settings_; | 541 TrayPopupTextButton* settings_; |
513 TrayPopupTextButton* proxy_settings_; | 542 TrayPopupTextButton* proxy_settings_; |
514 | 543 |
515 views::BubbleDelegateView* info_bubble_; | 544 views::BubbleDelegateView* info_bubble_; |
516 | 545 |
517 DISALLOW_COPY_AND_ASSIGN(NetworkDetailedView); | 546 DISALLOW_COPY_AND_ASSIGN(NetworkDetailedView); |
518 }; | 547 }; |
519 | 548 |
| 549 class NetworkErrorView : public views::View, |
| 550 public views::LinkListener { |
| 551 public: |
| 552 NetworkErrorView(TrayNetwork* tray, |
| 553 TrayNetwork::ErrorType error_type, |
| 554 const NetworkErrors::Message& error) |
| 555 : tray_(tray), |
| 556 error_type_(error_type) { |
| 557 set_border(views::Border::CreateEmptyBorder( |
| 558 kTrayPopupPaddingBetweenItems, kTrayPopupPaddingHorizontal, |
| 559 kTrayPopupPaddingBetweenItems, kTrayPopupPaddingHorizontal)); |
| 560 |
| 561 const int msg_width = kTrayPopupWidth - kNotificationCloseButtonWidth - |
| 562 kTrayPopupPaddingHorizontal - kNotificationIconWidth; |
| 563 |
| 564 views::ImageView* icon = new views::ImageView; |
| 565 icon->SetImage(ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
| 566 GetErrorIcon(error_type))); |
| 567 |
| 568 int num_rows = 0; |
| 569 views::Label* title = new views::Label(error.title); |
| 570 title->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 571 title->SetFont(title->font().DeriveFont(0, gfx::Font::BOLD)); |
| 572 ++num_rows; |
| 573 |
| 574 views::Label* message = new views::Label(error.message); |
| 575 message->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 576 message->SetMultiLine(true); |
| 577 message->SizeToFit(msg_width); |
| 578 ++num_rows; |
| 579 |
| 580 views::Link* link = NULL; |
| 581 if (!error.link_text.empty()) { |
| 582 link = new views::Link(error.link_text); |
| 583 link->set_listener(this); |
| 584 link->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 585 link->SetMultiLine(true); |
| 586 link->SizeToFit(msg_width); |
| 587 ++num_rows; |
| 588 } |
| 589 |
| 590 views::GridLayout* layout = new views::GridLayout(this); |
| 591 SetLayoutManager(layout); |
| 592 |
| 593 views::ColumnSet* columns = layout->AddColumnSet(0); |
| 594 |
| 595 // Icon |
| 596 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, |
| 597 0 /* resize percent */, |
| 598 views::GridLayout::FIXED, |
| 599 kNotificationIconWidth, kNotificationIconWidth); |
| 600 |
| 601 columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal/2); |
| 602 |
| 603 // Title + message + link |
| 604 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, |
| 605 0 /* resize percent */, |
| 606 views::GridLayout::FIXED, msg_width, msg_width); |
| 607 |
| 608 // Layout rows |
| 609 layout->AddPaddingRow(0, kTrayPopupPaddingBetweenItems); |
| 610 |
| 611 layout->StartRow(0, 0); |
| 612 layout->AddView(icon, 1, num_rows); |
| 613 layout->AddView(title); |
| 614 |
| 615 layout->StartRow(0, 0); |
| 616 layout->SkipColumns(1); |
| 617 layout->AddView(message); |
| 618 |
| 619 if (link) { |
| 620 layout->StartRow(0, 0); |
| 621 layout->SkipColumns(1); |
| 622 layout->AddView(link); |
| 623 } |
| 624 |
| 625 layout->AddPaddingRow(0, kTrayPopupPaddingBetweenItems); |
| 626 |
| 627 } |
| 628 |
| 629 virtual ~NetworkErrorView() { |
| 630 } |
| 631 |
| 632 // Overridden from views::LinkListener. |
| 633 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE { |
| 634 tray_->LinkClicked(error_type_); |
| 635 } |
| 636 |
| 637 TrayNetwork::ErrorType error_type() const { return error_type_; } |
| 638 |
| 639 private: |
| 640 int GetErrorIcon(TrayNetwork::ErrorType error_type) { |
| 641 switch(error_type) { |
| 642 case TrayNetwork::ERROR_CONNECT_FAILED: |
| 643 return IDR_AURA_UBER_TRAY_NETWORK_FAILED; |
| 644 case TrayNetwork::ERROR_DATA_LOW: |
| 645 return IDR_AURA_UBER_TRAY_NETWORK_DATA_LOW; |
| 646 case TrayNetwork::ERROR_DATA_NONE: |
| 647 return IDR_AURA_UBER_TRAY_NETWORK_DATA_NONE; |
| 648 } |
| 649 NOTREACHED(); |
| 650 return 0; |
| 651 } |
| 652 |
| 653 TrayNetwork* tray_; |
| 654 TrayNetwork::ErrorType error_type_; |
| 655 |
| 656 DISALLOW_COPY_AND_ASSIGN(NetworkErrorView); |
| 657 }; |
| 658 |
| 659 class NetworkNotificationView : public TrayNotificationView { |
| 660 public: |
| 661 explicit NetworkNotificationView(TrayNetwork* tray) |
| 662 : tray_(tray) { |
| 663 CreateView(); |
| 664 } |
| 665 |
| 666 // Overridden from TrayNotificationView. |
| 667 virtual void OnClose() OVERRIDE { |
| 668 tray_->ClearNetworkError(network_error_view_->error_type()); |
| 669 } |
| 670 |
| 671 // Overridden from views::View. |
| 672 virtual bool OnMousePressed(const views::MouseEvent& event) OVERRIDE { |
| 673 tray_->PopupDetailedView(0, true); |
| 674 return true; |
| 675 } |
| 676 |
| 677 void Update() { |
| 678 RemoveAllChildViews(true); |
| 679 CreateView(); |
| 680 Layout(); |
| 681 PreferredSizeChanged(); |
| 682 SchedulePaint(); |
| 683 } |
| 684 |
| 685 private: |
| 686 void CreateView() { |
| 687 // Display the first (highest priority) error. |
| 688 CHECK(!tray_->errors()->messages().empty()); |
| 689 NetworkErrors::ErrorMap::const_iterator iter = |
| 690 tray_->errors()->messages().begin(); |
| 691 network_error_view_ = |
| 692 new NetworkErrorView(tray_, iter->first, iter->second); |
| 693 InitView(network_error_view_); |
| 694 } |
| 695 |
| 696 TrayNetwork* tray_; |
| 697 tray::NetworkErrorView* network_error_view_; |
| 698 |
| 699 DISALLOW_COPY_AND_ASSIGN(NetworkNotificationView); |
| 700 }; |
| 701 |
520 } // namespace tray | 702 } // namespace tray |
521 | 703 |
522 TrayNetwork::TrayNetwork() | 704 TrayNetwork::TrayNetwork() |
523 : tray_(NULL), | 705 : tray_(NULL), |
524 default_(NULL), | 706 default_(NULL), |
525 detailed_(NULL) { | 707 detailed_(NULL), |
| 708 notification_(NULL), |
| 709 errors_(new tray::NetworkErrors()) { |
526 } | 710 } |
527 | 711 |
528 TrayNetwork::~TrayNetwork() { | 712 TrayNetwork::~TrayNetwork() { |
529 } | 713 } |
530 | 714 |
531 views::View* TrayNetwork::CreateTrayView(user::LoginStatus status) { | 715 views::View* TrayNetwork::CreateTrayView(user::LoginStatus status) { |
532 CHECK(tray_ == NULL); | 716 CHECK(tray_ == NULL); |
533 tray_ = new tray::NetworkTrayView(tray::LIGHT, true /*tray_icon*/); | 717 tray_ = new tray::NetworkTrayView(tray::LIGHT, true /*tray_icon*/); |
534 return tray_; | 718 return tray_; |
535 } | 719 } |
536 | 720 |
537 views::View* TrayNetwork::CreateDefaultView(user::LoginStatus status) { | 721 views::View* TrayNetwork::CreateDefaultView(user::LoginStatus status) { |
538 CHECK(default_ == NULL); | 722 CHECK(default_ == NULL); |
539 default_ = new tray::NetworkDefaultView(this); | 723 default_ = new tray::NetworkDefaultView(this); |
540 return default_; | 724 return default_; |
541 } | 725 } |
542 | 726 |
543 views::View* TrayNetwork::CreateDetailedView(user::LoginStatus status) { | 727 views::View* TrayNetwork::CreateDetailedView(user::LoginStatus status) { |
544 CHECK(detailed_ == NULL); | 728 CHECK(detailed_ == NULL); |
545 detailed_ = new tray::NetworkDetailedView(status); | 729 detailed_ = new tray::NetworkDetailedView(status); |
546 return detailed_; | 730 return detailed_; |
547 } | 731 } |
548 | 732 |
| 733 views::View* TrayNetwork::CreateNotificationView(user::LoginStatus status) { |
| 734 CHECK(notification_ == NULL); |
| 735 notification_ = new tray::NetworkNotificationView(this); |
| 736 return notification_; |
| 737 } |
| 738 |
549 void TrayNetwork::DestroyTrayView() { | 739 void TrayNetwork::DestroyTrayView() { |
550 tray_ = NULL; | 740 tray_ = NULL; |
551 } | 741 } |
552 | 742 |
553 void TrayNetwork::DestroyDefaultView() { | 743 void TrayNetwork::DestroyDefaultView() { |
554 default_ = NULL; | 744 default_ = NULL; |
555 } | 745 } |
556 | 746 |
557 void TrayNetwork::DestroyDetailedView() { | 747 void TrayNetwork::DestroyDetailedView() { |
558 detailed_ = NULL; | 748 detailed_ = NULL; |
559 } | 749 } |
560 | 750 |
| 751 void TrayNetwork::DestroyNotificationView() { |
| 752 notification_ = NULL; |
| 753 } |
| 754 |
561 void TrayNetwork::UpdateAfterLoginStatusChange(user::LoginStatus status) { | 755 void TrayNetwork::UpdateAfterLoginStatusChange(user::LoginStatus status) { |
562 } | 756 } |
563 | 757 |
564 void TrayNetwork::OnNetworkRefresh(const NetworkIconInfo& info) { | 758 void TrayNetwork::OnNetworkRefresh(const NetworkIconInfo& info) { |
565 if (tray_) | 759 if (tray_) |
566 tray_->Update(info); | 760 tray_->Update(info); |
567 if (default_) | 761 if (default_) |
568 default_->Update(); | 762 default_->Update(); |
569 if (detailed_) | 763 if (detailed_) |
570 detailed_->Update(); | 764 detailed_->Update(); |
571 } | 765 } |
572 | 766 |
| 767 void TrayNetwork::SetNetworkError(NetworkTrayDelegate* delegate, |
| 768 ErrorType error_type, |
| 769 const string16& title, |
| 770 const string16& message, |
| 771 const string16& link_text) { |
| 772 errors_->messages()[error_type] = |
| 773 tray::NetworkErrors::Message(delegate, title, message, link_text); |
| 774 if (notification_) |
| 775 notification_->Update(); |
| 776 else |
| 777 ShowNotificationView(); |
| 778 } |
| 779 |
| 780 void TrayNetwork::ClearNetworkError(ErrorType error_type) { |
| 781 errors_->messages().erase(error_type); |
| 782 if (errors_->messages().empty()) { |
| 783 if (notification_) |
| 784 HideNotificationView(); |
| 785 return; |
| 786 } |
| 787 if (notification_) |
| 788 notification_->Update(); |
| 789 else |
| 790 ShowNotificationView(); |
| 791 } |
| 792 |
| 793 void TrayNetwork::LinkClicked(ErrorType error_type) { |
| 794 tray::NetworkErrors::ErrorMap::const_iterator iter = |
| 795 errors()->messages().find(error_type); |
| 796 if (iter != errors()->messages().end() && iter->second.delegate) |
| 797 iter->second.delegate->NotificationLinkClicked(); |
| 798 } |
| 799 |
573 } // namespace internal | 800 } // namespace internal |
574 } // namespace ash | 801 } // namespace ash |
OLD | NEW |