• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "athena/system/status_icon_container_view.h"
6 
7 #include "athena/resources/athena_resources.h"
8 #include "athena/system/network_selector.h"
9 #include "base/bind.h"
10 #include "base/macros.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chromeos/dbus/dbus_thread_manager.h"
14 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
15 #include "chromeos/dbus/power_manager_client.h"
16 #include "chromeos/dbus/update_engine_client.h"
17 #include "chromeos/network/network_state.h"
18 #include "chromeos/network/network_state_handler.h"
19 #include "chromeos/network/network_state_handler_observer.h"
20 #include "chromeos/network/network_type_pattern.h"
21 #include "extensions/shell/common/version.h"
22 #include "ui/aura/window.h"
23 #include "ui/base/resource/resource_bundle.h"
24 #include "ui/gfx/image/image.h"
25 #include "ui/gfx/image/image_skia.h"
26 #include "ui/gfx/image/image_skia_operations.h"
27 #include "ui/views/controls/image_view.h"
28 #include "ui/views/controls/label.h"
29 #include "ui/views/layout/box_layout.h"
30 
31 namespace athena {
32 namespace {
33 
CreateLabel(SystemUI::ColorScheme color_scheme,const std::string & text)34 views::Label* CreateLabel(SystemUI::ColorScheme color_scheme,
35                           const std::string& text) {
36   views::Label* label = new views::Label(base::UTF8ToUTF16(text));
37   label->SetEnabledColor((color_scheme == SystemUI::COLOR_SCHEME_LIGHT)
38                              ? SK_ColorWHITE
39                              : SK_ColorDKGRAY);
40   label->SetAutoColorReadabilityEnabled(false);
41   label->SetSubpixelRenderingEnabled(false);
42   label->SetFontList(gfx::FontList().DeriveWithStyle(gfx::Font::BOLD));
43   return label;
44 }
45 
46 }  // namespace
47 
48 class StatusIconContainerView::PowerStatus
49     : public chromeos::PowerManagerClient::Observer {
50  public:
PowerStatus(SystemUI::ColorScheme color_scheme,views::ImageView * icon)51   PowerStatus(SystemUI::ColorScheme color_scheme,
52               views::ImageView* icon)
53       : color_scheme_(color_scheme),
54         icon_(icon) {
55     chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(
56         this);
57     chromeos::DBusThreadManager::Get()
58         ->GetPowerManagerClient()
59         ->RequestStatusUpdate();
60   }
61 
~PowerStatus()62   virtual ~PowerStatus() {
63     chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(
64         this);
65   }
66 
67  private:
GetPowerIcon(const power_manager::PowerSupplyProperties & proto) const68   const gfx::ImageSkia GetPowerIcon(
69       const power_manager::PowerSupplyProperties& proto) const {
70     // Width and height of battery images.
71     const int kBatteryImageHeight = 25;
72     const int kBatteryImageWidth = 25;
73 
74     // Number of different power states.
75     const int kNumPowerImages = 15;
76 
77     gfx::Image all = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
78         (color_scheme_ == SystemUI::COLOR_SCHEME_LIGHT)
79             ? IDR_AURA_UBER_TRAY_POWER_SMALL
80             : IDR_AURA_UBER_TRAY_POWER_SMALL_DARK);
81     int horiz_offset = IsCharging(proto) ? 1 : 0;
82     int vert_offset = -1;
83     if (proto.battery_percent() >= 100) {
84       vert_offset = kNumPowerImages - 1;
85     } else {
86       vert_offset = static_cast<int>((kNumPowerImages - 1) *
87                                      proto.battery_percent() / 100);
88       vert_offset = std::max(std::min(vert_offset, kNumPowerImages - 2), 0);
89     }
90     gfx::Rect region(horiz_offset * kBatteryImageWidth,
91                      vert_offset * kBatteryImageHeight,
92                      kBatteryImageWidth,
93                      kBatteryImageHeight);
94     return gfx::ImageSkiaOperations::ExtractSubset(*all.ToImageSkia(), region);
95   }
96 
IsCharging(const power_manager::PowerSupplyProperties & proto) const97   bool IsCharging(const power_manager::PowerSupplyProperties& proto) const {
98     return proto.external_power() !=
99            power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED;
100   }
101 
102   // chromeos::PowerManagerClient::Observer:
PowerChanged(const power_manager::PowerSupplyProperties & proto)103   virtual void PowerChanged(
104       const power_manager::PowerSupplyProperties& proto) OVERRIDE {
105     icon_->SetImage(GetPowerIcon(proto));
106   }
107 
108   SystemUI::ColorScheme color_scheme_;
109   views::ImageView* icon_;
110 
111   DISALLOW_COPY_AND_ASSIGN(PowerStatus);
112 };
113 
114 class StatusIconContainerView::NetworkStatus
115     : public chromeos::NetworkStateHandlerObserver {
116  public:
NetworkStatus(views::Label * label)117   explicit NetworkStatus(views::Label* label) : label_(label) {
118     chromeos::NetworkStateHandler* handler =
119         chromeos::NetworkHandler::Get()->network_state_handler();
120     handler->AddObserver(this, FROM_HERE);
121   }
122 
~NetworkStatus()123   virtual ~NetworkStatus() {
124     chromeos::NetworkStateHandler* handler =
125         chromeos::NetworkHandler::Get()->network_state_handler();
126     handler->RemoveObserver(this, FROM_HERE);
127   }
128 
129  private:
Update()130   void Update() {
131     std::string status = "<unknown>";
132     chromeos::NetworkStateHandler* handler =
133         chromeos::NetworkHandler::Get()->network_state_handler();
134     const chromeos::NetworkState* network = handler->DefaultNetwork();
135     if (!network) {
136       network = handler->ConnectedNetworkByType(
137           chromeos::NetworkTypePattern::NonVirtual());
138     }
139     if (network) {
140       status = base::StringPrintf(
141           "%s (%s)", network->ip_address().c_str(), network->name().c_str());
142     }
143     label_->SetText(base::UTF8ToUTF16(status));
144   }
145 
146   // chromeos::NetworkStateHandlerObserver:
DefaultNetworkChanged(const chromeos::NetworkState * network)147   virtual void DefaultNetworkChanged(
148       const chromeos::NetworkState* network) OVERRIDE {
149     Update();
150   }
151 
NetworkConnectionStateChanged(const chromeos::NetworkState * network)152   virtual void NetworkConnectionStateChanged(
153       const chromeos::NetworkState* network) OVERRIDE {
154     Update();
155   }
156 
NetworkPropertiesUpdated(const chromeos::NetworkState * network)157   virtual void NetworkPropertiesUpdated(
158       const chromeos::NetworkState* network) OVERRIDE {
159     Update();
160   }
161 
162   views::Label* label_;
163 
164   DISALLOW_COPY_AND_ASSIGN(NetworkStatus);
165 };
166 
StartUpdateCallback(chromeos::UpdateEngineClient::UpdateCheckResult result)167 void StartUpdateCallback(
168     chromeos::UpdateEngineClient::UpdateCheckResult result) {
169   VLOG(1) << "Callback from RequestUpdateCheck, result " << result;
170 }
171 
172 class StatusIconContainerView::UpdateStatus
173     : public chromeos::UpdateEngineClient::Observer {
174  public:
UpdateStatus(SystemUI::ColorScheme color_scheme,views::ImageView * icon)175   UpdateStatus(SystemUI::ColorScheme color_scheme, views::ImageView* icon)
176       : color_scheme_(color_scheme),
177         icon_(icon) {
178     chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->AddObserver(
179         this);
180     chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->
181         RequestUpdateCheck(base::Bind(StartUpdateCallback));
182   }
183 
~UpdateStatus()184   virtual ~UpdateStatus() {
185     chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(
186         this);
187   }
188 
189   // chromeos::UpdateEngineClient::Observer:
UpdateStatusChanged(const chromeos::UpdateEngineClient::Status & status)190   virtual void UpdateStatusChanged(
191       const chromeos::UpdateEngineClient::Status& status) OVERRIDE {
192     if (status.status !=
193         chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) {
194       return;
195     }
196     int image_id = (color_scheme_ == SystemUI::COLOR_SCHEME_LIGHT)
197                        ? IDR_AURA_UBER_TRAY_UPDATE
198                        : IDR_AURA_UBER_TRAY_UPDATE_DARK;
199     icon_->SetImage(
200         ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(image_id));
201   }
202 
203  private:
204   SystemUI::ColorScheme color_scheme_;
205   views::ImageView* icon_;
206 
207   DISALLOW_COPY_AND_ASSIGN(UpdateStatus);
208 };
209 
StatusIconContainerView(SystemUI::ColorScheme color_scheme,aura::Window * system_modal_container)210 StatusIconContainerView::StatusIconContainerView(
211     SystemUI::ColorScheme color_scheme,
212     aura::Window* system_modal_container)
213     : system_modal_container_(system_modal_container) {
214   const int kHorizontalSpacing = 10;
215   const int kVerticalSpacing = 3;
216   const int kBetweenChildSpacing = 10;
217   SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
218                                         kHorizontalSpacing,
219                                         kVerticalSpacing,
220                                         kBetweenChildSpacing));
221 
222   std::string version_text =
223       base::StringPrintf("%s (Build %s)", PRODUCT_VERSION, LAST_CHANGE);
224   AddChildView(CreateLabel(color_scheme, version_text));
225 
226   AddChildView(CreateLabel(color_scheme, "Network:"));
227   views::Label* network_label = CreateLabel(color_scheme, std::string());
228   AddChildView(network_label);
229   network_status_.reset(new NetworkStatus(network_label));
230 
231   views::ImageView* battery_view = new views::ImageView();
232   AddChildView(battery_view);
233   power_status_.reset(new PowerStatus(color_scheme, battery_view));
234 
235   views::ImageView* update_view = new views::ImageView();
236   AddChildView(update_view);
237   update_status_.reset(new UpdateStatus(color_scheme, update_view));
238 }
239 
~StatusIconContainerView()240 StatusIconContainerView::~StatusIconContainerView() {
241 }
242 
OnMousePressed(const ui::MouseEvent & event)243 bool StatusIconContainerView::OnMousePressed(const ui::MouseEvent& event) {
244   CreateNetworkSelector(system_modal_container_);
245   return true;
246 }
247 
OnGestureEvent(ui::GestureEvent * event)248 void StatusIconContainerView::OnGestureEvent(ui::GestureEvent* event) {
249   if (event->type() == ui::ET_GESTURE_TAP) {
250     CreateNetworkSelector(system_modal_container_);
251     event->SetHandled();
252   }
253 }
254 
ChildPreferredSizeChanged(views::View * child)255 void StatusIconContainerView::ChildPreferredSizeChanged(views::View* child) {
256   PreferredSizeChanged();
257 }
258 
259 }  // namespace athena
260