| // Copyright (c) 2013 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 "chrome/browser/ui/toolbar/wrench_icon_painter.h" |
| |
| #include "grit/theme_resources.h" |
| #include "ui/base/theme_provider.h" |
| #include "ui/gfx/animation/multi_animation.h" |
| #include "ui/gfx/canvas.h" |
| #include "ui/gfx/image/image_skia.h" |
| #include "ui/gfx/rect.h" |
| |
| namespace { |
| |
| // The wrench icon is made up of this many bars stacked vertically. |
| const int kBarCount = 3; |
| |
| // |value| is the animation progress from 0 to 1. |index| is the index of the |
| // bar being drawn. This function returns a new progress value (from 0 to 1) |
| // such that bars appear staggered. |
| double GetStaggeredValue(double value, int index) { |
| // When animating the wrench icon's bars the bars are staggered by this |
| // factor. |
| const double kStaggerFactor = 0.15; |
| double maxStaggeredValue = 1.0 - (kBarCount - 1) * kStaggerFactor; |
| double staggeredValue = (value - kStaggerFactor * index) / maxStaggeredValue; |
| return std::min(1.0, std::max(0.0, staggeredValue)); |
| } |
| |
| } // namespace |
| |
| // static |
| WrenchIconPainter::Severity WrenchIconPainter::SeverityFromUpgradeLevel( |
| UpgradeDetector::UpgradeNotificationAnnoyanceLevel level) { |
| switch (level) { |
| case UpgradeDetector::UPGRADE_ANNOYANCE_NONE: |
| return SEVERITY_NONE; |
| case UpgradeDetector::UPGRADE_ANNOYANCE_LOW: |
| return SEVERITY_LOW; |
| case UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED: |
| return SEVERITY_MEDIUM; |
| case UpgradeDetector::UPGRADE_ANNOYANCE_HIGH: |
| return SEVERITY_HIGH; |
| case UpgradeDetector::UPGRADE_ANNOYANCE_SEVERE: |
| return SEVERITY_HIGH; |
| case UpgradeDetector::UPGRADE_ANNOYANCE_CRITICAL: |
| return SEVERITY_HIGH; |
| } |
| NOTREACHED(); |
| return SEVERITY_NONE; |
| } |
| |
| // static |
| bool WrenchIconPainter::ShouldAnimateUpgradeLevel( |
| UpgradeDetector::UpgradeNotificationAnnoyanceLevel level) { |
| bool should_animate = true; |
| if (level == UpgradeDetector::UPGRADE_ANNOYANCE_LOW) { |
| // Only animate low severity upgrades once. |
| static bool should_animate_low_severity = true; |
| should_animate = should_animate_low_severity; |
| should_animate_low_severity = false; |
| } |
| return should_animate; |
| } |
| |
| // static |
| WrenchIconPainter::Severity WrenchIconPainter::GlobalErrorSeverity() { |
| // If you change this make sure to also change the menu icon and the bubble |
| // icon. |
| return SEVERITY_MEDIUM; |
| } |
| |
| WrenchIconPainter::WrenchIconPainter(Delegate* delegate) |
| : delegate_(delegate), |
| severity_(SEVERITY_NONE) { |
| } |
| |
| WrenchIconPainter::~WrenchIconPainter() {} |
| |
| void WrenchIconPainter::SetSeverity(Severity severity, bool animate) { |
| if (severity_ == severity) |
| return; |
| |
| severity_ = severity; |
| delegate_->ScheduleWrenchIconPaint(); |
| animation_.reset(); |
| if (severity_ == SEVERITY_NONE || !animate) |
| return; |
| |
| gfx::MultiAnimation::Parts parts; |
| // Animate the bars left to right. |
| parts.push_back(gfx::MultiAnimation::Part(1300, gfx::Tween::LINEAR)); |
| // Fade out animation. |
| parts.push_back(gfx::MultiAnimation::Part(1000, gfx::Tween::EASE_IN)); |
| // Again, animate the bars left to right. |
| parts.push_back(gfx::MultiAnimation::Part(1300, gfx::Tween::LINEAR)); |
| |
| animation_.reset( |
| new gfx::MultiAnimation(parts, base::TimeDelta::FromMilliseconds(40))); |
| animation_->set_delegate(this); |
| animation_->set_continuous(false); |
| animation_->Start(); |
| } |
| |
| void WrenchIconPainter::Paint(gfx::Canvas* canvas, |
| ui::ThemeProvider* theme_provider, |
| const gfx::Rect& rect, |
| BezelType bezel_type) { |
| gfx::Point center = rect.CenterPoint(); |
| |
| // Bezel. |
| if (bezel_type != BEZEL_NONE) { |
| gfx::ImageSkia* image = theme_provider->GetImageSkiaNamed( |
| bezel_type == BEZEL_HOVER ? IDR_TOOLBAR_BEZEL_HOVER |
| : IDR_TOOLBAR_BEZEL_PRESSED); |
| canvas->DrawImageInt(*image, |
| center.x() - image->width() / 2, |
| center.y() - image->height() / 2); |
| } |
| |
| // The bars with no color. |
| { |
| gfx::ImageSkia* image = theme_provider->GetImageSkiaNamed(IDR_TOOLS_BAR); |
| int x = center.x() - image->width() / 2; |
| int y = center.y() - image->height() * kBarCount / 2; |
| for (int i = 0; i < kBarCount; ++i) { |
| canvas->DrawImageInt(*image, x, y); |
| y += image->height(); |
| } |
| } |
| |
| // The bars with color based on severity. |
| int severity_image_id = GetCurrentSeverityImageID(); |
| if (severity_image_id) { |
| gfx::ImageSkia* image = |
| theme_provider->GetImageSkiaNamed(severity_image_id); |
| int x = center.x() - image->width() / 2; |
| int y = center.y() - image->height() * kBarCount / 2; |
| for (int i = 0; i < kBarCount; ++i) { |
| SkPaint paint; |
| int width = image->width(); |
| |
| if (animation_ && animation_->is_animating()) { |
| if (animation_->current_part_index() % 2 == 1) { |
| // Fade out. |
| int alpha = animation_->CurrentValueBetween(0xFF, 0); |
| if (alpha == 0) |
| continue; |
| paint.setAlpha(alpha); |
| } else { |
| // Stagger the widths. |
| width = image->width() * |
| GetStaggeredValue(animation_->GetCurrentValue(), i); |
| if (width == 0) |
| continue; |
| } |
| } |
| |
| canvas->DrawImageInt(*image, 0, 0, width, image->height(), |
| x, y, width, image->height(), false, paint); |
| y += image->height(); |
| } |
| } |
| |
| if (!badge_.isNull()) |
| canvas->DrawImageInt(badge_, 0, 0); |
| } |
| |
| void WrenchIconPainter::AnimationProgressed(const gfx::Animation* animation) { |
| delegate_->ScheduleWrenchIconPaint(); |
| } |
| |
| int WrenchIconPainter::GetCurrentSeverityImageID() const { |
| switch (severity_) { |
| case SEVERITY_NONE: |
| return 0; |
| case SEVERITY_LOW: |
| return IDR_TOOLS_BAR_LOW; |
| case SEVERITY_MEDIUM: |
| return IDR_TOOLS_BAR_MEDIUM; |
| case SEVERITY_HIGH: |
| return IDR_TOOLS_BAR_HIGH; |
| } |
| NOTREACHED(); |
| return 0; |
| } |