OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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. | |
4 | |
5 #include "ash/system/network/tray_network.h" | |
6 | |
7 #include "ash/shell.h" | |
8 #include "ash/shell_window_ids.h" | |
9 #include "ash/system/tray/system_tray.h" | |
10 #include "ash/system/tray/system_tray_delegate.h" | |
11 #include "ash/system/tray/tray_constants.h" | |
12 #include "ash/system/tray/tray_details_view.h" | |
13 #include "ash/system/tray/tray_item_more.h" | |
14 #include "ash/system/tray/tray_item_view.h" | |
15 #include "ash/system/tray/tray_notification_view.h" | |
16 #include "ash/system/tray/tray_views.h" | |
17 #include "base/utf_string_conversions.h" | |
18 #include "grit/ash_resources.h" | |
19 #include "grit/ash_strings.h" | |
20 #include "third_party/skia/include/core/SkColor.h" | |
21 #include "ui/aura/window.h" | |
22 #include "ui/base/l10n/l10n_util.h" | |
23 #include "ui/base/resource/resource_bundle.h" | |
24 #include "ui/gfx/canvas.h" | |
25 #include "ui/gfx/font.h" | |
26 #include "ui/gfx/image/image.h" | |
27 #include "ui/gfx/skia_util.h" | |
28 #include "ui/views/bubble/bubble_border.h" | |
29 #include "ui/views/bubble/bubble_delegate.h" | |
30 #include "ui/views/controls/button/button.h" | |
31 #include "ui/views/controls/button/image_button.h" | |
32 #include "ui/views/controls/image_view.h" | |
33 #include "ui/views/controls/label.h" | |
34 #include "ui/views/controls/link.h" | |
35 #include "ui/views/controls/link_listener.h" | |
36 #include "ui/views/controls/scroll_view.h" | |
37 #include "ui/views/layout/box_layout.h" | |
38 #include "ui/views/layout/fill_layout.h" | |
39 #include "ui/views/view.h" | |
40 #include "ui/views/widget/widget.h" | |
41 | |
42 namespace { | |
43 | |
44 // Height of the list of networks in the popup. | |
45 const int kNetworkListHeight = 203; | |
46 | |
47 // Create a label with the font size and color used in the network info bubble. | |
48 views::Label* CreateInfoBubbleLabel(const string16& text) { | |
49 const SkColor text_color = SkColorSetARGB(127, 0, 0, 0); | |
50 views::Label* label = new views::Label(text); | |
51 label->SetFont(label->font().DeriveFont(-1)); | |
52 label->SetEnabledColor(text_color); | |
53 return label; | |
54 } | |
55 | |
56 // Create a row of labels for the network info bubble. | |
57 views::View* CreateInfoBubbleLine(const string16& text_label, | |
58 const std::string& text_string) { | |
59 views::View* view = new views::View; | |
60 view->SetLayoutManager( | |
61 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 1)); | |
62 view->AddChildView(CreateInfoBubbleLabel(text_label)); | |
63 view->AddChildView(CreateInfoBubbleLabel(UTF8ToUTF16(": "))); | |
64 view->AddChildView(CreateInfoBubbleLabel(UTF8ToUTF16(text_string))); | |
65 return view; | |
66 } | |
67 | |
68 // A bubble that cannot be activated. | |
69 class NonActivatableSettingsBubble : public views::BubbleDelegateView { | |
70 public: | |
71 NonActivatableSettingsBubble(views::View* anchor, views::View* content) | |
72 : views::BubbleDelegateView(anchor, views::BubbleBorder::TOP_RIGHT) { | |
73 set_use_focusless(true); | |
74 set_parent_window(ash::Shell::GetContainer( | |
75 anchor->GetWidget()->GetNativeWindow()->GetRootWindow(), | |
76 ash::internal::kShellWindowId_SettingBubbleContainer)); | |
77 SetLayoutManager(new views::FillLayout()); | |
78 AddChildView(content); | |
79 } | |
80 | |
81 virtual ~NonActivatableSettingsBubble() {} | |
82 | |
83 virtual bool CanActivate() const OVERRIDE { | |
84 return false; | |
85 } | |
86 | |
87 private: | |
88 DISALLOW_COPY_AND_ASSIGN(NonActivatableSettingsBubble); | |
89 }; | |
90 | |
91 using ash::internal::TrayNetwork; | |
92 | |
93 int GetMessageIcon(TrayNetwork::MessageType message_type) { | |
94 switch(message_type) { | |
95 case TrayNetwork::ERROR_CONNECT_FAILED: | |
96 return IDR_AURA_UBER_TRAY_NETWORK_FAILED; | |
97 case TrayNetwork::MESSAGE_DATA_LOW: | |
98 return IDR_AURA_UBER_TRAY_NETWORK_DATA_LOW; | |
99 case TrayNetwork::MESSAGE_DATA_NONE: | |
100 return IDR_AURA_UBER_TRAY_NETWORK_DATA_NONE; | |
101 case TrayNetwork::MESSAGE_DATA_PROMO: | |
102 return IDR_AURA_UBER_TRAY_NOTIFICATION_3G; | |
103 } | |
104 NOTREACHED(); | |
105 return 0; | |
106 } | |
107 | |
108 } // namespace | |
109 | |
110 namespace ash { | |
111 namespace internal { | |
112 | |
113 namespace tray { | |
114 | |
115 enum ColorTheme { | |
116 LIGHT, | |
117 DARK, | |
118 }; | |
119 | |
120 class NetworkMessages { | |
121 public: | |
122 struct Message { | |
123 Message() : delegate(NULL) {} | |
124 Message(NetworkTrayDelegate* in_delegate, | |
125 const string16& in_title, | |
126 const string16& in_message, | |
127 const std::vector<string16>& in_links) : | |
128 delegate(in_delegate), | |
129 title(in_title), | |
130 message(in_message), | |
131 links(in_links) {} | |
132 NetworkTrayDelegate* delegate; | |
133 string16 title; | |
134 string16 message; | |
135 std::vector<string16> links; | |
136 }; | |
137 typedef std::map<TrayNetwork::MessageType, Message> MessageMap; | |
138 | |
139 MessageMap& messages() { return messages_; } | |
140 const MessageMap& messages() const { return messages_; } | |
141 | |
142 private: | |
143 MessageMap messages_; | |
144 }; | |
145 | |
146 class NetworkTrayView : public TrayItemView { | |
147 public: | |
148 NetworkTrayView(ColorTheme size, bool tray_icon) | |
149 : color_theme_(size), tray_icon_(tray_icon) { | |
150 SetLayoutManager( | |
151 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0)); | |
152 | |
153 image_view_ = color_theme_ == DARK ? | |
154 new FixedSizedImageView(0, kTrayPopupItemHeight) : | |
155 new views::ImageView; | |
156 AddChildView(image_view_); | |
157 | |
158 NetworkIconInfo info; | |
159 Shell::GetInstance()->tray_delegate()-> | |
160 GetMostRelevantNetworkIcon(&info, false); | |
161 Update(info); | |
162 } | |
163 | |
164 virtual ~NetworkTrayView() {} | |
165 | |
166 void Update(const NetworkIconInfo& info) { | |
167 image_view_->SetImage(info.image); | |
168 if (tray_icon_) | |
169 SetVisible(info.tray_icon_visible); | |
170 SchedulePaint(); | |
171 } | |
172 | |
173 private: | |
174 views::ImageView* image_view_; | |
175 ColorTheme color_theme_; | |
176 bool tray_icon_; | |
177 | |
178 DISALLOW_COPY_AND_ASSIGN(NetworkTrayView); | |
179 }; | |
180 | |
181 class NetworkDefaultView : public TrayItemMore { | |
182 public: | |
183 explicit NetworkDefaultView(SystemTrayItem* owner) | |
184 : TrayItemMore(owner) { | |
185 Update(); | |
186 } | |
187 | |
188 virtual ~NetworkDefaultView() {} | |
189 | |
190 void Update() { | |
191 NetworkIconInfo info; | |
192 Shell::GetInstance()->tray_delegate()-> | |
193 GetMostRelevantNetworkIcon(&info, true); | |
194 SetImage(&info.image); | |
195 SetLabel(info.description); | |
196 SetAccessibleName(info.description); | |
197 } | |
198 | |
199 private: | |
200 DISALLOW_COPY_AND_ASSIGN(NetworkDefaultView); | |
201 }; | |
202 | |
203 class NetworkDetailedView : public TrayDetailsView { | |
204 public: | |
205 NetworkDetailedView() {} | |
206 | |
207 virtual ~NetworkDetailedView() {} | |
208 | |
209 virtual TrayNetwork::DetailedViewType GetViewType() const = 0; | |
210 | |
211 virtual void Update() = 0; | |
212 }; | |
213 | |
214 class NetworkListDetailedView : public NetworkDetailedView, | |
215 public views::ButtonListener, | |
216 public ViewClickListener { | |
217 public: | |
218 NetworkListDetailedView(user::LoginStatus login) | |
219 : login_(login), | |
220 airplane_(NULL), | |
221 info_icon_(NULL), | |
222 button_wifi_(NULL), | |
223 button_mobile_(NULL), | |
224 view_mobile_account_(NULL), | |
225 setup_mobile_account_(NULL), | |
226 other_wifi_(NULL), | |
227 turn_on_wifi_(NULL), | |
228 other_mobile_(NULL), | |
229 settings_(NULL), | |
230 proxy_settings_(NULL), | |
231 info_bubble_(NULL) { | |
232 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate(); | |
233 delegate->RequestNetworkScan(); | |
234 CreateItems(); | |
235 Update(); | |
236 } | |
237 | |
238 virtual ~NetworkListDetailedView() { | |
239 if (info_bubble_) | |
240 info_bubble_->GetWidget()->CloseNow(); | |
241 } | |
242 | |
243 void CreateItems() { | |
244 RemoveAllChildViews(true); | |
245 | |
246 airplane_ = NULL; | |
247 info_icon_ = NULL; | |
248 button_wifi_ = NULL; | |
249 button_mobile_ = NULL; | |
250 view_mobile_account_ = NULL; | |
251 setup_mobile_account_ = NULL; | |
252 other_wifi_ = NULL; | |
253 turn_on_wifi_ = NULL; | |
254 other_mobile_ = NULL; | |
255 settings_ = NULL; | |
256 proxy_settings_ = NULL; | |
257 | |
258 AppendNetworkEntries(); | |
259 AppendNetworkExtra(); | |
260 AppendHeaderEntry(); | |
261 AppendHeaderButtons(); | |
262 | |
263 Update(); | |
264 } | |
265 | |
266 // Overridden from NetworkDetailedView: | |
267 virtual TrayNetwork::DetailedViewType GetViewType() const OVERRIDE { | |
268 return TrayNetwork::LIST_VIEW; | |
269 } | |
270 | |
271 virtual void Update() OVERRIDE { | |
272 UpdateAvailableNetworkList(); | |
273 UpdateHeaderButtons(); | |
274 UpdateNetworkEntries(); | |
275 UpdateNetworkExtra(); | |
276 | |
277 Layout(); | |
278 } | |
279 | |
280 private: | |
281 void AppendHeaderEntry() { | |
282 CreateSpecialRow(IDS_ASH_STATUS_TRAY_NETWORK, this); | |
283 } | |
284 | |
285 void AppendHeaderButtons() { | |
286 button_wifi_ = new TrayPopupHeaderButton(this, | |
287 IDR_AURA_UBER_TRAY_WIFI_ENABLED, | |
288 IDR_AURA_UBER_TRAY_WIFI_DISABLED, | |
289 IDR_AURA_UBER_TRAY_WIFI_ENABLED_HOVER, | |
290 IDR_AURA_UBER_TRAY_WIFI_DISABLED_HOVER, | |
291 IDS_ASH_STATUS_TRAY_WIFI); | |
292 button_wifi_->SetTooltipText( | |
293 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISABLE_WIFI)); | |
294 button_wifi_->SetToggledTooltipText( | |
295 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ENABLE_WIFI)); | |
296 footer()->AddButton(button_wifi_); | |
297 | |
298 button_mobile_ = new TrayPopupHeaderButton(this, | |
299 IDR_AURA_UBER_TRAY_CELLULAR_ENABLED, | |
300 IDR_AURA_UBER_TRAY_CELLULAR_DISABLED, | |
301 IDR_AURA_UBER_TRAY_CELLULAR_ENABLED_HOVER, | |
302 IDR_AURA_UBER_TRAY_CELLULAR_DISABLED_HOVER, | |
303 IDS_ASH_STATUS_TRAY_CELLULAR); | |
304 button_mobile_->SetTooltipText( | |
305 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISABLE_MOBILE)); | |
306 button_mobile_->SetToggledTooltipText( | |
307 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ENABLE_MOBILE)); | |
308 footer()->AddButton(button_mobile_); | |
309 | |
310 info_icon_ = new TrayPopupHeaderButton(this, | |
311 IDR_AURA_UBER_TRAY_NETWORK_INFO, | |
312 IDR_AURA_UBER_TRAY_NETWORK_INFO, | |
313 IDR_AURA_UBER_TRAY_NETWORK_INFO_HOVER, | |
314 IDR_AURA_UBER_TRAY_NETWORK_INFO_HOVER, | |
315 IDS_ASH_STATUS_TRAY_NETWORK_INFO); | |
316 info_icon_->SetTooltipText( | |
317 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_INFO)); | |
318 footer()->AddButton(info_icon_); | |
319 } | |
320 | |
321 void UpdateHeaderButtons() { | |
322 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate(); | |
323 button_wifi_->SetToggled(!delegate->GetWifiEnabled()); | |
324 button_mobile_->SetToggled(!delegate->GetMobileEnabled()); | |
325 button_mobile_->SetVisible(delegate->GetMobileAvailable()); | |
326 if (proxy_settings_) | |
327 proxy_settings_->SetEnabled(delegate->IsNetworkConnected()); | |
328 } | |
329 | |
330 void AppendNetworkEntries() { | |
331 CreateScrollableList(); | |
332 | |
333 HoverHighlightView* container = new HoverHighlightView(this); | |
334 container->set_fixed_height(kTrayPopupItemHeight); | |
335 container->AddLabel(ui::ResourceBundle::GetSharedInstance(). | |
336 GetLocalizedString(IDS_ASH_STATUS_TRAY_MOBILE_VIEW_ACCOUNT), | |
337 gfx::Font::NORMAL); | |
338 AddChildView(container); | |
339 view_mobile_account_ = container; | |
340 | |
341 container = new HoverHighlightView(this); | |
342 container->set_fixed_height(kTrayPopupItemHeight); | |
343 container->AddLabel(ui::ResourceBundle::GetSharedInstance(). | |
344 GetLocalizedString(IDS_ASH_STATUS_TRAY_SETUP_MOBILE), | |
345 gfx::Font::NORMAL); | |
346 AddChildView(container); | |
347 setup_mobile_account_ = container; | |
348 } | |
349 | |
350 void UpdateAvailableNetworkList() { | |
351 network_list_.clear(); | |
352 Shell::GetInstance()->tray_delegate()->GetAvailableNetworks(&network_list_); | |
353 } | |
354 | |
355 void RefreshNetworkScrollWithUpdatedNetworkList() { | |
356 network_map_.clear(); | |
357 std::set<std::string> new_service_paths; | |
358 | |
359 bool needs_relayout = false; | |
360 views::View* highlighted_view = NULL; | |
361 | |
362 if (service_path_map_.empty()) | |
363 scroll_content()->RemoveAllChildViews(true); | |
364 | |
365 for (size_t i = 0; i < network_list_.size(); ++i) { | |
366 std::map<std::string, HoverHighlightView*>::const_iterator it = | |
367 service_path_map_.find(network_list_[i].service_path); | |
368 HoverHighlightView* container = NULL; | |
369 if (it == service_path_map_.end()) { | |
370 // Create a new view. | |
371 container = new HoverHighlightView(this); | |
372 container->set_fixed_height(kTrayPopupItemHeight); | |
373 container->AddIconAndLabel(network_list_[i].image, | |
374 network_list_[i].description.empty() ? | |
375 network_list_[i].name : network_list_[i].description, | |
376 network_list_[i].highlight ? | |
377 gfx::Font::BOLD : gfx::Font::NORMAL); | |
378 scroll_content()->AddChildViewAt(container, i); | |
379 container->set_border(views::Border::CreateEmptyBorder(0, | |
380 kTrayPopupPaddingHorizontal, 0, 0)); | |
381 needs_relayout = true; | |
382 } else { | |
383 container = it->second; | |
384 container->RemoveAllChildViews(true); | |
385 container->AddIconAndLabel(network_list_[i].image, | |
386 network_list_[i].description.empty() ? | |
387 network_list_[i].name : network_list_[i].description, | |
388 network_list_[i].highlight ? gfx::Font::BOLD : gfx::Font::NORMAL); | |
389 container->Layout(); | |
390 container->SchedulePaint(); | |
391 | |
392 // Reordering the view if necessary. | |
393 views::View* child = scroll_content()->child_at(i); | |
394 if (child != container) { | |
395 scroll_content()->ReorderChildView(container, i); | |
396 needs_relayout = true; | |
397 } | |
398 } | |
399 | |
400 if (network_list_[i].highlight) | |
401 highlighted_view = container; | |
402 network_map_[container] = network_list_[i].service_path; | |
403 service_path_map_[network_list_[i].service_path] = container; | |
404 new_service_paths.insert(network_list_[i].service_path); | |
405 } | |
406 | |
407 std::set<std::string> remove_service_paths; | |
408 for (std::map<std::string, HoverHighlightView*>::const_iterator it = | |
409 service_path_map_.begin(); it != service_path_map_.end(); ++it) { | |
410 if (new_service_paths.find(it->first) == new_service_paths.end()) { | |
411 remove_service_paths.insert(it->first); | |
412 scroll_content()->RemoveChildView(it->second); | |
413 needs_relayout = true; | |
414 } | |
415 } | |
416 | |
417 for (std::set<std::string>::const_iterator remove_it = | |
418 remove_service_paths.begin(); | |
419 remove_it != remove_service_paths.end(); ++remove_it) { | |
420 service_path_map_.erase(*remove_it); | |
421 } | |
422 | |
423 if (needs_relayout) { | |
424 scroll_content()->SizeToPreferredSize(); | |
425 static_cast<views::View*>(scroller())->Layout(); | |
426 if (highlighted_view) | |
427 scroll_content()->ScrollRectToVisible(highlighted_view->bounds()); | |
428 } | |
429 } | |
430 | |
431 void RefreshNetworkScrollWithEmptyNetworkList() { | |
432 service_path_map_.clear(); | |
433 network_map_.clear(); | |
434 scroll_content()->RemoveAllChildViews(true); | |
435 HoverHighlightView* container = new HoverHighlightView(this); | |
436 container->set_fixed_height(kTrayPopupItemHeight); | |
437 | |
438 if (Shell::GetInstance()->tray_delegate()->GetWifiEnabled()) { | |
439 NetworkIconInfo info; | |
440 Shell::GetInstance()->tray_delegate()-> | |
441 GetMostRelevantNetworkIcon(&info, true); | |
442 container->AddIconAndLabel(info.image, | |
443 info.description, | |
444 gfx::Font::NORMAL); | |
445 container->set_border(views::Border::CreateEmptyBorder(0, | |
446 kTrayPopupPaddingHorizontal, 0, 0)); | |
447 | |
448 } else { | |
449 container->AddLabel(ui::ResourceBundle::GetSharedInstance(). | |
450 GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED), | |
451 gfx::Font::NORMAL); | |
452 } | |
453 | |
454 scroll_content()->AddChildViewAt(container, 0); | |
455 scroll_content()->SizeToPreferredSize(); | |
456 static_cast<views::View*>(scroller())->Layout(); | |
457 } | |
458 | |
459 void UpdateNetworkEntries() { | |
460 if (network_list_.size() > 0 ) | |
461 RefreshNetworkScrollWithUpdatedNetworkList(); | |
462 else | |
463 RefreshNetworkScrollWithEmptyNetworkList(); | |
464 | |
465 view_mobile_account_->SetVisible(false); | |
466 setup_mobile_account_->SetVisible(false); | |
467 | |
468 if (login_ == user::LOGGED_IN_NONE) | |
469 return; | |
470 | |
471 std::string carrier_id, topup_url, setup_url; | |
472 if (Shell::GetInstance()->tray_delegate()-> | |
473 GetCellularCarrierInfo(&carrier_id, | |
474 &topup_url, | |
475 &setup_url)) { | |
476 if (carrier_id != carrier_id_) { | |
477 carrier_id_ = carrier_id; | |
478 if (!topup_url.empty()) | |
479 topup_url_ = topup_url; | |
480 } | |
481 | |
482 if (!setup_url.empty()) | |
483 setup_url_ = setup_url; | |
484 | |
485 if (!topup_url_.empty()) | |
486 view_mobile_account_->SetVisible(true); | |
487 if (!setup_url_.empty()) | |
488 setup_mobile_account_->SetVisible(true); | |
489 } | |
490 } | |
491 | |
492 void AppendNetworkExtra() { | |
493 if (login_ == user::LOGGED_IN_LOCKED) | |
494 return; | |
495 | |
496 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
497 | |
498 TrayPopupTextButtonContainer* bottom_row = | |
499 new TrayPopupTextButtonContainer; | |
500 | |
501 other_wifi_ = new TrayPopupTextButton(this, | |
502 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_OTHER_WIFI)); | |
503 bottom_row->AddTextButton(other_wifi_); | |
504 | |
505 turn_on_wifi_ = new TrayPopupTextButton(this, | |
506 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_TURN_ON_WIFI)); | |
507 bottom_row->AddTextButton(turn_on_wifi_); | |
508 | |
509 other_mobile_ = new TrayPopupTextButton(this, | |
510 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_OTHER_MOBILE)); | |
511 bottom_row->AddTextButton(other_mobile_); | |
512 | |
513 CreateSettingsEntry(); | |
514 DCHECK(settings_ || proxy_settings_); | |
515 bottom_row->AddTextButton(settings_ ? settings_ : proxy_settings_); | |
516 | |
517 AddChildView(bottom_row); | |
518 } | |
519 | |
520 void UpdateNetworkExtra() { | |
521 if (login_ == user::LOGGED_IN_LOCKED) | |
522 return; | |
523 | |
524 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate(); | |
525 if (network_list_.size() == 0 && !delegate->GetWifiEnabled()) { | |
526 turn_on_wifi_->SetVisible(true); | |
527 other_wifi_->SetVisible(false); | |
528 } else { | |
529 turn_on_wifi_->SetVisible(false); | |
530 other_wifi_->SetVisible(true); | |
531 other_wifi_->SetEnabled(delegate->GetWifiEnabled()); | |
532 } | |
533 other_mobile_->SetVisible(delegate->GetMobileAvailable() && | |
534 delegate->GetMobileScanSupported()); | |
535 if (other_mobile_->visible()) | |
536 other_mobile_->SetEnabled(delegate->GetMobileEnabled()); | |
537 | |
538 turn_on_wifi_->parent()->Layout(); | |
539 } | |
540 | |
541 // Adds a settings entry when logged in, and an entry for changing proxy | |
542 // settings otherwise. | |
543 void CreateSettingsEntry() { | |
544 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
545 if (login_ != user::LOGGED_IN_NONE) { | |
546 // Settings, only if logged in. | |
547 settings_ = new TrayPopupTextButton(this, | |
548 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS)); | |
549 } else { | |
550 proxy_settings_ = new TrayPopupTextButton(this, | |
551 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_PROXY_SETTINGS)); | |
552 } | |
553 } | |
554 | |
555 views::View* CreateNetworkInfoView() { | |
556 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | |
557 std::string ip_address, ethernet_address, wifi_address; | |
558 Shell::GetInstance()->tray_delegate()->GetNetworkAddresses(&ip_address, | |
559 ðernet_address, &wifi_address); | |
560 | |
561 views::View* container = new views::View; | |
562 container->SetLayoutManager(new | |
563 views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); | |
564 container->set_border(views::Border::CreateEmptyBorder(0, 5, 0, 5)); | |
565 | |
566 // GetNetworkAddresses returns empty strings if no information is available. | |
567 if (!ip_address.empty()) { | |
568 container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString( | |
569 IDS_ASH_STATUS_TRAY_IP), ip_address)); | |
570 } | |
571 if (!ethernet_address.empty()) { | |
572 container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString( | |
573 IDS_ASH_STATUS_TRAY_ETHERNET), ethernet_address)); | |
574 } | |
575 if (!wifi_address.empty()) { | |
576 container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString( | |
577 IDS_ASH_STATUS_TRAY_WIFI), wifi_address)); | |
578 } | |
579 | |
580 // Avoid an empty bubble in the unlikely event that there is no network | |
581 // information at all. | |
582 if (!container->has_children()) { | |
583 container->AddChildView(CreateInfoBubbleLabel(bundle.GetLocalizedString( | |
584 IDS_ASH_STATUS_TRAY_NO_NETWORKS))); | |
585 } | |
586 | |
587 return container; | |
588 } | |
589 | |
590 void ToggleInfoBubble() { | |
591 if (ResetInfoBubble()) | |
592 return; | |
593 | |
594 info_bubble_ = new NonActivatableSettingsBubble( | |
595 info_icon_, CreateNetworkInfoView()); | |
596 views::BubbleDelegateView::CreateBubble(info_bubble_); | |
597 info_bubble_->Show(); | |
598 } | |
599 | |
600 // Returns whether an existing info-bubble was closed. | |
601 bool ResetInfoBubble() { | |
602 if (!info_bubble_) | |
603 return false; | |
604 info_bubble_->GetWidget()->Close(); | |
605 info_bubble_ = NULL; | |
606 return true; | |
607 } | |
608 | |
609 // Overridden from ButtonListener. | |
610 virtual void ButtonPressed(views::Button* sender, | |
611 const ui::Event& event) OVERRIDE { | |
612 ash::SystemTrayDelegate* delegate = | |
613 ash::Shell::GetInstance()->tray_delegate(); | |
614 if (sender == info_icon_) { | |
615 ToggleInfoBubble(); | |
616 return; | |
617 } | |
618 | |
619 // If the info bubble was visible, close it when some other item is clicked | |
620 // on. | |
621 ResetInfoBubble(); | |
622 if (sender == button_wifi_) | |
623 delegate->ToggleWifi(); | |
624 else if (sender == button_mobile_) | |
625 delegate->ToggleMobile(); | |
626 else if (sender == settings_) | |
627 delegate->ShowNetworkSettings(); | |
628 else if (sender == proxy_settings_) | |
629 delegate->ChangeProxySettings(); | |
630 else if (sender == other_mobile_) | |
631 delegate->ShowOtherCellular(); | |
632 else if (sender == other_wifi_) | |
633 delegate->ShowOtherWifi(); | |
634 else if (sender == turn_on_wifi_) | |
635 delegate->ToggleWifi(); | |
636 else | |
637 NOTREACHED(); | |
638 } | |
639 | |
640 // Overridden from ViewClickListener. | |
641 virtual void ClickedOn(views::View* sender) OVERRIDE { | |
642 ash::SystemTrayDelegate* delegate = | |
643 ash::Shell::GetInstance()->tray_delegate(); | |
644 // If the info bubble was visible, close it when some other item is clicked | |
645 // on. | |
646 ResetInfoBubble(); | |
647 | |
648 if (sender == footer()->content()) { | |
649 Shell::GetInstance()->system_tray()->ShowDefaultView(BUBBLE_USE_EXISTING); | |
650 return; | |
651 } | |
652 | |
653 if (login_ == user::LOGGED_IN_LOCKED) | |
654 return; | |
655 | |
656 if (sender == view_mobile_account_) { | |
657 delegate->ShowCellularURL(topup_url_); | |
658 } else if (sender == setup_mobile_account_) { | |
659 delegate->ShowCellularURL(setup_url_); | |
660 } else if (sender == airplane_) { | |
661 delegate->ToggleAirplaneMode(); | |
662 } else { | |
663 std::map<views::View*, std::string>::iterator find; | |
664 find = network_map_.find(sender); | |
665 if (find != network_map_.end()) { | |
666 std::string network_id = find->second; | |
667 delegate->ConnectToNetwork(network_id); | |
668 } | |
669 } | |
670 } | |
671 | |
672 std::string carrier_id_; | |
673 std::string topup_url_; | |
674 std::string setup_url_; | |
675 | |
676 user::LoginStatus login_; | |
677 std::map<views::View*, std::string> network_map_; | |
678 std::map<std::string, HoverHighlightView*> service_path_map_; | |
679 std::vector<NetworkIconInfo> network_list_; | |
680 views::View* airplane_; | |
681 TrayPopupHeaderButton* info_icon_; | |
682 TrayPopupHeaderButton* button_wifi_; | |
683 TrayPopupHeaderButton* button_mobile_; | |
684 views::View* view_mobile_account_; | |
685 views::View* setup_mobile_account_; | |
686 TrayPopupTextButton* other_wifi_; | |
687 TrayPopupTextButton* turn_on_wifi_; | |
688 TrayPopupTextButton* other_mobile_; | |
689 TrayPopupTextButton* settings_; | |
690 TrayPopupTextButton* proxy_settings_; | |
691 | |
692 views::BubbleDelegateView* info_bubble_; | |
693 | |
694 DISALLOW_COPY_AND_ASSIGN(NetworkListDetailedView); | |
695 }; | |
696 | |
697 class NetworkWifiDetailedView : public NetworkDetailedView { | |
698 public: | |
699 explicit NetworkWifiDetailedView(bool wifi_enabled) { | |
700 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, | |
701 kTrayPopupPaddingHorizontal, | |
702 10, | |
703 kTrayPopupPaddingBetweenItems)); | |
704 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | |
705 views::ImageView* image = new views::ImageView; | |
706 const int image_id = wifi_enabled ? | |
707 IDR_AURA_UBER_TRAY_WIFI_ENABLED : IDR_AURA_UBER_TRAY_WIFI_DISABLED; | |
708 image->SetImage(bundle.GetImageNamed(image_id).ToImageSkia()); | |
709 AddChildView(image); | |
710 | |
711 const int string_id = wifi_enabled ? | |
712 IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED: | |
713 IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED; | |
714 views::Label* label = | |
715 new views::Label(bundle.GetLocalizedString(string_id)); | |
716 label->SetMultiLine(true); | |
717 label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
718 AddChildView(label); | |
719 } | |
720 | |
721 virtual ~NetworkWifiDetailedView() {} | |
722 | |
723 // Overridden from NetworkDetailedView: | |
724 virtual TrayNetwork::DetailedViewType GetViewType() const OVERRIDE { | |
725 return TrayNetwork::WIFI_VIEW; | |
726 } | |
727 | |
728 virtual void Update() OVERRIDE {} | |
729 | |
730 private: | |
731 DISALLOW_COPY_AND_ASSIGN(NetworkWifiDetailedView); | |
732 }; | |
733 | |
734 class NetworkMessageView : public views::View, | |
735 public views::LinkListener { | |
736 public: | |
737 NetworkMessageView(TrayNetwork* tray, | |
738 TrayNetwork::MessageType message_type, | |
739 const NetworkMessages::Message& network_msg) | |
740 : tray_(tray), | |
741 message_type_(message_type) { | |
742 SetLayoutManager( | |
743 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); | |
744 | |
745 if (!network_msg.title.empty()) { | |
746 views::Label* title = new views::Label(network_msg.title); | |
747 title->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
748 title->SetFont(title->font().DeriveFont(0, gfx::Font::BOLD)); | |
749 AddChildView(title); | |
750 } | |
751 | |
752 if (!network_msg.message.empty()) { | |
753 views::Label* message = new views::Label(network_msg.message); | |
754 message->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
755 message->SetMultiLine(true); | |
756 message->SizeToFit(kTrayNotificationContentsWidth); | |
757 AddChildView(message); | |
758 } | |
759 | |
760 if (!network_msg.links.empty()) { | |
761 for (size_t i = 0; i < network_msg.links.size(); ++i) { | |
762 views::Link* link = new views::Link(network_msg.links[i]); | |
763 link->set_id(i); | |
764 link->set_listener(this); | |
765 link->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
766 link->SetMultiLine(true); | |
767 link->SizeToFit(kTrayNotificationContentsWidth); | |
768 AddChildView(link); | |
769 } | |
770 } | |
771 } | |
772 | |
773 virtual ~NetworkMessageView() { | |
774 } | |
775 | |
776 // Overridden from views::LinkListener. | |
777 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE { | |
778 tray_->LinkClicked(message_type_, source->id()); | |
779 } | |
780 | |
781 TrayNetwork::MessageType message_type() const { return message_type_; } | |
782 | |
783 private: | |
784 TrayNetwork* tray_; | |
785 TrayNetwork::MessageType message_type_; | |
786 | |
787 DISALLOW_COPY_AND_ASSIGN(NetworkMessageView); | |
788 }; | |
789 | |
790 class NetworkNotificationView : public TrayNotificationView { | |
791 public: | |
792 explicit NetworkNotificationView(TrayNetwork* tray) | |
793 : TrayNotificationView(tray, 0) { | |
794 CreateMessageView(); | |
795 InitView(network_message_view_); | |
796 SetIconImage(*ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
797 GetMessageIcon(network_message_view_->message_type()))); | |
798 } | |
799 | |
800 // Overridden from TrayNotificationView. | |
801 virtual void OnClose() OVERRIDE { | |
802 tray_network()->ClearNetworkMessage(network_message_view_->message_type()); | |
803 } | |
804 | |
805 virtual void OnClickAction() OVERRIDE { | |
806 if (network_message_view_->message_type() != | |
807 TrayNetwork::MESSAGE_DATA_PROMO) | |
808 tray()->PopupDetailedView(0, true); | |
809 } | |
810 | |
811 void Update() { | |
812 CreateMessageView(); | |
813 UpdateViewAndImage(network_message_view_, | |
814 *ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
815 GetMessageIcon(network_message_view_->message_type()))); | |
816 } | |
817 | |
818 private: | |
819 TrayNetwork* tray_network() { | |
820 return static_cast<TrayNetwork*>(tray()); | |
821 } | |
822 | |
823 void CreateMessageView() { | |
824 // Display the first (highest priority) message. | |
825 CHECK(!tray_network()->messages()->messages().empty()); | |
826 NetworkMessages::MessageMap::const_iterator iter = | |
827 tray_network()->messages()->messages().begin(); | |
828 network_message_view_ = | |
829 new NetworkMessageView(tray_network(), iter->first, iter->second); | |
830 } | |
831 | |
832 tray::NetworkMessageView* network_message_view_; | |
833 | |
834 DISALLOW_COPY_AND_ASSIGN(NetworkNotificationView); | |
835 }; | |
836 | |
837 } // namespace tray | |
838 | |
839 TrayNetwork::TrayNetwork() | |
840 : tray_(NULL), | |
841 default_(NULL), | |
842 detailed_(NULL), | |
843 notification_(NULL), | |
844 messages_(new tray::NetworkMessages()), | |
845 request_wifi_view_(false) { | |
846 } | |
847 | |
848 TrayNetwork::~TrayNetwork() { | |
849 } | |
850 | |
851 views::View* TrayNetwork::CreateTrayView(user::LoginStatus status) { | |
852 CHECK(tray_ == NULL); | |
853 tray_ = new tray::NetworkTrayView(tray::LIGHT, true /*tray_icon*/); | |
854 return tray_; | |
855 } | |
856 | |
857 views::View* TrayNetwork::CreateDefaultView(user::LoginStatus status) { | |
858 CHECK(default_ == NULL); | |
859 default_ = new tray::NetworkDefaultView(this); | |
860 return default_; | |
861 } | |
862 | |
863 views::View* TrayNetwork::CreateDetailedView(user::LoginStatus status) { | |
864 CHECK(detailed_ == NULL); | |
865 // Clear any notifications when showing the detailed view. | |
866 messages_->messages().clear(); | |
867 HideNotificationView(); | |
868 if (request_wifi_view_) { | |
869 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate(); | |
870 // The Wi-Fi state is not toggled yet at this point. | |
871 detailed_ = new tray::NetworkWifiDetailedView(!delegate->GetWifiEnabled()); | |
872 request_wifi_view_ = false; | |
873 } else { | |
874 detailed_ = new tray::NetworkListDetailedView(status); | |
875 } | |
876 return detailed_; | |
877 } | |
878 | |
879 views::View* TrayNetwork::CreateNotificationView(user::LoginStatus status) { | |
880 CHECK(notification_ == NULL); | |
881 if (messages_->messages().empty()) | |
882 return NULL; // Message has already been cleared. | |
883 notification_ = new tray::NetworkNotificationView(this); | |
884 return notification_; | |
885 } | |
886 | |
887 void TrayNetwork::DestroyTrayView() { | |
888 tray_ = NULL; | |
889 } | |
890 | |
891 void TrayNetwork::DestroyDefaultView() { | |
892 default_ = NULL; | |
893 } | |
894 | |
895 void TrayNetwork::DestroyDetailedView() { | |
896 detailed_ = NULL; | |
897 } | |
898 | |
899 void TrayNetwork::DestroyNotificationView() { | |
900 notification_ = NULL; | |
901 } | |
902 | |
903 void TrayNetwork::UpdateAfterLoginStatusChange(user::LoginStatus status) { | |
904 } | |
905 | |
906 void TrayNetwork::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) { | |
907 SetTrayImageItemBorder(tray_, alignment); | |
908 } | |
909 | |
910 void TrayNetwork::OnNetworkRefresh(const NetworkIconInfo& info) { | |
911 if (tray_) | |
912 tray_->Update(info); | |
913 if (default_) | |
914 default_->Update(); | |
915 if (detailed_) | |
916 detailed_->Update(); | |
917 } | |
918 | |
919 void TrayNetwork::SetNetworkMessage(NetworkTrayDelegate* delegate, | |
920 MessageType message_type, | |
921 const string16& title, | |
922 const string16& message, | |
923 const std::vector<string16>& links) { | |
924 messages_->messages()[message_type] = | |
925 tray::NetworkMessages::Message(delegate, title, message, links); | |
926 if (notification_) | |
927 notification_->Update(); | |
928 else | |
929 ShowNotificationView(); | |
930 } | |
931 | |
932 void TrayNetwork::ClearNetworkMessage(MessageType message_type) { | |
933 messages_->messages().erase(message_type); | |
934 if (messages_->messages().empty()) { | |
935 HideNotificationView(); | |
936 return; | |
937 } | |
938 if (notification_) | |
939 notification_->Update(); | |
940 else | |
941 ShowNotificationView(); | |
942 } | |
943 | |
944 void TrayNetwork::OnWillToggleWifi() { | |
945 if (!detailed_ || detailed_->GetViewType() == WIFI_VIEW) { | |
946 request_wifi_view_ = true; | |
947 PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false); | |
948 } | |
949 } | |
950 | |
951 void TrayNetwork::LinkClicked(MessageType message_type, int link_id) { | |
952 tray::NetworkMessages::MessageMap::const_iterator iter = | |
953 messages()->messages().find(message_type); | |
954 if (iter != messages()->messages().end() && iter->second.delegate) | |
955 iter->second.delegate->NotificationLinkClicked(link_id); | |
956 } | |
957 | |
958 } // namespace internal | |
959 } // namespace ash | |
OLD | NEW |