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.
5 #include "chrome/browser/ui/toolbar/wrench_icon_painter.h"
7 #include "grit/theme_resources.h"
8 #include "ui/base/theme_provider.h"
9 #include "ui/gfx/animation/multi_animation.h"
10 #include "ui/gfx/canvas.h"
11 #include "ui/gfx/image/image_skia.h"
12 #include "ui/gfx/rect.h"
16 // The wrench icon is made up of this many bars stacked vertically.
17 const int kBarCount
= 3;
19 // |value| is the animation progress from 0 to 1. |index| is the index of the
20 // bar being drawn. This function returns a new progress value (from 0 to 1)
21 // such that bars appear staggered.
22 double GetStaggeredValue(double value
, int index
) {
23 // When animating the wrench icon's bars the bars are staggered by this
25 const double kStaggerFactor
= 0.15;
26 double maxStaggeredValue
= 1.0 - (kBarCount
- 1) * kStaggerFactor
;
27 double staggeredValue
= (value
- kStaggerFactor
* index
) / maxStaggeredValue
;
28 return std::min(1.0, std::max(0.0, staggeredValue
));
34 WrenchIconPainter::Severity
WrenchIconPainter::SeverityFromUpgradeLevel(
35 UpgradeDetector::UpgradeNotificationAnnoyanceLevel level
) {
37 case UpgradeDetector::UPGRADE_ANNOYANCE_NONE
:
39 case UpgradeDetector::UPGRADE_ANNOYANCE_LOW
:
41 case UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED
:
42 return SEVERITY_MEDIUM
;
43 case UpgradeDetector::UPGRADE_ANNOYANCE_HIGH
:
45 case UpgradeDetector::UPGRADE_ANNOYANCE_SEVERE
:
47 case UpgradeDetector::UPGRADE_ANNOYANCE_CRITICAL
:
55 bool WrenchIconPainter::ShouldAnimateUpgradeLevel(
56 UpgradeDetector::UpgradeNotificationAnnoyanceLevel level
) {
57 bool should_animate
= true;
58 if (level
== UpgradeDetector::UPGRADE_ANNOYANCE_LOW
) {
59 // Only animate low severity upgrades once.
60 static bool should_animate_low_severity
= true;
61 should_animate
= should_animate_low_severity
;
62 should_animate_low_severity
= false;
64 return should_animate
;
68 WrenchIconPainter::Severity
WrenchIconPainter::GlobalErrorSeverity() {
69 // If you change this make sure to also change the menu icon and the bubble
71 return SEVERITY_MEDIUM
;
74 WrenchIconPainter::WrenchIconPainter(Delegate
* delegate
)
75 : delegate_(delegate
),
76 severity_(SEVERITY_NONE
) {
79 WrenchIconPainter::~WrenchIconPainter() {}
81 void WrenchIconPainter::SetSeverity(Severity severity
, bool animate
) {
82 if (severity_
== severity
)
86 delegate_
->ScheduleWrenchIconPaint();
88 if (severity_
== SEVERITY_NONE
|| !animate
)
91 gfx::MultiAnimation::Parts parts
;
92 // Animate the bars left to right.
93 parts
.push_back(gfx::MultiAnimation::Part(1300, gfx::Tween::LINEAR
));
94 // Fade out animation.
95 parts
.push_back(gfx::MultiAnimation::Part(1000, gfx::Tween::EASE_IN
));
96 // Again, animate the bars left to right.
97 parts
.push_back(gfx::MultiAnimation::Part(1300, gfx::Tween::LINEAR
));
100 new gfx::MultiAnimation(parts
, base::TimeDelta::FromMilliseconds(40)));
101 animation_
->set_delegate(this);
102 animation_
->set_continuous(false);
106 void WrenchIconPainter::Paint(gfx::Canvas
* canvas
,
107 ui::ThemeProvider
* theme_provider
,
108 const gfx::Rect
& rect
,
109 BezelType bezel_type
) {
110 gfx::Point center
= rect
.CenterPoint();
113 if (bezel_type
!= BEZEL_NONE
) {
114 gfx::ImageSkia
* image
= theme_provider
->GetImageSkiaNamed(
115 bezel_type
== BEZEL_HOVER
? IDR_TOOLBAR_BEZEL_HOVER
116 : IDR_TOOLBAR_BEZEL_PRESSED
);
117 canvas
->DrawImageInt(*image
,
118 center
.x() - image
->width() / 2,
119 center
.y() - image
->height() / 2);
122 // The bars with no color.
124 gfx::ImageSkia
* image
= theme_provider
->GetImageSkiaNamed(IDR_TOOLS_BAR
);
125 int x
= center
.x() - image
->width() / 2;
126 int y
= center
.y() - image
->height() * kBarCount
/ 2;
127 for (int i
= 0; i
< kBarCount
; ++i
) {
128 canvas
->DrawImageInt(*image
, x
, y
);
129 y
+= image
->height();
133 // The bars with color based on severity.
134 int severity_image_id
= GetCurrentSeverityImageID();
135 if (severity_image_id
) {
136 gfx::ImageSkia
* image
=
137 theme_provider
->GetImageSkiaNamed(severity_image_id
);
138 int x
= center
.x() - image
->width() / 2;
139 int y
= center
.y() - image
->height() * kBarCount
/ 2;
140 for (int i
= 0; i
< kBarCount
; ++i
) {
142 int width
= image
->width();
144 if (animation_
&& animation_
->is_animating()) {
145 if (animation_
->current_part_index() % 2 == 1) {
147 int alpha
= animation_
->CurrentValueBetween(0xFF, 0);
150 paint
.setAlpha(alpha
);
152 // Stagger the widths.
153 width
= image
->width() *
154 GetStaggeredValue(animation_
->GetCurrentValue(), i
);
160 canvas
->DrawImageInt(*image
, 0, 0, width
, image
->height(),
161 x
, y
, width
, image
->height(), false, paint
);
162 y
+= image
->height();
166 if (!badge_
.isNull())
167 canvas
->DrawImageInt(badge_
, 0, 0);
170 void WrenchIconPainter::AnimationProgressed(const gfx::Animation
* animation
) {
171 delegate_
->ScheduleWrenchIconPaint();
174 int WrenchIconPainter::GetCurrentSeverityImageID() const {
179 return IDR_TOOLS_BAR_LOW
;
180 case SEVERITY_MEDIUM
:
181 return IDR_TOOLS_BAR_MEDIUM
;
183 return IDR_TOOLS_BAR_HIGH
;