| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 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 "views/controls/progress_bar.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <string> | |
| 9 | |
| 10 #include "base/logging.h" | |
| 11 #include "base/string_util.h" | |
| 12 #include "base/utf_string_conversions.h" | |
| 13 #include "third_party/skia/include/effects/SkBlurMaskFilter.h" | |
| 14 #include "third_party/skia/include/effects/SkGradientShader.h" | |
| 15 #include "ui/base/accessibility/accessible_view_state.h" | |
| 16 #include "ui/gfx/canvas_skia.h" | |
| 17 #include "ui/gfx/color_utils.h" | |
| 18 #include "ui/gfx/font.h" | |
| 19 #include "ui/gfx/insets.h" | |
| 20 #include "views/background.h" | |
| 21 #include "views/border.h" | |
| 22 #include "views/painter.h" | |
| 23 | |
| 24 namespace { | |
| 25 | |
| 26 // Corner radius for the progress bar's border. | |
| 27 const int kCornerRadius = 3; | |
| 28 | |
| 29 // Progress bar's border width | |
| 30 const int kBorderWidth = 1; | |
| 31 | |
| 32 void AddRoundRectPathWithPadding(int x, int y, | |
| 33 int w, int h, | |
| 34 int corner_radius, | |
| 35 SkScalar padding, | |
| 36 SkPath* path) { | |
| 37 DCHECK(path); | |
| 38 if (path == NULL) | |
| 39 return; | |
| 40 SkRect rect; | |
| 41 rect.set( | |
| 42 SkIntToScalar(x) + padding, SkIntToScalar(y) + padding, | |
| 43 SkIntToScalar(x + w) - padding, SkIntToScalar(y + h) - padding); | |
| 44 path->addRoundRect( | |
| 45 rect, | |
| 46 SkIntToScalar(corner_radius) - padding, | |
| 47 SkIntToScalar(corner_radius) - padding); | |
| 48 } | |
| 49 | |
| 50 void AddRoundRectPath(int x, int y, | |
| 51 int w, int h, | |
| 52 int corner_radius, | |
| 53 SkPath* path) { | |
| 54 static const SkScalar half = SkIntToScalar(1) / 2; | |
| 55 AddRoundRectPathWithPadding(x, y, w, h, corner_radius, half, path); | |
| 56 } | |
| 57 | |
| 58 void FillRoundRect(gfx::Canvas* canvas, | |
| 59 int x, int y, | |
| 60 int w, int h, | |
| 61 int corner_radius, | |
| 62 const SkColor colors[], | |
| 63 const SkScalar points[], | |
| 64 int count, | |
| 65 bool gradient_horizontal) { | |
| 66 SkPath path; | |
| 67 AddRoundRectPath(x, y, w, h, corner_radius, &path); | |
| 68 SkPaint paint; | |
| 69 paint.setStyle(SkPaint::kFill_Style); | |
| 70 paint.setFlags(SkPaint::kAntiAlias_Flag); | |
| 71 | |
| 72 SkPoint p[2]; | |
| 73 p[0].set(SkIntToScalar(x), SkIntToScalar(y)); | |
| 74 if (gradient_horizontal) { | |
| 75 p[1].set(SkIntToScalar(x + w), SkIntToScalar(y)); | |
| 76 } else { | |
| 77 p[1].set(SkIntToScalar(x), SkIntToScalar(y + h)); | |
| 78 } | |
| 79 SkShader* s = SkGradientShader::CreateLinear( | |
| 80 p, colors, points, count, SkShader::kClamp_TileMode, NULL); | |
| 81 paint.setShader(s); | |
| 82 // Need to unref shader, otherwise never deleted. | |
| 83 s->unref(); | |
| 84 | |
| 85 canvas->GetSkCanvas()->drawPath(path, paint); | |
| 86 } | |
| 87 | |
| 88 void FillRoundRect(gfx::Canvas* canvas, | |
| 89 int x, int y, | |
| 90 int w, int h, | |
| 91 int corner_radius, | |
| 92 SkColor gradient_start_color, | |
| 93 SkColor gradient_end_color, | |
| 94 bool gradient_horizontal) { | |
| 95 if (gradient_start_color != gradient_end_color) { | |
| 96 SkColor colors[2] = { gradient_start_color, gradient_end_color }; | |
| 97 FillRoundRect(canvas, x, y, w, h, corner_radius, | |
| 98 colors, NULL, 2, gradient_horizontal); | |
| 99 } else { | |
| 100 SkPath path; | |
| 101 AddRoundRectPath(x, y, w, h, corner_radius, &path); | |
| 102 SkPaint paint; | |
| 103 paint.setStyle(SkPaint::kFill_Style); | |
| 104 paint.setFlags(SkPaint::kAntiAlias_Flag); | |
| 105 paint.setColor(gradient_start_color); | |
| 106 canvas->GetSkCanvas()->drawPath(path, paint); | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 void StrokeRoundRect(gfx::Canvas* canvas, | |
| 111 int x, int y, | |
| 112 int w, int h, | |
| 113 int corner_radius, | |
| 114 SkColor stroke_color, | |
| 115 int stroke_width) { | |
| 116 SkPath path; | |
| 117 AddRoundRectPath(x, y, w, h, corner_radius, &path); | |
| 118 SkPaint paint; | |
| 119 paint.setShader(NULL); | |
| 120 paint.setColor(stroke_color); | |
| 121 paint.setStyle(SkPaint::kStroke_Style); | |
| 122 paint.setFlags(SkPaint::kAntiAlias_Flag); | |
| 123 paint.setStrokeWidth(SkIntToScalar(stroke_width)); | |
| 124 canvas->GetSkCanvas()->drawPath(path, paint); | |
| 125 } | |
| 126 | |
| 127 } // namespace | |
| 128 | |
| 129 namespace views { | |
| 130 | |
| 131 // static | |
| 132 const char ProgressBar::kViewClassName[] = "views/ProgressBar"; | |
| 133 | |
| 134 ProgressBar::ProgressBar() | |
| 135 : min_display_value_(0.0), | |
| 136 max_display_value_(1.0), | |
| 137 current_value_(0.0) { | |
| 138 } | |
| 139 | |
| 140 ProgressBar::~ProgressBar() { | |
| 141 } | |
| 142 | |
| 143 void ProgressBar::SetDisplayRange(double min_display_value, | |
| 144 double max_display_value) { | |
| 145 if (min_display_value != min_display_value_ || | |
| 146 max_display_value != max_display_value_) { | |
| 147 DCHECK(min_display_value < max_display_value); | |
| 148 min_display_value_ = min_display_value; | |
| 149 max_display_value_ = max_display_value; | |
| 150 SchedulePaint(); | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 void ProgressBar::SetValue(double value) { | |
| 155 if (value != current_value_) { | |
| 156 current_value_ = value; | |
| 157 SchedulePaint(); | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 void ProgressBar::SetTooltipText(const string16& tooltip_text) { | |
| 162 tooltip_text_ = tooltip_text; | |
| 163 } | |
| 164 | |
| 165 bool ProgressBar::GetTooltipText(const gfx::Point& p, string16* tooltip) const { | |
| 166 DCHECK(tooltip); | |
| 167 if (tooltip == NULL) | |
| 168 return false; | |
| 169 tooltip->assign(tooltip_text_); | |
| 170 return !tooltip_text_.empty(); | |
| 171 } | |
| 172 | |
| 173 void ProgressBar::GetAccessibleState(ui::AccessibleViewState* state) { | |
| 174 state->role = ui::AccessibilityTypes::ROLE_PROGRESSBAR; | |
| 175 state->state = ui::AccessibilityTypes::STATE_READONLY; | |
| 176 } | |
| 177 | |
| 178 gfx::Size ProgressBar::GetPreferredSize() { | |
| 179 return gfx::Size(100, 16); | |
| 180 } | |
| 181 | |
| 182 std::string ProgressBar::GetClassName() const { | |
| 183 return kViewClassName; | |
| 184 } | |
| 185 | |
| 186 void ProgressBar::OnPaint(gfx::Canvas* canvas) { | |
| 187 const double capped_value = std::min( | |
| 188 std::max(current_value_, min_display_value_), max_display_value_); | |
| 189 const double capped_fraction = | |
| 190 (capped_value - min_display_value_) / | |
| 191 (max_display_value_ - min_display_value_); | |
| 192 const int progress_width = static_cast<int>(width() * capped_fraction + 0.5); | |
| 193 | |
| 194 #if defined(OS_CHROMEOS) | |
| 195 const SkColor background_colors[] = { | |
| 196 SkColorSetRGB(0xBB, 0xBB, 0xBB), | |
| 197 SkColorSetRGB(0xE7, 0xE7, 0xE7), | |
| 198 SkColorSetRGB(0xFE, 0xFE, 0xFE) | |
| 199 }; | |
| 200 | |
| 201 const SkScalar background_points[] = { | |
| 202 SkDoubleToScalar(0), | |
| 203 SkDoubleToScalar(0.1), | |
| 204 SkDoubleToScalar(1) | |
| 205 }; | |
| 206 const SkColor background_border_color = SkColorSetRGB(0xA1, 0xA1, 0xA1); | |
| 207 | |
| 208 // Draw background. | |
| 209 FillRoundRect(canvas, | |
| 210 0, 0, width(), height(), | |
| 211 kCornerRadius, | |
| 212 background_colors, | |
| 213 background_points, | |
| 214 arraysize(background_colors), | |
| 215 false); | |
| 216 StrokeRoundRect(canvas, | |
| 217 0, 0, | |
| 218 width(), height(), | |
| 219 kCornerRadius, | |
| 220 background_border_color, | |
| 221 kBorderWidth); | |
| 222 | |
| 223 if (progress_width > 1) { | |
| 224 const bool enabled = IsEnabled(); | |
| 225 | |
| 226 const SkColor bar_color_start = enabled ? | |
| 227 SkColorSetRGB(100, 116, 147) : | |
| 228 SkColorSetRGB(229, 232, 237); | |
| 229 const SkColor bar_color_end = enabled ? | |
| 230 SkColorSetRGB(65, 73, 87) : | |
| 231 SkColorSetRGB(224, 225, 227); | |
| 232 | |
| 233 const SkColor bar_outer_color = enabled ? | |
| 234 SkColorSetRGB(0x4A, 0x4A, 0x4A) : | |
| 235 SkColorSetARGB(0x80, 0x4A, 0x4A, 0x4A); | |
| 236 | |
| 237 const SkColor bar_inner_border_color = | |
| 238 SkColorSetARGB(0x3F, 0xFF, 0xFF, 0xFF); // 0.25 white | |
| 239 const SkColor bar_inner_shadow_color = | |
| 240 SkColorSetARGB(0x54, 0xFF, 0xFF, 0xFF); // 0.33 white | |
| 241 | |
| 242 // Draw bar background | |
| 243 FillRoundRect(canvas, | |
| 244 0, 0, progress_width, height(), | |
| 245 kCornerRadius, | |
| 246 bar_color_start, | |
| 247 bar_color_end, | |
| 248 false); | |
| 249 | |
| 250 // Draw inner stroke and shadow if wide enough. | |
| 251 if (progress_width > 2 * kBorderWidth) { | |
| 252 canvas->GetSkCanvas()->save(); | |
| 253 | |
| 254 SkPath inner_path; | |
| 255 AddRoundRectPathWithPadding( | |
| 256 0, 0, progress_width, height(), | |
| 257 kCornerRadius, | |
| 258 SkIntToScalar(kBorderWidth), | |
| 259 &inner_path); | |
| 260 canvas->GetSkCanvas()->clipPath(inner_path); | |
| 261 | |
| 262 // Draw bar inner stroke | |
| 263 StrokeRoundRect(canvas, | |
| 264 kBorderWidth, kBorderWidth, | |
| 265 progress_width - 2 * kBorderWidth, | |
| 266 height() - 2 * kBorderWidth, | |
| 267 kCornerRadius - kBorderWidth, | |
| 268 bar_inner_border_color, | |
| 269 kBorderWidth); | |
| 270 | |
| 271 // Draw bar inner shadow | |
| 272 StrokeRoundRect(canvas, | |
| 273 0, kBorderWidth, progress_width, height(), | |
| 274 kCornerRadius, | |
| 275 bar_inner_shadow_color, | |
| 276 kBorderWidth); | |
| 277 | |
| 278 canvas->GetSkCanvas()->restore(); | |
| 279 } | |
| 280 | |
| 281 // Draw bar stroke | |
| 282 StrokeRoundRect(canvas, | |
| 283 0, 0, progress_width, height(), | |
| 284 kCornerRadius, | |
| 285 bar_outer_color, | |
| 286 kBorderWidth); | |
| 287 } | |
| 288 #else | |
| 289 SkColor bar_color_start = SkColorSetRGB(81, 138, 223); | |
| 290 SkColor bar_color_end = SkColorSetRGB(51, 103, 205); | |
| 291 SkColor background_color_start = SkColorSetRGB(212, 212, 212); | |
| 292 SkColor background_color_end = SkColorSetRGB(252, 252, 252); | |
| 293 SkColor border_color = SkColorSetRGB(144, 144, 144); | |
| 294 | |
| 295 FillRoundRect(canvas, | |
| 296 0, 0, width(), height(), | |
| 297 kCornerRadius, | |
| 298 background_color_start, | |
| 299 background_color_end, | |
| 300 false); | |
| 301 if (progress_width > 1) { | |
| 302 FillRoundRect(canvas, | |
| 303 0, 0, | |
| 304 progress_width, height(), | |
| 305 kCornerRadius, | |
| 306 bar_color_start, | |
| 307 bar_color_end, | |
| 308 false); | |
| 309 } | |
| 310 StrokeRoundRect(canvas, | |
| 311 0, 0, | |
| 312 width(), height(), | |
| 313 kCornerRadius, | |
| 314 border_color, | |
| 315 kBorderWidth); | |
| 316 #endif | |
| 317 } | |
| 318 | |
| 319 } // namespace views | |
| OLD | NEW |