Home | History | Annotate | Download | only in scrollbar
      1 // Copyright 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.
      4 
      5 #include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
      6 
      7 #include "third_party/skia/include/core/SkColor.h"
      8 #include "third_party/skia/include/core/SkXfermode.h"
      9 #include "ui/gfx/canvas.h"
     10 #include "ui/views/background.h"
     11 #include "ui/views/border.h"
     12 #include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
     13 
     14 namespace views {
     15 namespace {
     16 
     17 const int kScrollbarWidth = 10;
     18 const int kThumbInsetInside = 3;
     19 const int kThumbInsetFromEdge = 1;
     20 const int kThumbCornerRadius = 2;
     21 const int kThumbMinimumSize = kScrollbarWidth;
     22 const int kThumbHoverAlpha = 128;
     23 const int kThumbDefaultAlpha = 64;
     24 
     25 class OverlayScrollBarThumb : public BaseScrollBarThumb,
     26                               public ui::AnimationDelegate {
     27  public:
     28   explicit OverlayScrollBarThumb(BaseScrollBar* scroll_bar);
     29   virtual ~OverlayScrollBarThumb();
     30 
     31  protected:
     32   // View overrides:
     33   virtual gfx::Size GetPreferredSize() OVERRIDE;
     34   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
     35 
     36   // ui::AnimationDelegate overrides:
     37   virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
     38 
     39  private:
     40   double animation_opacity_;
     41   DISALLOW_COPY_AND_ASSIGN(OverlayScrollBarThumb);
     42 };
     43 
     44 OverlayScrollBarThumb::OverlayScrollBarThumb(BaseScrollBar* scroll_bar)
     45     : BaseScrollBarThumb(scroll_bar),
     46       animation_opacity_(0.0) {
     47   if (get_use_acceleration_when_possible()) {
     48     // This is necessary, otherwise the thumb will be rendered below the views
     49     // if those views paint to their own layers.
     50     SetPaintToLayer(true);
     51     SetFillsBoundsOpaquely(false);
     52   }
     53 }
     54 
     55 OverlayScrollBarThumb::~OverlayScrollBarThumb() {
     56 }
     57 
     58 gfx::Size OverlayScrollBarThumb::GetPreferredSize() {
     59   return gfx::Size(kThumbMinimumSize, kThumbMinimumSize);
     60 }
     61 
     62 void OverlayScrollBarThumb::OnPaint(gfx::Canvas* canvas) {
     63   gfx::Rect local_bounds(GetLocalBounds());
     64   SkPaint paint;
     65   int alpha = kThumbDefaultAlpha * animation_opacity_;
     66   if (GetState() == CustomButton::STATE_HOVERED) {
     67     alpha = kThumbHoverAlpha * animation_opacity_;
     68   } else if(GetState() == CustomButton::STATE_PRESSED) {
     69     // If we are in pressed state, no need to worry about animation,
     70     // just display the deeper color.
     71     alpha = kThumbHoverAlpha;
     72   }
     73 
     74   paint.setStyle(SkPaint::kFill_Style);
     75   paint.setColor(SkColorSetARGB(alpha, 0, 0, 0));
     76   canvas->DrawRoundRect(local_bounds, kThumbCornerRadius, paint);
     77 }
     78 
     79 void OverlayScrollBarThumb::AnimationProgressed(
     80     const ui::Animation* animation) {
     81   animation_opacity_ = animation->GetCurrentValue();
     82   SchedulePaint();
     83 }
     84 
     85 }  // namespace
     86 
     87 OverlayScrollBar::OverlayScrollBar(bool horizontal)
     88     : BaseScrollBar(horizontal, new OverlayScrollBarThumb(this)),
     89       animation_(static_cast<OverlayScrollBarThumb*>(GetThumb())) {
     90   set_notify_enter_exit_on_child(true);
     91 }
     92 
     93 OverlayScrollBar::~OverlayScrollBar() {
     94 }
     95 
     96 gfx::Rect OverlayScrollBar::GetTrackBounds() const {
     97   gfx::Rect local_bounds(GetLocalBounds());
     98   if (IsHorizontal()) {
     99     local_bounds.Inset(kThumbInsetFromEdge, kThumbInsetInside,
    100                        kThumbInsetFromEdge, kThumbInsetFromEdge);
    101   } else {
    102     local_bounds.Inset(kThumbInsetInside, kThumbInsetFromEdge,
    103                        kThumbInsetFromEdge, kThumbInsetFromEdge);
    104   }
    105   gfx::Size track_size = local_bounds.size();
    106   track_size.SetToMax(GetThumb()->size());
    107   local_bounds.set_size(track_size);
    108   return local_bounds;
    109 }
    110 
    111 int OverlayScrollBar::GetLayoutSize() const {
    112   return 0;
    113 }
    114 
    115 int OverlayScrollBar::GetContentOverlapSize() const {
    116   return kScrollbarWidth;
    117 }
    118 
    119 void OverlayScrollBar::OnMouseEnteredScrollView(const ui::MouseEvent& event) {
    120   animation_.Show();
    121 }
    122 
    123 void OverlayScrollBar::OnMouseExitedScrollView(const ui::MouseEvent& event) {
    124   animation_.Hide();
    125 }
    126 
    127 void OverlayScrollBar::OnGestureEvent(ui::GestureEvent* event) {
    128   switch (event->type()) {
    129     case ui::ET_GESTURE_SCROLL_BEGIN:
    130       animation_.Show();
    131       break;
    132     case ui::ET_GESTURE_SCROLL_END:
    133     case ui::ET_SCROLL_FLING_START:
    134     case ui::ET_GESTURE_END:
    135       animation_.Hide();
    136       break;
    137     default:
    138       break;
    139   }
    140   BaseScrollBar::OnGestureEvent(event);
    141 }
    142 
    143 gfx::Size OverlayScrollBar::GetPreferredSize() {
    144   return gfx::Size();
    145 }
    146 
    147 void OverlayScrollBar::Layout() {
    148   gfx::Rect thumb_bounds = GetTrackBounds();
    149   BaseScrollBarThumb* thumb = GetThumb();
    150   if (IsHorizontal()) {
    151     thumb_bounds.set_x(thumb->x());
    152     thumb_bounds.set_width(thumb->width());
    153   } else {
    154     thumb_bounds.set_y(thumb->y());
    155     thumb_bounds.set_height(thumb->height());
    156   }
    157   thumb->SetBoundsRect(thumb_bounds);
    158 }
    159 
    160 void OverlayScrollBar::OnPaint(gfx::Canvas* canvas) {
    161 }
    162 
    163 }  // namespace views
    164