// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "athena/system/status_icon_container_view.h" #include "athena/resources/athena_resources.h" #include "athena/system/network_selector.h" #include "base/bind.h" #include "base/macros.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/power_manager/power_supply_properties.pb.h" #include "chromeos/dbus/power_manager_client.h" #include "chromeos/dbus/update_engine_client.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" #include "chromeos/network/network_state_handler_observer.h" #include "chromeos/network/network_type_pattern.h" #include "extensions/shell/common/version.h" #include "ui/aura/window.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_operations.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" namespace athena { namespace { views::Label* CreateLabel(SystemUI::ColorScheme color_scheme, const std::string& text) { views::Label* label = new views::Label(base::UTF8ToUTF16(text)); label->SetEnabledColor((color_scheme == SystemUI::COLOR_SCHEME_LIGHT) ? SK_ColorWHITE : SK_ColorDKGRAY); label->SetAutoColorReadabilityEnabled(false); label->SetSubpixelRenderingEnabled(false); label->SetFontList(gfx::FontList().DeriveWithStyle(gfx::Font::BOLD)); return label; } } // namespace class StatusIconContainerView::PowerStatus : public chromeos::PowerManagerClient::Observer { public: PowerStatus(SystemUI::ColorScheme color_scheme, views::ImageView* icon) : color_scheme_(color_scheme), icon_(icon) { chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver( this); chromeos::DBusThreadManager::Get() ->GetPowerManagerClient() ->RequestStatusUpdate(); } ~PowerStatus() override { chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver( this); } private: const gfx::ImageSkia GetPowerIcon( const power_manager::PowerSupplyProperties& proto) const { // Width and height of battery images. const int kBatteryImageHeight = 25; const int kBatteryImageWidth = 25; // Number of different power states. const int kNumPowerImages = 15; gfx::Image all = ui::ResourceBundle::GetSharedInstance().GetImageNamed( (color_scheme_ == SystemUI::COLOR_SCHEME_LIGHT) ? IDR_AURA_UBER_TRAY_POWER_SMALL : IDR_AURA_UBER_TRAY_POWER_SMALL_DARK); int horiz_offset = IsCharging(proto) ? 1 : 0; int vert_offset = -1; if (proto.battery_percent() >= 100) { vert_offset = kNumPowerImages - 1; } else { vert_offset = static_cast((kNumPowerImages - 1) * proto.battery_percent() / 100); vert_offset = std::max(std::min(vert_offset, kNumPowerImages - 2), 0); } gfx::Rect region(horiz_offset * kBatteryImageWidth, vert_offset * kBatteryImageHeight, kBatteryImageWidth, kBatteryImageHeight); return gfx::ImageSkiaOperations::ExtractSubset(*all.ToImageSkia(), region); } bool IsCharging(const power_manager::PowerSupplyProperties& proto) const { return proto.external_power() != power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED; } // chromeos::PowerManagerClient::Observer: virtual void PowerChanged( const power_manager::PowerSupplyProperties& proto) override { icon_->SetImage(GetPowerIcon(proto)); } SystemUI::ColorScheme color_scheme_; views::ImageView* icon_; DISALLOW_COPY_AND_ASSIGN(PowerStatus); }; class StatusIconContainerView::NetworkStatus : public chromeos::NetworkStateHandlerObserver { public: explicit NetworkStatus(views::Label* label) : label_(label) { chromeos::NetworkStateHandler* handler = chromeos::NetworkHandler::Get()->network_state_handler(); handler->AddObserver(this, FROM_HERE); } ~NetworkStatus() override { chromeos::NetworkStateHandler* handler = chromeos::NetworkHandler::Get()->network_state_handler(); handler->RemoveObserver(this, FROM_HERE); } private: void Update() { std::string status = ""; chromeos::NetworkStateHandler* handler = chromeos::NetworkHandler::Get()->network_state_handler(); const chromeos::NetworkState* network = handler->DefaultNetwork(); if (!network) { network = handler->ConnectedNetworkByType( chromeos::NetworkTypePattern::NonVirtual()); } if (network) { status = base::StringPrintf( "%s (%s)", network->ip_address().c_str(), network->name().c_str()); } label_->SetText(base::UTF8ToUTF16(status)); } // chromeos::NetworkStateHandlerObserver: virtual void DefaultNetworkChanged( const chromeos::NetworkState* network) override { Update(); } virtual void NetworkConnectionStateChanged( const chromeos::NetworkState* network) override { Update(); } virtual void NetworkPropertiesUpdated( const chromeos::NetworkState* network) override { Update(); } views::Label* label_; DISALLOW_COPY_AND_ASSIGN(NetworkStatus); }; void StartUpdateCallback( chromeos::UpdateEngineClient::UpdateCheckResult result) { VLOG(1) << "Callback from RequestUpdateCheck, result " << result; } class StatusIconContainerView::UpdateStatus : public chromeos::UpdateEngineClient::Observer { public: UpdateStatus(SystemUI::ColorScheme color_scheme, views::ImageView* icon) : color_scheme_(color_scheme), icon_(icon) { chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->AddObserver( this); chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()-> RequestUpdateCheck(base::Bind(StartUpdateCallback)); } ~UpdateStatus() override { chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver( this); } // chromeos::UpdateEngineClient::Observer: virtual void UpdateStatusChanged( const chromeos::UpdateEngineClient::Status& status) override { if (status.status != chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) { return; } int image_id = (color_scheme_ == SystemUI::COLOR_SCHEME_LIGHT) ? IDR_AURA_UBER_TRAY_UPDATE : IDR_AURA_UBER_TRAY_UPDATE_DARK; icon_->SetImage( ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(image_id)); } private: SystemUI::ColorScheme color_scheme_; views::ImageView* icon_; DISALLOW_COPY_AND_ASSIGN(UpdateStatus); }; StatusIconContainerView::StatusIconContainerView( SystemUI::ColorScheme color_scheme) { const int kHorizontalSpacing = 10; const int kVerticalSpacing = 3; const int kBetweenChildSpacing = 10; SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, kHorizontalSpacing, kVerticalSpacing, kBetweenChildSpacing)); std::string version_text = base::StringPrintf("%s (Build %s)", PRODUCT_VERSION, LAST_CHANGE); AddChildView(CreateLabel(color_scheme, version_text)); AddChildView(CreateLabel(color_scheme, "Network:")); views::Label* network_label = CreateLabel(color_scheme, std::string()); AddChildView(network_label); if (chromeos::NetworkHandler::IsInitialized()) network_status_.reset(new NetworkStatus(network_label)); views::ImageView* battery_view = new views::ImageView(); AddChildView(battery_view); power_status_.reset(new PowerStatus(color_scheme, battery_view)); views::ImageView* update_view = new views::ImageView(); AddChildView(update_view); update_status_.reset(new UpdateStatus(color_scheme, update_view)); } StatusIconContainerView::~StatusIconContainerView() { } bool StatusIconContainerView::OnMousePressed(const ui::MouseEvent& event) { CreateNetworkSelector(); return true; } void StatusIconContainerView::OnGestureEvent(ui::GestureEvent* event) { if (event->type() == ui::ET_GESTURE_TAP) { CreateNetworkSelector(); event->SetHandled(); } } void StatusIconContainerView::ChildPreferredSizeChanged(views::View* child) { PreferredSizeChanged(); } } // namespace athena