1// Copyright (c) 2012 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/animation/bounds_animator.h" 6 7#include "testing/gtest/include/gtest/gtest.h" 8#include "ui/gfx/animation/slide_animation.h" 9#include "ui/gfx/animation/test_animation_delegate.h" 10#include "ui/views/view.h" 11 12using gfx::Animation; 13using gfx::SlideAnimation; 14using gfx::TestAnimationDelegate; 15 16namespace views { 17namespace { 18 19class TestBoundsAnimator : public BoundsAnimator { 20 public: 21 explicit TestBoundsAnimator(View* view) : BoundsAnimator(view) { 22 } 23 24 protected: 25 virtual SlideAnimation* CreateAnimation() OVERRIDE { 26 SlideAnimation* animation = BoundsAnimator::CreateAnimation(); 27 animation->SetSlideDuration(10); 28 return animation; 29 } 30 31 private: 32 DISALLOW_COPY_AND_ASSIGN(TestBoundsAnimator); 33}; 34 35class OwnedDelegate : public gfx::AnimationDelegate { 36 public: 37 OwnedDelegate() {} 38 39 virtual ~OwnedDelegate() { 40 deleted_ = true; 41 } 42 43 static bool GetAndClearDeleted() { 44 bool value = deleted_; 45 deleted_ = false; 46 return value; 47 } 48 49 static bool GetAndClearCanceled() { 50 bool value = canceled_; 51 canceled_ = false; 52 return value; 53 } 54 55 // Overridden from gfx::AnimationDelegate: 56 virtual void AnimationCanceled(const Animation* animation) OVERRIDE { 57 canceled_ = true; 58 } 59 60 private: 61 static bool deleted_; 62 static bool canceled_; 63 64 DISALLOW_COPY_AND_ASSIGN(OwnedDelegate); 65}; 66 67// static 68bool OwnedDelegate::deleted_ = false; 69bool OwnedDelegate::canceled_ = false; 70 71class TestView : public View { 72 public: 73 TestView() {} 74 75 virtual void SchedulePaintInRect(const gfx::Rect& r) OVERRIDE { 76 if (dirty_rect_.IsEmpty()) 77 dirty_rect_ = r; 78 else 79 dirty_rect_.Union(r); 80 } 81 82 const gfx::Rect& dirty_rect() const { return dirty_rect_; } 83 84 private: 85 gfx::Rect dirty_rect_; 86 87 DISALLOW_COPY_AND_ASSIGN(TestView); 88}; 89 90} // namespace 91 92class BoundsAnimatorTest : public testing::Test { 93 public: 94 BoundsAnimatorTest() : child_(new TestView()), animator_(&parent_) { 95 parent_.AddChildView(child_); 96 } 97 98 TestView* parent() { return &parent_; } 99 TestView* child() { return child_; } 100 TestBoundsAnimator* animator() { return &animator_; } 101 102 private: 103 base::MessageLoopForUI message_loop_; 104 TestView parent_; 105 TestView* child_; // Owned by |parent_|. 106 TestBoundsAnimator animator_; 107 108 DISALLOW_COPY_AND_ASSIGN(BoundsAnimatorTest); 109}; 110 111// Checks animate view to. 112TEST_F(BoundsAnimatorTest, AnimateViewTo) { 113 gfx::Rect initial_bounds(0, 0, 10, 10); 114 child()->SetBoundsRect(initial_bounds); 115 gfx::Rect target_bounds(10, 10, 20, 20); 116 animator()->AnimateViewTo(child(), target_bounds); 117 animator()->SetAnimationDelegate( 118 child(), scoped_ptr<gfx::AnimationDelegate>(new TestAnimationDelegate())); 119 120 // The animator should be animating now. 121 EXPECT_TRUE(animator()->IsAnimating()); 122 123 // Run the message loop; the delegate exits the loop when the animation is 124 // done. 125 base::MessageLoop::current()->Run(); 126 127 // Make sure the bounds match of the view that was animated match. 128 EXPECT_EQ(target_bounds, child()->bounds()); 129 130 // The parent should have been told to repaint as the animation progressed. 131 // The resulting rect is the union of the original and target bounds. 132 EXPECT_EQ(gfx::UnionRects(target_bounds, initial_bounds), 133 parent()->dirty_rect()); 134} 135 136// Make sure an AnimationDelegate is deleted when canceled. 137TEST_F(BoundsAnimatorTest, DeleteDelegateOnCancel) { 138 animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10)); 139 animator()->SetAnimationDelegate( 140 child(), scoped_ptr<gfx::AnimationDelegate>(new OwnedDelegate())); 141 142 animator()->Cancel(); 143 144 // The animator should no longer be animating. 145 EXPECT_FALSE(animator()->IsAnimating()); 146 147 // The cancel should both cancel the delegate and delete it. 148 EXPECT_TRUE(OwnedDelegate::GetAndClearCanceled()); 149 EXPECT_TRUE(OwnedDelegate::GetAndClearDeleted()); 150} 151 152// Make sure an AnimationDelegate is deleted when another animation is 153// scheduled. 154TEST_F(BoundsAnimatorTest, DeleteDelegateOnNewAnimate) { 155 animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10)); 156 animator()->SetAnimationDelegate( 157 child(), scoped_ptr<gfx::AnimationDelegate>(new OwnedDelegate())); 158 159 animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10)); 160 161 // Starting a new animation should both cancel the delegate and delete it. 162 EXPECT_TRUE(OwnedDelegate::GetAndClearDeleted()); 163 EXPECT_TRUE(OwnedDelegate::GetAndClearCanceled()); 164} 165 166// Makes sure StopAnimating works. 167TEST_F(BoundsAnimatorTest, StopAnimating) { 168 scoped_ptr<OwnedDelegate> delegate(new OwnedDelegate()); 169 170 animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10)); 171 animator()->SetAnimationDelegate( 172 child(), scoped_ptr<gfx::AnimationDelegate>(new OwnedDelegate())); 173 174 animator()->StopAnimatingView(child()); 175 176 // Shouldn't be animating now. 177 EXPECT_FALSE(animator()->IsAnimating()); 178 179 // Stopping should both cancel the delegate and delete it. 180 EXPECT_TRUE(OwnedDelegate::GetAndClearDeleted()); 181 EXPECT_TRUE(OwnedDelegate::GetAndClearCanceled()); 182} 183 184} // namespace views 185