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