root/chrome/browser/ui/toolbar/wrench_icon_painter.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GetStaggeredValue
  2. SeverityFromUpgradeLevel
  3. ShouldAnimateUpgradeLevel
  4. GlobalErrorSeverity
  5. severity_
  6. SetSeverity
  7. AnimationProgressed
  8. GetCurrentSeverityImageID

// 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;
}

/* [<][>][^][v][top][bottom][index][help] */