blob: 8e750d7f974a76d8cff9d80bf38df99895759cc2 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/network/tray_network.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/system/tray/system_tray.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/tray_constants.h"
#include "ash/system/tray/tray_details_view.h"
#include "ash/system/tray/tray_item_more.h"
#include "ash/system/tray/tray_item_view.h"
#include "ash/system/tray/tray_notification_view.h"
#include "ash/system/tray/tray_views.h"
#include "base/utf_string_conversions.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#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/box_layout.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
namespace {
// Height of the list of networks in the popup.
const int kNetworkListHeight = 203;
// Create a label with the font size and color used in the network info bubble.
views::Label* CreateInfoBubbleLabel(const string16& text) {
const SkColor text_color = SkColorSetARGB(127, 0, 0, 0);
views::Label* label = new views::Label(text);
label->SetFont(label->font().DeriveFont(-1));
label->SetEnabledColor(text_color);
return label;
}
// Create a row of labels for the network info bubble.
views::View* CreateInfoBubbleLine(const string16& text_label,
const std::string& text_string) {
views::View* view = new views::View;
view->SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 1));
view->AddChildView(CreateInfoBubbleLabel(text_label));
view->AddChildView(CreateInfoBubbleLabel(UTF8ToUTF16(": ")));
view->AddChildView(CreateInfoBubbleLabel(UTF8ToUTF16(text_string)));
return view;
}
// A bubble that cannot be activated.
class NonActivatableSettingsBubble : public views::BubbleDelegateView {
public:
NonActivatableSettingsBubble(views::View* anchor, views::View* content)
: views::BubbleDelegateView(anchor, views::BubbleBorder::TOP_RIGHT) {
set_use_focusless(true);
set_parent_window(ash::Shell::GetContainer(
anchor->GetWidget()->GetNativeWindow()->GetRootWindow(),
ash::internal::kShellWindowId_SettingBubbleContainer));
SetLayoutManager(new views::FillLayout());
AddChildView(content);
}
virtual ~NonActivatableSettingsBubble() {}
virtual bool CanActivate() const OVERRIDE {
return false;
}
private:
DISALLOW_COPY_AND_ASSIGN(NonActivatableSettingsBubble);
};
using ash::internal::TrayNetwork;
int GetMessageIcon(TrayNetwork::MessageType message_type) {
switch(message_type) {
case TrayNetwork::ERROR_CONNECT_FAILED:
return IDR_AURA_UBER_TRAY_NETWORK_FAILED;
case TrayNetwork::MESSAGE_DATA_LOW:
return IDR_AURA_UBER_TRAY_NETWORK_DATA_LOW;
case TrayNetwork::MESSAGE_DATA_NONE:
return IDR_AURA_UBER_TRAY_NETWORK_DATA_NONE;
case TrayNetwork::MESSAGE_DATA_PROMO:
return IDR_AURA_UBER_TRAY_NOTIFICATION_3G;
}
NOTREACHED();
return 0;
}
} // namespace
namespace ash {
namespace internal {
namespace tray {
enum ColorTheme {
LIGHT,
DARK,
};
class NetworkMessages {
public:
struct Message {
Message() : delegate(NULL) {}
Message(NetworkTrayDelegate* in_delegate,
const string16& in_title,
const string16& in_message,
const std::vector<string16>& in_links) :
delegate(in_delegate),
title(in_title),
message(in_message),
links(in_links) {}
NetworkTrayDelegate* delegate;
string16 title;
string16 message;
std::vector<string16> links;
};
typedef std::map<TrayNetwork::MessageType, Message> MessageMap;
MessageMap& messages() { return messages_; }
const MessageMap& messages() const { return messages_; }
private:
MessageMap messages_;
};
class NetworkTrayView : public TrayItemView {
public:
NetworkTrayView(ColorTheme size, bool tray_icon)
: color_theme_(size), tray_icon_(tray_icon) {
SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
image_view_ = color_theme_ == DARK ?
new FixedSizedImageView(0, kTrayPopupItemHeight) :
new views::ImageView;
AddChildView(image_view_);
NetworkIconInfo info;
Shell::GetInstance()->tray_delegate()->
GetMostRelevantNetworkIcon(&info, false);
Update(info);
}
virtual ~NetworkTrayView() {}
void Update(const NetworkIconInfo& info) {
image_view_->SetImage(info.image);
if (tray_icon_)
SetVisible(info.tray_icon_visible);
SchedulePaint();
}
private:
views::ImageView* image_view_;
ColorTheme color_theme_;
bool tray_icon_;
DISALLOW_COPY_AND_ASSIGN(NetworkTrayView);
};
class NetworkDefaultView : public TrayItemMore {
public:
explicit NetworkDefaultView(SystemTrayItem* owner)
: TrayItemMore(owner) {
Update();
}
virtual ~NetworkDefaultView() {}
void Update() {
NetworkIconInfo info;
Shell::GetInstance()->tray_delegate()->
GetMostRelevantNetworkIcon(&info, true);
SetImage(&info.image);
SetLabel(info.description);
SetAccessibleName(info.description);
}
private:
DISALLOW_COPY_AND_ASSIGN(NetworkDefaultView);
};
class NetworkDetailedView : public TrayDetailsView {
public:
NetworkDetailedView() {}
virtual ~NetworkDetailedView() {}
virtual TrayNetwork::DetailedViewType GetViewType() const = 0;
virtual void Update() = 0;
};
class NetworkListDetailedView : public NetworkDetailedView,
public views::ButtonListener,
public ViewClickListener {
public:
NetworkListDetailedView(user::LoginStatus login)
: login_(login),
airplane_(NULL),
info_icon_(NULL),
button_wifi_(NULL),
button_mobile_(NULL),
view_mobile_account_(NULL),
setup_mobile_account_(NULL),
other_wifi_(NULL),
turn_on_wifi_(NULL),
other_mobile_(NULL),
settings_(NULL),
proxy_settings_(NULL),
info_bubble_(NULL) {
SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate();
delegate->RequestNetworkScan();
CreateItems();
Update();
}
virtual ~NetworkListDetailedView() {
if (info_bubble_)
info_bubble_->GetWidget()->CloseNow();
}
void CreateItems() {
RemoveAllChildViews(true);
airplane_ = NULL;
info_icon_ = NULL;
button_wifi_ = NULL;
button_mobile_ = NULL;
view_mobile_account_ = NULL;
setup_mobile_account_ = NULL;
other_wifi_ = NULL;
turn_on_wifi_ = NULL;
other_mobile_ = NULL;
settings_ = NULL;
proxy_settings_ = NULL;
AppendNetworkEntries();
AppendNetworkExtra();
AppendHeaderEntry();
AppendHeaderButtons();
Update();
}
// Overridden from NetworkDetailedView:
virtual TrayNetwork::DetailedViewType GetViewType() const OVERRIDE {
return TrayNetwork::LIST_VIEW;
}
virtual void Update() OVERRIDE {
UpdateAvailableNetworkList();
UpdateHeaderButtons();
UpdateNetworkEntries();
UpdateNetworkExtra();
Layout();
}
private:
void AppendHeaderEntry() {
CreateSpecialRow(IDS_ASH_STATUS_TRAY_NETWORK, this);
}
void AppendHeaderButtons() {
button_wifi_ = new TrayPopupHeaderButton(this,
IDR_AURA_UBER_TRAY_WIFI_ENABLED,
IDR_AURA_UBER_TRAY_WIFI_DISABLED,
IDR_AURA_UBER_TRAY_WIFI_ENABLED_HOVER,
IDR_AURA_UBER_TRAY_WIFI_DISABLED_HOVER,
IDS_ASH_STATUS_TRAY_WIFI);
button_wifi_->SetTooltipText(
l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISABLE_WIFI));
button_wifi_->SetToggledTooltipText(
l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ENABLE_WIFI));
footer()->AddButton(button_wifi_);
button_mobile_ = new TrayPopupHeaderButton(this,
IDR_AURA_UBER_TRAY_CELLULAR_ENABLED,
IDR_AURA_UBER_TRAY_CELLULAR_DISABLED,
IDR_AURA_UBER_TRAY_CELLULAR_ENABLED_HOVER,
IDR_AURA_UBER_TRAY_CELLULAR_DISABLED_HOVER,
IDS_ASH_STATUS_TRAY_CELLULAR);
button_mobile_->SetTooltipText(
l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISABLE_MOBILE));
button_mobile_->SetToggledTooltipText(
l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ENABLE_MOBILE));
footer()->AddButton(button_mobile_);
info_icon_ = new TrayPopupHeaderButton(this,
IDR_AURA_UBER_TRAY_NETWORK_INFO,
IDR_AURA_UBER_TRAY_NETWORK_INFO,
IDR_AURA_UBER_TRAY_NETWORK_INFO_HOVER,
IDR_AURA_UBER_TRAY_NETWORK_INFO_HOVER,
IDS_ASH_STATUS_TRAY_NETWORK_INFO);
info_icon_->SetTooltipText(
l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_INFO));
footer()->AddButton(info_icon_);
}
void UpdateHeaderButtons() {
SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate();
button_wifi_->SetToggled(!delegate->GetWifiEnabled());
button_mobile_->SetToggled(!delegate->GetMobileEnabled());
button_mobile_->SetVisible(delegate->GetMobileAvailable());
if (proxy_settings_)
proxy_settings_->SetEnabled(delegate->IsNetworkConnected());
}
void AppendNetworkEntries() {
CreateScrollableList();
HoverHighlightView* container = new HoverHighlightView(this);
container->set_fixed_height(kTrayPopupItemHeight);
container->AddLabel(ui::ResourceBundle::GetSharedInstance().
GetLocalizedString(IDS_ASH_STATUS_TRAY_MOBILE_VIEW_ACCOUNT),
gfx::Font::NORMAL);
AddChildView(container);
view_mobile_account_ = container;
container = new HoverHighlightView(this);
container->set_fixed_height(kTrayPopupItemHeight);
container->AddLabel(ui::ResourceBundle::GetSharedInstance().
GetLocalizedString(IDS_ASH_STATUS_TRAY_SETUP_MOBILE),
gfx::Font::NORMAL);
AddChildView(container);
setup_mobile_account_ = container;
}
void UpdateAvailableNetworkList() {
network_list_.clear();
Shell::GetInstance()->tray_delegate()->GetAvailableNetworks(&network_list_);
}
void RefreshNetworkScrollWithUpdatedNetworkList() {
network_map_.clear();
std::set<std::string> new_service_paths;
bool needs_relayout = false;
views::View* highlighted_view = NULL;
if (service_path_map_.empty())
scroll_content()->RemoveAllChildViews(true);
for (size_t i = 0; i < network_list_.size(); ++i) {
std::map<std::string, HoverHighlightView*>::const_iterator it =
service_path_map_.find(network_list_[i].service_path);
HoverHighlightView* container = NULL;
if (it == service_path_map_.end()) {
// Create a new view.
container = new HoverHighlightView(this);
container->set_fixed_height(kTrayPopupItemHeight);
container->AddIconAndLabel(network_list_[i].image,
network_list_[i].description.empty() ?
network_list_[i].name : network_list_[i].description,
network_list_[i].highlight ?
gfx::Font::BOLD : gfx::Font::NORMAL);
scroll_content()->AddChildViewAt(container, i);
container->set_border(views::Border::CreateEmptyBorder(0,
kTrayPopupPaddingHorizontal, 0, 0));
needs_relayout = true;
} else {
container = it->second;
container->RemoveAllChildViews(true);
container->AddIconAndLabel(network_list_[i].image,
network_list_[i].description.empty() ?
network_list_[i].name : network_list_[i].description,
network_list_[i].highlight ? gfx::Font::BOLD : gfx::Font::NORMAL);
container->Layout();
container->SchedulePaint();
// Reordering the view if necessary.
views::View* child = scroll_content()->child_at(i);
if (child != container) {
scroll_content()->ReorderChildView(container, i);
needs_relayout = true;
}
}
if (network_list_[i].highlight)
highlighted_view = container;
network_map_[container] = network_list_[i].service_path;
service_path_map_[network_list_[i].service_path] = container;
new_service_paths.insert(network_list_[i].service_path);
}
std::set<std::string> remove_service_paths;
for (std::map<std::string, HoverHighlightView*>::const_iterator it =
service_path_map_.begin(); it != service_path_map_.end(); ++it) {
if (new_service_paths.find(it->first) == new_service_paths.end()) {
remove_service_paths.insert(it->first);
scroll_content()->RemoveChildView(it->second);
needs_relayout = true;
}
}
for (std::set<std::string>::const_iterator remove_it =
remove_service_paths.begin();
remove_it != remove_service_paths.end(); ++remove_it) {
service_path_map_.erase(*remove_it);
}
if (needs_relayout) {
scroll_content()->SizeToPreferredSize();
static_cast<views::View*>(scroller())->Layout();
if (highlighted_view)
scroll_content()->ScrollRectToVisible(highlighted_view->bounds());
}
}
void RefreshNetworkScrollWithEmptyNetworkList() {
service_path_map_.clear();
network_map_.clear();
scroll_content()->RemoveAllChildViews(true);
HoverHighlightView* container = new HoverHighlightView(this);
container->set_fixed_height(kTrayPopupItemHeight);
if (Shell::GetInstance()->tray_delegate()->GetWifiEnabled()) {
NetworkIconInfo info;
Shell::GetInstance()->tray_delegate()->
GetMostRelevantNetworkIcon(&info, true);
container->AddIconAndLabel(info.image,
info.description,
gfx::Font::NORMAL);
container->set_border(views::Border::CreateEmptyBorder(0,
kTrayPopupPaddingHorizontal, 0, 0));
} else {
container->AddLabel(ui::ResourceBundle::GetSharedInstance().
GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED),
gfx::Font::NORMAL);
}
scroll_content()->AddChildViewAt(container, 0);
scroll_content()->SizeToPreferredSize();
static_cast<views::View*>(scroller())->Layout();
}
void UpdateNetworkEntries() {
if (network_list_.size() > 0 )
RefreshNetworkScrollWithUpdatedNetworkList();
else
RefreshNetworkScrollWithEmptyNetworkList();
view_mobile_account_->SetVisible(false);
setup_mobile_account_->SetVisible(false);
if (login_ == user::LOGGED_IN_NONE)
return;
std::string carrier_id, topup_url, setup_url;
if (Shell::GetInstance()->tray_delegate()->
GetCellularCarrierInfo(&carrier_id,
&topup_url,
&setup_url)) {
if (carrier_id != carrier_id_) {
carrier_id_ = carrier_id;
if (!topup_url.empty())
topup_url_ = topup_url;
}
if (!setup_url.empty())
setup_url_ = setup_url;
if (!topup_url_.empty())
view_mobile_account_->SetVisible(true);
if (!setup_url_.empty())
setup_mobile_account_->SetVisible(true);
}
}
void AppendNetworkExtra() {
if (login_ == user::LOGGED_IN_LOCKED)
return;
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
TrayPopupTextButtonContainer* bottom_row =
new TrayPopupTextButtonContainer;
other_wifi_ = new TrayPopupTextButton(this,
rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_OTHER_WIFI));
bottom_row->AddTextButton(other_wifi_);
turn_on_wifi_ = new TrayPopupTextButton(this,
rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_TURN_ON_WIFI));
bottom_row->AddTextButton(turn_on_wifi_);
other_mobile_ = new TrayPopupTextButton(this,
rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_OTHER_MOBILE));
bottom_row->AddTextButton(other_mobile_);
CreateSettingsEntry();
DCHECK(settings_ || proxy_settings_);
bottom_row->AddTextButton(settings_ ? settings_ : proxy_settings_);
AddChildView(bottom_row);
}
void UpdateNetworkExtra() {
if (login_ == user::LOGGED_IN_LOCKED)
return;
SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate();
if (network_list_.size() == 0 && !delegate->GetWifiEnabled()) {
turn_on_wifi_->SetVisible(true);
other_wifi_->SetVisible(false);
} else {
turn_on_wifi_->SetVisible(false);
other_wifi_->SetVisible(true);
other_wifi_->SetEnabled(delegate->GetWifiEnabled());
}
other_mobile_->SetVisible(delegate->GetMobileAvailable() &&
delegate->GetMobileScanSupported());
if (other_mobile_->visible())
other_mobile_->SetEnabled(delegate->GetMobileEnabled());
turn_on_wifi_->parent()->Layout();
}
// Adds a settings entry when logged in, and an entry for changing proxy
// settings otherwise.
void CreateSettingsEntry() {
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
if (login_ != user::LOGGED_IN_NONE) {
// Settings, only if logged in.
settings_ = new TrayPopupTextButton(this,
rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS));
} else {
proxy_settings_ = new TrayPopupTextButton(this,
rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_PROXY_SETTINGS));
}
}
views::View* CreateNetworkInfoView() {
ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
std::string ip_address, ethernet_address, wifi_address;
Shell::GetInstance()->tray_delegate()->GetNetworkAddresses(&ip_address,
&ethernet_address, &wifi_address);
views::View* container = new views::View;
container->SetLayoutManager(new
views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
container->set_border(views::Border::CreateEmptyBorder(0, 5, 0, 5));
// GetNetworkAddresses returns empty strings if no information is available.
if (!ip_address.empty()) {
container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString(
IDS_ASH_STATUS_TRAY_IP), ip_address));
}
if (!ethernet_address.empty()) {
container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString(
IDS_ASH_STATUS_TRAY_ETHERNET), ethernet_address));
}
if (!wifi_address.empty()) {
container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString(
IDS_ASH_STATUS_TRAY_WIFI), wifi_address));
}
// Avoid an empty bubble in the unlikely event that there is no network
// information at all.
if (!container->has_children()) {
container->AddChildView(CreateInfoBubbleLabel(bundle.GetLocalizedString(
IDS_ASH_STATUS_TRAY_NO_NETWORKS)));
}
return container;
}
void ToggleInfoBubble() {
if (ResetInfoBubble())
return;
info_bubble_ = new NonActivatableSettingsBubble(
info_icon_, CreateNetworkInfoView());
views::BubbleDelegateView::CreateBubble(info_bubble_);
info_bubble_->Show();
}
// Returns whether an existing info-bubble was closed.
bool ResetInfoBubble() {
if (!info_bubble_)
return false;
info_bubble_->GetWidget()->Close();
info_bubble_ = NULL;
return true;
}
// Overridden from ButtonListener.
virtual void ButtonPressed(views::Button* sender,
const ui::Event& event) OVERRIDE {
ash::SystemTrayDelegate* delegate =
ash::Shell::GetInstance()->tray_delegate();
if (sender == info_icon_) {
ToggleInfoBubble();
return;
}
// If the info bubble was visible, close it when some other item is clicked
// on.
ResetInfoBubble();
if (sender == button_wifi_)
delegate->ToggleWifi();
else if (sender == button_mobile_)
delegate->ToggleMobile();
else if (sender == settings_)
delegate->ShowNetworkSettings();
else if (sender == proxy_settings_)
delegate->ChangeProxySettings();
else if (sender == other_mobile_)
delegate->ShowOtherCellular();
else if (sender == other_wifi_)
delegate->ShowOtherWifi();
else if (sender == turn_on_wifi_)
delegate->ToggleWifi();
else
NOTREACHED();
}
// Overridden from ViewClickListener.
virtual void ClickedOn(views::View* sender) OVERRIDE {
ash::SystemTrayDelegate* delegate =
ash::Shell::GetInstance()->tray_delegate();
// If the info bubble was visible, close it when some other item is clicked
// on.
ResetInfoBubble();
if (sender == footer()->content()) {
Shell::GetInstance()->system_tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
return;
}
if (login_ == user::LOGGED_IN_LOCKED)
return;
if (sender == view_mobile_account_) {
delegate->ShowCellularURL(topup_url_);
} else if (sender == setup_mobile_account_) {
delegate->ShowCellularURL(setup_url_);
} else if (sender == airplane_) {
delegate->ToggleAirplaneMode();
} else {
std::map<views::View*, std::string>::iterator find;
find = network_map_.find(sender);
if (find != network_map_.end()) {
std::string network_id = find->second;
delegate->ConnectToNetwork(network_id);
}
}
}
std::string carrier_id_;
std::string topup_url_;
std::string setup_url_;
user::LoginStatus login_;
std::map<views::View*, std::string> network_map_;
std::map<std::string, HoverHighlightView*> service_path_map_;
std::vector<NetworkIconInfo> network_list_;
views::View* airplane_;
TrayPopupHeaderButton* info_icon_;
TrayPopupHeaderButton* button_wifi_;
TrayPopupHeaderButton* button_mobile_;
views::View* view_mobile_account_;
views::View* setup_mobile_account_;
TrayPopupTextButton* other_wifi_;
TrayPopupTextButton* turn_on_wifi_;
TrayPopupTextButton* other_mobile_;
TrayPopupTextButton* settings_;
TrayPopupTextButton* proxy_settings_;
views::BubbleDelegateView* info_bubble_;
DISALLOW_COPY_AND_ASSIGN(NetworkListDetailedView);
};
class NetworkWifiDetailedView : public NetworkDetailedView {
public:
explicit NetworkWifiDetailedView(bool wifi_enabled) {
SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
kTrayPopupPaddingHorizontal,
10,
kTrayPopupPaddingBetweenItems));
ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
views::ImageView* image = new views::ImageView;
const int image_id = wifi_enabled ?
IDR_AURA_UBER_TRAY_WIFI_ENABLED : IDR_AURA_UBER_TRAY_WIFI_DISABLED;
image->SetImage(bundle.GetImageNamed(image_id).ToImageSkia());
AddChildView(image);
const int string_id = wifi_enabled ?
IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED:
IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED;
views::Label* label =
new views::Label(bundle.GetLocalizedString(string_id));
label->SetMultiLine(true);
label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
AddChildView(label);
}
virtual ~NetworkWifiDetailedView() {}
// Overridden from NetworkDetailedView:
virtual TrayNetwork::DetailedViewType GetViewType() const OVERRIDE {
return TrayNetwork::WIFI_VIEW;
}
virtual void Update() OVERRIDE {}
private:
DISALLOW_COPY_AND_ASSIGN(NetworkWifiDetailedView);
};
class NetworkMessageView : public views::View,
public views::LinkListener {
public:
NetworkMessageView(TrayNetwork* tray,
TrayNetwork::MessageType message_type,
const NetworkMessages::Message& network_msg)
: tray_(tray),
message_type_(message_type) {
SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
if (!network_msg.title.empty()) {
views::Label* title = new views::Label(network_msg.title);
title->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
title->SetFont(title->font().DeriveFont(0, gfx::Font::BOLD));
AddChildView(title);
}
if (!network_msg.message.empty()) {
views::Label* message = new views::Label(network_msg.message);
message->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
message->SetMultiLine(true);
message->SizeToFit(kTrayNotificationContentsWidth);
AddChildView(message);
}
if (!network_msg.links.empty()) {
for (size_t i = 0; i < network_msg.links.size(); ++i) {
views::Link* link = new views::Link(network_msg.links[i]);
link->set_id(i);
link->set_listener(this);
link->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
link->SetMultiLine(true);
link->SizeToFit(kTrayNotificationContentsWidth);
AddChildView(link);
}
}
}
virtual ~NetworkMessageView() {
}
// Overridden from views::LinkListener.
virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE {
tray_->LinkClicked(message_type_, source->id());
}
TrayNetwork::MessageType message_type() const { return message_type_; }
private:
TrayNetwork* tray_;
TrayNetwork::MessageType message_type_;
DISALLOW_COPY_AND_ASSIGN(NetworkMessageView);
};
class NetworkNotificationView : public TrayNotificationView {
public:
explicit NetworkNotificationView(TrayNetwork* tray)
: TrayNotificationView(tray, 0) {
CreateMessageView();
InitView(network_message_view_);
SetIconImage(*ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
GetMessageIcon(network_message_view_->message_type())));
}
// Overridden from TrayNotificationView.
virtual void OnClose() OVERRIDE {
tray_network()->ClearNetworkMessage(network_message_view_->message_type());
}
virtual void OnClickAction() OVERRIDE {
if (network_message_view_->message_type() !=
TrayNetwork::MESSAGE_DATA_PROMO)
tray()->PopupDetailedView(0, true);
}
void Update() {
CreateMessageView();
UpdateViewAndImage(network_message_view_,
*ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
GetMessageIcon(network_message_view_->message_type())));
}
private:
TrayNetwork* tray_network() {
return static_cast<TrayNetwork*>(tray());
}
void CreateMessageView() {
// Display the first (highest priority) message.
CHECK(!tray_network()->messages()->messages().empty());
NetworkMessages::MessageMap::const_iterator iter =
tray_network()->messages()->messages().begin();
network_message_view_ =
new NetworkMessageView(tray_network(), iter->first, iter->second);
}
tray::NetworkMessageView* network_message_view_;
DISALLOW_COPY_AND_ASSIGN(NetworkNotificationView);
};
} // namespace tray
TrayNetwork::TrayNetwork()
: tray_(NULL),
default_(NULL),
detailed_(NULL),
notification_(NULL),
messages_(new tray::NetworkMessages()),
request_wifi_view_(false) {
}
TrayNetwork::~TrayNetwork() {
}
views::View* TrayNetwork::CreateTrayView(user::LoginStatus status) {
CHECK(tray_ == NULL);
tray_ = new tray::NetworkTrayView(tray::LIGHT, true /*tray_icon*/);
return tray_;
}
views::View* TrayNetwork::CreateDefaultView(user::LoginStatus status) {
CHECK(default_ == NULL);
default_ = new tray::NetworkDefaultView(this);
return default_;
}
views::View* TrayNetwork::CreateDetailedView(user::LoginStatus status) {
CHECK(detailed_ == NULL);
if (request_wifi_view_) {
SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate();
// The Wi-Fi state is not toggled yet at this point.
detailed_ = new tray::NetworkWifiDetailedView(!delegate->GetWifiEnabled());
request_wifi_view_ = false;
} else {
detailed_ = new tray::NetworkListDetailedView(status);
}
return detailed_;
}
views::View* TrayNetwork::CreateNotificationView(user::LoginStatus status) {
CHECK(notification_ == NULL);
if (messages_->messages().empty())
return NULL; // Message has already been cleared.
notification_ = new tray::NetworkNotificationView(this);
return notification_;
}
void TrayNetwork::DestroyTrayView() {
tray_ = NULL;
}
void TrayNetwork::DestroyDefaultView() {
default_ = NULL;
}
void TrayNetwork::DestroyDetailedView() {
detailed_ = NULL;
}
void TrayNetwork::DestroyNotificationView() {
notification_ = NULL;
}
void TrayNetwork::UpdateAfterLoginStatusChange(user::LoginStatus status) {
}
void TrayNetwork::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
SetTrayImageItemBorder(tray_, alignment);
}
void TrayNetwork::OnNetworkRefresh(const NetworkIconInfo& info) {
if (tray_)
tray_->Update(info);
if (default_)
default_->Update();
if (detailed_)
detailed_->Update();
}
void TrayNetwork::SetNetworkMessage(NetworkTrayDelegate* delegate,
MessageType message_type,
const string16& title,
const string16& message,
const std::vector<string16>& links) {
messages_->messages()[message_type] =
tray::NetworkMessages::Message(delegate, title, message, links);
if (notification_)
notification_->Update();
else
ShowNotificationView();
}
void TrayNetwork::ClearNetworkMessage(MessageType message_type) {
messages_->messages().erase(message_type);
if (messages_->messages().empty()) {
if (notification_)
HideNotificationView();
return;
}
if (notification_)
notification_->Update();
else
ShowNotificationView();
}
void TrayNetwork::OnWillToggleWifi() {
if (!detailed_ || detailed_->GetViewType() == WIFI_VIEW) {
request_wifi_view_ = true;
PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false);
}
}
void TrayNetwork::LinkClicked(MessageType message_type, int link_id) {
tray::NetworkMessages::MessageMap::const_iterator iter =
messages()->messages().find(message_type);
if (iter != messages()->messages().end() && iter->second.delegate)
iter->second.delegate->NotificationLinkClicked(link_id);
}
} // namespace internal
} // namespace ash