Index: ash/common/system/chromeos/power/power_status.cc |
diff --git a/ash/common/system/chromeos/power/power_status.cc b/ash/common/system/chromeos/power/power_status.cc |
index 806db347d2dda4f038931ac4472640a3d6fb9ab3..48e8647093bb849a526005fd9ff273adea53ad4a 100644 |
--- a/ash/common/system/chromeos/power/power_status.cc |
+++ b/ash/common/system/chromeos/power/power_status.cc |
@@ -7,6 +7,7 @@ |
#include <algorithm> |
#include <cmath> |
+#include "ash/common/material_design/material_design_controller.h" |
#include "base/logging.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/utf_string_conversions.h" |
@@ -17,9 +18,14 @@ |
#include "ui/base/l10n/l10n_util.h" |
#include "ui/base/l10n/time_format.h" |
#include "ui/base/resource/resource_bundle.h" |
+#include "ui/display/display.h" |
+#include "ui/display/screen.h" |
+#include "ui/gfx/canvas.h" |
#include "ui/gfx/geometry/rect.h" |
#include "ui/gfx/image/image.h" |
#include "ui/gfx/image/image_skia_operations.h" |
+#include "ui/gfx/paint_vector_icon.h" |
+#include "ui/gfx/vector_icons_public.h" |
namespace ash { |
namespace { |
@@ -93,6 +99,23 @@ int PowerSourceToMessageID( |
return 0; |
} |
+gfx::VectorIconId VectorIconIdForIconBadge(PowerStatus::IconBadge icon_badge) { |
+ switch (icon_badge) { |
+ case PowerStatus::ICON_BADGE_NONE: |
+ return gfx::VectorIconId::VECTOR_ICON_NONE; |
+ case PowerStatus::ICON_BADGE_ALERT: |
+ return gfx::VectorIconId::SYSTEM_TRAY_BATTERY_ALERT; |
+ case PowerStatus::ICON_BADGE_BOLT: |
+ return gfx::VectorIconId::SYSTEM_TRAY_BATTERY_BOLT; |
+ case PowerStatus::ICON_BADGE_X: |
+ return gfx::VectorIconId::SYSTEM_TRAY_BATTERY_X; |
+ case PowerStatus::ICON_BADGE_UNRELIABLE: |
+ return gfx::VectorIconId::SYSTEM_TRAY_BATTERY_UNRELIABLE; |
+ } |
+ NOTREACHED(); |
+ return gfx::VectorIconId::VECTOR_ICON_NONE; |
+} |
+ |
static PowerStatus* g_power_status = NULL; |
// Minimum battery percentage rendered in UI. |
@@ -105,10 +128,50 @@ const int kBatteryImageWidth = 25; |
// Number of different power states. |
const int kNumPowerImages = 15; |
+// The height of the battery icon in material design (as measured from the |
+// user-visible bottom of the icon to the user-visible top of the icon). |
+const int kBatteryImageHeightMd = 12; |
+ |
+// The dimensions of the canvas containing the material design battery icon. |
+const int kBatteryCanvasSizeMd = 16; |
+ |
+// The minimum height (in dp) of the charged region of the material design |
+// battery icon when the battery is present and has a charge greater than 0. |
+const int kMinVisualChargeLevelMd = 1; |
+ |
+// The empty background color of the battery icon in the system tray. Used |
+// for material design. |
+// TODO(tdanderson): Move these constants to a shared location if they are |
+// shared by more than one material design system icon. |
+const SkColor kBatteryBaseColor = SkColorSetA(SK_ColorWHITE, 0x4C); |
+ |
+// The background color of the charged region of the battery in the system |
+// tray. Used for material design. |
+const SkColor kBatteryChargeColor = SK_ColorWHITE; |
+ |
+// The color of the battery's badge (bolt, unreliable, X). |
+const SkColor kBatteryBadgeColor = SkColorSetA(SK_ColorBLACK, 0xB2); |
+ |
+// The color used for the battery's badge and charged color when the battery |
+// charge level is critically low. |
+const SkColor kBatteryAlertColor = SkColorSetRGB(0xDA, 0x27, 0x12); |
+ |
} // namespace |
+bool PowerStatus::BatteryImageInfo::operator==( |
+ const BatteryImageInfo& o) const { |
+ if (ash::MaterialDesignController::UseMaterialDesignSystemIcons()) |
+ return icon_badge == o.icon_badge && charge_level == o.charge_level; |
+ |
+ // TODO(tdanderson): |resource_id|, |offset|, and |index| are only used for |
+ // non-MD. Remove these once MD is enabled by default. See crbug.com/614453. |
+ return resource_id == o.resource_id && offset == o.offset && index == o.index; |
+} |
+ |
const int PowerStatus::kMaxBatteryTimeToDisplaySec = 24 * 60 * 60; |
+const double PowerStatus::kCriticalBatteryChargePercentageMd = 5; |
+ |
// static |
void PowerStatus::Initialize() { |
CHECK(!g_power_status); |
@@ -260,35 +323,114 @@ std::string PowerStatus::GetCurrentPowerSourceID() const { |
PowerStatus::BatteryImageInfo PowerStatus::GetBatteryImageInfo( |
IconSet icon_set) const { |
BatteryImageInfo info; |
+ if (MaterialDesignController::UseMaterialDesignSystemIcons()) |
+ CalculateBatteryImageInfoMd(&info); |
+ else |
+ CalculateBatteryImageInfoNonMd(&info, icon_set); |
+ return info; |
+} |
+void PowerStatus::CalculateBatteryImageInfoMd(BatteryImageInfo* info) const { |
+ if (!IsUsbChargerConnected() && !IsBatteryPresent()) { |
+ info->icon_badge = ICON_BADGE_X; |
+ info->charge_level = 0; |
+ return; |
+ } |
+ |
+ if (IsUsbChargerConnected()) |
+ info->icon_badge = ICON_BADGE_UNRELIABLE; |
+ else if (IsLinePowerConnected()) |
+ info->icon_badge = ICON_BADGE_BOLT; |
+ else |
+ info->icon_badge = ICON_BADGE_NONE; |
+ |
+ // |charge_state| is a value between 0 and kBatteryImageHeightMd representing |
+ // the number of device pixels the battery image should be shown charged. The |
+ // exception is when |charge_state| is 0 (a critically-low battery); in this |
+ // case, still draw 1dp of charge. |
+ int charge_state = |
+ static_cast<int>(GetBatteryPercent() / 100.0 * kBatteryImageHeightMd); |
+ charge_state = std::max(std::min(charge_state, kBatteryImageHeightMd), 0); |
+ info->charge_level = std::max(charge_state, kMinVisualChargeLevelMd); |
+ |
+ // Use ICON_BADGE_ALERT if the battery is critically low and does not already |
+ // have a badge assigned. |
+ if (GetBatteryPercent() < kCriticalBatteryChargePercentageMd && |
+ info->icon_badge == ICON_BADGE_NONE) { |
+ info->icon_badge = ICON_BADGE_ALERT; |
+ } |
+} |
+ |
+void PowerStatus::CalculateBatteryImageInfoNonMd( |
+ BatteryImageInfo* info, |
+ const IconSet& icon_set) const { |
if (IsUsbChargerConnected()) { |
- info.resource_id = |
+ info->resource_id = |
(icon_set == ICON_DARK) |
? IDR_AURA_UBER_TRAY_POWER_SMALL_CHARGING_UNRELIABLE_DARK |
: IDR_AURA_UBER_TRAY_POWER_SMALL_CHARGING_UNRELIABLE; |
} else { |
- info.resource_id = (icon_set == ICON_DARK) |
- ? IDR_AURA_UBER_TRAY_POWER_SMALL_DARK |
- : IDR_AURA_UBER_TRAY_POWER_SMALL; |
+ info->resource_id = (icon_set == ICON_DARK) |
+ ? IDR_AURA_UBER_TRAY_POWER_SMALL_DARK |
+ : IDR_AURA_UBER_TRAY_POWER_SMALL; |
} |
- info.offset = IsUsbChargerConnected() ? 0 : (IsLinePowerConnected() ? 1 : 0); |
+ info->offset = IsUsbChargerConnected() ? 0 : (IsLinePowerConnected() ? 1 : 0); |
if (GetBatteryPercent() >= 100.0) { |
- info.index = kNumPowerImages - 1; |
+ info->index = kNumPowerImages - 1; |
} else if (!IsBatteryPresent()) { |
- info.index = kNumPowerImages; |
+ info->index = kNumPowerImages; |
} else { |
- info.index = |
+ info->index = |
static_cast<int>(GetBatteryPercent() / 100.0 * (kNumPowerImages - 1)); |
- info.index = std::max(std::min(info.index, kNumPowerImages - 2), 0); |
+ info->index = std::max(std::min(info->index, kNumPowerImages - 2), 0); |
+ } |
+} |
+ |
+gfx::ImageSkia PowerStatus::GetBatteryImage( |
+ const BatteryImageInfo& info) const { |
+ if (!MaterialDesignController::UseMaterialDesignSystemIcons()) |
+ return GetBatteryImageNonMd(info); |
+ |
+ const bool use_alert_color = |
+ (info.charge_level == kMinVisualChargeLevelMd && !IsLinePowerConnected()); |
+ const SkColor badge_color = |
+ use_alert_color ? kBatteryAlertColor : kBatteryBadgeColor; |
+ const SkColor charge_color = |
+ use_alert_color ? kBatteryAlertColor : kBatteryChargeColor; |
+ gfx::Canvas canvas( |
+ gfx::Size(kBatteryCanvasSizeMd, kBatteryCanvasSizeMd), |
+ display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor(), |
+ true); |
+ |
+ // Paint the battery's base (background) color. |
+ PaintVectorIcon(&canvas, gfx::VectorIconId::SYSTEM_TRAY_BATTERY, |
+ kBatteryCanvasSizeMd, kBatteryBaseColor); |
+ |
+ // Paint the charged portion of the battery. Note that |charge_height| adjusts |
+ // for the 2dp of padding between the bottom of the battery icon and the |
+ // bottom edge of |canvas|. |
+ const int charge_height = info.charge_level + 2; |
+ gfx::Rect clip_rect(0, kBatteryCanvasSizeMd - charge_height, |
+ kBatteryCanvasSizeMd, charge_height); |
+ canvas.Save(); |
+ canvas.ClipRect(clip_rect); |
+ PaintVectorIcon(&canvas, gfx::VectorIconId::SYSTEM_TRAY_BATTERY, |
+ kBatteryCanvasSizeMd, charge_color); |
+ canvas.Restore(); |
+ |
+ // Paint the badge over top of the battery, if applicable. |
+ if (info.icon_badge != ICON_BADGE_NONE) { |
+ PaintVectorIcon(&canvas, VectorIconIdForIconBadge(info.icon_badge), |
+ kBatteryCanvasSizeMd, badge_color); |
} |
- return info; |
+ return gfx::ImageSkia(canvas.ExtractImageRep()); |
} |
-gfx::ImageSkia PowerStatus::GetBatteryImage(IconSet icon_set) const { |
- const BatteryImageInfo info = GetBatteryImageInfo(icon_set); |
+gfx::ImageSkia PowerStatus::GetBatteryImageNonMd( |
+ const BatteryImageInfo& info) const { |
gfx::Image all; |
all = ui::ResourceBundle::GetSharedInstance().GetImageNamed(info.resource_id); |
gfx::Rect region(info.offset * kBatteryImageWidth, |