Index: ash/system/chromeos/network/network_state_list_detailed_view.cc |
diff --git a/ash/system/chromeos/network/network_state_list_detailed_view.cc b/ash/system/chromeos/network/network_state_list_detailed_view.cc |
index db2fd263eb5ca8e1123e7f59957c20646e4a18f9..d6a11df10ea2496199b297493ed4293ae18541d4 100644 |
--- a/ash/system/chromeos/network/network_state_list_detailed_view.cc |
+++ b/ash/system/chromeos/network/network_state_list_detailed_view.cc |
@@ -20,6 +20,7 @@ |
#include "ash/system/tray/hover_highlight_view.h" |
#include "ash/system/tray/system_tray.h" |
#include "ash/system/tray/system_tray_delegate.h" |
+#include "ash/system/tray/throbber_view.h" |
#include "ash/system/tray/tray_constants.h" |
#include "ash/system/tray/tray_details_view.h" |
#include "ash/system/tray/tray_popup_header_button.h" |
@@ -47,11 +48,14 @@ |
#include "ui/chromeos/network/network_list.h" |
#include "ui/chromeos/network/network_list_view_base.h" |
#include "ui/chromeos/resources/grit/ui_chromeos_resources.h" |
+#include "ui/compositor/layer.h" |
+#include "ui/compositor/scoped_layer_animation_settings.h" |
#include "ui/gfx/text_constants.h" |
#include "ui/views/bubble/bubble_delegate.h" |
#include "ui/views/controls/label.h" |
#include "ui/views/layout/box_layout.h" |
#include "ui/views/layout/fill_layout.h" |
+#include "ui/views/layout/layout_manager.h" |
#include "ui/views/widget/widget.h" |
using chromeos::DeviceState; |
@@ -120,6 +124,109 @@ class NetworkStateListDetailedView::InfoBubble |
}; |
//------------------------------------------------------------------------------ |
+ |
+// A throbber button that can also be clicked on. |
+class ThrobberButton : public ThrobberView { |
+ public: |
+ explicit ThrobberButton(NetworkStateListDetailedView* owner) |
+ : owner_(owner) {} |
+ ~ThrobberButton() override {} |
+ |
+ // views::View |
+ bool OnMousePressed(const ui::MouseEvent& event) override { |
+ return owner_->ThrobberPressed(this, event); |
+ } |
+ |
+ private: |
+ NetworkStateListDetailedView* owner_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ThrobberButton); |
+}; |
+ |
+//------------------------------------------------------------------------------ |
+ |
+const int kFadeIconMs = 500; |
+ |
+// A TrayPopupHeaderButton that fades in/out when shown/hidden. |
+class InfoIcon : public TrayPopupHeaderButton { |
+ public: |
+ explicit InfoIcon(views::ButtonListener* listener) |
+ : TrayPopupHeaderButton(listener, |
+ 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) { |
+ SetPaintToLayer(true); |
+ layer()->SetFillsBoundsOpaquely(false); |
+ layer()->SetOpacity(1.0); |
+ } |
+ ~InfoIcon() override {} |
+ |
+ // views::View |
+ void SetVisible(bool visible) override { |
+ layer()->GetAnimator()->StopAnimating(); // Stop any previous animation. |
+ ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator()); |
+ animation.SetTransitionDuration( |
+ base::TimeDelta::FromMilliseconds(kFadeIconMs)); |
+ layer()->SetOpacity(visible ? 1.0 : 0.0); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(InfoIcon); |
+}; |
+ |
+//------------------------------------------------------------------------------ |
+ |
+// Special layout to overlap the scanning throbber and the info button. |
+class InfoThrobberLayout : public views::LayoutManager { |
+ public: |
+ InfoThrobberLayout() {} |
+ ~InfoThrobberLayout() override {} |
+ |
+ // views::LayoutManager |
+ void Layout(views::View* host) override { |
+ gfx::Size max_size(GetMaxChildSize(host)); |
+ // Center each child view within |max_size|. |
+ for (int i = 0; i < host->child_count(); ++i) { |
+ views::View* child = host->child_at(i); |
+ if (!child->visible()) |
+ continue; |
+ gfx::Size child_size = child->GetPreferredSize(); |
+ gfx::Point origin; |
+ origin.set_x((max_size.width() - child_size.width()) / 2); |
+ origin.set_y((max_size.height() - child_size.height()) / 2); |
+ gfx::Rect bounds(origin, child_size); |
+ bounds.Inset(-host->GetInsets()); |
+ child->SetBoundsRect(bounds); |
+ } |
+ } |
+ |
+ gfx::Size GetPreferredSize(const views::View* host) const override { |
+ gfx::Point origin; |
+ gfx::Rect rect(origin, GetMaxChildSize(host)); |
+ rect.Inset(-host->GetInsets()); |
+ return rect.size(); |
+ } |
+ |
+ private: |
+ gfx::Size GetMaxChildSize(const views::View* host) const { |
+ int width = 0, height = 0; |
+ for (int i = 0; i < host->child_count(); ++i) { |
+ const views::View* child = host->child_at(i); |
+ if (!child->visible()) |
+ continue; |
+ gfx::Size child_size = child->GetPreferredSize(); |
+ width = std::max(width, child_size.width()); |
+ height = std::max(height, child_size.width()); |
+ } |
+ return gfx::Size(width, height); |
+ } |
+ |
+ DISALLOW_COPY_AND_ASSIGN(InfoThrobberLayout); |
+}; |
+ |
+//------------------------------------------------------------------------------ |
// NetworkStateListDetailedView |
NetworkStateListDetailedView::NetworkStateListDetailedView( |
@@ -129,6 +236,7 @@ NetworkStateListDetailedView::NetworkStateListDetailedView( |
: NetworkDetailedView(owner), |
list_type_(list_type), |
login_(login), |
+ wifi_scanning_(false), |
info_icon_(nullptr), |
button_wifi_(nullptr), |
button_mobile_(nullptr), |
@@ -137,7 +245,8 @@ NetworkStateListDetailedView::NetworkStateListDetailedView( |
other_mobile_(nullptr), |
settings_(nullptr), |
proxy_settings_(nullptr), |
- info_bubble_(nullptr) { |
+ info_bubble_(nullptr), |
+ scanning_throbber_(nullptr) { |
if (list_type == LIST_TYPE_VPN) { |
// Use a specialized class to list VPNs. |
network_list_view_.reset(new VPNListView(this)); |
@@ -163,19 +272,19 @@ void NetworkStateListDetailedView::Update() { |
void NetworkStateListDetailedView::Init() { |
Reset(); |
- info_icon_ = NULL; |
- button_wifi_ = NULL; |
- button_mobile_ = NULL; |
- other_wifi_ = NULL; |
- turn_on_wifi_ = NULL; |
- other_mobile_ = NULL; |
- settings_ = NULL; |
- proxy_settings_ = NULL; |
+ info_icon_ = nullptr; |
+ button_wifi_ = nullptr; |
+ button_mobile_ = nullptr; |
+ other_wifi_ = nullptr; |
+ turn_on_wifi_ = nullptr; |
+ other_mobile_ = nullptr; |
+ settings_ = nullptr; |
+ proxy_settings_ = nullptr; |
+ scanning_throbber_ = nullptr; |
CreateScrollableList(); |
CreateNetworkExtra(); |
CreateHeaderEntry(); |
- CreateHeaderButtons(); |
network_list_view_->set_container(scroll_content()); |
Update(); |
@@ -231,6 +340,14 @@ void NetworkStateListDetailedView::ButtonPressed(views::Button* sender, |
} |
} |
+bool NetworkStateListDetailedView::ThrobberPressed(views::View* sender, |
+ const ui::Event& event) { |
+ if (sender != scanning_throbber_) |
+ return false; |
+ ToggleInfoBubble(); |
+ return true; |
+} |
+ |
void NetworkStateListDetailedView::OnViewClicked(views::View* sender) { |
// If the info bubble was visible, close it when some other item is clicked. |
ResetInfoBubble(); |
@@ -270,9 +387,7 @@ void NetworkStateListDetailedView::OnViewClicked(views::View* sender) { |
void NetworkStateListDetailedView::CreateHeaderEntry() { |
CreateSpecialRow(IDS_ASH_STATUS_TRAY_NETWORK, this); |
-} |
-void NetworkStateListDetailedView::CreateHeaderButtons() { |
if (list_type_ != LIST_TYPE_VPN) { |
button_wifi_ = new TrayPopupHeaderButton( |
this, IDR_AURA_UBER_TRAY_WIFI_ENABLED, IDR_AURA_UBER_TRAY_WIFI_DISABLED, |
@@ -297,13 +412,20 @@ void NetworkStateListDetailedView::CreateHeaderButtons() { |
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( |
+ views::View* info_throbber_container = new views::View(); |
+ InfoThrobberLayout* info_throbber_layout = new InfoThrobberLayout; |
+ info_throbber_container->SetLayoutManager(info_throbber_layout); |
+ footer()->AddView(info_throbber_container, true /* add_separator */); |
+ |
+ info_icon_ = new InfoIcon(this); |
+ info_throbber_container->AddChildView(info_icon_); |
+ |
+ scanning_throbber_ = new ThrobberButton(this); |
+ // Since the throbber is added last, it will be "on top" of the info button, |
+ // so it gets the info tooltip. |
+ scanning_throbber_->SetTooltipText( |
l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_INFO)); |
- footer()->AddButton(info_icon_); |
+ info_throbber_container->AddChildView(scanning_throbber_); |
} |
void NetworkStateListDetailedView::CreateNetworkExtra() { |
@@ -335,7 +457,7 @@ void NetworkStateListDetailedView::CreateNetworkExtra() { |
CreateSettingsEntry(); |
- // Both settings_ and proxy_settings_ can be NULL. This happens when |
+ // Both settings_ and proxy_settings_ can be null. This happens when |
// we're logged in but showing settings page is not enabled. |
// Example: supervised user creation flow where user session is active |
// but all action happens on the login window. |
@@ -357,7 +479,26 @@ void NetworkStateListDetailedView::UpdateHeaderButtons() { |
UpdateTechnologyButton(button_mobile_, NetworkTypePattern::Mobile()); |
} |
if (proxy_settings_) |
- proxy_settings_->SetEnabled(handler->DefaultNetwork() != NULL); |
+ proxy_settings_->SetEnabled(handler->DefaultNetwork() != nullptr); |
+ |
+ // Update Wifi Scanning throbber. |
+ bool scanning = |
+ NetworkHandler::Get()->network_state_handler()->GetScanningByType( |
+ NetworkTypePattern::WiFi()); |
+ if (scanning != wifi_scanning_) { |
+ wifi_scanning_ = scanning; |
+ if (scanning) { |
+ info_icon_->SetVisible(false); |
+ scanning_throbber_->Start(); |
+ scanning_throbber_->SetTooltipText( |
+ l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_WIFI_SCANNING_MESSAGE)); |
+ } else { |
+ scanning_throbber_->Stop(); |
+ scanning_throbber_->SetTooltipText( |
+ l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_INFO)); |
+ info_icon_->SetVisible(true); |
+ } |
+ } |
static_cast<views::View*>(footer())->Layout(); |
} |
@@ -404,7 +545,7 @@ void NetworkStateListDetailedView::UpdateNetworkExtra() { |
if (login_ == user::LOGGED_IN_LOCKED) |
return; |
- View* layout_parent = NULL; // All these buttons have the same parent. |
+ View* layout_parent = nullptr; // All these buttons have the same parent. |
NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); |
if (other_wifi_) { |
DCHECK(turn_on_wifi_); |
@@ -491,12 +632,12 @@ bool NetworkStateListDetailedView::ResetInfoBubble() { |
if (!info_bubble_) |
return false; |
info_bubble_->GetWidget()->Close(); |
- info_bubble_ = NULL; |
+ info_bubble_ = nullptr; |
return true; |
} |
void NetworkStateListDetailedView::OnInfoBubbleDestroyed() { |
- info_bubble_ = NULL; |
+ info_bubble_ = nullptr; |
} |
views::View* NetworkStateListDetailedView::CreateNetworkInfoView() { |