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
),
34 no_wifi_networks_view_(NULL
),
35 no_cellular_networks_view_(NULL
) {
39 NetworkListView::~NetworkListView() {
40 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
43 void NetworkListView::Update() {
45 NetworkStateHandler::NetworkStateList network_list
;
46 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
47 handler
->GetVisibleNetworkList(&network_list
);
48 UpdateNetworks(network_list
);
50 UpdateNetworkListInternal();
53 bool NetworkListView::IsNetworkEntry(views::View
* view
,
54 std::string
* service_path
) const {
55 std::map
<views::View
*, std::string
>::const_iterator found
=
56 network_map_
.find(view
);
57 if (found
== network_map_
.end())
59 *service_path
= found
->second
;
63 void NetworkListView::UpdateNetworks(
64 const NetworkStateHandler::NetworkStateList
& networks
) {
65 SCOPED_NET_LOG_IF_SLOW();
66 network_list_
.clear();
67 const NetworkTypePattern pattern
= delegate_
->GetNetworkTypePattern();
68 for (NetworkStateHandler::NetworkStateList::const_iterator iter
=
70 iter
!= networks
.end();
72 const chromeos::NetworkState
* network
= *iter
;
73 if (!pattern
.MatchesType(network
->type()))
75 NetworkInfo
* info
= new NetworkInfo(network
->path());
76 network_list_
.push_back(info
);
80 void NetworkListView::UpdateNetworkIcons() {
81 SCOPED_NET_LOG_IF_SLOW();
82 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
84 // First, update state for all networks
85 bool animating
= false;
86 for (size_t i
= 0; i
< network_list_
.size(); ++i
) {
87 NetworkInfo
* info
= network_list_
[i
];
88 const chromeos::NetworkState
* network
=
89 handler
->GetNetworkState(info
->service_path
);
93 network_icon::GetImageForNetwork(network
, network_icon::ICON_TYPE_LIST
);
95 network_icon::GetLabelForNetwork(network
, network_icon::ICON_TYPE_LIST
);
97 network
->IsConnectedState() || network
->IsConnectingState();
99 network
->activation_state() == shill::kActivationStateActivating
;
100 if (!animating
&& network
->IsConnectingState())
104 network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
106 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
109 void NetworkListView::UpdateNetworkListInternal() {
110 SCOPED_NET_LOG_IF_SLOW();
111 // Get the updated list entries
112 network_map_
.clear();
113 std::set
<std::string
> new_service_paths
;
114 bool needs_relayout
= UpdateNetworkListEntries(&new_service_paths
);
116 // Remove old children
117 std::set
<std::string
> remove_service_paths
;
118 for (ServicePathMap::const_iterator it
= service_path_map_
.begin();
119 it
!= service_path_map_
.end();
121 if (new_service_paths
.find(it
->first
) == new_service_paths
.end()) {
122 remove_service_paths
.insert(it
->first
);
123 network_map_
.erase(it
->second
);
124 container_
->RemoveChildView(it
->second
);
125 needs_relayout
= true;
129 for (std::set
<std::string
>::const_iterator remove_it
=
130 remove_service_paths
.begin();
131 remove_it
!= remove_service_paths
.end();
133 service_path_map_
.erase(*remove_it
);
140 void NetworkListView::HandleRelayout() {
141 views::View
* selected_view
= NULL
;
142 for (auto& iter
: service_path_map_
) {
143 if (delegate_
->IsViewHovered(iter
.second
)) {
144 selected_view
= iter
.second
;
148 container_
->SizeToPreferredSize();
149 delegate_
->RelayoutScrollList();
151 container_
->ScrollRectToVisible(selected_view
->bounds());
154 bool NetworkListView::UpdateNetworkListEntries(
155 std::set
<std::string
>* new_service_paths
) {
156 bool needs_relayout
= false;
157 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
159 // Insert child views
162 // Highlighted networks
164 UpdateNetworkChildren(new_service_paths
, &index
, true /* highlighted */);
166 const NetworkTypePattern pattern
= delegate_
->GetNetworkTypePattern();
167 if (pattern
.MatchesPattern(NetworkTypePattern::Cellular())) {
168 // Cellular initializing
169 int message_id
= network_icon::GetCellularUninitializedMsg();
171 handler
->IsTechnologyEnabled(NetworkTypePattern::Mobile()) &&
172 !handler
->FirstNetworkByType(NetworkTypePattern::Mobile())) {
173 message_id
= IDS_ASH_STATUS_TRAY_NO_CELLULAR_NETWORKS
;
176 UpdateInfoLabel(message_id
, index
, &no_cellular_networks_view_
);
182 if (pattern
.MatchesPattern(NetworkTypePattern::WiFi())) {
183 // "Wifi Enabled / Disabled"
185 if (network_list_
.empty()) {
186 message_id
= handler
->IsTechnologyEnabled(NetworkTypePattern::WiFi())
187 ? IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED
188 : IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED
;
191 UpdateInfoLabel(message_id
, index
, &no_wifi_networks_view_
);
196 // Un-highlighted networks
197 needs_relayout
|= UpdateNetworkChildren(new_service_paths
, &index
,
198 false /* not highlighted */);
200 // No networks or other messages (fallback)
202 needs_relayout
|= UpdateInfoLabel(IDS_ASH_STATUS_TRAY_NO_NETWORKS
, index
,
203 &no_wifi_networks_view_
);
206 return needs_relayout
;
209 bool NetworkListView::UpdateNetworkChildren(
210 std::set
<std::string
>* new_service_paths
,
213 bool needs_relayout
= false;
214 int index
= *child_index
;
215 for (auto& info
: network_list_
) {
216 if (info
->highlight
!= highlighted
)
218 needs_relayout
|= UpdateNetworkChild(index
++, info
);
219 new_service_paths
->insert(info
->service_path
);
221 *child_index
= index
;
222 return needs_relayout
;
225 bool NetworkListView::UpdateNetworkChild(int index
, const NetworkInfo
* info
) {
226 bool needs_relayout
= false;
227 views::View
* container
= NULL
;
228 ServicePathMap::const_iterator found
=
229 service_path_map_
.find(info
->service_path
);
230 if (found
== service_path_map_
.end()) {
231 container
= delegate_
->CreateViewForNetwork(*info
);
232 container_
->AddChildViewAt(container
, index
);
233 needs_relayout
= true;
235 container
= found
->second
;
236 container
->RemoveAllChildViews(true);
237 delegate_
->UpdateViewForNetwork(container
, *info
);
239 container
->SchedulePaint();
240 needs_relayout
= PlaceViewAtIndex(container
, index
);
243 container
->SetEnabled(false);
244 network_map_
[container
] = info
->service_path
;
245 service_path_map_
[info
->service_path
] = container
;
246 return needs_relayout
;
249 bool NetworkListView::PlaceViewAtIndex(views::View
* view
, int index
) {
250 if (container_
->child_at(index
) == view
)
252 container_
->ReorderChildView(view
, index
);
256 bool NetworkListView::UpdateInfoLabel(int message_id
,
258 views::Label
** label
) {
260 bool needs_relayout
= false;
262 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
263 base::string16 text
= rb
.GetLocalizedString(message_id
);
265 *label
= delegate_
->CreateInfoLabel();
266 (*label
)->SetText(text
);
267 container_
->AddChildViewAt(*label
, index
);
268 needs_relayout
= true;
270 (*label
)->SetText(text
);
271 needs_relayout
= PlaceViewAtIndex(*label
, index
);
274 container_
->RemoveChildView(*label
);
277 needs_relayout
= true;
279 return needs_relayout
;
282 void NetworkListView::NetworkIconChanged() {