blob: 1396bd1ec99a7ec7612b00f9d081dad7d5406403 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkXfermode.h"
#include "ui/gfx/canvas.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
namespace views {
namespace {
const int kScrollbarWidth = 10;
const int kThumbInsetInside = 3;
const int kThumbInsetFromEdge = 1;
const int kThumbCornerRadius = 2;
const int kThumbMinimumSize = kScrollbarWidth;
const int kThumbHoverAlpha = 128;
const int kThumbDefaultAlpha = 64;
class OverlayScrollBarThumb : public BaseScrollBarThumb,
public gfx::AnimationDelegate {
public:
explicit OverlayScrollBarThumb(BaseScrollBar* scroll_bar);
virtual ~OverlayScrollBarThumb();
protected:
// View overrides:
virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
// gfx::AnimationDelegate overrides:
virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
private:
double animation_opacity_;
DISALLOW_COPY_AND_ASSIGN(OverlayScrollBarThumb);
};
OverlayScrollBarThumb::OverlayScrollBarThumb(BaseScrollBar* scroll_bar)
: BaseScrollBarThumb(scroll_bar),
animation_opacity_(0.0) {
// This is necessary, otherwise the thumb will be rendered below the views if
// those views paint to their own layers.
SetPaintToLayer(true);
SetFillsBoundsOpaquely(false);
}
OverlayScrollBarThumb::~OverlayScrollBarThumb() {
}
gfx::Size OverlayScrollBarThumb::GetPreferredSize() const {
return gfx::Size(kThumbMinimumSize, kThumbMinimumSize);
}
void OverlayScrollBarThumb::OnPaint(gfx::Canvas* canvas) {
gfx::Rect local_bounds(GetLocalBounds());
SkPaint paint;
int alpha = kThumbDefaultAlpha * animation_opacity_;
if (GetState() == CustomButton::STATE_HOVERED) {
alpha = kThumbHoverAlpha * animation_opacity_;
} else if(GetState() == CustomButton::STATE_PRESSED) {
// If we are in pressed state, no need to worry about animation,
// just display the deeper color.
alpha = kThumbHoverAlpha;
}
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(SkColorSetARGB(alpha, 0, 0, 0));
canvas->DrawRoundRect(local_bounds, kThumbCornerRadius, paint);
}
void OverlayScrollBarThumb::AnimationProgressed(
const gfx::Animation* animation) {
animation_opacity_ = animation->GetCurrentValue();
SchedulePaint();
}
} // namespace
OverlayScrollBar::OverlayScrollBar(bool horizontal)
: BaseScrollBar(horizontal, new OverlayScrollBarThumb(this)),
animation_(static_cast<OverlayScrollBarThumb*>(GetThumb())) {
set_notify_enter_exit_on_child(true);
}
OverlayScrollBar::~OverlayScrollBar() {
}
gfx::Rect OverlayScrollBar::GetTrackBounds() const {
gfx::Rect local_bounds(GetLocalBounds());
if (IsHorizontal()) {
local_bounds.Inset(kThumbInsetFromEdge, kThumbInsetInside,
kThumbInsetFromEdge, kThumbInsetFromEdge);
} else {
local_bounds.Inset(kThumbInsetInside, kThumbInsetFromEdge,
kThumbInsetFromEdge, kThumbInsetFromEdge);
}
gfx::Size track_size = local_bounds.size();
track_size.SetToMax(GetThumb()->size());
local_bounds.set_size(track_size);
return local_bounds;
}
int OverlayScrollBar::GetLayoutSize() const {
return 0;
}
int OverlayScrollBar::GetContentOverlapSize() const {
return kScrollbarWidth;
}
void OverlayScrollBar::OnMouseEnteredScrollView(const ui::MouseEvent& event) {
animation_.Show();
}
void OverlayScrollBar::OnMouseExitedScrollView(const ui::MouseEvent& event) {
animation_.Hide();
}
void OverlayScrollBar::OnGestureEvent(ui::GestureEvent* event) {
switch (event->type()) {
case ui::ET_GESTURE_SCROLL_BEGIN:
animation_.Show();
break;
case ui::ET_GESTURE_SCROLL_END:
case ui::ET_SCROLL_FLING_START:
case ui::ET_GESTURE_END:
animation_.Hide();
break;
default:
break;
}
BaseScrollBar::OnGestureEvent(event);
}
gfx::Size OverlayScrollBar::GetPreferredSize() const {
return gfx::Size();
}
void OverlayScrollBar::Layout() {
gfx::Rect thumb_bounds = GetTrackBounds();
BaseScrollBarThumb* thumb = GetThumb();
if (IsHorizontal()) {
thumb_bounds.set_x(thumb->x());
thumb_bounds.set_width(thumb->width());
} else {
thumb_bounds.set_y(thumb->y());
thumb_bounds.set_height(thumb->height());
}
thumb->SetBoundsRect(thumb_bounds);
}
void OverlayScrollBar::OnPaint(gfx::Canvas* canvas) {
}
} // namespace views