15e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)// found in the LICENSE file.
45e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
55e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
65e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
75e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "third_party/skia/include/core/SkColor.h"
85e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "third_party/skia/include/core/SkXfermode.h"
95e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "ui/gfx/canvas.h"
105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "ui/views/background.h"
115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "ui/views/border.h"
125e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)namespace views {
155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)namespace {
165e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
175e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)const int kScrollbarWidth = 10;
185e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)const int kThumbInsetInside = 3;
195e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)const int kThumbInsetFromEdge = 1;
205e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)const int kThumbCornerRadius = 2;
215e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)const int kThumbMinimumSize = kScrollbarWidth;
225e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)const int kThumbHoverAlpha = 128;
235e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)const int kThumbDefaultAlpha = 64;
245e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
255e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)class OverlayScrollBarThumb : public BaseScrollBarThumb,
26d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                              public gfx::AnimationDelegate {
275e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) public:
285e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  explicit OverlayScrollBarThumb(BaseScrollBar* scroll_bar);
295e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  virtual ~OverlayScrollBarThumb();
305e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
315e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) protected:
325e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  // View overrides:
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual gfx::Size GetPreferredSize() const OVERRIDE;
345e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
355e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // gfx::AnimationDelegate overrides:
37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
385e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
395e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) private:
405e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  double animation_opacity_;
415e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OverlayScrollBarThumb);
425e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)};
435e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
445e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)OverlayScrollBarThumb::OverlayScrollBarThumb(BaseScrollBar* scroll_bar)
455e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    : BaseScrollBarThumb(scroll_bar),
465e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      animation_opacity_(0.0) {
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // This is necessary, otherwise the thumb will be rendered below the views if
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // those views paint to their own layers.
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetPaintToLayer(true);
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetFillsBoundsOpaquely(false);
515e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
525e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
535e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)OverlayScrollBarThumb::~OverlayScrollBarThumb() {
545e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
555e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size OverlayScrollBarThumb::GetPreferredSize() const {
575e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  return gfx::Size(kThumbMinimumSize, kThumbMinimumSize);
585e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
595e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
605e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OverlayScrollBarThumb::OnPaint(gfx::Canvas* canvas) {
615e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  gfx::Rect local_bounds(GetLocalBounds());
625e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  SkPaint paint;
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int alpha = kThumbDefaultAlpha * animation_opacity_;
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetState() == CustomButton::STATE_HOVERED) {
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    alpha = kThumbHoverAlpha * animation_opacity_;
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else if(GetState() == CustomButton::STATE_PRESSED) {
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // If we are in pressed state, no need to worry about animation,
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // just display the deeper color.
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    alpha = kThumbHoverAlpha;
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
725e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  paint.setStyle(SkPaint::kFill_Style);
735e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  paint.setColor(SkColorSetARGB(alpha, 0, 0, 0));
745e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  canvas->DrawRoundRect(local_bounds, kThumbCornerRadius, paint);
755e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
765e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
775e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OverlayScrollBarThumb::AnimationProgressed(
78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const gfx::Animation* animation) {
795e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  animation_opacity_ = animation->GetCurrentValue();
805e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  SchedulePaint();
815e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
825e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
835e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}  // namespace
845e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
855e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)OverlayScrollBar::OverlayScrollBar(bool horizontal)
865e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    : BaseScrollBar(horizontal, new OverlayScrollBarThumb(this)),
875e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      animation_(static_cast<OverlayScrollBarThumb*>(GetThumb())) {
885e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  set_notify_enter_exit_on_child(true);
895e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
905e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
915e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)OverlayScrollBar::~OverlayScrollBar() {
925e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
935e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
945e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)gfx::Rect OverlayScrollBar::GetTrackBounds() const {
955e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  gfx::Rect local_bounds(GetLocalBounds());
965e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  if (IsHorizontal()) {
975e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    local_bounds.Inset(kThumbInsetFromEdge, kThumbInsetInside,
985e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)                       kThumbInsetFromEdge, kThumbInsetFromEdge);
995e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  } else {
1005e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    local_bounds.Inset(kThumbInsetInside, kThumbInsetFromEdge,
1015e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)                       kThumbInsetFromEdge, kThumbInsetFromEdge);
1025e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  }
1035e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  gfx::Size track_size = local_bounds.size();
1045e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  track_size.SetToMax(GetThumb()->size());
1055e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  local_bounds.set_size(track_size);
1065e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  return local_bounds;
1075e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
1085e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1095e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)int OverlayScrollBar::GetLayoutSize() const {
1105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  return 0;
1115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
1125e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)int OverlayScrollBar::GetContentOverlapSize() const {
1145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  return kScrollbarWidth;
1155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
1165e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1175e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OverlayScrollBar::OnMouseEnteredScrollView(const ui::MouseEvent& event) {
1185e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  animation_.Show();
1195e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
1205e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1215e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OverlayScrollBar::OnMouseExitedScrollView(const ui::MouseEvent& event) {
1225e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  animation_.Hide();
1235e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
1245e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid OverlayScrollBar::OnGestureEvent(ui::GestureEvent* event) {
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (event->type()) {
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case ui::ET_GESTURE_SCROLL_BEGIN:
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      animation_.Show();
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case ui::ET_GESTURE_SCROLL_END:
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case ui::ET_SCROLL_FLING_START:
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case ui::ET_GESTURE_END:
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      animation_.Hide();
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  BaseScrollBar::OnGestureEvent(event);
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size OverlayScrollBar::GetPreferredSize() const {
1425e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  return gfx::Size();
1435e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
1445e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1455e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OverlayScrollBar::Layout() {
1465e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  gfx::Rect thumb_bounds = GetTrackBounds();
1475e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  BaseScrollBarThumb* thumb = GetThumb();
1485e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  if (IsHorizontal()) {
1495e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    thumb_bounds.set_x(thumb->x());
1505e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    thumb_bounds.set_width(thumb->width());
1515e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  } else {
1525e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    thumb_bounds.set_y(thumb->y());
1535e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    thumb_bounds.set_height(thumb->height());
1545e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  }
1555e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  thumb->SetBoundsRect(thumb_bounds);
1565e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
1575e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1585e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OverlayScrollBar::OnPaint(gfx::Canvas* canvas) {
1595e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}
1605e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1615e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)}  // namespace views
162