diff options
-rw-r--r-- | ash/ash.gyp | 4 | ||||
-rw-r--r-- | ash/launcher/launcher_unittest.cc | 3 | ||||
-rw-r--r-- | ash/launcher/launcher_view.cc | 49 | ||||
-rw-r--r-- | ash/launcher/launcher_view.h | 23 | ||||
-rw-r--r-- | ash/launcher/launcher_view_unittest.cc | 179 | ||||
-rw-r--r-- | ash/test/launcher_view_test_api.cc | 83 | ||||
-rw-r--r-- | ash/test/launcher_view_test_api.h | 53 | ||||
-rw-r--r-- | ui/views/animation/bounds_animator.cc | 28 | ||||
-rw-r--r-- | ui/views/animation/bounds_animator.h | 18 |
9 files changed, 365 insertions, 75 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index cc24271..5eb5c8a 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -346,9 +346,11 @@ 'launcher/launcher_view_unittest.cc', 'monitor/multi_monitor_manager_unittest.cc', 'shell_unittest.cc', - 'test/ash_unittests.cc', 'test/ash_test_base.cc', 'test/ash_test_base.h', + 'test/ash_unittests.cc', + 'test/launcher_view_test_api.cc', + 'test/launcher_view_test_api.h', 'test/test_activation_delegate.cc', 'test/test_activation_delegate.h', 'test/test_launcher_delegate.cc', diff --git a/ash/launcher/launcher_unittest.cc b/ash/launcher/launcher_unittest.cc index 83f78f5..bdb92fc 100644 --- a/ash/launcher/launcher_unittest.cc +++ b/ash/launcher/launcher_unittest.cc @@ -9,6 +9,7 @@ #include "ash/shell.h" #include "ash/test/ash_test_base.h" +#include "ash/test/launcher_view_test_api.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" @@ -36,7 +37,7 @@ TEST_F(LauncherTest, OpenBrowser) { Launcher* launcher = Shell::GetInstance()->launcher(); ASSERT_TRUE(launcher); LauncherView* launcher_view = launcher->GetLauncherViewForTest(); - LauncherView::TestAPI test(launcher_view); + test::LauncherViewTestAPI test(launcher_view); LauncherModel* model = launcher->model(); // Initially we have the app list and chrome icon. diff --git a/ash/launcher/launcher_view.cc b/ash/launcher/launcher_view.cc index fb9f928..3f581d4 100644 --- a/ash/launcher/launcher_view.cc +++ b/ash/launcher/launcher_view.cc @@ -182,6 +182,7 @@ void ReflectItemStatus(const ash::LauncherItem& item, break; } } + } // namespace // AnimationDelegate used when inserting a new item. This steadily decreased the @@ -226,7 +227,6 @@ class LauncherView::StartFadeAnimationDelegate : // AnimationDelegate overrides: virtual void AnimationEnded(const Animation* animation) OVERRIDE { - view_->SetVisible(true); launcher_view_->FadeIn(view_); } virtual void AnimationCanceled(const Animation* animation) OVERRIDE { @@ -240,18 +240,6 @@ class LauncherView::StartFadeAnimationDelegate : DISALLOW_COPY_AND_ASSIGN(StartFadeAnimationDelegate); }; -int LauncherView::TestAPI::GetButtonCount() { - return launcher_view_->view_model_->view_size(); -} - -LauncherButton* LauncherView::TestAPI::GetButton(int index) { - if (index == 0) - return NULL; - - return static_cast<LauncherButton*>( - launcher_view_->view_model_->view_at(index)); -} - LauncherView::LauncherView(LauncherModel* model, LauncherDelegate* delegate) : model_(model), delegate_(delegate), @@ -369,20 +357,14 @@ void LauncherView::CalculateIdealBounds(IdealBounds* bounds) { last_visible_index_ = DetermineLastVisibleIndex( available_width - kLeadingInset - bounds->overflow_bounds.width() - kButtonSpacing - kButtonWidth); - bool show_overflow = - (last_visible_index_ + 1 != view_model_->view_size()); int app_list_index = view_model_->view_size() - 1; - if (overflow_button_->visible() != show_overflow) { - // Only change visibility of the views if the visibility of the overflow - // button changes. Otherwise we'll effect the insertion animation, which - // changes the visibility. - for (int i = 0; i <= last_visible_index_; ++i) - view_model_->view_at(i)->SetVisible(true); - for (int i = last_visible_index_ + 1; i < view_model_->view_size(); ++i) { - if (i != app_list_index) - view_model_->view_at(i)->SetVisible(false); - } + bool show_overflow = (last_visible_index_ + 1 < app_list_index); + + for (int i = 0; i < view_model_->view_size(); ++i) { + view_model_->view_at(i)->SetVisible( + i == app_list_index || i <= last_visible_index_); } + overflow_button_->SetVisible(show_overflow); if (show_overflow) { DCHECK_NE(0, view_model_->view_size()); @@ -688,11 +670,13 @@ void LauncherView::LauncherItemAdded(int model_index) { views::View* view = CreateViewForItem(model_->items()[model_index]); AddChildView(view); - // Hide the view, it'll be made visible when the animation is done. - view->SetVisible(false); + // Hide the view, it'll be made visible when the animation is done. Using + // opacity 0 here to avoid messing with CalculateIdealBounds which touches + // the view's visibility. + view->layer()->SetOpacity(0); view_model_->Add(view, model_index); - // Give the button it's ideal bounds. That way if we end up animating the + // Give the button its ideal bounds. That way if we end up animating the // button before this animation completes it doesn't appear at some random // spot (because it was in the middle of animating from 0,0 0x0 to its // target). @@ -700,13 +684,16 @@ void LauncherView::LauncherItemAdded(int model_index) { CalculateIdealBounds(&ideal_bounds); view->SetBoundsRect(view_model_->ideal_bounds(model_index)); - // The first animation moves all the views to their target position. |view| is - // hidden, so it visually appears as though we are providing space for + // The first animation moves all the views to their target position. |view| + // is hidden, so it visually appears as though we are providing space for // it. When done we'll fade the view in. AnimateToIdealBounds(); - if (!overflow_button_->visible()) { + if (model_index <= last_visible_index_) { bounds_animator_->SetAnimationDelegate( view, new StartFadeAnimationDelegate(this, view), true); + } else { + // Undo the hiding if animation does not run. + view->layer()->SetOpacity(1.0f); } FOR_EACH_OBSERVER(LauncherIconObserver, observers_, diff --git a/ash/launcher/launcher_view.h b/ash/launcher/launcher_view.h index f367c3a..59cf6ba 100644 --- a/ash/launcher/launcher_view.h +++ b/ash/launcher/launcher_view.h @@ -26,6 +26,10 @@ class ViewModel; namespace ash { +namespace test { +class LauncherViewTestAPI; +} + class LauncherDelegate; struct LauncherItem; class LauncherIconObserver; @@ -42,23 +46,6 @@ class ASH_EXPORT LauncherView : public views::View, public views::ContextMenuController, public views::FocusTraversable { public: - // Use the api in this class for testing only. - class ASH_EXPORT TestAPI { - public: - explicit TestAPI(LauncherView* launcher_view) - : launcher_view_(launcher_view) { - } - // Number of icons displayed. - int GetButtonCount(); - // Retrieve the button at |index|. - LauncherButton* GetButton(int index); - - private: - LauncherView* launcher_view_; - - DISALLOW_COPY_AND_ASSIGN(TestAPI); - }; - LauncherView(LauncherModel* model, LauncherDelegate* delegate); virtual ~LauncherView(); @@ -80,6 +67,8 @@ class ASH_EXPORT LauncherView : public views::View, virtual View* GetFocusTraversableParentView() OVERRIDE; private: + friend class ash::test::LauncherViewTestAPI; + class FadeOutAnimationDelegate; class StartFadeAnimationDelegate; diff --git a/ash/launcher/launcher_view_unittest.cc b/ash/launcher/launcher_view_unittest.cc index 78836f6..14727dc 100644 --- a/ash/launcher/launcher_view_unittest.cc +++ b/ash/launcher/launcher_view_unittest.cc @@ -4,23 +4,28 @@ #include "ash/launcher/launcher_view.h" -#include "ash/ash_switches.h" #include "ash/launcher/launcher.h" +#include "ash/launcher/launcher_button.h" +#include "ash/launcher/launcher_model.h" #include "ash/launcher/launcher_icon_observer.h" #include "ash/shell.h" -#include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" +#include "ash/test/launcher_view_test_api.h" #include "ash/test/test_launcher_delegate.h" #include "base/basictypes.h" -#include "base/command_line.h" #include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" #include "ui/aura/window.h" +#include "ui/aura/test/aura_test_base.h" +#include "ui/gfx/compositor/layer.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" namespace ash { +namespace test { -namespace { +//////////////////////////////////////////////////////////////////////////////// +// LauncherIconObserver tests. class TestLauncherIconObserver : public LauncherIconObserver { public: @@ -34,7 +39,7 @@ class TestLauncherIconObserver : public LauncherIconObserver { // LauncherIconObserver implementation. void OnLauncherIconPositionsChanged() OVERRIDE { - count_++; + ++count_; } int count() const { return count_; } @@ -46,10 +51,10 @@ class TestLauncherIconObserver : public LauncherIconObserver { DISALLOW_COPY_AND_ASSIGN(TestLauncherIconObserver); }; -class LauncherViewTest : public ash::test::AshTestBase { +class LauncherViewIconObserverTest : public ash::test::AshTestBase { public: - LauncherViewTest() {} - virtual ~LauncherViewTest() {} + LauncherViewIconObserverTest() {} + virtual ~LauncherViewIconObserverTest() {} virtual void SetUp() OVERRIDE { AshTestBase::SetUp(); @@ -66,10 +71,10 @@ class LauncherViewTest : public ash::test::AshTestBase { private: scoped_ptr<TestLauncherIconObserver> observer_; - DISALLOW_COPY_AND_ASSIGN(LauncherViewTest); + DISALLOW_COPY_AND_ASSIGN(LauncherViewIconObserverTest); }; -TEST_F(LauncherViewTest, AddRemove) { +TEST_F(LauncherViewIconObserverTest, AddRemove) { ash::test::TestLauncherDelegate* launcher_delegate = ash::test::TestLauncherDelegate::instance(); ASSERT_TRUE(launcher_delegate); @@ -90,7 +95,7 @@ TEST_F(LauncherViewTest, AddRemove) { observer()->Reset(); } -TEST_F(LauncherViewTest, BoundsChanged) { +TEST_F(LauncherViewIconObserverTest, BoundsChanged) { Launcher* launcher = Shell::GetInstance()->launcher(); int total_width = launcher->widget()->GetWindowScreenBounds().width(); ASSERT_GT(total_width, 0); @@ -99,6 +104,156 @@ TEST_F(LauncherViewTest, BoundsChanged) { observer()->Reset(); } -} // namespace +//////////////////////////////////////////////////////////////////////////////// +// LauncherView tests. + +class LauncherViewTest : public aura::test::AuraTestBase { + public: + LauncherViewTest() {} + virtual ~LauncherViewTest() {} + + virtual void SetUp() OVERRIDE { + aura::test::AuraTestBase::SetUp(); + + model_.reset(new LauncherModel); + + launcher_view_.reset(new internal::LauncherView(model_.get(), NULL)); + launcher_view_->Init(); + // The bounds should be big enough for 4 buttons + overflow chevron. + launcher_view_->SetBounds(0, 0, 500, 50); + + test_api_.reset(new LauncherViewTestAPI(launcher_view_.get())); + test_api_->SetAnimationDuration(1); // Speeds up animation for test. + } + + protected: + LauncherID AddAppShortcut() { + LauncherItem item; + item.type = TYPE_APP_SHORTCUT; + item.status = STATUS_CLOSED; + + int id = model_->next_id(); + model_->Add(item); + test_api_->RunMessageLoopUntilAnimationsDone(); + return id; + } + + LauncherID AddTabbedBrowser() { + LauncherItem item; + item.type = TYPE_TABBED; + item.status = STATUS_RUNNING; + + int id = model_->next_id(); + model_->Add(item); + test_api_->RunMessageLoopUntilAnimationsDone(); + return id; + } + + void RemoveByID(LauncherID id) { + model_->RemoveItemAt(model_->ItemIndexByID(id)); + test_api_->RunMessageLoopUntilAnimationsDone(); + } + + internal::LauncherButton* GetButtonByID(LauncherID id) { + int index = model_->ItemIndexByID(id); + return test_api_->GetButton(index); + } + + scoped_ptr<LauncherModel> model_; + scoped_ptr<internal::LauncherView> launcher_view_; + scoped_ptr<LauncherViewTestAPI> test_api_; + + private: + DISALLOW_COPY_AND_ASSIGN(LauncherViewTest); +}; + +// Adds browser button until overflow and verifies that the last added browser +// button is hidden. +TEST_F(LauncherViewTest, AddBrowserUntilOverflow) { + // All buttons should be visible. + ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1, + test_api_->GetButtonCount()); + + // Add tabbed browser until overflow. + LauncherID last_added = AddTabbedBrowser(); + while (!test_api_->IsOverflowButtonVisible()) { + // Added button is visible after animation while in this loop. + EXPECT_TRUE(GetButtonByID(last_added)->visible()); + + last_added = AddTabbedBrowser(); + } + + // The last added button should be invisible. + EXPECT_FALSE(GetButtonByID(last_added)->visible()); +} + +// Adds one browser button then adds app shortcut until overflow. Verifies that +// the browser button gets hidden on overflow and last added app shortcut is +// still visible. +TEST_F(LauncherViewTest, AddAppShortcutWithBrowserButtonUntilOverflow) { + // All buttons should be visible. + ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1, + test_api_->GetButtonCount()); + + LauncherID browser_button_id = AddTabbedBrowser(); + + // Add app shortcut until overflow. + LauncherID last_added = AddAppShortcut(); + while (!test_api_->IsOverflowButtonVisible()) { + // Added button is visible after animation while in this loop. + EXPECT_TRUE(GetButtonByID(last_added)->visible()); + + last_added = AddAppShortcut(); + } + + // The last added app short button should be visible. + EXPECT_TRUE(GetButtonByID(last_added)->visible()); + // And the browser button is invisible. + EXPECT_FALSE(GetButtonByID(browser_button_id)->visible()); +} + +// Adds button until overflow then removes first added one. Verifies that +// the last added one changes from invisible to visible and overflow +// chevron is gone. +TEST_F(LauncherViewTest, RemoveButtonRevealsOverflowed) { + // All buttons should be visible. + ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1, + test_api_->GetButtonCount()); + + // Add tabbed browser until overflow. + LauncherID first_added= AddTabbedBrowser(); + LauncherID last_added = first_added; + while (!test_api_->IsOverflowButtonVisible()) + last_added = AddTabbedBrowser(); + + // Expect add more than 1 button. First added is visible and last is not. + EXPECT_NE(first_added, last_added); + EXPECT_TRUE(GetButtonByID(first_added)->visible()); + EXPECT_FALSE(GetButtonByID(last_added)->visible()); + + // Remove first added. + RemoveByID(first_added); + + // Last added button becomes visible and overflow chevron is gone. + EXPECT_TRUE(GetButtonByID(last_added)->visible()); + EXPECT_EQ(1.0f, GetButtonByID(last_added)->layer()->opacity()); + EXPECT_FALSE(test_api_->IsOverflowButtonVisible()); +} + +// Verifies that remove last overflowed button should hide overflow chevron. +TEST_F(LauncherViewTest, RemoveLastOverflowed) { + // All buttons should be visible. + ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1, + test_api_->GetButtonCount()); + + // Add tabbed browser until overflow. + LauncherID last_added= AddTabbedBrowser(); + while (!test_api_->IsOverflowButtonVisible()) + last_added = AddTabbedBrowser(); + + RemoveByID(last_added); + EXPECT_FALSE(test_api_->IsOverflowButtonVisible()); +} +} // namespace test } // namespace ash diff --git a/ash/test/launcher_view_test_api.cc b/ash/test/launcher_view_test_api.cc new file mode 100644 index 0000000..3dc45bf --- /dev/null +++ b/ash/test/launcher_view_test_api.cc @@ -0,0 +1,83 @@ +// Copyright (c) 2012 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 "ash/test/launcher_view_test_api.h" + +#include "ash/launcher/launcher_button.h" +#include "ash/launcher/launcher_view.h" +#include "base/message_loop.h" +#include "ui/views/animation/bounds_animator.h" +#include "ui/views/controls/button/image_button.h" +#include "ui/views/view_model.h" + +namespace { + +// A class used to wait for animations. +class TestAPIAnimationObserver : public views::BoundsAnimatorObserver { + public: + TestAPIAnimationObserver() {} + virtual ~TestAPIAnimationObserver() {} + + // views::BoundsAnimatorObserver overrides: + virtual void OnBoundsAnimatorDone(views::BoundsAnimator* animator) OVERRIDE { + MessageLoop::current()->Quit(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(TestAPIAnimationObserver); +}; + +} // namespace + +namespace ash { +namespace test { + +LauncherViewTestAPI::LauncherViewTestAPI(internal::LauncherView* launcher_view) + : launcher_view_(launcher_view) { +} + +LauncherViewTestAPI::~LauncherViewTestAPI() { +} + +int LauncherViewTestAPI::GetButtonCount() { + return launcher_view_->view_model_->view_size(); +} + +internal::LauncherButton* LauncherViewTestAPI::GetButton(int index) { + // App list button is not a LauncherButton. + if (index == GetButtonCount() - 1) + return NULL; + + return static_cast<internal::LauncherButton*>( + launcher_view_->view_model_->view_at(index)); +} + +int LauncherViewTestAPI::GetLastVisibleIndex() { + return launcher_view_->last_visible_index_; +} + +bool LauncherViewTestAPI::IsOverflowButtonVisible() { + return launcher_view_->overflow_button_->visible(); +} + +void LauncherViewTestAPI::SetAnimationDuration(int duration_ms) { + launcher_view_->bounds_animator_->SetAnimationDuration(duration_ms); +} + +void LauncherViewTestAPI::RunMessageLoopUntilAnimationsDone() { + if (!launcher_view_->bounds_animator_->IsAnimating()) + return; + + scoped_ptr<TestAPIAnimationObserver> observer(new TestAPIAnimationObserver()); + launcher_view_->bounds_animator_->AddObserver(observer.get()); + + // This nested loop will quit when TestAPIAnimationObserver's + // OnBoundsAnimatorDone is called. + MessageLoop::current()->Run(); + + launcher_view_->bounds_animator_->RemoveObserver(observer.get()); +} + +} // namespace test +} // namespace ash diff --git a/ash/test/launcher_view_test_api.h b/ash/test/launcher_view_test_api.h new file mode 100644 index 0000000..651e2a0 --- /dev/null +++ b/ash/test/launcher_view_test_api.h @@ -0,0 +1,53 @@ +// Copyright (c) 2012 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. + +#ifndef ASH_TEST_LAUNCHER_VIEW_TEST_API_H_ +#define ASH_TEST_LAUNCHER_VIEW_TEST_API_H_ +#pragma once + +#include "base/basictypes.h" + +namespace ash { + +namespace internal { +class LauncherButton; +class LauncherView; +} + +namespace test { + +// Use the api in this class to test LauncherView. +class LauncherViewTestAPI { + public: + explicit LauncherViewTestAPI(internal::LauncherView* launcher_view); + ~LauncherViewTestAPI(); + + // Number of icons displayed. + int GetButtonCount(); + + // Retrieve the button at |index|. + internal::LauncherButton* GetButton(int index); + + // Last visible button index. + int GetLastVisibleIndex(); + + // Returns true if overflow button is visible. + bool IsOverflowButtonVisible(); + + // Sets animation duration in milliseconds for test. + void SetAnimationDuration(int duration_ms); + + // Runs message loop and waits until all add/remove animations are done. + void RunMessageLoopUntilAnimationsDone(); + + private: + internal::LauncherView* launcher_view_; + + DISALLOW_COPY_AND_ASSIGN(LauncherViewTestAPI); +}; + +} // namespace test +} // namespace ash + +#endif // ASH_TEST_LAUNCHER_VIEW_TEST_API_H_ diff --git a/ui/views/animation/bounds_animator.cc b/ui/views/animation/bounds_animator.cc index 2e4b0c1..3e7c93e 100644 --- a/ui/views/animation/bounds_animator.cc +++ b/ui/views/animation/bounds_animator.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -10,7 +10,7 @@ #include "ui/views/view.h" // Duration in milliseconds for animations. -static const int kAnimationDuration = 200; +static const int kDefaultAnimationDuration = 200; using ui::Animation; using ui::AnimationContainer; @@ -21,8 +21,8 @@ namespace views { BoundsAnimator::BoundsAnimator(View* parent) : parent_(parent), - observer_(NULL), - container_(new AnimationContainer()) { + container_(new AnimationContainer()), + animation_duration_ms_(kDefaultAnimationDuration) { container_->set_observer(this); } @@ -137,10 +137,22 @@ void BoundsAnimator::Cancel() { AnimationContainerProgressed(container_.get()); } +void BoundsAnimator::SetAnimationDuration(int duration_ms) { + animation_duration_ms_ = duration_ms; +} + +void BoundsAnimator::AddObserver(BoundsAnimatorObserver* observer) { + observers_.AddObserver(observer); +} + +void BoundsAnimator::RemoveObserver(BoundsAnimatorObserver* observer) { + observers_.RemoveObserver(observer); +} + SlideAnimation* BoundsAnimator::CreateAnimation() { SlideAnimation* animation = new SlideAnimation(this); animation->SetContainer(container_.get()); - animation->SetSlideDuration(kAnimationDuration); + animation->SetSlideDuration(animation_duration_ms_); animation->SetTweenType(Tween::EASE_OUT); return animation; } @@ -249,10 +261,12 @@ void BoundsAnimator::AnimationContainerProgressed( repaint_bounds_.SetRect(0, 0, 0, 0); } - if (observer_ && !IsAnimating()) { + if (!IsAnimating()) { // Notify here rather than from AnimationXXX to avoid deleting the animation // while the animation is calling us. - observer_->OnBoundsAnimatorDone(this); + FOR_EACH_OBSERVER(BoundsAnimatorObserver, + observers_, + OnBoundsAnimatorDone(this)); } } diff --git a/ui/views/animation/bounds_animator.h b/ui/views/animation/bounds_animator.h index d0e2c2e..f84c2d0 100644 --- a/ui/views/animation/bounds_animator.h +++ b/ui/views/animation/bounds_animator.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -10,6 +10,7 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" +#include "base/observer_list.h" #include "ui/base/animation/animation_container_observer.h" #include "ui/base/animation/animation_delegate.h" #include "ui/gfx/rect.h" @@ -24,7 +25,7 @@ namespace views { class BoundsAnimator; class View; -class BoundsAnimatorObserver { +class VIEWS_EXPORT BoundsAnimatorObserver { public: // Invoked when all animations are complete. virtual void OnBoundsAnimatorDone(BoundsAnimator* animator) = 0; @@ -92,9 +93,12 @@ class VIEWS_EXPORT BoundsAnimator : public ui::AnimationDelegate, // size. Any views marked for deletion are deleted. void Cancel(); - void set_observer(BoundsAnimatorObserver* observer) { - observer_ = observer; - } + // Overrides default animation duration. |duration_ms| is the new duration in + // milliseconds. + void SetAnimationDuration(int duration_ms); + + void AddObserver(BoundsAnimatorObserver* observer); + void RemoveObserver(BoundsAnimatorObserver* observer); protected: // Creates the animation to use for animating views. @@ -165,7 +169,7 @@ class VIEWS_EXPORT BoundsAnimator : public ui::AnimationDelegate, // Parent of all views being animated. View* parent_; - BoundsAnimatorObserver* observer_; + ObserverList<BoundsAnimatorObserver> observers_; // All animations we create up with the same container. scoped_refptr<ui::AnimationContainer> container_; @@ -182,6 +186,8 @@ class VIEWS_EXPORT BoundsAnimator : public ui::AnimationDelegate, // to repaint these bounds. gfx::Rect repaint_bounds_; + int animation_duration_ms_; + DISALLOW_COPY_AND_ASSIGN(BoundsAnimator); }; |