| Index: ash/system/network/tray_network.cc
|
| diff --git a/ash/system/network/tray_network.cc b/ash/system/network/tray_network.cc
|
| index 95e588ea584402e113d41cd5a3003f7c0b09cf22..82ef6b073d529289ec2d2bf008af09479fa07c30 100644
|
| --- a/ash/system/network/tray_network.cc
|
| +++ b/ash/system/network/tray_network.cc
|
| @@ -23,16 +23,19 @@
|
| #include "ui/gfx/font.h"
|
| #include "ui/gfx/image/image.h"
|
| #include "ui/gfx/skia_util.h"
|
| +#include "ui/views/bubble/bubble_border.h"
|
| +#include "ui/views/bubble/bubble_delegate.h"
|
| #include "ui/views/controls/button/button.h"
|
| #include "ui/views/controls/button/image_button.h"
|
| #include "ui/views/controls/image_view.h"
|
| #include "ui/views/controls/label.h"
|
| +#include "ui/views/controls/link.h"
|
| +#include "ui/views/controls/link_listener.h"
|
| #include "ui/views/controls/scroll_view.h"
|
| -#include "ui/views/layout/fill_layout.h"
|
| #include "ui/views/layout/box_layout.h"
|
| +#include "ui/views/layout/fill_layout.h"
|
| +#include "ui/views/layout/grid_layout.h"
|
| #include "ui/views/view.h"
|
| -#include "ui/views/bubble/bubble_border.h"
|
| -#include "ui/views/bubble/bubble_delegate.h"
|
| #include "ui/views/widget/widget.h"
|
|
|
| namespace {
|
| @@ -95,6 +98,32 @@ enum ColorTheme {
|
| DARK,
|
| };
|
|
|
| +class NetworkErrors {
|
| + public:
|
| + struct Message {
|
| + Message() : delegate(NULL) {}
|
| + Message(NetworkTrayDelegate* in_delegate,
|
| + const string16& in_title,
|
| + const string16& in_message,
|
| + const string16& in_link_text) :
|
| + delegate(in_delegate),
|
| + title(in_title),
|
| + message(in_message),
|
| + link_text(in_link_text) {}
|
| + NetworkTrayDelegate* delegate;
|
| + string16 title;
|
| + string16 message;
|
| + string16 link_text;
|
| + };
|
| + typedef std::map<TrayNetwork::ErrorType, Message> ErrorMap;
|
| +
|
| + ErrorMap& messages() { return messages_; }
|
| + const ErrorMap& messages() const { return messages_; }
|
| +
|
| + private:
|
| + ErrorMap messages_;
|
| +};
|
| +
|
| class NetworkTrayView : public TrayItemView {
|
| public:
|
| NetworkTrayView(ColorTheme size, bool tray_icon)
|
| @@ -517,12 +546,167 @@ class NetworkDetailedView : public TrayDetailsView,
|
| DISALLOW_COPY_AND_ASSIGN(NetworkDetailedView);
|
| };
|
|
|
| +class NetworkErrorView : public views::View,
|
| + public views::LinkListener {
|
| + public:
|
| + NetworkErrorView(TrayNetwork* tray,
|
| + TrayNetwork::ErrorType error_type,
|
| + const NetworkErrors::Message& error)
|
| + : tray_(tray),
|
| + error_type_(error_type) {
|
| + set_border(views::Border::CreateEmptyBorder(
|
| + kTrayPopupPaddingBetweenItems, kTrayPopupPaddingHorizontal,
|
| + kTrayPopupPaddingBetweenItems, kTrayPopupPaddingHorizontal));
|
| +
|
| + const int msg_width = kTrayPopupWidth - kNotificationCloseButtonWidth -
|
| + kTrayPopupPaddingHorizontal - kNotificationIconWidth;
|
| +
|
| + views::ImageView* icon = new views::ImageView;
|
| + icon->SetImage(ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
|
| + GetErrorIcon(error_type)));
|
| +
|
| + int num_rows = 0;
|
| + views::Label* title = new views::Label(error.title);
|
| + title->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| + title->SetFont(title->font().DeriveFont(0, gfx::Font::BOLD));
|
| + ++num_rows;
|
| +
|
| + views::Label* message = new views::Label(error.message);
|
| + message->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| + message->SetMultiLine(true);
|
| + message->SizeToFit(msg_width);
|
| + ++num_rows;
|
| +
|
| + views::Link* link = NULL;
|
| + if (!error.link_text.empty()) {
|
| + link = new views::Link(error.link_text);
|
| + link->set_listener(this);
|
| + link->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| + link->SetMultiLine(true);
|
| + link->SizeToFit(msg_width);
|
| + ++num_rows;
|
| + }
|
| +
|
| + views::GridLayout* layout = new views::GridLayout(this);
|
| + SetLayoutManager(layout);
|
| +
|
| + views::ColumnSet* columns = layout->AddColumnSet(0);
|
| +
|
| + // Icon
|
| + columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
|
| + 0 /* resize percent */,
|
| + views::GridLayout::FIXED,
|
| + kNotificationIconWidth, kNotificationIconWidth);
|
| +
|
| + columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal/2);
|
| +
|
| + // Title + message + link
|
| + columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
|
| + 0 /* resize percent */,
|
| + views::GridLayout::FIXED, msg_width, msg_width);
|
| +
|
| + // Layout rows
|
| + layout->AddPaddingRow(0, kTrayPopupPaddingBetweenItems);
|
| +
|
| + layout->StartRow(0, 0);
|
| + layout->AddView(icon, 1, num_rows);
|
| + layout->AddView(title);
|
| +
|
| + layout->StartRow(0, 0);
|
| + layout->SkipColumns(1);
|
| + layout->AddView(message);
|
| +
|
| + if (link) {
|
| + layout->StartRow(0, 0);
|
| + layout->SkipColumns(1);
|
| + layout->AddView(link);
|
| + }
|
| +
|
| + layout->AddPaddingRow(0, kTrayPopupPaddingBetweenItems);
|
| +
|
| + }
|
| +
|
| + virtual ~NetworkErrorView() {
|
| + }
|
| +
|
| + // Overridden from views::LinkListener.
|
| + virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE {
|
| + tray_->LinkClicked(error_type_);
|
| + }
|
| +
|
| + TrayNetwork::ErrorType error_type() const { return error_type_; }
|
| +
|
| + private:
|
| + int GetErrorIcon(TrayNetwork::ErrorType error_type) {
|
| + switch(error_type) {
|
| + case TrayNetwork::ERROR_CONNECT_FAILED:
|
| + return IDR_AURA_UBER_TRAY_NETWORK_FAILED;
|
| + case TrayNetwork::ERROR_DATA_LOW:
|
| + return IDR_AURA_UBER_TRAY_NETWORK_DATA_LOW;
|
| + case TrayNetwork::ERROR_DATA_NONE:
|
| + return IDR_AURA_UBER_TRAY_NETWORK_DATA_NONE;
|
| + }
|
| + NOTREACHED();
|
| + return 0;
|
| + }
|
| +
|
| + TrayNetwork* tray_;
|
| + TrayNetwork::ErrorType error_type_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(NetworkErrorView);
|
| +};
|
| +
|
| +class NetworkNotificationView : public TrayNotificationView {
|
| + public:
|
| + explicit NetworkNotificationView(TrayNetwork* tray)
|
| + : tray_(tray) {
|
| + CreateView();
|
| + }
|
| +
|
| + // Overridden from TrayNotificationView.
|
| + virtual void OnClose() OVERRIDE {
|
| + tray_->ClearNetworkError(network_error_view_->error_type());
|
| + }
|
| +
|
| + // Overridden from views::View.
|
| + virtual bool OnMousePressed(const views::MouseEvent& event) OVERRIDE {
|
| + tray_->PopupDetailedView(0, true);
|
| + return true;
|
| + }
|
| +
|
| + void Update() {
|
| + RemoveAllChildViews(true);
|
| + CreateView();
|
| + Layout();
|
| + PreferredSizeChanged();
|
| + SchedulePaint();
|
| + }
|
| +
|
| + private:
|
| + void CreateView() {
|
| + // Display the first (highest priority) error.
|
| + CHECK(!tray_->errors()->messages().empty());
|
| + NetworkErrors::ErrorMap::const_iterator iter =
|
| + tray_->errors()->messages().begin();
|
| + network_error_view_ =
|
| + new NetworkErrorView(tray_, iter->first, iter->second);
|
| + InitView(network_error_view_);
|
| + }
|
| +
|
| + TrayNetwork* tray_;
|
| + tray::NetworkErrorView* network_error_view_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(NetworkNotificationView);
|
| +};
|
| +
|
| } // namespace tray
|
|
|
| TrayNetwork::TrayNetwork()
|
| : tray_(NULL),
|
| default_(NULL),
|
| - detailed_(NULL) {
|
| + detailed_(NULL),
|
| + notification_(NULL),
|
| + errors_(new tray::NetworkErrors()) {
|
| }
|
|
|
| TrayNetwork::~TrayNetwork() {
|
| @@ -546,6 +730,12 @@ views::View* TrayNetwork::CreateDetailedView(user::LoginStatus status) {
|
| return detailed_;
|
| }
|
|
|
| +views::View* TrayNetwork::CreateNotificationView(user::LoginStatus status) {
|
| + CHECK(notification_ == NULL);
|
| + notification_ = new tray::NetworkNotificationView(this);
|
| + return notification_;
|
| +}
|
| +
|
| void TrayNetwork::DestroyTrayView() {
|
| tray_ = NULL;
|
| }
|
| @@ -558,6 +748,10 @@ void TrayNetwork::DestroyDetailedView() {
|
| detailed_ = NULL;
|
| }
|
|
|
| +void TrayNetwork::DestroyNotificationView() {
|
| + notification_ = NULL;
|
| +}
|
| +
|
| void TrayNetwork::UpdateAfterLoginStatusChange(user::LoginStatus status) {
|
| }
|
|
|
| @@ -570,5 +764,38 @@ void TrayNetwork::OnNetworkRefresh(const NetworkIconInfo& info) {
|
| detailed_->Update();
|
| }
|
|
|
| +void TrayNetwork::SetNetworkError(NetworkTrayDelegate* delegate,
|
| + ErrorType error_type,
|
| + const string16& title,
|
| + const string16& message,
|
| + const string16& link_text) {
|
| + errors_->messages()[error_type] =
|
| + tray::NetworkErrors::Message(delegate, title, message, link_text);
|
| + if (notification_)
|
| + notification_->Update();
|
| + else
|
| + ShowNotificationView();
|
| +}
|
| +
|
| +void TrayNetwork::ClearNetworkError(ErrorType error_type) {
|
| + errors_->messages().erase(error_type);
|
| + if (errors_->messages().empty()) {
|
| + if (notification_)
|
| + HideNotificationView();
|
| + return;
|
| + }
|
| + if (notification_)
|
| + notification_->Update();
|
| + else
|
| + ShowNotificationView();
|
| +}
|
| +
|
| +void TrayNetwork::LinkClicked(ErrorType error_type) {
|
| + tray::NetworkErrors::ErrorMap::const_iterator iter =
|
| + errors()->messages().find(error_type);
|
| + if (iter != errors()->messages().end() && iter->second.delegate)
|
| + iter->second.delegate->NotificationLinkClicked();
|
| +}
|
| +
|
| } // namespace internal
|
| } // namespace ash
|
|
|