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/chromeos/power/power_status_view.h" 6 7 #include "ash/shell.h" 8 #include "ash/shell_delegate.h" 9 #include "ash/system/chromeos/power/power_status.h" 10 #include "ash/system/chromeos/power/tray_power.h" 11 #include "ash/system/tray/fixed_sized_image_view.h" 12 #include "ash/system/tray/tray_constants.h" 13 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "grit/ash_strings.h" 16 #include "ui/base/l10n/l10n_util.h" 17 #include "ui/base/l10n/time_format.h" 18 #include "ui/base/resource/resource_bundle.h" 19 #include "ui/views/controls/image_view.h" 20 #include "ui/views/controls/label.h" 21 #include "ui/views/layout/box_layout.h" 22 #include "ui/views/layout/grid_layout.h" 23 24 namespace ash { 25 namespace internal { 26 27 // Padding between battery status text and battery icon on default view. 28 const int kPaddingBetweenBatteryStatusAndIcon = 3; 29 30 PowerStatusView::PowerStatusView(ViewType view_type, 31 bool default_view_right_align) 32 : default_view_right_align_(default_view_right_align), 33 status_label_(NULL), 34 time_label_(NULL), 35 time_status_label_(NULL), 36 percentage_label_(NULL), 37 icon_(NULL), 38 view_type_(view_type) { 39 PowerStatus::Get()->AddObserver(this); 40 if (view_type == VIEW_DEFAULT) { 41 time_status_label_ = new views::Label; 42 percentage_label_ = new views::Label; 43 percentage_label_->SetEnabledColor(kHeaderTextColorNormal); 44 LayoutDefaultView(); 45 } else { 46 status_label_ = new views::Label; 47 time_label_ = new views::Label; 48 LayoutNotificationView(); 49 } 50 OnPowerStatusChanged(); 51 } 52 53 PowerStatusView::~PowerStatusView() { 54 PowerStatus::Get()->RemoveObserver(this); 55 } 56 57 void PowerStatusView::OnPowerStatusChanged() { 58 view_type_ == VIEW_DEFAULT ? 59 UpdateTextForDefaultView() : UpdateTextForNotificationView(); 60 61 if (icon_) { 62 icon_->SetImage( 63 PowerStatus::Get()->GetBatteryImage(PowerStatus::ICON_DARK)); 64 icon_->SetVisible(true); 65 } 66 } 67 68 void PowerStatusView::LayoutDefaultView() { 69 if (default_view_right_align_) { 70 views::BoxLayout* layout = 71 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 72 kPaddingBetweenBatteryStatusAndIcon); 73 SetLayoutManager(layout); 74 75 AddChildView(percentage_label_); 76 AddChildView(time_status_label_); 77 78 icon_ = new views::ImageView; 79 AddChildView(icon_); 80 } else { 81 // PowerStatusView is left aligned on the system tray pop up item. 82 views::BoxLayout* layout = 83 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 84 kTrayPopupPaddingBetweenItems); 85 SetLayoutManager(layout); 86 87 icon_ = 88 new ash::internal::FixedSizedImageView(0, ash::kTrayPopupItemHeight); 89 AddChildView(icon_); 90 91 AddChildView(percentage_label_); 92 AddChildView(time_status_label_); 93 } 94 } 95 96 void PowerStatusView::LayoutNotificationView() { 97 SetLayoutManager( 98 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); 99 status_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 100 AddChildView(status_label_); 101 102 time_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 103 AddChildView(time_label_); 104 } 105 106 void PowerStatusView::UpdateTextForDefaultView() { 107 const PowerStatus& status = *PowerStatus::Get(); 108 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 109 base::string16 battery_percentage; 110 base::string16 battery_time_status; 111 112 if (status.IsBatteryFull()) { 113 battery_time_status = 114 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_FULL); 115 } else { 116 battery_percentage = l10n_util::GetStringFUTF16( 117 IDS_ASH_STATUS_TRAY_BATTERY_PERCENT_ONLY, 118 base::IntToString16(status.GetRoundedBatteryPercent())); 119 if (status.IsUsbChargerConnected()) { 120 battery_time_status = rb.GetLocalizedString( 121 IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE); 122 } else if (status.IsBatteryTimeBeingCalculated()) { 123 battery_time_status = 124 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING); 125 } else { 126 base::TimeDelta time = status.IsBatteryCharging() ? 127 status.GetBatteryTimeToFull() : status.GetBatteryTimeToEmpty(); 128 if (PowerStatus::ShouldDisplayBatteryTime(time) && 129 !status.IsBatteryDischargingOnLinePower()) { 130 int hour = 0, min = 0; 131 PowerStatus::SplitTimeIntoHoursAndMinutes(time, &hour, &min); 132 base::string16 minute = min < 10 ? 133 ASCIIToUTF16("0") + base::IntToString16(min) : 134 base::IntToString16(min); 135 battery_time_status = 136 l10n_util::GetStringFUTF16( 137 status.IsBatteryCharging() ? 138 IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL_SHORT : 139 IDS_ASH_STATUS_TRAY_BATTERY_TIME_LEFT_SHORT, 140 base::IntToString16(hour), 141 minute); 142 } 143 } 144 battery_percentage = battery_time_status.empty() ? 145 battery_percentage : battery_percentage + ASCIIToUTF16(" - "); 146 } 147 percentage_label_->SetVisible(!battery_percentage.empty()); 148 percentage_label_->SetText(battery_percentage); 149 time_status_label_->SetVisible(!battery_time_status.empty()); 150 time_status_label_->SetText(battery_time_status); 151 } 152 153 void PowerStatusView::UpdateTextForNotificationView() { 154 const PowerStatus& status = *PowerStatus::Get(); 155 if (status.IsBatteryFull()) { 156 status_label_->SetText( 157 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( 158 IDS_ASH_STATUS_TRAY_BATTERY_FULL)); 159 } else { 160 status_label_->SetText( 161 l10n_util::GetStringFUTF16( 162 IDS_ASH_STATUS_TRAY_BATTERY_PERCENT, 163 base::IntToString16(status.GetRoundedBatteryPercent()))); 164 } 165 166 const base::TimeDelta time = status.IsBatteryCharging() ? 167 status.GetBatteryTimeToFull() : status.GetBatteryTimeToEmpty(); 168 169 if (status.IsUsbChargerConnected()) { 170 time_label_->SetText( 171 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( 172 IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE)); 173 } else if (status.IsBatteryTimeBeingCalculated()) { 174 time_label_->SetText( 175 ui::ResourceBundle::GetSharedInstance().GetLocalizedString( 176 IDS_ASH_STATUS_TRAY_BATTERY_CALCULATING)); 177 } else if (PowerStatus::ShouldDisplayBatteryTime(time) && 178 !status.IsBatteryDischargingOnLinePower()) { 179 int hour = 0, min = 0; 180 PowerStatus::SplitTimeIntoHoursAndMinutes(time, &hour, &min); 181 if (status.IsBatteryCharging()) { 182 time_label_->SetText( 183 l10n_util::GetStringFUTF16( 184 IDS_ASH_STATUS_TRAY_BATTERY_TIME_UNTIL_FULL, 185 base::IntToString16(hour), 186 base::IntToString16(min))); 187 } else { 188 // This is a low battery warning prompting the user in minutes. 189 time_label_->SetText(ui::TimeFormat::TimeRemaining( 190 base::TimeDelta::FromMinutes(hour * 60 + min))); 191 } 192 } else { 193 time_label_->SetText(base::string16()); 194 } 195 } 196 197 void PowerStatusView::ChildPreferredSizeChanged(views::View* child) { 198 PreferredSizeChanged(); 199 } 200 201 gfx::Size PowerStatusView::GetPreferredSize() { 202 gfx::Size size = views::View::GetPreferredSize(); 203 return gfx::Size(size.width(), kTrayPopupItemHeight); 204 } 205 206 int PowerStatusView::GetHeightForWidth(int width) { 207 return kTrayPopupItemHeight; 208 } 209 210 void PowerStatusView::Layout() { 211 views::View::Layout(); 212 213 // Move the time_status_label_ closer to percentage_label_. 214 if (percentage_label_ && time_status_label_ && 215 percentage_label_->visible() && time_status_label_->visible()) { 216 time_status_label_->SetX(percentage_label_->bounds().right() + 1); 217 } 218 } 219 220 } // namespace internal 221 } // namespace ash 222