1// Copyright (c) 2012 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 "ui/views/controls/glow_hover_controller.h"
6
7#include "third_party/skia/include/effects/SkGradientShader.h"
8#include "ui/gfx/canvas.h"
9#include "ui/gfx/image/image_skia.h"
10#include "ui/gfx/image/image_skia_operations.h"
11#include "ui/views/view.h"
12
13namespace views {
14
15// Amount to scale the opacity.
16static const double kTrackOpacityScale = 0.5;
17static const double kHighlightOpacityScale = 1.0;
18
19// How long the hover state takes.
20static const int kTrackHoverDurationMs = 400;
21
22GlowHoverController::GlowHoverController(views::View* view)
23    : view_(view),
24      animation_(this),
25      opacity_scale_(kTrackOpacityScale) {
26  animation_.set_delegate(this);
27}
28
29GlowHoverController::~GlowHoverController() {
30}
31
32void GlowHoverController::SetAnimationContainer(
33    gfx::AnimationContainer* container) {
34  animation_.SetContainer(container);
35}
36
37void GlowHoverController::SetLocation(const gfx::Point& location) {
38  location_ = location;
39  if (ShouldDraw())
40    view_->SchedulePaint();
41}
42
43void GlowHoverController::Show(Style style) {
44  switch (style) {
45    case SUBTLE:
46      opacity_scale_ = kTrackOpacityScale;
47      animation_.SetSlideDuration(kTrackHoverDurationMs);
48      animation_.SetTweenType(gfx::Tween::EASE_OUT);
49      animation_.Show();
50      break;
51    case PRONOUNCED:
52      opacity_scale_ = kHighlightOpacityScale;
53      // Force the end state to show immediately.
54      animation_.Show();
55      animation_.End();
56      break;
57  }
58}
59
60void GlowHoverController::Hide() {
61  animation_.SetTweenType(gfx::Tween::EASE_IN);
62  animation_.Hide();
63}
64
65void GlowHoverController::HideImmediately() {
66  if (ShouldDraw())
67    view_->SchedulePaint();
68  animation_.Reset();
69}
70
71double GlowHoverController::GetAnimationValue() const {
72  return animation_.GetCurrentValue();
73}
74
75bool GlowHoverController::ShouldDraw() const {
76  return animation_.IsShowing() || animation_.is_animating();
77}
78
79void GlowHoverController::Draw(gfx::Canvas* canvas,
80                               const gfx::ImageSkia& mask_image) const {
81  if (!ShouldDraw())
82    return;
83
84  // Draw a radial gradient to hover_canvas.
85  gfx::Canvas hover_canvas(gfx::Size(mask_image.width(), mask_image.height()),
86                           canvas->image_scale(),
87                           false);
88
89  // Draw a radial gradient to hover_canvas.
90  int radius = view_->width() / 3;
91
92  SkPoint center_point;
93  center_point.iset(location_.x(), location_.y());
94  SkColor colors[2];
95  int hover_alpha =
96      static_cast<int>(255 * opacity_scale_ * animation_.GetCurrentValue());
97  colors[0] = SkColorSetARGB(hover_alpha, 255, 255, 255);
98  colors[1] = SkColorSetARGB(0, 255, 255, 255);
99  skia::RefPtr<SkShader> shader = skia::AdoptRef(
100      SkGradientShader::CreateRadial(
101          center_point, SkIntToScalar(radius), colors, NULL, 2,
102          SkShader::kClamp_TileMode));
103  // Shader can end up null when radius = 0.
104  // If so, this results in default full tab glow behavior.
105  if (shader) {
106    SkPaint paint;
107    paint.setStyle(SkPaint::kFill_Style);
108    paint.setAntiAlias(true);
109    paint.setShader(shader.get());
110    hover_canvas.DrawRect(gfx::Rect(location_.x() - radius,
111                                    location_.y() - radius,
112                                    radius * 2, radius * 2), paint);
113  }
114  gfx::ImageSkia result = gfx::ImageSkiaOperations::CreateMaskedImage(
115      gfx::ImageSkia(hover_canvas.ExtractImageRep()), mask_image);
116  canvas->DrawImageInt(result, (view_->width() - mask_image.width()) / 2,
117                       (view_->height() - mask_image.height()) / 2);
118}
119
120void GlowHoverController::AnimationEnded(const gfx::Animation* animation) {
121  view_->SchedulePaint();
122}
123
124void GlowHoverController::AnimationProgressed(const gfx::Animation* animation) {
125  view_->SchedulePaint();
126}
127
128}  // namespace views
129