15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/animation/bounds_animator.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/slide_animation.h" 9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/test_animation_delegate.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using gfx::Animation; 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using gfx::SlideAnimation; 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using gfx::TestAnimationDelegate; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestBoundsAnimator : public BoundsAnimator { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit TestBoundsAnimator(View* view) : BoundsAnimator(view) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual SlideAnimation* CreateAnimation() OVERRIDE { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SlideAnimation* animation = BoundsAnimator::CreateAnimation(); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation->SetSlideDuration(10); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return animation; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TestBoundsAnimator); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class OwnedDelegate : public gfx::AnimationDelegate { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OwnedDelegate() {} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~OwnedDelegate() { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleted_ = true; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool GetAndClearDeleted() { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool value = deleted_; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleted_ = false; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool GetAndClearCanceled() { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool value = canceled_; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canceled_ = false; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Overridden from gfx::AnimationDelegate: 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void AnimationCanceled(const Animation* animation) OVERRIDE { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canceled_ = true; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool deleted_; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool canceled_; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(OwnedDelegate); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OwnedDelegate::deleted_ = false; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OwnedDelegate::canceled_ = false; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestView : public View { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestView() {} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SchedulePaintInRect(const gfx::Rect& r) OVERRIDE { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dirty_rect_.IsEmpty()) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dirty_rect_ = r; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dirty_rect_.Union(r); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& dirty_rect() const { return dirty_rect_; } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect dirty_rect_; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TestView); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BoundsAnimatorTest : public testing::Test { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BoundsAnimatorTest() : child_(new TestView()), animator_(&parent_) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent_.AddChildView(child_); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestView* parent() { return &parent_; } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestView* child() { return child_; } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestBoundsAnimator* animator() { return &animator_; } 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForUI message_loop_; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestView parent_; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestView* child_; // Owned by |parent_|. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestBoundsAnimator animator_; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(BoundsAnimatorTest); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks animate view to. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BoundsAnimatorTest, AnimateViewTo) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect initial_bounds(0, 0, 10, 10); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child()->SetBoundsRect(initial_bounds); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect target_bounds(10, 10, 20, 20); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animator()->AnimateViewTo(child(), target_bounds); 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) animator()->SetAnimationDelegate( 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) child(), scoped_ptr<gfx::AnimationDelegate>(new TestAnimationDelegate())); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The animator should be animating now. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(animator()->IsAnimating()); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run the message loop; the delegate exits the loop when the animation is 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // done. 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->Run(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure the bounds match of the view that was animated match. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(target_bounds, child()->bounds()); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The parent should have been told to repaint as the animation progressed. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The resulting rect is the union of the original and target bounds. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(gfx::UnionRects(target_bounds, initial_bounds), 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent()->dirty_rect()); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make sure an AnimationDelegate is deleted when canceled. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BoundsAnimatorTest, DeleteDelegateOnCancel) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10)); 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) animator()->SetAnimationDelegate( 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) child(), scoped_ptr<gfx::AnimationDelegate>(new OwnedDelegate())); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animator()->Cancel(); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The animator should no longer be animating. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(animator()->IsAnimating()); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The cancel should both cancel the delegate and delete it. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(OwnedDelegate::GetAndClearCanceled()); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(OwnedDelegate::GetAndClearDeleted()); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make sure an AnimationDelegate is deleted when another animation is 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// scheduled. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BoundsAnimatorTest, DeleteDelegateOnNewAnimate) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10)); 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) animator()->SetAnimationDelegate( 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) child(), scoped_ptr<gfx::AnimationDelegate>(new OwnedDelegate())); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10)); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Starting a new animation should both cancel the delegate and delete it. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(OwnedDelegate::GetAndClearDeleted()); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(OwnedDelegate::GetAndClearCanceled()); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Makes sure StopAnimating works. 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BoundsAnimatorTest, StopAnimating) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<OwnedDelegate> delegate(new OwnedDelegate()); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10)); 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) animator()->SetAnimationDelegate( 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) child(), scoped_ptr<gfx::AnimationDelegate>(new OwnedDelegate())); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animator()->StopAnimatingView(child()); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shouldn't be animating now. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(animator()->IsAnimating()); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stopping should both cancel the delegate and delete it. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(OwnedDelegate::GetAndClearDeleted()); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(OwnedDelegate::GetAndClearCanceled()); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace views 185