Index: ui/views/controls/progress_bar.cc |
diff --git a/ui/views/controls/progress_bar.cc b/ui/views/controls/progress_bar.cc |
index 0278e5b51b0fdb0b4276b1e7c99dda704856effd..59275ba055fe7403148e4a912d20a4317bce976c 100644 |
--- a/ui/views/controls/progress_bar.cc |
+++ b/ui/views/controls/progress_bar.cc |
@@ -14,120 +14,10 @@ |
#include "third_party/skia/include/core/SkXfermode.h" |
#include "third_party/skia/include/effects/SkGradientShader.h" |
#include "ui/accessibility/ax_view_state.h" |
+#include "ui/gfx/animation/linear_animation.h" |
#include "ui/gfx/canvas.h" |
- |
-namespace { |
- |
-// Progress bar's border width. |
-const int kBorderWidth = 1; |
- |
-// Corner radius for the progress bar's border. |
-const int kCornerRadius = 2; |
- |
-// The width of the highlight at the right of the progress bar. |
-const int kHighlightWidth = 18; |
- |
-const SkColor kBackgroundColor = SkColorSetRGB(230, 230, 230); |
-const SkColor kBackgroundBorderColor = SkColorSetRGB(208, 208, 208); |
-const SkColor kBarBorderColor = SkColorSetRGB(65, 137, 237); |
-const SkColor kBarTopColor = SkColorSetRGB(110, 188, 249); |
-const SkColor kBarColorStart = SkColorSetRGB(86, 167, 247); |
-const SkColor kBarColorEnd = SkColorSetRGB(76, 148, 245); |
-const SkColor kBarHighlightEnd = SkColorSetRGB(114, 206, 251); |
-const SkColor kDisabledBarBorderColor = SkColorSetRGB(191, 191, 191); |
-const SkColor kDisabledBarColorStart = SkColorSetRGB(224, 224, 224); |
-const SkColor kDisabledBarColorEnd = SkColorSetRGB(212, 212, 212); |
- |
-void AddRoundRectPathWithPadding(int x, int y, |
- int w, int h, |
- int corner_radius, |
- SkScalar padding, |
- SkPath* path) { |
- DCHECK(path); |
- SkRect rect; |
- rect.set( |
- SkIntToScalar(x) + padding, SkIntToScalar(y) + padding, |
- SkIntToScalar(x + w) - padding, SkIntToScalar(y + h) - padding); |
- path->addRoundRect( |
- rect, |
- SkIntToScalar(corner_radius) - padding, |
- SkIntToScalar(corner_radius) - padding); |
-} |
- |
-void AddRoundRectPath(int x, int y, |
- int w, int h, |
- int corner_radius, |
- SkPath* path) { |
- AddRoundRectPathWithPadding(x, y, w, h, corner_radius, SK_ScalarHalf, path); |
-} |
- |
-void FillRoundRect(gfx::Canvas* canvas, |
- int x, int y, |
- int w, int h, |
- int corner_radius, |
- const SkColor colors[], |
- const SkScalar points[], |
- int count, |
- bool gradient_horizontal) { |
- SkPath path; |
- AddRoundRectPath(x, y, w, h, corner_radius, &path); |
- SkPaint paint; |
- paint.setStyle(SkPaint::kFill_Style); |
- paint.setFlags(SkPaint::kAntiAlias_Flag); |
- |
- SkPoint p[2]; |
- p[0].iset(x, y); |
- if (gradient_horizontal) { |
- p[1].iset(x + w, y); |
- } else { |
- p[1].iset(x, y + h); |
- } |
- paint.setShader(SkGradientShader::MakeLinear(p, colors, points, count, |
- SkShader::kClamp_TileMode)); |
- |
- canvas->DrawPath(path, paint); |
-} |
- |
-void FillRoundRect(gfx::Canvas* canvas, |
- int x, int y, |
- int w, int h, |
- int corner_radius, |
- SkColor gradient_start_color, |
- SkColor gradient_end_color, |
- bool gradient_horizontal) { |
- if (gradient_start_color != gradient_end_color) { |
- SkColor colors[2] = { gradient_start_color, gradient_end_color }; |
- FillRoundRect(canvas, x, y, w, h, corner_radius, |
- colors, NULL, 2, gradient_horizontal); |
- } else { |
- SkPath path; |
- AddRoundRectPath(x, y, w, h, corner_radius, &path); |
- SkPaint paint; |
- paint.setStyle(SkPaint::kFill_Style); |
- paint.setFlags(SkPaint::kAntiAlias_Flag); |
- paint.setColor(gradient_start_color); |
- canvas->DrawPath(path, paint); |
- } |
-} |
- |
-void StrokeRoundRect(gfx::Canvas* canvas, |
- int x, int y, |
- int w, int h, |
- int corner_radius, |
- SkColor stroke_color, |
- int stroke_width) { |
- SkPath path; |
- AddRoundRectPath(x, y, w, h, corner_radius, &path); |
- SkPaint paint; |
- paint.setShader(NULL); |
- paint.setColor(stroke_color); |
- paint.setStyle(SkPaint::kStroke_Style); |
- paint.setFlags(SkPaint::kAntiAlias_Flag); |
- paint.setStrokeWidth(SkIntToScalar(stroke_width)); |
- canvas->DrawPath(path, paint); |
-} |
- |
-} // namespace |
+#include "ui/gfx/color_utils.h" |
+#include "ui/native_theme/native_theme.h" |
namespace views { |
@@ -185,7 +75,7 @@ void ProgressBar::GetAccessibleState(ui::AXViewState* state) { |
} |
gfx::Size ProgressBar::GetPreferredSize() const { |
- gfx::Size pref_size(100, 11); |
+ gfx::Size pref_size(1, 2); |
gfx::Insets insets = GetInsets(); |
pref_size.Enlarge(insets.width(), insets.height()); |
return pref_size; |
@@ -195,124 +85,149 @@ const char* ProgressBar::GetClassName() const { |
return kViewClassName; |
} |
-void ProgressBar::OnPaint(gfx::Canvas* canvas) { |
+SkColor ProgressBar::GetForegroundColor() const { |
+ return GetNativeTheme()->GetSystemColor( |
+ ui::NativeTheme::kColorId_CallToActionColor); |
+} |
+ |
+SkColor ProgressBar::GetBackgroundColor() const { |
+ // The default foreground is GoogleBlue500, and the default background is |
+ // that color but 80% lighter. |
+ return color_utils::BlendTowardOppositeLuma(GetForegroundColor(), 0xCC); |
+} |
+ |
+// DeterminateProgressBar ////////////////////////////////////////////////////// |
+ |
+DeterminateProgressBar::DeterminateProgressBar() {} |
+ |
+DeterminateProgressBar::~DeterminateProgressBar() {} |
+ |
+bool DeterminateProgressBar::is_indeterminate() { |
+ return false; |
+} |
+ |
+void DeterminateProgressBar::OnPaint(gfx::Canvas* canvas) { |
gfx::Rect content_bounds = GetContentsBounds(); |
- int bar_left = content_bounds.x(); |
- int bar_top = content_bounds.y(); |
- int bar_width = content_bounds.width(); |
- int bar_height = content_bounds.height(); |
- const int progress_width = |
- static_cast<int>(bar_width * GetNormalizedValue() + 0.5); |
+ // Draw background. |
+ SkPath background_path; |
+ background_path.addRect(gfx::RectToSkRect(content_bounds)); |
+ SkPaint background_paint; |
+ background_paint.setStyle(SkPaint::kFill_Style); |
+ background_paint.setFlags(SkPaint::kAntiAlias_Flag); |
+ background_paint.setColor(GetBackgroundColor()); |
+ canvas->DrawPath(background_path, background_paint); |
+ |
+ // Draw slice. |
+ SkPath slice_path; |
+ const int slice_width = |
+ static_cast<int>(content_bounds.width() * GetNormalizedValue() + 0.5); |
+ if (slice_width < 1) |
+ return; |
+ |
+ gfx::Rect slice_bounds = content_bounds; |
+ slice_bounds.set_width(slice_width); |
+ slice_path.addRect(gfx::RectToSkRect(slice_bounds)); |
+ |
+ SkPaint slice_paint; |
+ slice_paint.setStyle(SkPaint::kFill_Style); |
+ slice_paint.setFlags(SkPaint::kAntiAlias_Flag); |
+ slice_paint.setColor(GetForegroundColor()); |
+ canvas->DrawPath(slice_path, slice_paint); |
+} |
+ |
+// IndeterminateProgressBar //////////////////////////////////////////////////// |
+ |
+IndeterminateProgressBar::IndeterminateProgressBar() { |
+ indeterminate_bar_animation_.reset(new gfx::LinearAnimation(this)); |
+ indeterminate_bar_animation_->SetDuration(2000); // In milliseconds. |
+ indeterminate_bar_animation_->Start(); |
+} |
+ |
+IndeterminateProgressBar::~IndeterminateProgressBar() { |
+ indeterminate_bar_animation_->Stop(); // Just in case. |
+} |
+ |
+bool IndeterminateProgressBar::is_indeterminate() { |
+ return true; |
+} |
+ |
+void IndeterminateProgressBar::OnPaint(gfx::Canvas* canvas) { |
+ gfx::Rect content_bounds = GetContentsBounds(); |
// Draw background. |
- FillRoundRect(canvas, |
- bar_left, bar_top, bar_width, bar_height, |
- kCornerRadius, |
- kBackgroundColor, kBackgroundColor, |
- false); |
- StrokeRoundRect(canvas, |
- bar_left, bar_top, |
- bar_width, bar_height, |
- kCornerRadius, |
- kBackgroundBorderColor, |
- kBorderWidth); |
- |
- if (progress_width > 1) { |
- // Draw inner if wide enough. |
- if (progress_width > kBorderWidth * 2) { |
- canvas->Save(); |
- |
- SkPath inner_path; |
- AddRoundRectPathWithPadding( |
- bar_left, bar_top, progress_width, bar_height, |
- kCornerRadius, |
- 0, |
- &inner_path); |
- canvas->ClipPath(inner_path, false); |
- |
- const SkColor bar_colors[] = { |
- kBarTopColor, |
- kBarTopColor, |
- kBarColorStart, |
- kBarColorEnd, |
- kBarColorEnd, |
- }; |
- // We want a thin 1-pixel line for kBarTopColor. |
- SkScalar scalar_height = SkIntToScalar(bar_height); |
- SkScalar highlight_width = 1 / scalar_height; |
- SkScalar border_width = kBorderWidth / scalar_height; |
- const SkScalar bar_points[] = { |
- 0, |
- border_width, |
- border_width + highlight_width, |
- SK_Scalar1 - border_width, |
- SK_Scalar1, |
- }; |
- |
- const SkColor disabled_bar_colors[] = { |
- kDisabledBarColorStart, |
- kDisabledBarColorStart, |
- kDisabledBarColorEnd, |
- kDisabledBarColorEnd, |
- }; |
- |
- const SkScalar disabled_bar_points[] = { |
- 0, |
- border_width, |
- SK_Scalar1 - border_width, |
- SK_Scalar1 |
- }; |
- |
- // Do not start from (kBorderWidth, kBorderWidth) because it makes gaps |
- // between the inner and the border. |
- FillRoundRect(canvas, |
- bar_left, bar_top, |
- progress_width, bar_height, |
- kCornerRadius, |
- enabled() ? bar_colors : disabled_bar_colors, |
- enabled() ? bar_points : disabled_bar_points, |
- enabled() ? arraysize(bar_colors) : |
- arraysize(disabled_bar_colors), |
- false); |
- |
- if (enabled()) { |
- // Draw the highlight to the right. |
- const SkColor highlight_colors[] = { |
- SkColorSetA(kBarHighlightEnd, 0), |
- kBarHighlightEnd, |
- kBarHighlightEnd, |
- }; |
- const SkScalar highlight_points[] = { |
- 0, SK_Scalar1 - kBorderWidth / scalar_height, SK_Scalar1, |
- }; |
- SkPaint paint; |
- paint.setStyle(SkPaint::kFill_Style); |
- paint.setFlags(SkPaint::kAntiAlias_Flag); |
- |
- SkPoint p[2]; |
- int highlight_left = |
- std::max(0, progress_width - kHighlightWidth - kBorderWidth); |
- p[0].iset(highlight_left, 0); |
- p[1].iset(progress_width, 0); |
- paint.setShader(SkGradientShader::MakeLinear( |
- p, highlight_colors, highlight_points, arraysize(highlight_colors), |
- SkShader::kClamp_TileMode)); |
- paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); |
- canvas->DrawRect(gfx::Rect(highlight_left, 0, |
- kHighlightWidth + kBorderWidth, bar_height), |
- paint); |
- } |
- |
- canvas->Restore(); |
- } |
- |
- // Draw bar stroke |
- StrokeRoundRect(canvas, |
- bar_left, bar_top, progress_width, bar_height, |
- kCornerRadius, |
- enabled() ? kBarBorderColor : kDisabledBarBorderColor, |
- kBorderWidth); |
+ SkPath background_path; |
+ background_path.addRect(gfx::RectToSkRect(content_bounds)); |
+ SkPaint background_paint; |
+ background_paint.setStyle(SkPaint::kFill_Style); |
+ background_paint.setFlags(SkPaint::kAntiAlias_Flag); |
+ background_paint.setColor(GetBackgroundColor()); |
+ canvas->DrawPath(background_path, background_paint); |
+ |
+ // Draw slice. |
+ SkPath slice_path; |
+ double time = indeterminate_bar_animation_->GetCurrentValue(); |
+ |
+ // The animation spec corresponds to the material design lite's parameter. |
+ // (cf. https://github.com/google/material-design-lite/) |
+ double bar1_left; |
+ double bar1_width; |
+ double bar2_left; |
+ double bar2_width; |
+ if (time < 0.50) { |
+ bar1_left = time / 2; |
+ bar1_width = time * 1.5; |
+ bar2_left = 0; |
+ bar2_width = 0; |
+ } else if (time < 0.75) { |
+ bar1_left = time * 3 - 1.25; |
+ bar1_width = 0.75 - (time - 0.5) * 3; |
+ bar2_left = 0; |
+ bar2_width = time - 0.5; |
+ } else { |
+ bar1_left = 1; |
+ bar1_width = 0; |
+ bar2_left = (time - 0.75) * 4; |
+ bar2_width = 0.25 - (time - 0.75); |
+ } |
+ |
+ int bar1_x = static_cast<int>(content_bounds.width() * bar1_left); |
+ int bar1_w = |
+ std::min(static_cast<int>(content_bounds.width() * bar1_width + 0.5), |
+ content_bounds.width() - bar1_x); |
+ int bar2_x = static_cast<int>(content_bounds.width() * bar2_left); |
+ int bar2_w = |
+ std::min(static_cast<int>(content_bounds.width() * bar2_width + 0.5), |
+ content_bounds.width() - bar2_x); |
+ |
+ gfx::Rect slice_bounds = content_bounds; |
+ slice_bounds.set_x(content_bounds.x() + bar1_x); |
+ slice_bounds.set_width(bar1_w); |
+ slice_path.addRect(gfx::RectToSkRect(slice_bounds)); |
+ slice_bounds.set_x(content_bounds.x() + bar2_x); |
+ slice_bounds.set_width(bar2_w); |
+ slice_path.addRect(gfx::RectToSkRect(slice_bounds)); |
+ |
+ SkPaint slice_paint; |
+ slice_paint.setStyle(SkPaint::kFill_Style); |
+ slice_paint.setFlags(SkPaint::kAntiAlias_Flag); |
+ slice_paint.setColor(GetForegroundColor()); |
+ canvas->DrawPath(slice_path, slice_paint); |
+} |
+ |
+void IndeterminateProgressBar::AnimationProgressed( |
+ const gfx::Animation* animation) { |
+ if (animation == indeterminate_bar_animation_.get()) { |
+ DCHECK(indeterminate_bar_animation_); |
+ SchedulePaint(); |
+ } |
+} |
+ |
+void IndeterminateProgressBar::AnimationEnded(const gfx::Animation* animation) { |
+ // Restarts animation. |
+ if (animation == indeterminate_bar_animation_.get()) { |
+ DCHECK(indeterminate_bar_animation_); |
+ indeterminate_bar_animation_->Start(); |
} |
} |