Home | History | Annotate | Download | only in animation
      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/base/animation/slide_animation.h"
      9 #include "ui/base/animation/test_animation_delegate.h"
     10 #include "ui/views/view.h"
     11 
     12 using ui::Animation;
     13 using ui::SlideAnimation;
     14 using ui::TestAnimationDelegate;
     15 
     16 namespace views {
     17 namespace {
     18 
     19 class 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 
     35 class OwnedDelegate : public BoundsAnimator::OwnedAnimationDelegate {
     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 ui::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
     68 bool OwnedDelegate::deleted_ = false;
     69 bool OwnedDelegate::canceled_ = false;
     70 
     71 class 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 
     92 class 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.
    112 TEST_F(BoundsAnimatorTest, AnimateViewTo) {
    113   TestAnimationDelegate delegate;
    114   gfx::Rect initial_bounds(0, 0, 10, 10);
    115   child()->SetBoundsRect(initial_bounds);
    116   gfx::Rect target_bounds(10, 10, 20, 20);
    117   animator()->AnimateViewTo(child(), target_bounds);
    118   animator()->SetAnimationDelegate(child(), &delegate, false);
    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.
    137 TEST_F(BoundsAnimatorTest, DeleteDelegateOnCancel) {
    138   animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10));
    139   animator()->SetAnimationDelegate(child(), new OwnedDelegate(), true);
    140 
    141   animator()->Cancel();
    142 
    143   // The animator should no longer be animating.
    144   EXPECT_FALSE(animator()->IsAnimating());
    145 
    146   // The cancel should both cancel the delegate and delete it.
    147   EXPECT_TRUE(OwnedDelegate::GetAndClearCanceled());
    148   EXPECT_TRUE(OwnedDelegate::GetAndClearDeleted());
    149 }
    150 
    151 // Make sure an AnimationDelegate is deleted when another animation is
    152 // scheduled.
    153 TEST_F(BoundsAnimatorTest, DeleteDelegateOnNewAnimate) {
    154   animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10));
    155   animator()->SetAnimationDelegate(child(), new OwnedDelegate(), true);
    156 
    157   animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10));
    158 
    159   // Starting a new animation should both cancel the delegate and delete it.
    160   EXPECT_TRUE(OwnedDelegate::GetAndClearDeleted());
    161   EXPECT_TRUE(OwnedDelegate::GetAndClearCanceled());
    162 }
    163 
    164 // Makes sure StopAnimating works.
    165 TEST_F(BoundsAnimatorTest, StopAnimating) {
    166   scoped_ptr<OwnedDelegate> delegate(new OwnedDelegate());
    167 
    168   animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10));
    169   animator()->SetAnimationDelegate(child(), new OwnedDelegate(), true);
    170 
    171   animator()->StopAnimatingView(child());
    172 
    173   // Shouldn't be animating now.
    174   EXPECT_FALSE(animator()->IsAnimating());
    175 
    176   // Stopping should both cancel the delegate and delete it.
    177   EXPECT_TRUE(OwnedDelegate::GetAndClearDeleted());
    178   EXPECT_TRUE(OwnedDelegate::GetAndClearCanceled());
    179 }
    180 
    181 }  // namespace views
    182