1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/chromeos/network/network_list.h"
7 #include "chromeos/dbus/dbus_thread_manager.h"
8 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
9 #include "chromeos/dbus/power_manager_client.h"
10 #include "chromeos/network/network_state.h"
11 #include "chromeos/network/network_state_handler.h"
12 #include "chromeos/network/network_state_handler_observer.h"
13 #include "components/device_event_log/device_event_log.h"
14 #include "grit/ui_chromeos_strings.h"
15 #include "ui/base/resource/resource_bundle.h"
16 #include "ui/chromeos/network/network_icon.h"
17 #include "ui/chromeos/network/network_icon_animation.h"
18 #include "ui/chromeos/network/network_info.h"
19 #include "ui/chromeos/network/network_list_delegate.h"
20 #include "ui/gfx/font.h"
21 #include "ui/views/controls/label.h"
22 #include "ui/views/view.h"
24 using chromeos::NetworkHandler
;
25 using chromeos::NetworkStateHandler
;
26 using chromeos::NetworkTypePattern
;
32 NetworkListView::NetworkListView(NetworkListDelegate
* delegate
)
33 : delegate_(delegate
),
35 no_wifi_networks_view_(NULL
),
36 no_cellular_networks_view_(NULL
) {
40 NetworkListView::~NetworkListView() {
41 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
44 void NetworkListView::Update() {
46 NetworkStateHandler::NetworkStateList network_list
;
47 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
48 handler
->GetVisibleNetworkList(&network_list
);
49 UpdateNetworks(network_list
);
51 UpdateNetworkListInternal();
54 bool NetworkListView::IsNetworkEntry(views::View
* view
,
55 std::string
* service_path
) const {
56 std::map
<views::View
*, std::string
>::const_iterator found
=
57 network_map_
.find(view
);
58 if (found
== network_map_
.end())
60 *service_path
= found
->second
;
64 void NetworkListView::UpdateNetworks(
65 const NetworkStateHandler::NetworkStateList
& networks
) {
66 SCOPED_NET_LOG_IF_SLOW();
67 network_list_
.clear();
68 const NetworkTypePattern pattern
= delegate_
->GetNetworkTypePattern();
69 for (NetworkStateHandler::NetworkStateList::const_iterator iter
=
71 iter
!= networks
.end();
73 const chromeos::NetworkState
* network
= *iter
;
74 if (!pattern
.MatchesType(network
->type()))
76 NetworkInfo
* info
= new NetworkInfo(network
->path());
77 network_list_
.push_back(info
);
81 void NetworkListView::UpdateNetworkIcons() {
82 SCOPED_NET_LOG_IF_SLOW();
83 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
85 // First, update state for all networks
86 bool animating
= false;
87 for (size_t i
= 0; i
< network_list_
.size(); ++i
) {
88 NetworkInfo
* info
= network_list_
[i
];
89 const chromeos::NetworkState
* network
=
90 handler
->GetNetworkState(info
->service_path
);
94 network_icon::GetImageForNetwork(network
, network_icon::ICON_TYPE_LIST
);
96 network_icon::GetLabelForNetwork(network
, network_icon::ICON_TYPE_LIST
);
98 network
->IsConnectedState() || network
->IsConnectingState();
100 network
->activation_state() == shill::kActivationStateActivating
;
101 if (!animating
&& network
->IsConnectingState())
105 network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
107 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
110 void NetworkListView::UpdateNetworkListInternal() {
111 SCOPED_NET_LOG_IF_SLOW();
112 // Get the updated list entries
113 network_map_
.clear();
114 std::set
<std::string
> new_service_paths
;
115 bool needs_relayout
= UpdateNetworkListEntries(&new_service_paths
);
117 // Remove old children
118 std::set
<std::string
> remove_service_paths
;
119 for (ServicePathMap::const_iterator it
= service_path_map_
.begin();
120 it
!= service_path_map_
.end();
122 if (new_service_paths
.find(it
->first
) == new_service_paths
.end()) {
123 remove_service_paths
.insert(it
->first
);
124 network_map_
.erase(it
->second
);
125 container_
->RemoveChildView(it
->second
);
126 needs_relayout
= true;
130 for (std::set
<std::string
>::const_iterator remove_it
=
131 remove_service_paths
.begin();
132 remove_it
!= remove_service_paths
.end();
134 service_path_map_
.erase(*remove_it
);
141 void NetworkListView::HandleRelayout() {
142 views::View
* selected_view
= NULL
;
143 for (auto& iter
: service_path_map_
) {
144 if (delegate_
->IsViewHovered(iter
.second
)) {
145 selected_view
= iter
.second
;
149 container_
->SizeToPreferredSize();
150 delegate_
->RelayoutScrollList();
152 container_
->ScrollRectToVisible(selected_view
->bounds());
155 bool NetworkListView::UpdateNetworkListEntries(
156 std::set
<std::string
>* new_service_paths
) {
157 bool needs_relayout
= false;
158 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
160 // Insert child views
163 // Highlighted networks
165 UpdateNetworkChildren(new_service_paths
, &index
, true /* highlighted */);
167 const NetworkTypePattern pattern
= delegate_
->GetNetworkTypePattern();
168 if (pattern
.MatchesPattern(NetworkTypePattern::Cellular())) {
169 // Cellular initializing
170 int message_id
= network_icon::GetCellularUninitializedMsg();
172 handler
->IsTechnologyEnabled(NetworkTypePattern::Mobile()) &&
173 !handler
->FirstNetworkByType(NetworkTypePattern::Mobile())) {
174 message_id
= IDS_ASH_STATUS_TRAY_NO_CELLULAR_NETWORKS
;
177 UpdateInfoLabel(message_id
, index
, &no_cellular_networks_view_
);
183 if (pattern
.MatchesPattern(NetworkTypePattern::WiFi())) {
184 // "Wifi Enabled / Disabled"
186 if (network_list_
.empty()) {
187 message_id
= handler
->IsTechnologyEnabled(NetworkTypePattern::WiFi())
188 ? IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED
189 : IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED
;
192 UpdateInfoLabel(message_id
, index
, &no_wifi_networks_view_
);
198 if (handler
->GetScanningByType(NetworkTypePattern::WiFi()))
199 message_id
= IDS_ASH_STATUS_TRAY_WIFI_SCANNING_MESSAGE
;
200 needs_relayout
|= UpdateInfoLabel(message_id
, index
, &scanning_view_
);
205 // Un-highlighted networks
206 needs_relayout
|= UpdateNetworkChildren(new_service_paths
, &index
,
207 false /* not highlighted */);
209 // No networks or other messages (fallback)
211 needs_relayout
|= UpdateInfoLabel(IDS_ASH_STATUS_TRAY_NO_NETWORKS
, index
,
215 return needs_relayout
;
218 bool NetworkListView::UpdateNetworkChildren(
219 std::set
<std::string
>* new_service_paths
,
222 bool needs_relayout
= false;
223 int index
= *child_index
;
224 for (auto& info
: network_list_
) {
225 if (info
->highlight
!= highlighted
)
227 needs_relayout
|= UpdateNetworkChild(index
++, info
);
228 new_service_paths
->insert(info
->service_path
);
230 *child_index
= index
;
231 return needs_relayout
;
234 bool NetworkListView::UpdateNetworkChild(int index
, const NetworkInfo
* info
) {
235 bool needs_relayout
= false;
236 views::View
* container
= NULL
;
237 ServicePathMap::const_iterator found
=
238 service_path_map_
.find(info
->service_path
);
239 if (found
== service_path_map_
.end()) {
240 container
= delegate_
->CreateViewForNetwork(*info
);
241 container_
->AddChildViewAt(container
, index
);
242 needs_relayout
= true;
244 container
= found
->second
;
245 container
->RemoveAllChildViews(true);
246 delegate_
->UpdateViewForNetwork(container
, *info
);
248 container
->SchedulePaint();
249 needs_relayout
= PlaceViewAtIndex(container
, index
);
252 container
->SetEnabled(false);
253 network_map_
[container
] = info
->service_path
;
254 service_path_map_
[info
->service_path
] = container
;
255 return needs_relayout
;
258 bool NetworkListView::PlaceViewAtIndex(views::View
* view
, int index
) {
259 if (container_
->child_at(index
) == view
)
261 container_
->ReorderChildView(view
, index
);
265 bool NetworkListView::UpdateInfoLabel(int message_id
,
267 views::Label
** label
) {
269 bool needs_relayout
= false;
271 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
272 base::string16 text
= rb
.GetLocalizedString(message_id
);
274 *label
= delegate_
->CreateInfoLabel();
275 (*label
)->SetText(text
);
276 container_
->AddChildViewAt(*label
, index
);
277 needs_relayout
= true;
279 (*label
)->SetText(text
);
280 needs_relayout
= PlaceViewAtIndex(*label
, index
);
283 container_
->RemoveChildView(*label
);
286 needs_relayout
= true;
288 return needs_relayout
;
291 void NetworkListView::NetworkIconChanged() {