Index: ash/system/network/tray_network.cc |
diff --git a/ash/system/network/tray_network.cc b/ash/system/network/tray_network.cc |
index 8837feb1205ed2e30966b46ac59ec3d80c0b572e..1efcfbf771a515c5037562da5e1fed712bf383d8 100644 |
--- a/ash/system/network/tray_network.cc |
+++ b/ash/system/network/tray_network.cc |
@@ -5,12 +5,137 @@ |
#include "ash/system/network/tray_network.h" |
#include "ash/shell.h" |
+#include "ash/system/tray/system_tray.h" |
#include "ash/system/tray/system_tray_delegate.h" |
+#include "base/utf_string_conversions.h" |
+#include "grit/ash_strings.h" |
+#include "grit/ui_resources.h" |
+#include "ui/base/resource/resource_bundle.h" |
+#include "ui/gfx/font.h" |
+#include "ui/gfx/image/image.h" |
#include "ui/views/controls/image_view.h" |
#include "ui/views/controls/label.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/view.h" |
+#include "ui/views/widget/widget.h" |
+ |
+namespace { |
+ |
+// Width of the icon, and the padding on the right of the icon. These are used |
+// to make sure that all icons are of the same size so that they line up |
+// properly, including the items that don't have any icons. |
+const int kIconWidth = 27; |
+const int kIconPaddingLeft = 5; |
+ |
+// Height of the list of networks in the popup. |
+const int kNetworkListHeight = 160; |
+ |
+// An image view with that always has a fixed width (kIconWidth) so that |
+// all the items line up properly. |
+class FixedWidthImageView : public views::ImageView { |
+ public: |
+ FixedWidthImageView() { |
+ SetHorizontalAlignment(views::ImageView::CENTER); |
+ SetVerticalAlignment(views::ImageView::CENTER); |
+ } |
+ |
+ virtual ~FixedWidthImageView() {} |
+ |
+ private: |
+ virtual gfx::Size GetPreferredSize() OVERRIDE { |
+ gfx::Size size = views::ImageView::GetPreferredSize(); |
+ return gfx::Size(kIconWidth, size.height()); |
+ } |
+ |
+ DISALLOW_COPY_AND_ASSIGN(FixedWidthImageView); |
+}; |
+ |
+class ViewClickListener { |
+ public: |
+ virtual ~ViewClickListener() {} |
+ virtual void ClickedOn(views::View* sender) = 0; |
+}; |
+ |
+class HoverHighlightView : public views::View { |
+ public: |
+ explicit HoverHighlightView(ViewClickListener* listener) |
+ : listener_(listener) { |
+ set_notify_enter_exit_on_child(true); |
+ } |
+ |
+ virtual ~HoverHighlightView() {} |
+ |
+ // Convenience function for adding an icon and a label. |
+ void AddIconAndLabel(const SkBitmap& image, const string16& label) { |
+ SetLayoutManager(new views::BoxLayout( |
+ views::BoxLayout::kHorizontal, 0, 3, kIconPaddingLeft)); |
+ views::ImageView* image_view = new FixedWidthImageView; |
+ image_view->SetImage(image); |
+ AddChildView(image_view); |
+ AddChildView(new views::Label(label)); |
+ } |
+ |
+ void AddLabel(const string16& text) { |
+ SetLayoutManager(new views::FillLayout()); |
+ views::Label* label = new views::Label(text); |
+ label->set_border(views::Border::CreateEmptyBorder( |
+ 5, kIconWidth + kIconPaddingLeft, 5, 0)); |
+ label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
+ AddChildView(label); |
+ } |
+ |
+ private: |
+ // Overridden from views::View. |
+ virtual bool OnMousePressed(const views::MouseEvent& event) OVERRIDE { |
+ if (!listener_) |
+ return false; |
+ listener_->ClickedOn(this); |
+ return true; |
+ } |
+ |
+ virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE { |
+ set_background(views::Background::CreateSolidBackground( |
+ SkColorSetARGB(10, 0, 0, 0))); |
+ SchedulePaint(); |
+ } |
+ |
+ virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE { |
+ set_background(NULL); |
+ SchedulePaint(); |
+ } |
+ |
+ ViewClickListener* listener_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(HoverHighlightView); |
+}; |
+ |
+// A custom scroll-view that has a specified dimension. |
+class FixedSizedScrollView : public views::ScrollView { |
+ public: |
+ FixedSizedScrollView() {} |
+ virtual ~FixedSizedScrollView() {} |
+ |
+ void SetContentsView(View* view) { |
+ SetContents(view); |
+ view->SetBoundsRect(gfx::Rect(view->GetPreferredSize())); |
+ } |
+ |
+ void set_fixed_size(gfx::Size size) { fixed_size_ = size; } |
+ |
+ private: |
+ // Overridden from views::View. |
+ virtual gfx::Size GetPreferredSize() OVERRIDE { |
+ return fixed_size_; |
+ } |
+ |
+ gfx::Size fixed_size_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(FixedSizedScrollView); |
+}; |
+ |
+} |
namespace ash { |
namespace internal { |
@@ -30,7 +155,8 @@ class NetworkTrayView : public views::View { |
image_view_ = new views::ImageView; |
AddChildView(image_view_); |
- Update(Shell::GetInstance()->tray_delegate()->GetMostRelevantNetworkIcon()); |
+ Update(Shell::GetInstance()->tray_delegate()-> |
+ GetMostRelevantNetworkIcon(resource_size_ == LARGE)); |
} |
virtual ~NetworkTrayView() {} |
@@ -49,7 +175,7 @@ class NetworkTrayView : public views::View { |
class NetworkDefaultView : public views::View { |
public: |
- NetworkDefaultView() { |
+ explicit NetworkDefaultView(SystemTrayItem* owner) : owner_(owner) { |
SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, |
0, 0, 5)); |
@@ -59,7 +185,13 @@ class NetworkDefaultView : public views::View { |
label_ = new views::Label(); |
AddChildView(label_); |
- Update(Shell::GetInstance()->tray_delegate()->GetMostRelevantNetworkIcon()); |
+ views::ImageView* more = new views::ImageView; |
+ more->SetImage(ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
+ IDR_AURA_UBER_TRAY_MORE).ToSkBitmap()); |
+ AddChildView(more); |
+ |
+ Update(Shell::GetInstance()->tray_delegate()-> |
+ GetMostRelevantNetworkIcon(true)); |
} |
virtual ~NetworkDefaultView() {} |
@@ -70,12 +202,147 @@ class NetworkDefaultView : public views::View { |
} |
private: |
+ // Overridden from views::View. |
+ virtual bool OnMousePressed(const views::MouseEvent& event) OVERRIDE { |
+ owner_->PopupDetailedView(0, true); |
+ return true; |
+ } |
+ |
+ SystemTrayItem* owner_; |
NetworkTrayView* icon_; |
views::Label* label_; |
DISALLOW_COPY_AND_ASSIGN(NetworkDefaultView); |
}; |
+class NetworkDetailedView : public views::View, |
+ public ViewClickListener { |
+ public: |
+ explicit NetworkDetailedView(user::LoginStatus login) |
+ : login_(login), |
+ header_(NULL), |
+ airplane_(NULL), |
+ settings_(NULL), |
+ proxy_settings_(NULL) { |
+ SetLayoutManager(new views::BoxLayout( |
+ views::BoxLayout::kVertical, 1, 1, 1)); |
+ Update(); |
+ } |
+ |
+ virtual ~NetworkDetailedView() {} |
+ |
+ void Update() { |
+ RemoveAllChildViews(true); |
+ |
+ AppendHeaderEntry(); |
+ AppendNetworkEntries(); |
+ AppendAirplaneModeEntry(); |
+ AppendSettingsEntry(); |
+ } |
+ |
+ private: |
+ void AppendHeaderEntry() { |
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
+ HoverHighlightView* container = new HoverHighlightView(this); |
+ container->SetLayoutManager(new |
+ views::BoxLayout(views::BoxLayout::kHorizontal, 0, 3, 5)); |
+ views::ImageView* back = new FixedWidthImageView; |
+ back->SetImage(rb.GetImageNamed(IDR_AURA_UBER_TRAY_LESS).ToSkBitmap()); |
+ container->AddChildView(back); |
+ views::Label* header = new views::Label(rb.GetLocalizedString( |
+ IDS_ASH_STATUS_TRAY_NETWORK)); |
+ header->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
+ header->SetFont(header->font().DeriveFont(4)); |
+ container->AddChildView(header); |
+ AddChildView(container); |
+ header_ = container; |
+ } |
+ |
+ void AppendNetworkEntries() { |
+ std::vector<NetworkIconInfo> list; |
+ Shell::GetInstance()->tray_delegate()->GetAvailableNetworks(&list); |
+ FixedSizedScrollView* scroller = new FixedSizedScrollView; |
+ views::View* networks = new views::View; |
+ networks->SetLayoutManager(new views::BoxLayout( |
+ views::BoxLayout::kVertical, 0, 0, 1)); |
+ for (size_t i = 0; i < list.size(); i++) { |
+ HoverHighlightView* container = new HoverHighlightView(this); |
+ container->AddIconAndLabel(list[i].image, list[i].name); |
+ networks->AddChildView(container); |
+ network_map_[container] = list[i].unique_id; |
+ } |
+ scroller->set_border(views::Border::CreateSolidSidedBorder(1, 0, 1, 0, |
+ SkColorSetARGB(25, 0, 0, 0))); |
+ scroller->set_fixed_size( |
+ gfx::Size(networks->GetPreferredSize().width() + |
+ scroller->GetScrollBarWidth(), |
+ kNetworkListHeight)); |
+ scroller->SetContentsView(networks); |
+ AddChildView(scroller); |
+ } |
+ |
+ void AppendAirplaneModeEntry() { |
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
+ HoverHighlightView* container = new HoverHighlightView(this); |
+ container->AddIconAndLabel( |
+ *rb.GetImageNamed(IDR_AURA_UBER_TRAY_NETWORK_AIRPLANE).ToSkBitmap(), |
+ rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_AIRPLANE_MODE)); |
+ AddChildView(container); |
+ airplane_ = container; |
+ } |
+ |
+ // Adds a settings entry when logged in, and an entry for changing proxy |
+ // settings otherwise. |
+ void AppendSettingsEntry() { |
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
+ if (login_ != user::LOGGED_IN_NONE) { |
+ // Settings, only if logged in. |
+ HoverHighlightView* container = new HoverHighlightView(this); |
+ container->AddLabel(rb.GetLocalizedString( |
+ IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS)); |
+ AddChildView(container); |
+ settings_ = container; |
+ } else { |
+ // Allow changing proxy settings in the login screen. |
+ HoverHighlightView* container = new HoverHighlightView(this); |
+ container->AddLabel(rb.GetLocalizedString( |
+ IDS_ASH_STATUS_TRAY_NETWORK_PROXY_SETTINGS)); |
+ AddChildView(container); |
+ proxy_settings_ = container; |
+ } |
+ } |
+ |
+ // Overridden from ViewClickListener. |
+ virtual void ClickedOn(views::View* sender) OVERRIDE { |
+ ash::SystemTrayDelegate* delegate = |
+ ash::Shell::GetInstance()->tray_delegate(); |
+ if (sender == header_) { |
+ Shell::GetInstance()->tray()->ShowDefaultView(); |
+ } else if (sender == settings_) { |
+ delegate->ShowNetworkSettings(); |
+ } else if (sender == proxy_settings_) { |
+ delegate->ChangeProxySettings(); |
+ } 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); |
+ } |
+ } |
+ } |
+ |
+ user::LoginStatus login_; |
+ std::map<views::View*, std::string> network_map_; |
+ views::View* header_; |
+ views::View* airplane_; |
+ views::View* settings_; |
+ views::View* proxy_settings_; |
+ DISALLOW_COPY_AND_ASSIGN(NetworkDetailedView); |
+}; |
+ |
} // namespace tray |
TrayNetwork::TrayNetwork() { |
@@ -90,12 +357,13 @@ views::View* TrayNetwork::CreateTrayView(user::LoginStatus status) { |
} |
views::View* TrayNetwork::CreateDefaultView(user::LoginStatus status) { |
- default_.reset(new tray::NetworkDefaultView); |
+ default_.reset(new tray::NetworkDefaultView(this)); |
return default_.get(); |
} |
views::View* TrayNetwork::CreateDetailedView(user::LoginStatus status) { |
- return NULL; |
+ detailed_.reset(new tray::NetworkDetailedView(status)); |
+ return detailed_.get(); |
} |
void TrayNetwork::DestroyTrayView() { |
@@ -107,6 +375,7 @@ void TrayNetwork::DestroyDefaultView() { |
} |
void TrayNetwork::DestroyDetailedView() { |
+ detailed_.reset(); |
} |
void TrayNetwork::OnNetworkRefresh(const NetworkIconInfo& info) { |
@@ -114,6 +383,8 @@ void TrayNetwork::OnNetworkRefresh(const NetworkIconInfo& info) { |
tray_->Update(info); |
if (default_.get()) |
default_->Update(info); |
+ if (detailed_.get()) |
+ detailed_->Update(); |
} |
} // namespace internal |