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/gfx/animation/slide_animation.h"
      9 #include "ui/gfx/animation/test_animation_delegate.h"
     10 #include "ui/views/view.h"
     11 
     12 using gfx::Animation;
     13 using gfx::SlideAnimation;
     14 using gfx::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 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
     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   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.
    137 TEST_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.
    154 TEST_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.
    167 TEST_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