1 // Copyright (c) 2013 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 "chrome/browser/ui/toolbar/wrench_icon_painter.h" 6 7 #include <algorithm> 8 9 #include "grit/theme_resources.h" 10 #include "ui/base/theme_provider.h" 11 #include "ui/gfx/animation/multi_animation.h" 12 #include "ui/gfx/canvas.h" 13 #include "ui/gfx/image/image_skia.h" 14 #include "ui/gfx/rect.h" 15 16 namespace { 17 18 // The wrench icon is made up of this many bars stacked vertically. 19 const int kBarCount = 3; 20 21 // |value| is the animation progress from 0 to 1. |index| is the index of the 22 // bar being drawn. This function returns a new progress value (from 0 to 1) 23 // such that bars appear staggered. 24 double GetStaggeredValue(double value, int index) { 25 // When animating the wrench icon's bars the bars are staggered by this 26 // factor. 27 const double kStaggerFactor = 0.15; 28 double maxStaggeredValue = 1.0 - (kBarCount - 1) * kStaggerFactor; 29 double staggeredValue = (value - kStaggerFactor * index) / maxStaggeredValue; 30 return std::min(1.0, std::max(0.0, staggeredValue)); 31 } 32 33 } // namespace 34 35 WrenchIconPainter::WrenchIconPainter(Delegate* delegate) 36 : delegate_(delegate), 37 severity_(SEVERITY_NONE) { 38 } 39 40 WrenchIconPainter::~WrenchIconPainter() {} 41 42 void WrenchIconPainter::SetSeverity(Severity severity, bool animate) { 43 if (severity_ == severity) 44 return; 45 46 severity_ = severity; 47 delegate_->ScheduleWrenchIconPaint(); 48 animation_.reset(); 49 if (severity_ == SEVERITY_NONE || !animate) 50 return; 51 52 gfx::MultiAnimation::Parts parts; 53 // Animate the bars left to right. 54 parts.push_back(gfx::MultiAnimation::Part(1300, gfx::Tween::LINEAR)); 55 // Fade out animation. 56 parts.push_back(gfx::MultiAnimation::Part(1000, gfx::Tween::EASE_IN)); 57 // Again, animate the bars left to right. 58 parts.push_back(gfx::MultiAnimation::Part(1300, gfx::Tween::LINEAR)); 59 60 animation_.reset( 61 new gfx::MultiAnimation(parts, base::TimeDelta::FromMilliseconds(40))); 62 animation_->set_delegate(this); 63 animation_->set_continuous(false); 64 animation_->Start(); 65 } 66 67 void WrenchIconPainter::Paint(gfx::Canvas* canvas, 68 ui::ThemeProvider* theme_provider, 69 const gfx::Rect& rect, 70 BezelType bezel_type) { 71 gfx::Point center = rect.CenterPoint(); 72 73 // Bezel. 74 if (bezel_type != BEZEL_NONE) { 75 gfx::ImageSkia* image = theme_provider->GetImageSkiaNamed( 76 bezel_type == BEZEL_HOVER ? IDR_TOOLBAR_BEZEL_HOVER 77 : IDR_TOOLBAR_BEZEL_PRESSED); 78 canvas->DrawImageInt(*image, 79 center.x() - image->width() / 2, 80 center.y() - image->height() / 2); 81 } 82 83 // The bars with no color. 84 { 85 gfx::ImageSkia* image = theme_provider->GetImageSkiaNamed(IDR_TOOLS_BAR); 86 int x = center.x() - image->width() / 2; 87 int y = center.y() - image->height() * kBarCount / 2; 88 for (int i = 0; i < kBarCount; ++i) { 89 canvas->DrawImageInt(*image, x, y); 90 y += image->height(); 91 } 92 } 93 94 // The bars with color based on severity. 95 int severity_image_id = GetCurrentSeverityImageID(); 96 if (severity_image_id) { 97 gfx::ImageSkia* image = 98 theme_provider->GetImageSkiaNamed(severity_image_id); 99 int x = center.x() - image->width() / 2; 100 int y = center.y() - image->height() * kBarCount / 2; 101 for (int i = 0; i < kBarCount; ++i) { 102 SkPaint paint; 103 int width = image->width(); 104 105 if (animation_ && animation_->is_animating()) { 106 if (animation_->current_part_index() % 2 == 1) { 107 // Fade out. 108 int alpha = animation_->CurrentValueBetween(0xFF, 0); 109 if (alpha == 0) 110 continue; 111 paint.setAlpha(alpha); 112 } else { 113 // Stagger the widths. 114 width = image->width() * 115 GetStaggeredValue(animation_->GetCurrentValue(), i); 116 if (width == 0) 117 continue; 118 } 119 } 120 121 canvas->DrawImageInt(*image, 0, 0, width, image->height(), 122 x, y, width, image->height(), false, paint); 123 y += image->height(); 124 } 125 } 126 127 if (!badge_.isNull()) 128 canvas->DrawImageInt(badge_, 0, 0); 129 } 130 131 void WrenchIconPainter::AnimationProgressed(const gfx::Animation* animation) { 132 delegate_->ScheduleWrenchIconPaint(); 133 } 134 135 int WrenchIconPainter::GetCurrentSeverityImageID() const { 136 switch (severity_) { 137 case SEVERITY_NONE: 138 return 0; 139 case SEVERITY_LOW: 140 return IDR_TOOLS_BAR_LOW; 141 case SEVERITY_MEDIUM: 142 return IDR_TOOLS_BAR_MEDIUM; 143 case SEVERITY_HIGH: 144 return IDR_TOOLS_BAR_HIGH; 145 } 146 NOTREACHED(); 147 return 0; 148 } 149