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: 335e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) virtual gfx::Size GetPreferredSize() 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) { 475e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) if (get_use_acceleration_when_possible()) { 485e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) // This is necessary, otherwise the thumb will be rendered below the views 495e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) // if those views paint to their own layers. 505e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) SetPaintToLayer(true); 515e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) SetFillsBoundsOpaquely(false); 525e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) } 535e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 545e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 555e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)OverlayScrollBarThumb::~OverlayScrollBarThumb() { 565e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 575e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 585e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)gfx::Size OverlayScrollBarThumb::GetPreferredSize() { 595e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) return gfx::Size(kThumbMinimumSize, kThumbMinimumSize); 605e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 615e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 625e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OverlayScrollBarThumb::OnPaint(gfx::Canvas* canvas) { 635e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) gfx::Rect local_bounds(GetLocalBounds()); 645e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) SkPaint paint; 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int alpha = kThumbDefaultAlpha * animation_opacity_; 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (GetState() == CustomButton::STATE_HOVERED) { 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch alpha = kThumbHoverAlpha * animation_opacity_; 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else if(GetState() == CustomButton::STATE_PRESSED) { 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // If we are in pressed state, no need to worry about animation, 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // just display the deeper color. 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch alpha = kThumbHoverAlpha; 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 745e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) paint.setStyle(SkPaint::kFill_Style); 755e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) paint.setColor(SkColorSetARGB(alpha, 0, 0, 0)); 765e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) canvas->DrawRoundRect(local_bounds, kThumbCornerRadius, paint); 775e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 785e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 795e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OverlayScrollBarThumb::AnimationProgressed( 80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const gfx::Animation* animation) { 815e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) animation_opacity_ = animation->GetCurrentValue(); 825e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) SchedulePaint(); 835e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 845e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 855e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} // namespace 865e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 875e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)OverlayScrollBar::OverlayScrollBar(bool horizontal) 885e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) : BaseScrollBar(horizontal, new OverlayScrollBarThumb(this)), 895e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) animation_(static_cast<OverlayScrollBarThumb*>(GetThumb())) { 905e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) set_notify_enter_exit_on_child(true); 915e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 925e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 935e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)OverlayScrollBar::~OverlayScrollBar() { 945e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 955e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 965e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)gfx::Rect OverlayScrollBar::GetTrackBounds() const { 975e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) gfx::Rect local_bounds(GetLocalBounds()); 985e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) if (IsHorizontal()) { 995e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) local_bounds.Inset(kThumbInsetFromEdge, kThumbInsetInside, 1005e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) kThumbInsetFromEdge, kThumbInsetFromEdge); 1015e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) } else { 1025e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) local_bounds.Inset(kThumbInsetInside, kThumbInsetFromEdge, 1035e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) kThumbInsetFromEdge, kThumbInsetFromEdge); 1045e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) } 1055e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) gfx::Size track_size = local_bounds.size(); 1065e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) track_size.SetToMax(GetThumb()->size()); 1075e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) local_bounds.set_size(track_size); 1085e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) return local_bounds; 1095e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 1105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 1115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)int OverlayScrollBar::GetLayoutSize() const { 1125e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) return 0; 1135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 1145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 1155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)int OverlayScrollBar::GetContentOverlapSize() const { 1165e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) return kScrollbarWidth; 1175e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 1185e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 1195e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OverlayScrollBar::OnMouseEnteredScrollView(const ui::MouseEvent& event) { 1205e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) animation_.Show(); 1215e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 1225e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 1235e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OverlayScrollBar::OnMouseExitedScrollView(const ui::MouseEvent& event) { 1245e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) animation_.Hide(); 1255e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 1265e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid OverlayScrollBar::OnGestureEvent(ui::GestureEvent* event) { 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch switch (event->type()) { 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case ui::ET_GESTURE_SCROLL_BEGIN: 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch animation_.Show(); 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case ui::ET_GESTURE_SCROLL_END: 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case ui::ET_SCROLL_FLING_START: 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case ui::ET_GESTURE_END: 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch animation_.Hide(); 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch default: 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch BaseScrollBar::OnGestureEvent(event); 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1435e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)gfx::Size OverlayScrollBar::GetPreferredSize() { 1445e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) return gfx::Size(); 1455e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 1465e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 1475e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OverlayScrollBar::Layout() { 1485e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) gfx::Rect thumb_bounds = GetTrackBounds(); 1495e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) BaseScrollBarThumb* thumb = GetThumb(); 1505e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) if (IsHorizontal()) { 1515e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) thumb_bounds.set_x(thumb->x()); 1525e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) thumb_bounds.set_width(thumb->width()); 1535e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) } else { 1545e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) thumb_bounds.set_y(thumb->y()); 1555e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) thumb_bounds.set_height(thumb->height()); 1565e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) } 1575e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) thumb->SetBoundsRect(thumb_bounds); 1585e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 1595e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 1605e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OverlayScrollBar::OnPaint(gfx::Canvas* canvas) { 1615e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 1625e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 1635e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} // namespace views 164