diff options
author | davemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-12 22:34:26 +0000 |
---|---|---|
committer | davemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-12 22:34:26 +0000 |
commit | 65cbaa6f23b52b46373b53b494fd843f8ec0ef6f (patch) | |
tree | eb54f00ff200e244a437e6dd7ab6d41795ca4f40 | |
parent | 208849e7c4e9cf90380a23a3c73fdc72748a9366 (diff) | |
download | chromium_src-65cbaa6f23b52b46373b53b494fd843f8ec0ef6f.zip chromium_src-65cbaa6f23b52b46373b53b494fd843f8ec0ef6f.tar.gz chromium_src-65cbaa6f23b52b46373b53b494fd843f8ec0ef6f.tar.bz2 |
Implemented nicer battery status
BUG=chromium-os:17469
TEST=Click battery icon, confirm it meets spec
Review URL: http://codereview.chromium.org/7491083
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96643 0039d316-1c4b-4281-b951-d872f2087c98
56 files changed, 409 insertions, 239 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 446216a..89ec2d5 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -12107,8 +12107,14 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_STATUSBAR_BATTERY_CALCULATING_TIME_UNTIL_EMPTY" desc="In the power menu button, this is the message the shows when we are calculating time until empty."> Calculating remaining time </message> + <message name="IDS_STATUSBAR_BATTERY_DISCHARGING" desc="In the power menu popup, indicates that the battery is being used."> + Battery + </message> + <message name="IDS_STATUSBAR_BATTERY_CHARGING" desc="In the power menu popup, indicates that the battery is being charged."> + Charging + </message> <message name="IDS_STATUSBAR_BATTERY_IS_CHARGED" desc="In the power menu button, the battery is charged message."> - Battery is charged + Battery full </message> <message name="IDS_STATUSBAR_FEEDBACK_TOOLTIP" desc="Tooltip for the feedback status bar icon."> Report a bug diff --git a/chrome/app/theme/statusbar_battery10c.png b/chrome/app/theme/statusbar_battery10c.png Binary files differdeleted file mode 100644 index 2271e80..0000000 --- a/chrome/app/theme/statusbar_battery10c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery10d.png b/chrome/app/theme/statusbar_battery10d.png Binary files differdeleted file mode 100644 index 3d69674..0000000 --- a/chrome/app/theme/statusbar_battery10d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery11c.png b/chrome/app/theme/statusbar_battery11c.png Binary files differdeleted file mode 100644 index d592288..0000000 --- a/chrome/app/theme/statusbar_battery11c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery11d.png b/chrome/app/theme/statusbar_battery11d.png Binary files differdeleted file mode 100644 index e6fc8bf..0000000 --- a/chrome/app/theme/statusbar_battery11d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery12c.png b/chrome/app/theme/statusbar_battery12c.png Binary files differdeleted file mode 100644 index 19fd22c..0000000 --- a/chrome/app/theme/statusbar_battery12c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery12d.png b/chrome/app/theme/statusbar_battery12d.png Binary files differdeleted file mode 100644 index 4915cea..0000000 --- a/chrome/app/theme/statusbar_battery12d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery13c.png b/chrome/app/theme/statusbar_battery13c.png Binary files differdeleted file mode 100644 index f5ba11a..0000000 --- a/chrome/app/theme/statusbar_battery13c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery13d.png b/chrome/app/theme/statusbar_battery13d.png Binary files differdeleted file mode 100644 index 9b229742..0000000 --- a/chrome/app/theme/statusbar_battery13d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery14c.png b/chrome/app/theme/statusbar_battery14c.png Binary files differdeleted file mode 100644 index 1ad47b2..0000000 --- a/chrome/app/theme/statusbar_battery14c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery14d.png b/chrome/app/theme/statusbar_battery14d.png Binary files differdeleted file mode 100644 index 0454a5d..0000000 --- a/chrome/app/theme/statusbar_battery14d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery15c.png b/chrome/app/theme/statusbar_battery15c.png Binary files differdeleted file mode 100644 index ca92c63..0000000 --- a/chrome/app/theme/statusbar_battery15c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery15d.png b/chrome/app/theme/statusbar_battery15d.png Binary files differdeleted file mode 100644 index 418f64a..0000000 --- a/chrome/app/theme/statusbar_battery15d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery16c.png b/chrome/app/theme/statusbar_battery16c.png Binary files differdeleted file mode 100644 index b4e4bee..0000000 --- a/chrome/app/theme/statusbar_battery16c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery16d.png b/chrome/app/theme/statusbar_battery16d.png Binary files differdeleted file mode 100644 index 67f7893..0000000 --- a/chrome/app/theme/statusbar_battery16d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery17c.png b/chrome/app/theme/statusbar_battery17c.png Binary files differdeleted file mode 100644 index c2e7cf1..0000000 --- a/chrome/app/theme/statusbar_battery17c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery17d.png b/chrome/app/theme/statusbar_battery17d.png Binary files differdeleted file mode 100644 index 2cb6b7a..0000000 --- a/chrome/app/theme/statusbar_battery17d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery18c.png b/chrome/app/theme/statusbar_battery18c.png Binary files differdeleted file mode 100644 index 147f575..0000000 --- a/chrome/app/theme/statusbar_battery18c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery18d.png b/chrome/app/theme/statusbar_battery18d.png Binary files differdeleted file mode 100644 index 793e1bf..0000000 --- a/chrome/app/theme/statusbar_battery18d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery19c.png b/chrome/app/theme/statusbar_battery19c.png Binary files differdeleted file mode 100644 index aa1cf4c..0000000 --- a/chrome/app/theme/statusbar_battery19c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery19d.png b/chrome/app/theme/statusbar_battery19d.png Binary files differdeleted file mode 100644 index cfd1422..0000000 --- a/chrome/app/theme/statusbar_battery19d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery1c.png b/chrome/app/theme/statusbar_battery1c.png Binary files differdeleted file mode 100644 index bd4f960..0000000 --- a/chrome/app/theme/statusbar_battery1c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery1d.png b/chrome/app/theme/statusbar_battery1d.png Binary files differdeleted file mode 100644 index 9e4e331..0000000 --- a/chrome/app/theme/statusbar_battery1d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery2c.png b/chrome/app/theme/statusbar_battery2c.png Binary files differdeleted file mode 100644 index 244968c..0000000 --- a/chrome/app/theme/statusbar_battery2c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery2d.png b/chrome/app/theme/statusbar_battery2d.png Binary files differdeleted file mode 100644 index 11fbce3..0000000 --- a/chrome/app/theme/statusbar_battery2d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery3c.png b/chrome/app/theme/statusbar_battery3c.png Binary files differdeleted file mode 100644 index bcb9a40..0000000 --- a/chrome/app/theme/statusbar_battery3c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery3d.png b/chrome/app/theme/statusbar_battery3d.png Binary files differdeleted file mode 100644 index 2633fb3..0000000 --- a/chrome/app/theme/statusbar_battery3d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery4c.png b/chrome/app/theme/statusbar_battery4c.png Binary files differdeleted file mode 100644 index a647418..0000000 --- a/chrome/app/theme/statusbar_battery4c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery4d.png b/chrome/app/theme/statusbar_battery4d.png Binary files differdeleted file mode 100644 index 63a8836..0000000 --- a/chrome/app/theme/statusbar_battery4d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery5c.png b/chrome/app/theme/statusbar_battery5c.png Binary files differdeleted file mode 100644 index d9fd519..0000000 --- a/chrome/app/theme/statusbar_battery5c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery5d.png b/chrome/app/theme/statusbar_battery5d.png Binary files differdeleted file mode 100644 index d0390be..0000000 --- a/chrome/app/theme/statusbar_battery5d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery6c.png b/chrome/app/theme/statusbar_battery6c.png Binary files differdeleted file mode 100644 index b0b218a..0000000 --- a/chrome/app/theme/statusbar_battery6c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery6d.png b/chrome/app/theme/statusbar_battery6d.png Binary files differdeleted file mode 100644 index ecc2a3c..0000000 --- a/chrome/app/theme/statusbar_battery6d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery7c.png b/chrome/app/theme/statusbar_battery7c.png Binary files differdeleted file mode 100644 index c10e489..0000000 --- a/chrome/app/theme/statusbar_battery7c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery7d.png b/chrome/app/theme/statusbar_battery7d.png Binary files differdeleted file mode 100644 index ee7f3285..0000000 --- a/chrome/app/theme/statusbar_battery7d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery8c.png b/chrome/app/theme/statusbar_battery8c.png Binary files differdeleted file mode 100644 index 691c6de..0000000 --- a/chrome/app/theme/statusbar_battery8c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery8d.png b/chrome/app/theme/statusbar_battery8d.png Binary files differdeleted file mode 100644 index 158dd90..0000000 --- a/chrome/app/theme/statusbar_battery8d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery9c.png b/chrome/app/theme/statusbar_battery9c.png Binary files differdeleted file mode 100644 index 6c67bca..0000000 --- a/chrome/app/theme/statusbar_battery9c.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery9d.png b/chrome/app/theme/statusbar_battery9d.png Binary files differdeleted file mode 100644 index eea3e17..0000000 --- a/chrome/app/theme/statusbar_battery9d.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery_charged.png b/chrome/app/theme/statusbar_battery_charged.png Binary files differdeleted file mode 100644 index 1cb9b5ca..0000000 --- a/chrome/app/theme/statusbar_battery_charged.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery_missing.png b/chrome/app/theme/statusbar_battery_missing.png Binary files differdeleted file mode 100644 index eb8ad0b..0000000 --- a/chrome/app/theme/statusbar_battery_missing.png +++ /dev/null diff --git a/chrome/app/theme/statusbar_battery_unknown.png b/chrome/app/theme/statusbar_battery_unknown.png Binary files differdeleted file mode 100644 index 767b25c..0000000 --- a/chrome/app/theme/statusbar_battery_unknown.png +++ /dev/null diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index a74691a..b779e91 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd @@ -503,47 +503,8 @@ <include name="IDR_OOBE_PROGRESS_LINE_RIGHT" file="oobe_progress_line_right.png" type="BINDATA" /> <include name="IDR_SHUTDOWN_ICON" file="shutdown_icon.png" type="BINDATA" /> <include name="IDR_SPINNER" file="spinner.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGED" file="statusbar_battery_charged.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_1" file="statusbar_battery1c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_10" file="statusbar_battery10c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_11" file="statusbar_battery11c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_12" file="statusbar_battery12c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_13" file="statusbar_battery13c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_14" file="statusbar_battery14c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_15" file="statusbar_battery15c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_16" file="statusbar_battery16c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_17" file="statusbar_battery17c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_18" file="statusbar_battery18c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_19" file="statusbar_battery19c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_2" file="statusbar_battery2c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_3" file="statusbar_battery3c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_4" file="statusbar_battery4c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_5" file="statusbar_battery5c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_6" file="statusbar_battery6c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_7" file="statusbar_battery7c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_8" file="statusbar_battery8c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_CHARGING_9" file="statusbar_battery9c.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_1" file="statusbar_battery1d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_10" file="statusbar_battery10d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_11" file="statusbar_battery11d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_12" file="statusbar_battery12d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_13" file="statusbar_battery13d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_14" file="statusbar_battery14d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_15" file="statusbar_battery15d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_16" file="statusbar_battery16d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_17" file="statusbar_battery17d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_18" file="statusbar_battery18d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_19" file="statusbar_battery19d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_2" file="statusbar_battery2d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_3" file="statusbar_battery3d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_4" file="statusbar_battery4d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_5" file="statusbar_battery5d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_6" file="statusbar_battery6d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_7" file="statusbar_battery7d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_8" file="statusbar_battery8d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_DISCHARGING_9" file="statusbar_battery9d.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_MISSING" file="statusbar_battery_missing.png" type="BINDATA" /> - <include name="IDR_STATUSBAR_BATTERY_UNKNOWN" file="statusbar_battery_unknown.png" type="BINDATA" /> + <include name="IDR_STATUSBAR_BATTERY_LARGE_ALL" file="statusbar_battery_large_all.png" type="BINDATA" /> + <include name="IDR_STATUSBAR_BATTERY_SMALL_ALL" file="statusbar_battery_small_all.png" type="BINDATA" /> <include name="IDR_STATUSBAR_CAPS_LOCK" file="statusbar_caps_lock.png" type="BINDATA" /> <include name="IDR_STATUSBAR_MENU" file="statusbar_menu.png" type="BINDATA" /> <include name="IDR_STATUSBAR_NETWORK_3G" file="statusbar_network_3g.png" type="BINDATA" /> diff --git a/chrome/browser/chromeos/cros/power_library.cc b/chrome/browser/chromeos/cros/power_library.cc index bc61089..a8e62dc 100644 --- a/chrome/browser/chromeos/cros/power_library.cc +++ b/chrome/browser/chromeos/cros/power_library.cc @@ -9,6 +9,7 @@ #include "base/logging.h" #include "base/observer_list.h" #include "base/time.h" +#include "base/timer.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "content/browser/browser_thread.h" #include "third_party/cros/chromeos_power.h" @@ -162,29 +163,93 @@ class PowerLibraryImpl : public PowerLibrary { DISALLOW_COPY_AND_ASSIGN(PowerLibraryImpl); }; +// The stub implementation runs the battery up and down, pausing at the +// fully charged and fully depleted states. class PowerLibraryStubImpl : public PowerLibrary { public: - PowerLibraryStubImpl() {} + PowerLibraryStubImpl() + : discharging_(true), + battery_percentage_(20), + pause_count_(0) { + timer_.Start( + base::TimeDelta::FromMilliseconds(100), + this, + &PowerLibraryStubImpl::Update); + } + virtual ~PowerLibraryStubImpl() {} // Begin PowerLibrary implementation. virtual void Init() OVERRIDE {} - virtual void AddObserver(Observer* observer) OVERRIDE {} - virtual void RemoveObserver(Observer* observer) OVERRIDE {} - virtual bool line_power_on() const OVERRIDE { return false; } - virtual bool battery_fully_charged() const OVERRIDE { return false; } - virtual double battery_percentage() const OVERRIDE { return 50.0; } - virtual bool battery_is_present() const OVERRIDE { return true; } + virtual void AddObserver(Observer* observer) OVERRIDE { + observers_.AddObserver(observer); + } + + virtual void RemoveObserver(Observer* observer) OVERRIDE { + observers_.RemoveObserver(observer); + } + + virtual bool line_power_on() const OVERRIDE { + return !discharging_; + } + + virtual bool battery_fully_charged() const OVERRIDE { + return battery_percentage_ == 100; + } + + virtual double battery_percentage() const OVERRIDE { + return battery_percentage_; + } + + virtual bool battery_is_present() const OVERRIDE { + return true; + } + virtual base::TimeDelta battery_time_to_empty() const OVERRIDE { - return base::TimeDelta::FromSeconds(10 * 60); + if (battery_percentage_ == 0) + return base::TimeDelta::FromSeconds(1); + else + return (base::TimeDelta::FromHours(3) * battery_percentage_) / 100; } + virtual base::TimeDelta battery_time_to_full() const OVERRIDE { - return base::TimeDelta::FromSeconds(0); + if (battery_percentage_ == 100) + return base::TimeDelta::FromSeconds(1); + else + return base::TimeDelta::FromHours(3) - battery_time_to_empty(); } + virtual void EnableScreenLock(bool enable) OVERRIDE {} virtual void RequestRestart() OVERRIDE {} virtual void RequestShutdown() OVERRIDE {} // End PowerLibrary implementation. + + private: + void Update() { + // We pause at 0 and 100% so that it's easier to check those conditions. + if (pause_count_ > 1) { + pause_count_--; + return; + } + + if (battery_percentage_ == 0 || battery_percentage_ == 100) { + if (pause_count_) { + pause_count_ = 0; + discharging_ = !discharging_; + } else { + pause_count_ = 20; + return; + } + } + battery_percentage_ += (discharging_ ? -1 : 1); + FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(this)); + } + + bool discharging_; + int battery_percentage_; + int pause_count_; + ObserverList<Observer> observers_; + base::RepeatingTimer<PowerLibraryStubImpl> timer_; }; // static diff --git a/chrome/browser/chromeos/status/power_menu_button.cc b/chrome/browser/chromeos/status/power_menu_button.cc index eb1fcf4..8132ca2 100644 --- a/chrome/browser/chromeos/status/power_menu_button.cc +++ b/chrome/browser/chromeos/status/power_menu_button.cc @@ -15,6 +15,8 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/canvas_skia.h" +#include "ui/gfx/font.h" #include "views/controls/menu/menu_item_view.h" #include "views/controls/menu/submenu_view.h" #include "views/widget/widget.h" @@ -28,25 +30,219 @@ enum { POWER_NO_BATTERY, }; +enum ImageType { + DISCHARGING, + CHARGING, + BOLT +}; + +enum ImageSize { + SMALL, + LARGE +}; + +// Initialize time deltas to large values so they will be replaced when set +// to small values. +const int64 kInitialMS = 0x7fffffff; +// Width and height of small images. +const int kSmallImageWidth = 26, kSmallImageHeight = 24; +// Width and height of large images. +const int kLargeImageWidth = 57, kLargeImageHeight = 35; +// Number of different power states. +const int kNumPowerImages = 20; + +// Constants for status displayed when user clicks button. +// Padding around status. +const int kPadLeftX = 10, kPadRightX = 10, kPadY = 5; +// Padding between battery and text. +const int kBatteryPadX = 10; +// Spacing between lines of text. +const int kEstimateSpacing = 3; +// Color of text embedded within battery. +const SkColor kPercentageColor = 0xFF333333; +// Used for embossing text. +const SkColor kPercentageShadowColor = 0x80ffffff; +// Status text/ +const SkColor kEstimateColor = SK_ColorBLACK; +// Size of percentage w/in battery. +const int kBatteryFontSizeDelta = 3; + +// Battery images come from two collections (small and large). In each there +// are |kNumPowerImages| battery states for both on and off charge, followed +// by the missing battery image and the unknown image. +// They are layed out like this: +// Discharging Charging Bolt +// | | + +// || || + +// ... +// ||||| ||||| + +// ||X|| ||?|| +SkBitmap GetImage(ImageSize size, ImageType type, int index) { + int image_width, image_height, image_index; + + if (size == SMALL) { + image_index = IDR_STATUSBAR_BATTERY_SMALL_ALL; + image_width = kSmallImageWidth; + image_height = kSmallImageHeight; + } else { + image_index = IDR_STATUSBAR_BATTERY_LARGE_ALL; + image_width = kLargeImageWidth; + image_height = kLargeImageHeight; + } + SkBitmap* all_images = + ResourceBundle::GetSharedInstance().GetBitmapNamed(image_index); + SkIRect subset = + SkIRect::MakeXYWH( + static_cast<int>(type) * image_width, + index * image_height, + image_width, + image_height); + + SkBitmap image; + all_images->extractSubset(&image, subset); + return image; +} + +SkBitmap GetMissingImage(ImageSize size) { + return GetImage(size, DISCHARGING, kNumPowerImages); +} + +SkBitmap GetUnknownImage(ImageSize size) { + return GetImage(size, CHARGING, kNumPowerImages); +} + } // namespace namespace chromeos { using base::TimeDelta; +class PowerMenuButton::StatusView : public View { + public: + explicit StatusView(PowerMenuButton* menu_button) + : menu_button_(menu_button) { + estimate_font_ = + ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont); + percentage_font_ = + estimate_font_.DeriveFont(kBatteryFontSizeDelta, gfx::Font::BOLD); + } + + gfx::Size GetPreferredSize() { + int estimate_w, estimate_h, charging_w, charging_h; + string16 estimate_text = menu_button_->GetBatteryIsChargedText(); + string16 charging_text = l10n_util::GetStringUTF16( + menu_button_->line_power_on_ ? + IDS_STATUSBAR_BATTERY_CHARGING : + IDS_STATUSBAR_BATTERY_DISCHARGING); + gfx::CanvasSkia::SizeStringInt( + estimate_text, estimate_font_, &estimate_w, &estimate_h, 0); + gfx::CanvasSkia::SizeStringInt( + charging_text, estimate_font_, &charging_w, &charging_h, 0); + gfx::Size size = gfx::Size( + kPadLeftX + kLargeImageWidth + kBatteryPadX + kPadRightX + + std::max(charging_w, estimate_w), + (2 * kPadY) + + std::max(kLargeImageHeight, + kEstimateSpacing + (2 * estimate_font_.GetHeight()))); + return size; + } + + void Update() { + PreferredSizeChanged(); + // Force a paint even if the size didn't change. + SchedulePaint(); + } + + protected: + void OnPaint(gfx::Canvas* canvas) { + SkBitmap image; + + bool draw_percentage_text = false; + if (!CrosLibrary::Get()->EnsureLoaded()) { + image = GetUnknownImage(LARGE); + } else if (!menu_button_->battery_is_present_) { + image = GetMissingImage(LARGE); + } else { + image = GetImage( + LARGE, + menu_button_->line_power_on_ ? CHARGING : DISCHARGING, + menu_button_->battery_index_); + if (menu_button_->battery_percentage_ < 100 || + !menu_button_->line_power_on_) { + draw_percentage_text = true; + } + } + int image_x = kPadLeftX, image_y = (height() - image.height()) / 2; + canvas->DrawBitmapInt(image, image_x, image_y); + + if (draw_percentage_text) { + string16 text = UTF8ToUTF16(StringPrintf( + "%d%%", + static_cast<int>(menu_button_->battery_percentage_))); + int text_h = percentage_font_.GetHeight(); + int text_y = ((height() - text_h) / 2); + canvas->DrawStringInt( + text, percentage_font_, kPercentageShadowColor, + image_x, text_y + 1, image.width(), text_h, + gfx::Canvas::TEXT_ALIGN_CENTER | gfx::Canvas::NO_ELLIPSIS); + canvas->DrawStringInt( + text, percentage_font_, kPercentageColor, + image_x, text_y, image.width(), text_h, + gfx::Canvas::TEXT_ALIGN_CENTER | gfx::Canvas::NO_ELLIPSIS); + if (menu_button_->line_power_on_) { + image = GetImage(LARGE, BOLT, menu_button_->battery_index_); + canvas->DrawBitmapInt(image, image_x, image_y); + } + } + string16 charging_text = l10n_util::GetStringUTF16( + menu_button_->line_power_on_ ? + IDS_STATUSBAR_BATTERY_CHARGING : + IDS_STATUSBAR_BATTERY_DISCHARGING); + string16 estimate_text = menu_button_->GetBatteryIsChargedText(); + int text_h = estimate_font_.GetHeight(); + int text_x = image_x + kLargeImageWidth + kBatteryPadX; + int charging_y = (height() - (kEstimateSpacing + (2 * text_h))) / 2; + int estimate_y = charging_y + text_h + kEstimateSpacing; + canvas->DrawStringInt( + charging_text, estimate_font_, kEstimateColor, + text_x, charging_y, width() - text_x, text_h, + gfx::Canvas::TEXT_ALIGN_LEFT); + canvas->DrawStringInt( + estimate_text, estimate_font_, kEstimateColor, + text_x, estimate_y, width() - text_x, text_h, + gfx::Canvas::TEXT_ALIGN_LEFT); + } + + bool OnMousePressed(const views::MouseEvent& event) { + return true; + } + + void OnMouseReleased(const views::MouseEvent& event) { + if (event.IsLeftMouseButton()) { + DCHECK(menu_button_->menu_); + menu_button_->menu_->Cancel(); + } + } + + private: + PowerMenuButton* menu_button_; + gfx::Font percentage_font_; + gfx::Font estimate_font_; +}; + //////////////////////////////////////////////////////////////////////////////// // PowerMenuButton -// static -const int PowerMenuButton::kNumPowerImages = 19; - PowerMenuButton::PowerMenuButton(StatusAreaHost* host) : StatusAreaButton(host, this), battery_is_present_(false), line_power_on_(false), - battery_fully_charged_(false), battery_percentage_(0.0), - icon_id_(-1) { + battery_index_(-1), + battery_time_to_full_(TimeDelta::FromMicroseconds(kInitialMS)), + battery_time_to_empty_(TimeDelta::FromMicroseconds(kInitialMS)), + status_(NULL), + menu_(NULL) { UpdateIconAndLabelInfo(); CrosLibrary::Get()->GetPowerLibrary()->AddObserver(this); } @@ -58,19 +254,7 @@ PowerMenuButton::~PowerMenuButton() { // PowerMenuButton, views::MenuDelegate implementation: std::wstring PowerMenuButton::GetLabel(int id) const { - string16 label; - switch (id) { - case POWER_BATTERY_PERCENTAGE_ITEM: - label = GetBatteryPercentageText(); - break; - case POWER_BATTERY_IS_CHARGED_ITEM: - label = GetBatteryIsChargedText(); - break; - default: - NOTREACHED(); - } - - return UTF16ToWide(label); + return std::wstring(); } bool PowerMenuButton::IsCommandEnabled(int id) const { @@ -85,7 +269,7 @@ string16 PowerMenuButton::GetBatteryPercentageText() const { string16 PowerMenuButton::GetBatteryIsChargedText() const { // The second item shows the battery is charged if it is. - if (battery_fully_charged_) + if (battery_percentage_ >= 100 && line_power_on_) return l10n_util::GetStringUTF16(IDS_STATUSBAR_BATTERY_IS_CHARGED); // If battery is in an intermediate charge state, show how much time left. @@ -130,7 +314,18 @@ void PowerMenuButton::OnLocaleChanged() { // PowerMenuButton, views::ViewMenuDelegate implementation: void PowerMenuButton::RunMenu(views::View* source, const gfx::Point& pt) { - UpdateMenu(); + menu_ = new views::MenuItemView(this); + views::MenuItemView* submenu = + menu_->AppendMenuItem( + POWER_BATTERY_PERCENTAGE_ITEM, + std::wstring(), + views::MenuItemView::NORMAL); + status_ = new StatusView(this); + submenu->AddChildView(status_); + menu_->CreateSubmenu()->set_resize_open_menu(true); + menu_->SetMargins(0, 0); + submenu->SetMargins(0, 0); + menu_->ChildrenChanged(); gfx::Point screen_location; views::View::ConvertPointToScreen(source, &screen_location); @@ -141,6 +336,9 @@ void PowerMenuButton::RunMenu(views::View* source, const gfx::Point& pt) { bounds, views::MenuItemView::TOPRIGHT, true); + delete menu_; + status_ = NULL; + menu_ = NULL; } //////////////////////////////////////////////////////////////////////////////// @@ -162,87 +360,47 @@ void PowerMenuButton::UpdateIconAndLabelInfo() { if (cros_loaded) { battery_is_present_ = cros->battery_is_present(); line_power_on_ = cros->line_power_on(); - battery_fully_charged_ = cros->battery_fully_charged(); - battery_percentage_ = cros->battery_percentage(); + // If fully charged, always show 100% even if internal number is a bit less. - // Note: we always call cros->battery_percentage() for test predictability. - if (battery_fully_charged_) + if (cros->battery_fully_charged()) { + // We always call cros->battery_percentage() for test predictability. + cros->battery_percentage(); battery_percentage_ = 100.0; - // Map 1-100 to 0-100, so 1% shows up as 0%, and 100% remains 100%. - static const double k = 100.0/99; - battery_percentage_ = (battery_percentage_ > 1.0 ? - battery_percentage_ : 1.0) * k - k; + } else { + battery_percentage_ = cros->battery_percentage(); + } UpdateBatteryTime(&battery_time_to_full_, cros->battery_time_to_full()); UpdateBatteryTime(&battery_time_to_empty_, cros->battery_time_to_empty()); } if (!cros_loaded) { - icon_id_ = IDR_STATUSBAR_BATTERY_UNKNOWN; + battery_index_ = -1; + SetIcon(GetUnknownImage(SMALL)); } else if (!battery_is_present_) { - icon_id_ = IDR_STATUSBAR_BATTERY_MISSING; - } else if (line_power_on_ && battery_fully_charged_) { - icon_id_ = IDR_STATUSBAR_BATTERY_CHARGED; + battery_index_ = -1; + SetIcon(GetMissingImage(SMALL)); } else { - // Get the power image depending on battery percentage. Percentage is - // from 0 to 100, so we need to convert that to 0 to kNumPowerImages - 1. - // NOTE: Use an array rather than just calculating a resource number to - // avoid creating implicit ordering dependencies on the resource values. - static const int kChargingImages[kNumPowerImages] = { - IDR_STATUSBAR_BATTERY_CHARGING_1, - IDR_STATUSBAR_BATTERY_CHARGING_2, - IDR_STATUSBAR_BATTERY_CHARGING_3, - IDR_STATUSBAR_BATTERY_CHARGING_4, - IDR_STATUSBAR_BATTERY_CHARGING_5, - IDR_STATUSBAR_BATTERY_CHARGING_6, - IDR_STATUSBAR_BATTERY_CHARGING_7, - IDR_STATUSBAR_BATTERY_CHARGING_8, - IDR_STATUSBAR_BATTERY_CHARGING_9, - IDR_STATUSBAR_BATTERY_CHARGING_10, - IDR_STATUSBAR_BATTERY_CHARGING_11, - IDR_STATUSBAR_BATTERY_CHARGING_12, - IDR_STATUSBAR_BATTERY_CHARGING_13, - IDR_STATUSBAR_BATTERY_CHARGING_14, - IDR_STATUSBAR_BATTERY_CHARGING_15, - IDR_STATUSBAR_BATTERY_CHARGING_16, - IDR_STATUSBAR_BATTERY_CHARGING_17, - IDR_STATUSBAR_BATTERY_CHARGING_18, - IDR_STATUSBAR_BATTERY_CHARGING_19, - }; - static const int kDischargingImages[kNumPowerImages] = { - IDR_STATUSBAR_BATTERY_DISCHARGING_1, - IDR_STATUSBAR_BATTERY_DISCHARGING_2, - IDR_STATUSBAR_BATTERY_DISCHARGING_3, - IDR_STATUSBAR_BATTERY_DISCHARGING_4, - IDR_STATUSBAR_BATTERY_DISCHARGING_5, - IDR_STATUSBAR_BATTERY_DISCHARGING_6, - IDR_STATUSBAR_BATTERY_DISCHARGING_7, - IDR_STATUSBAR_BATTERY_DISCHARGING_8, - IDR_STATUSBAR_BATTERY_DISCHARGING_9, - IDR_STATUSBAR_BATTERY_DISCHARGING_10, - IDR_STATUSBAR_BATTERY_DISCHARGING_11, - IDR_STATUSBAR_BATTERY_DISCHARGING_12, - IDR_STATUSBAR_BATTERY_DISCHARGING_13, - IDR_STATUSBAR_BATTERY_DISCHARGING_14, - IDR_STATUSBAR_BATTERY_DISCHARGING_15, - IDR_STATUSBAR_BATTERY_DISCHARGING_16, - IDR_STATUSBAR_BATTERY_DISCHARGING_17, - IDR_STATUSBAR_BATTERY_DISCHARGING_18, - IDR_STATUSBAR_BATTERY_DISCHARGING_19, - }; - - int index = static_cast<int>(battery_percentage_ / 100.0 * - nextafter(static_cast<float>(kNumPowerImages), 0)); - index = std::max(std::min(index, kNumPowerImages - 1), 0); - icon_id_ = line_power_on_ ? - kChargingImages[index] : kDischargingImages[index]; + // Preserve the fully charged icon for 100% only. + if (battery_percentage_ >= 100) { + battery_index_ = kNumPowerImages - 1; + } else { + battery_index_ = + static_cast<int>(battery_percentage_ / 100.0 * + nextafter(static_cast<float>(kNumPowerImages - 1), 0)); + battery_index_ = + std::max(std::min(battery_index_, kNumPowerImages - 2), 0); + } + SetIcon(GetImage( + SMALL, line_power_on_ ? CHARGING : DISCHARGING, battery_index_)); } - SetIcon(*ResourceBundle::GetSharedInstance().GetBitmapNamed(icon_id_)); - SetTooltipText(GetLabel(POWER_BATTERY_PERCENTAGE_ITEM)); - SetAccessibleName(GetBatteryPercentageText()); - UpdateMenu(); + percentage_text_ = GetBatteryPercentageText(); + SetTooltipText(UTF16ToWide(percentage_text_)); + SetAccessibleName(percentage_text_); SchedulePaint(); + if (status_) + status_->Update(); } void PowerMenuButton::UpdateBatteryTime(TimeDelta* previous, @@ -252,29 +410,13 @@ void PowerMenuButton::UpdateBatteryTime(TimeDelta* previous, const TimeDelta diff = current - *previous; // If the diff is small and positive, ignore it in favor of // keeping time monotonically decreasing. - if (diff < kMinDiff || diff > kMaxDiff) + // If previous is 0, then it either was never set (initial condition) + // or got down to 0. + if (*previous == TimeDelta::FromMicroseconds(kInitialMS) || + diff < kMinDiff || + diff > kMaxDiff) { *previous = current; -} - -void PowerMenuButton::UpdateMenu() { - if (!menu_.get()) - menu_.reset(new views::MenuItemView(this)); - - // Remove existing items. - const int old_count = menu_->CreateSubmenu()->child_count(); - for (int i = 0; i < old_count; ++i) - menu_->RemoveMenuItemAt(0); - - if (battery_is_present_) { - // Create menu items whose text will be supplied by GetLabel(). - menu_->AppendDelegateMenuItem(POWER_BATTERY_PERCENTAGE_ITEM); - menu_->AppendDelegateMenuItem(POWER_BATTERY_IS_CHARGED_ITEM); - } else { - menu_->AppendMenuItemWithLabel( - POWER_NO_BATTERY, - UTF16ToWide(l10n_util::GetStringUTF16(IDS_STATUSBAR_NO_BATTERY))); } - menu_->ChildrenChanged(); } } // namespace chromeos diff --git a/chrome/browser/chromeos/status/power_menu_button.h b/chrome/browser/chromeos/status/power_menu_button.h index fab5360..f27f07e 100644 --- a/chrome/browser/chromeos/status/power_menu_button.h +++ b/chrome/browser/chromeos/status/power_menu_button.h @@ -37,12 +37,14 @@ class PowerMenuButton : public StatusAreaButton, virtual void PowerChanged(PowerLibrary* obj); virtual void SystemResumed() {} - int icon_id() const { return icon_id_; } + int battery_index() const { return battery_index_; } protected: virtual int icon_width(); private: + class StatusView; + // views::View virtual void OnLocaleChanged() OVERRIDE; @@ -61,26 +63,20 @@ class PowerMenuButton : public StatusAreaButton, void UpdateBatteryTime(base::TimeDelta* previous, const base::TimeDelta& current); - // Update the menu entries. - void UpdateMenu(); - - // The number of power images. - static const int kNumPowerImages; - // Stored data gathered from CrosLibrary::PowerLibrary. bool battery_is_present_; bool line_power_on_; - bool battery_fully_charged_; double battery_percentage_; + string16 percentage_text_; + int battery_index_; base::TimeDelta battery_time_to_full_; base::TimeDelta battery_time_to_empty_; - // The currently showing icon bitmap id. - int icon_id_; + // The currently showing status view. NULL if menu is not being displayed. + StatusView* status_; - // The power menu. This needs to be initialized last since it calls into - // GetLabelAt() during construction. - scoped_ptr<views::MenuItemView> menu_; + // The currently showing menu. NULL if menu is not being displayed. + views::MenuItemView* menu_; DISALLOW_COPY_AND_ASSIGN(PowerMenuButton); }; diff --git a/chrome/browser/chromeos/status/power_menu_button_browsertest.cc b/chrome/browser/chromeos/status/power_menu_button_browsertest.cc index c1a4313..515c325 100644 --- a/chrome/browser/chromeos/status/power_menu_button_browsertest.cc +++ b/chrome/browser/chromeos/status/power_menu_button_browsertest.cc @@ -13,6 +13,9 @@ #include "chrome/browser/ui/browser_window.h" #include "grit/theme_resources.h" +namespace { +const int kNumBatteryStates = 20; +} namespace chromeos { using ::testing::AnyNumber; using ::testing::InvokeWithoutArgs; @@ -41,10 +44,10 @@ class PowerMenuButtonTest : public CrosInProcessBrowserTest { return power; } - int CallPowerChangedAndGetIconId() { + int CallPowerChangedAndGetBatteryIndex() { PowerMenuButton* power = GetPowerMenuButton(); power->PowerChanged(mock_power_library_); - return power->icon_id(); + return power->battery_index(); } }; @@ -67,7 +70,7 @@ IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryMissingTest) { EXPECT_CALL(*mock_power_library_, battery_time_to_full()) .WillOnce((Return(base::TimeDelta::FromMinutes(24)))) .RetiresOnSaturation(); - EXPECT_EQ(IDR_STATUSBAR_BATTERY_MISSING, CallPowerChangedAndGetIconId()); + EXPECT_EQ(-1, CallPowerChangedAndGetBatteryIndex()); } IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargedTest) { @@ -89,7 +92,7 @@ IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargedTest) { EXPECT_CALL(*mock_power_library_, battery_time_to_full()) .WillOnce((Return(base::TimeDelta::FromMinutes(0)))) .RetiresOnSaturation(); - EXPECT_EQ(IDR_STATUSBAR_BATTERY_CHARGED, CallPowerChangedAndGetIconId()); + EXPECT_EQ(kNumBatteryStates - 1, CallPowerChangedAndGetBatteryIndex()); } IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargingTest) { @@ -115,38 +118,13 @@ IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargingTest) { .WillRepeatedly((Return(base::TimeDelta::FromMinutes(24)))) .RetiresOnSaturation(); - // Test the 16 battery charging states. - // NOTE: Use an array rather than just calculating a resource number to avoid - // creating implicit ordering dependencies on the resource values. - static const int kChargingImages[] = { - IDR_STATUSBAR_BATTERY_CHARGING_1, - IDR_STATUSBAR_BATTERY_CHARGING_2, - IDR_STATUSBAR_BATTERY_CHARGING_3, - IDR_STATUSBAR_BATTERY_CHARGING_4, - IDR_STATUSBAR_BATTERY_CHARGING_5, - IDR_STATUSBAR_BATTERY_CHARGING_6, - IDR_STATUSBAR_BATTERY_CHARGING_7, - IDR_STATUSBAR_BATTERY_CHARGING_8, - IDR_STATUSBAR_BATTERY_CHARGING_9, - IDR_STATUSBAR_BATTERY_CHARGING_10, - IDR_STATUSBAR_BATTERY_CHARGING_11, - IDR_STATUSBAR_BATTERY_CHARGING_12, - IDR_STATUSBAR_BATTERY_CHARGING_13, - IDR_STATUSBAR_BATTERY_CHARGING_14, - IDR_STATUSBAR_BATTERY_CHARGING_15, - IDR_STATUSBAR_BATTERY_CHARGING_16, - IDR_STATUSBAR_BATTERY_CHARGING_17, - IDR_STATUSBAR_BATTERY_CHARGING_18, - IDR_STATUSBAR_BATTERY_CHARGING_19, - }; - size_t id = 0; + int index = 0; for (float percent = 5.0; percent < 100.0; percent += 5.0) { EXPECT_CALL(*mock_power_library_, battery_percentage()) .WillOnce((Return(percent))) .RetiresOnSaturation(); - ASSERT_LT(id, arraysize(kChargingImages)); - EXPECT_EQ(kChargingImages[id], CallPowerChangedAndGetIconId()); - id++; + EXPECT_EQ(index, CallPowerChangedAndGetBatteryIndex()); + index++; } } @@ -173,38 +151,13 @@ IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryDischargingTest) { .WillRepeatedly((Return(base::TimeDelta::FromMinutes(24)))) .RetiresOnSaturation(); - // Test the 16 battery discharing states. - // NOTE: Use an array rather than just calculating a resource number to avoid - // creating implicit ordering dependencies on the resource values. - static const int kDischargingImages[] = { - IDR_STATUSBAR_BATTERY_DISCHARGING_1, - IDR_STATUSBAR_BATTERY_DISCHARGING_2, - IDR_STATUSBAR_BATTERY_DISCHARGING_3, - IDR_STATUSBAR_BATTERY_DISCHARGING_4, - IDR_STATUSBAR_BATTERY_DISCHARGING_5, - IDR_STATUSBAR_BATTERY_DISCHARGING_6, - IDR_STATUSBAR_BATTERY_DISCHARGING_7, - IDR_STATUSBAR_BATTERY_DISCHARGING_8, - IDR_STATUSBAR_BATTERY_DISCHARGING_9, - IDR_STATUSBAR_BATTERY_DISCHARGING_10, - IDR_STATUSBAR_BATTERY_DISCHARGING_11, - IDR_STATUSBAR_BATTERY_DISCHARGING_12, - IDR_STATUSBAR_BATTERY_DISCHARGING_13, - IDR_STATUSBAR_BATTERY_DISCHARGING_14, - IDR_STATUSBAR_BATTERY_DISCHARGING_15, - IDR_STATUSBAR_BATTERY_DISCHARGING_16, - IDR_STATUSBAR_BATTERY_DISCHARGING_17, - IDR_STATUSBAR_BATTERY_DISCHARGING_18, - IDR_STATUSBAR_BATTERY_DISCHARGING_19, - }; - size_t id = 0; + int index = 0; for (float percent = 5.0; percent < 100.0; percent += 5.0) { EXPECT_CALL(*mock_power_library_, battery_percentage()) .WillOnce((Return(percent))) .RetiresOnSaturation(); - ASSERT_LT(id, arraysize(kDischargingImages)); - EXPECT_EQ(kDischargingImages[id], CallPowerChangedAndGetIconId()); - id++; + EXPECT_EQ(index, CallPowerChangedAndGetBatteryIndex()); + index++; } } diff --git a/chrome/browser/chromeos/status/status_area_button.cc b/chrome/browser/chromeos/status/status_area_button.cc index 5c986fd..d98525b 100644 --- a/chrome/browser/chromeos/status/status_area_button.cc +++ b/chrome/browser/chromeos/status/status_area_button.cc @@ -22,7 +22,7 @@ static const SkColor kGrayEmbossedTextColor = 0xff4c4c4c; static const SkColor kGrayEmbossedShadowColor = 0x80ffffff; // Status area font is bigger. -const int kFontSizeDelta = 1; +const int kFontSizeDelta = 3; //////////////////////////////////////////////////////////////////////////////// // StatusAreaButton @@ -37,7 +37,7 @@ StatusAreaButton::StatusAreaButton(StatusAreaHost* host, set_use_menu_button_paint(true); gfx::Font font = ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont); - font = font.DeriveFont(3, gfx::Font::BOLD); + font = font.DeriveFont(kFontSizeDelta, gfx::Font::BOLD); SetFont(font); SetShowMultipleIconStates(false); set_alignment(TextButton::ALIGN_CENTER); diff --git a/ui/gfx/canvas_skia_linux.cc b/ui/gfx/canvas_skia_linux.cc index 7cf72d5..c6214d7 100644 --- a/ui/gfx/canvas_skia_linux.cc +++ b/ui/gfx/canvas_skia_linux.cc @@ -129,6 +129,8 @@ void SetupPangoLayout(PangoLayout* layout, pango_layout_set_width(layout, width * PANGO_SCALE); if (flags & gfx::Canvas::TEXT_ALIGN_CENTER) { + // We don't support center aligned w/ eliding. + DCHECK(gfx::Canvas::NO_ELLIPSIS); pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); } else if (flags & gfx::Canvas::TEXT_ALIGN_RIGHT) { pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT); diff --git a/views/controls/menu/menu_controller.h b/views/controls/menu/menu_controller.h index 84efb5b..cf2fa49 100644 --- a/views/controls/menu/menu_controller.h +++ b/views/controls/menu/menu_controller.h @@ -41,6 +41,7 @@ class VIEWS_EXPORT MenuController : public MessageLoop::Dispatcher { public: friend class MenuHostRootView; friend class MenuItemView; + friend class SubmenuView; // Enumeration of how the menu should exit. enum ExitType { diff --git a/views/controls/menu/menu_item_view.cc b/views/controls/menu/menu_item_view.cc index e6a2d4f..bfe1b75 100644 --- a/views/controls/menu/menu_item_view.cc +++ b/views/controls/menu/menu_item_view.cc @@ -110,6 +110,11 @@ MenuItemView::~MenuItemView() { STLDeleteElements(&removed_items_); } +void MenuItemView::ChildPreferredSizeChanged(View* child) { + pref_size_.SetSize(0, 0); + PreferredSizeChanged(); +} + bool MenuItemView::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) { *tooltip = UTF16ToWideHack(tooltip_); if (!tooltip->empty()) @@ -497,7 +502,7 @@ void MenuItemView::Layout() { // space. View* child = child_at(0); gfx::Size size = child->GetPreferredSize(); - child->SetBounds(label_start_, GetTopMargin(), size.width(), size.height()); + child->SetBounds(0, GetTopMargin(), size.width(), size.height()); } else { // Child views are laid out right aligned and given the full height. To // right align start with the last view and progress to the first. diff --git a/views/controls/menu/menu_item_view.h b/views/controls/menu/menu_item_view.h index 6a57979..af8f0f0 100644 --- a/views/controls/menu/menu_item_view.h +++ b/views/controls/menu/menu_item_view.h @@ -334,7 +334,9 @@ class VIEWS_EXPORT MenuItemView : public View { // Creates a MenuItemView. This is used by the various AddXXX methods. MenuItemView(MenuItemView* parent, int command, Type type); - virtual std::string GetClassName() const; + virtual void ChildPreferredSizeChanged(View* child) OVERRIDE; + + virtual std::string GetClassName() const OVERRIDE; private: // Calculates all sizes that we can from the OS. diff --git a/views/controls/menu/menu_item_view_gtk.cc b/views/controls/menu/menu_item_view_gtk.cc index d6dbd35..956a167 100644 --- a/views/controls/menu/menu_item_view_gtk.cc +++ b/views/controls/menu/menu_item_view_gtk.cc @@ -29,13 +29,19 @@ const int kMinTouchHeight = 46; #endif gfx::Size MenuItemView::CalculatePreferredSize() { + gfx::Size child_size = GetChildPreferredSize(); + if (child_count() == 1 && title_.size() == 0) { + return gfx::Size( + child_size.width(), + child_size.height() + GetBottomMargin() + GetTopMargin()); + } + const gfx::Font& font = GetFont(); #if defined(TOUCH_UI) int height = std::max(font.GetHeight(), kMinTouchHeight); #else int height = font.GetHeight(); #endif - gfx::Size child_size = GetChildPreferredSize(); return gfx::Size( font.GetStringWidth(title_) + label_start_ + item_right_margin_ + child_size.width(), diff --git a/views/controls/menu/menu_item_view_win.cc b/views/controls/menu/menu_item_view_win.cc index 923e268..cea5c4c 100644 --- a/views/controls/menu/menu_item_view_win.cc +++ b/views/controls/menu/menu_item_view_win.cc @@ -19,6 +19,12 @@ namespace views { gfx::Size MenuItemView::CalculatePreferredSize() { gfx::Size child_size = GetChildPreferredSize(); + if (child_count() == 1 && title_.empty()) { + return gfx::Size( + child_size.width(), + child_size.height() + GetBottomMargin() + GetTopMargin()); + } + const gfx::Font& font = GetFont(); return gfx::Size( font.GetStringWidth(title_) + label_start_ + item_right_margin_ + diff --git a/views/controls/menu/submenu_view.cc b/views/controls/menu/submenu_view.cc index 5664a8d..a68568d 100644 --- a/views/controls/menu/submenu_view.cc +++ b/views/controls/menu/submenu_view.cc @@ -38,7 +38,8 @@ SubmenuView::SubmenuView(MenuItemView* parent) drop_position_(MenuDelegate::DROP_NONE), scroll_view_container_(NULL), max_accelerator_width_(0), - minimum_preferred_width_(0) { + minimum_preferred_width_(0), + resize_open_menu_(false) { DCHECK(parent); // We'll delete ourselves, otherwise the ScrollView would delete us on close. set_parent_owned(false); @@ -72,6 +73,20 @@ MenuItemView* SubmenuView::GetMenuItemAt(int index) { return NULL; } +void SubmenuView::ChildPreferredSizeChanged(View* child) { + if (!resize_open_menu_) + return; + + MenuItemView *item = GetMenuItem(); + MenuController* controller = item->GetMenuController(); + + if (controller) { + bool dir; + gfx::Rect bounds = controller->CalculateMenuBounds(item, false, &dir); + Reposition(bounds); + } +} + void SubmenuView::Layout() { // We're in a ScrollView, and need to set our width/height ourselves. if (!parent()) diff --git a/views/controls/menu/submenu_view.h b/views/controls/menu/submenu_view.h index 037efbc..e176ac9 100644 --- a/views/controls/menu/submenu_view.h +++ b/views/controls/menu/submenu_view.h @@ -136,6 +136,12 @@ class VIEWS_EXPORT SubmenuView : public View { minimum_preferred_width_ = minimum_preferred_width; } + // Automatically resize menu if a subview's preferred size changes. + bool resize_open_menu() const { return resize_open_menu_; } + void set_resize_open_menu(bool resize_open_menu) { + resize_open_menu_ = resize_open_menu; + } + // Padding around the edges of the submenu. static const int kSubmenuBorderSize; @@ -147,6 +153,7 @@ class VIEWS_EXPORT SubmenuView : public View { // scrolling occurs, everything is repainted correctly. virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; + virtual void ChildPreferredSizeChanged(View* child) OVERRIDE; private: // Paints the drop indicator. This is only invoked if item is non-NULL and @@ -185,6 +192,9 @@ class VIEWS_EXPORT SubmenuView : public View { // Minimum width returned in GetPreferredSize(). int minimum_preferred_width_; + // Reposition open menu when contained views change size. + bool resize_open_menu_; + DISALLOW_COPY_AND_ASSIGN(SubmenuView); }; |