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 "grit/ui_chromeos_strings.h"
14 #include "ui/base/resource/resource_bundle.h"
15 #include "ui/chromeos/network/network_icon.h"
16 #include "ui/chromeos/network/network_icon_animation.h"
17 #include "ui/chromeos/network/network_info.h"
18 #include "ui/chromeos/network/network_list_delegate.h"
19 #include "ui/gfx/font.h"
20 #include "ui/views/controls/label.h"
21 #include "ui/views/view.h"
23 using chromeos::NetworkHandler
;
24 using chromeos::NetworkStateHandler
;
25 using chromeos::NetworkTypePattern
;
31 NetworkListView::NetworkListView(NetworkListDelegate
* delegate
)
32 : 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::UpdateNetworkList() {
46 NetworkStateHandler::NetworkStateList network_list
;
47 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
48 handler
->GetVisibleNetworkList(&network_list
);
49 UpdateNetworks(network_list
);
50 UpdateNetworkListInternal();
53 bool NetworkListView::IsViewInList(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 network_list_
.clear();
66 const NetworkTypePattern pattern
= delegate_
->GetNetworkTypePattern();
67 for (NetworkStateHandler::NetworkStateList::const_iterator iter
=
69 iter
!= networks
.end();
71 const chromeos::NetworkState
* network
= *iter
;
72 if (!pattern
.MatchesType(network
->type()))
74 NetworkInfo
* info
= new NetworkInfo(network
->path());
75 network_list_
.push_back(info
);
79 void NetworkListView::UpdateNetworkListInternal() {
80 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
82 // First, update state for all networks
83 bool animating
= false;
84 for (size_t i
= 0; i
< network_list_
.size(); ++i
) {
85 NetworkInfo
* info
= network_list_
[i
];
86 const chromeos::NetworkState
* network
=
87 handler
->GetNetworkState(info
->service_path
);
91 network_icon::GetImageForNetwork(network
, network_icon::ICON_TYPE_LIST
);
93 network_icon::GetLabelForNetwork(network
, network_icon::ICON_TYPE_LIST
);
95 network
->IsConnectedState() || network
->IsConnectingState();
97 network
->activation_state() == shill::kActivationStateActivating
;
98 if (!animating
&& network
->IsConnectingState())
103 network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
105 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
107 // Get the updated list entries
108 network_map_
.clear();
109 std::set
<std::string
> new_service_paths
;
110 bool needs_relayout
= UpdateNetworkListEntries(&new_service_paths
);
112 // Remove old children
113 std::set
<std::string
> remove_service_paths
;
114 for (ServicePathMap::const_iterator it
= service_path_map_
.begin();
115 it
!= service_path_map_
.end();
117 if (new_service_paths
.find(it
->first
) == new_service_paths
.end()) {
118 remove_service_paths
.insert(it
->first
);
119 network_map_
.erase(it
->second
);
120 content_
->RemoveChildView(it
->second
);
121 needs_relayout
= true;
125 for (std::set
<std::string
>::const_iterator remove_it
=
126 remove_service_paths
.begin();
127 remove_it
!= remove_service_paths
.end();
129 service_path_map_
.erase(*remove_it
);
132 if (needs_relayout
) {
133 views::View
* selected_view
= NULL
;
134 for (ServicePathMap::const_iterator iter
= service_path_map_
.begin();
135 iter
!= service_path_map_
.end();
137 if (delegate_
->IsViewHovered(iter
->second
)) {
138 selected_view
= iter
->second
;
142 content_
->SizeToPreferredSize();
143 delegate_
->RelayoutScrollList();
145 content_
->ScrollRectToVisible(selected_view
->bounds());
149 bool NetworkListView::UpdateNetworkListEntries(
150 std::set
<std::string
>* new_service_paths
) {
151 bool needs_relayout
= false;
152 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
154 // Insert child views
157 // Highlighted networks
158 for (size_t i
= 0; i
< network_list_
.size(); ++i
) {
159 const NetworkInfo
* info
= network_list_
[i
];
160 if (info
->highlight
) {
161 if (UpdateNetworkChild(index
++, info
))
162 needs_relayout
= true;
163 new_service_paths
->insert(info
->service_path
);
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
;
176 if (UpdateInfoLabel(message_id
, index
, &no_cellular_networks_view_
))
177 needs_relayout
= true;
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
;
190 if (UpdateInfoLabel(message_id
, index
, &no_wifi_networks_view_
))
191 needs_relayout
= true;
197 if (handler
->GetScanningByType(NetworkTypePattern::WiFi()))
198 message_id
= IDS_ASH_STATUS_TRAY_WIFI_SCANNING_MESSAGE
;
199 if (UpdateInfoLabel(message_id
, index
, &scanning_view_
))
200 needs_relayout
= true;
205 // Un-highlighted networks
206 for (size_t i
= 0; i
< network_list_
.size(); ++i
) {
207 const NetworkInfo
* info
= network_list_
[i
];
208 if (!info
->highlight
) {
209 if (UpdateNetworkChild(index
++, info
))
210 needs_relayout
= true;
211 new_service_paths
->insert(info
->service_path
);
215 // No networks or other messages (fallback)
218 if (pattern
.Equals(NetworkTypePattern::VPN()))
219 message_id
= IDS_ASH_STATUS_TRAY_NETWORK_NO_VPN
;
221 message_id
= IDS_ASH_STATUS_TRAY_NO_NETWORKS
;
222 if (UpdateInfoLabel(message_id
, index
, &scanning_view_
))
223 needs_relayout
= true;
226 return needs_relayout
;
229 bool NetworkListView::UpdateNetworkChild(int index
, const NetworkInfo
* info
) {
230 bool needs_relayout
= false;
231 views::View
* container
= NULL
;
232 ServicePathMap::const_iterator found
=
233 service_path_map_
.find(info
->service_path
);
234 if (found
== service_path_map_
.end()) {
235 container
= delegate_
->CreateViewForNetwork(*info
);
236 content_
->AddChildViewAt(container
, index
);
237 needs_relayout
= true;
239 container
= found
->second
;
240 container
->RemoveAllChildViews(true);
241 delegate_
->UpdateViewForNetwork(container
, *info
);
243 container
->SchedulePaint();
244 needs_relayout
= PlaceViewAtIndex(container
, index
);
247 container
->SetEnabled(false);
248 network_map_
[container
] = info
->service_path
;
249 service_path_map_
[info
->service_path
] = container
;
250 return needs_relayout
;
253 bool NetworkListView::PlaceViewAtIndex(views::View
* view
, int index
) {
254 if (content_
->child_at(index
) == view
)
256 content_
->ReorderChildView(view
, index
);
260 bool NetworkListView::UpdateInfoLabel(int message_id
,
262 views::Label
** label
) {
264 bool needs_relayout
= false;
266 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
267 base::string16 text
= rb
.GetLocalizedString(message_id
);
269 *label
= delegate_
->CreateInfoLabel();
270 (*label
)->SetText(text
);
271 content_
->AddChildViewAt(*label
, index
);
272 needs_relayout
= true;
274 (*label
)->SetText(text
);
275 needs_relayout
= PlaceViewAtIndex(*label
, index
);
278 content_
->RemoveChildView(*label
);
281 needs_relayout
= true;
283 return needs_relayout
;
286 void NetworkListView::NetworkIconChanged() {