summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-07 17:33:39 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-07 17:33:39 +0000
commitf676780687464428e340d008a0d1ca13d9944628 (patch)
tree489e8bd8188e31a7f6c53f15e8d1d9c6ba36d023 /ui
parent3b65bfd55c56cf8a6db025087d937494f49dc15f (diff)
downloadchromium_src-f676780687464428e340d008a0d1ca13d9944628.zip
chromium_src-f676780687464428e340d008a0d1ca13d9944628.tar.gz
chromium_src-f676780687464428e340d008a0d1ca13d9944628.tar.bz2
Move animation code to new ui/base/animation directory.
BUG=none TEST=none TBR=brettw Review URL: http://codereview.chromium.org/6154001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70743 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/base/animation/animation.cc124
-rw-r--r--ui/base/animation/animation.h109
-rw-r--r--ui/base/animation/animation_container.cc104
-rw-r--r--ui/base/animation/animation_container.h90
-rw-r--r--ui/base/animation/animation_container_element.h34
-rw-r--r--ui/base/animation/animation_container_observer.h31
-rw-r--r--ui/base/animation/animation_container_unittest.cc126
-rw-r--r--ui/base/animation/animation_delegate.h34
-rw-r--r--ui/base/animation/animation_unittest.cc146
-rw-r--r--ui/base/animation/linear_animation.cc96
-rw-r--r--ui/base/animation/linear_animation.h74
-rw-r--r--ui/base/animation/multi_animation.cc88
-rw-r--r--ui/base/animation/multi_animation.h94
-rw-r--r--ui/base/animation/multi_animation_unittest.cc93
-rw-r--r--ui/base/animation/slide_animation.cc114
-rw-r--r--ui/base/animation/slide_animation.h100
-rw-r--r--ui/base/animation/slide_animation_unittest.cc34
-rw-r--r--ui/base/animation/test_animation_delegate.h49
-rw-r--r--ui/base/animation/throb_animation.cc81
-rw-r--r--ui/base/animation/throb_animation.h69
-rw-r--r--ui/base/animation/tween.cc86
-rw-r--r--ui/base/animation/tween.h48
-rw-r--r--ui/base/run_all_unittests.cc9
-rw-r--r--ui/base/test_suite.h38
-rw-r--r--ui/base/ui_base.gypi100
-rw-r--r--ui/ui.gyp52
26 files changed, 2023 insertions, 0 deletions
diff --git a/ui/base/animation/animation.cc b/ui/base/animation/animation.cc
new file mode 100644
index 0000000..1824774
--- /dev/null
+++ b/ui/base/animation/animation.cc
@@ -0,0 +1,124 @@
+// Copyright (c) 2011 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 "ui/base/animation/animation.h"
+
+#include "gfx/rect.h"
+#include "ui/base/animation/animation_container.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/animation/tween.h"
+
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
+namespace ui {
+
+Animation::Animation(base::TimeDelta timer_interval)
+ : timer_interval_(timer_interval),
+ is_animating_(false),
+ delegate_(NULL) {
+}
+
+Animation::~Animation() {
+ // Don't send out notification from the destructor. Chances are the delegate
+ // owns us and is being deleted as well.
+ if (is_animating_)
+ container_->Stop(this);
+}
+
+void Animation::Start() {
+ if (is_animating_)
+ return;
+
+ if (!container_.get())
+ container_ = new AnimationContainer();
+
+ is_animating_ = true;
+
+ container_->Start(this);
+
+ AnimationStarted();
+}
+
+void Animation::Stop() {
+ if (!is_animating_)
+ return;
+
+ is_animating_ = false;
+
+ // Notify the container first as the delegate may delete us.
+ container_->Stop(this);
+
+ AnimationStopped();
+
+ if (delegate_) {
+ if (ShouldSendCanceledFromStop())
+ delegate_->AnimationCanceled(this);
+ else
+ delegate_->AnimationEnded(this);
+ }
+}
+
+double Animation::CurrentValueBetween(double start, double target) const {
+ return Tween::ValueBetween(GetCurrentValue(), start, target);
+}
+
+int Animation::CurrentValueBetween(int start, int target) const {
+ return Tween::ValueBetween(GetCurrentValue(), start, target);
+}
+
+gfx::Rect Animation::CurrentValueBetween(const gfx::Rect& start_bounds,
+ const gfx::Rect& target_bounds) const {
+ return Tween::ValueBetween(GetCurrentValue(), start_bounds, target_bounds);
+}
+
+void Animation::SetContainer(AnimationContainer* container) {
+ if (container == container_.get())
+ return;
+
+ if (is_animating_)
+ container_->Stop(this);
+
+ if (container)
+ container_ = container;
+ else
+ container_ = new AnimationContainer();
+
+ if (is_animating_)
+ container_->Start(this);
+}
+
+// static
+bool Animation::ShouldRenderRichAnimation() {
+#if defined(OS_WIN)
+ if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
+ BOOL result;
+ // Get "Turn off all unnecessary animations" value.
+ if (::SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &result, 0)) {
+ // There seems to be a typo in the MSDN document (as of May 2009):
+ // http://msdn.microsoft.com/en-us/library/ms724947(VS.85).aspx
+ // The document states that the result is TRUE when animations are
+ // _disabled_, but in fact, it is TRUE when they are _enabled_.
+ return !!result;
+ }
+ }
+ return !::GetSystemMetrics(SM_REMOTESESSION);
+#endif
+ return true;
+}
+
+bool Animation::ShouldSendCanceledFromStop() {
+ return false;
+}
+
+void Animation::SetStartTime(base::TimeTicks start_time) {
+ start_time_ = start_time;
+}
+
+base::TimeDelta Animation::GetTimerInterval() const {
+ return timer_interval_;
+}
+
+} // namespace ui
diff --git a/ui/base/animation/animation.h b/ui/base/animation/animation.h
new file mode 100644
index 0000000..bb4be5a
--- /dev/null
+++ b/ui/base/animation/animation.h
@@ -0,0 +1,109 @@
+// Copyright (c) 2011 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 UI_BASE_ANIMATION_ANIMATION_H_
+#define UI_BASE_ANIMATION_ANIMATION_H_
+#pragma once
+
+#include "base/ref_counted.h"
+#include "base/time.h"
+#include "ui/base/animation/animation_container_element.h"
+
+namespace gfx {
+class Rect;
+}
+
+namespace ui {
+
+class AnimationContainer;
+class AnimationDelegate;
+
+// Base class used in implementing animations. You only need use this class if
+// you're implementing a new animation type, otherwise you'll likely want one of
+// LinearAnimation, SlideAnimation, ThrobAnimation or MultiAnimation.
+//
+// To subclass override Step, which is invoked as the animation progresses and
+// GetCurrentValue() to return the value appropriate to the animation.
+class Animation : public AnimationContainerElement {
+ public:
+ explicit Animation(base::TimeDelta timer_interval);
+ virtual ~Animation();
+
+ // Starts the animation. Does nothing if the animation is already running.
+ void Start();
+
+ // Stops the animation. Does nothing if the animation is not running.
+ void Stop();
+
+ // Gets the value for the current state, according to the animation
+ // curve in use.
+ virtual double GetCurrentValue() const = 0;
+
+ // Convenience for returning a value between |start| and |target| based on
+ // the current value. This is (target - start) * GetCurrentValue() + start.
+ double CurrentValueBetween(double start, double target) const;
+ int CurrentValueBetween(int start, int target) const;
+ gfx::Rect CurrentValueBetween(const gfx::Rect& start_bounds,
+ const gfx::Rect& target_bounds) const;
+
+ // Sets the delegate.
+ void set_delegate(AnimationDelegate* delegate) { delegate_ = delegate; }
+
+ // Sets the container used to manage the timer. A value of NULL results in
+ // creating a new AnimationContainer.
+ void SetContainer(AnimationContainer* container);
+
+ bool is_animating() const { return is_animating_; }
+
+ base::TimeDelta timer_interval() const { return timer_interval_; }
+
+ // Returns true if rich animations should be rendered.
+ // Looks at session type (e.g. remote desktop) and accessibility settings
+ // to give guidance for heavy animations such as "start download" arrow.
+ static bool ShouldRenderRichAnimation();
+
+ protected:
+ // Invoked from Start to allow subclasses to prepare for the animation.
+ virtual void AnimationStarted() {}
+
+ // Invoked from Stop after we're removed from the container but before the
+ // delegate has been invoked.
+ virtual void AnimationStopped() {}
+
+ // Invoked from stop to determine if cancel should be invoked. If this returns
+ // true the delegate is notified the animation was canceled, otherwise the
+ // delegate is notified the animation stopped.
+ virtual bool ShouldSendCanceledFromStop();
+
+ AnimationContainer* container() { return container_.get(); }
+ base::TimeTicks start_time() const { return start_time_; }
+ AnimationDelegate* delegate() { return delegate_; }
+
+ // AnimationContainer::Element overrides
+ virtual void SetStartTime(base::TimeTicks start_time);
+ virtual void Step(base::TimeTicks time_now) = 0;
+ virtual base::TimeDelta GetTimerInterval() const;
+
+ private:
+ // Interval for the animation.
+ const base::TimeDelta timer_interval_;
+
+ // If true we're running.
+ bool is_animating_;
+
+ // Our delegate; may be null.
+ AnimationDelegate* delegate_;
+
+ // Container we're in. If non-null we're animating.
+ scoped_refptr<AnimationContainer> container_;
+
+ // Time we started at.
+ base::TimeTicks start_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(Animation);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_ANIMATION_ANIMATION_H_
diff --git a/ui/base/animation/animation_container.cc b/ui/base/animation/animation_container.cc
new file mode 100644
index 0000000..1e316cd
--- /dev/null
+++ b/ui/base/animation/animation_container.cc
@@ -0,0 +1,104 @@
+// Copyright (c) 2011 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 "ui/base/animation/animation_container.h"
+
+#include "ui/base/animation/animation_container_element.h"
+#include "ui/base/animation/animation_container_observer.h"
+
+using base::TimeDelta;
+using base::TimeTicks;
+
+namespace ui {
+
+AnimationContainer::AnimationContainer()
+ : last_tick_time_(TimeTicks::Now()),
+ observer_(NULL) {
+}
+
+AnimationContainer::~AnimationContainer() {
+ // The animations own us and stop themselves before being deleted. If
+ // elements_ is not empty, something is wrong.
+ DCHECK(elements_.empty());
+}
+
+void AnimationContainer::Start(AnimationContainerElement* element) {
+ DCHECK(elements_.count(element) == 0); // Start should only be invoked if the
+ // element isn't running.
+
+ if (elements_.empty()) {
+ last_tick_time_ = TimeTicks::Now();
+ SetMinTimerInterval(element->GetTimerInterval());
+ } else if (element->GetTimerInterval() < min_timer_interval_) {
+ SetMinTimerInterval(element->GetTimerInterval());
+ }
+
+ element->SetStartTime(last_tick_time_);
+ elements_.insert(element);
+}
+
+void AnimationContainer::Stop(AnimationContainerElement* element) {
+ DCHECK(elements_.count(element) > 0); // The element must be running.
+
+ elements_.erase(element);
+
+ if (elements_.empty()) {
+ timer_.Stop();
+ if (observer_)
+ observer_->AnimationContainerEmpty(this);
+ } else {
+ TimeDelta min_timer_interval = GetMinInterval();
+ if (min_timer_interval > min_timer_interval_)
+ SetMinTimerInterval(min_timer_interval);
+ }
+}
+
+void AnimationContainer::Run() {
+ // We notify the observer after updating all the elements. If all the elements
+ // are deleted as a result of updating then our ref count would go to zero and
+ // we would be deleted before we notify our observer. We add a reference to
+ // ourself here to make sure we're still valid after running all the elements.
+ scoped_refptr<AnimationContainer> this_ref(this);
+
+ TimeTicks current_time = TimeTicks::Now();
+
+ last_tick_time_ = current_time;
+
+ // Make a copy of the elements to iterate over so that if any elements are
+ // removed as part of invoking Step there aren't any problems.
+ Elements elements = elements_;
+
+ for (Elements::const_iterator i = elements.begin();
+ i != elements.end(); ++i) {
+ // Make sure the element is still valid.
+ if (elements_.find(*i) != elements_.end())
+ (*i)->Step(current_time);
+ }
+
+ if (observer_)
+ observer_->AnimationContainerProgressed(this);
+}
+
+void AnimationContainer::SetMinTimerInterval(base::TimeDelta delta) {
+ // This doesn't take into account how far along the current element is, but
+ // that shouldn't be a problem for uses of Animation/AnimationContainer.
+ timer_.Stop();
+ min_timer_interval_ = delta;
+ timer_.Start(min_timer_interval_, this, &AnimationContainer::Run);
+}
+
+TimeDelta AnimationContainer::GetMinInterval() {
+ DCHECK(!elements_.empty());
+
+ TimeDelta min;
+ Elements::const_iterator i = elements_.begin();
+ min = (*i)->GetTimerInterval();
+ for (++i; i != elements_.end(); ++i) {
+ if ((*i)->GetTimerInterval() < min)
+ min = (*i)->GetTimerInterval();
+ }
+ return min;
+}
+
+} // namespace ui
diff --git a/ui/base/animation/animation_container.h b/ui/base/animation/animation_container.h
new file mode 100644
index 0000000..337b421
--- /dev/null
+++ b/ui/base/animation/animation_container.h
@@ -0,0 +1,90 @@
+// Copyright (c) 2011 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 UI_BASE_ANIMATION_ANIMATION_CONTAINER_H_
+#define UI_BASE_ANIMATION_ANIMATION_CONTAINER_H_
+#pragma once
+
+#include <set>
+
+#include "base/ref_counted.h"
+#include "base/time.h"
+#include "base/timer.h"
+
+namespace ui {
+
+class AnimationContainerElement;
+class AnimationContainerObserver;
+
+// AnimationContainer is used by Animation to manage the underlying timer.
+// Internally each Animation creates a single AnimationContainer. You can
+// group a set of Animations into the same AnimationContainer by way of
+// Animation::SetContainer. Grouping a set of Animations into the same
+// AnimationContainer ensures they all update and start at the same time.
+//
+// AnimationContainer is ref counted. Each Animation contained within the
+// AnimationContainer own it.
+class AnimationContainer : public base::RefCounted<AnimationContainer> {
+ public:
+ AnimationContainer();
+
+ // Invoked by Animation when it needs to start. Starts the timer if necessary.
+ // NOTE: This is invoked by Animation for you, you shouldn't invoke this
+ // directly.
+ void Start(AnimationContainerElement* animation);
+
+ // Invoked by Animation when it needs to stop. If there are no more animations
+ // running the timer stops.
+ // NOTE: This is invoked by Animation for you, you shouldn't invoke this
+ // directly.
+ void Stop(AnimationContainerElement* animation);
+
+ void set_observer(AnimationContainerObserver* observer) {
+ observer_ = observer;
+ }
+
+ // The time the last animation ran at.
+ base::TimeTicks last_tick_time() const { return last_tick_time_; }
+
+ // Are there any timers running?
+ bool is_running() const { return !elements_.empty(); }
+
+ private:
+ friend class base::RefCounted<AnimationContainer>;
+
+ typedef std::set<AnimationContainerElement*> Elements;
+
+ ~AnimationContainer();
+
+ // Timer callback method.
+ void Run();
+
+ // Sets min_timer_interval_ and restarts the timer.
+ void SetMinTimerInterval(base::TimeDelta delta);
+
+ // Returns the min timer interval of all the timers.
+ base::TimeDelta GetMinInterval();
+
+ // Represents one of two possible values:
+ // . If only a single animation has been started and the timer hasn't yet
+ // fired this is the time the animation was added.
+ // . The time the last animation ran at (::Run was invoked).
+ base::TimeTicks last_tick_time_;
+
+ // Set of elements (animations) being managed.
+ Elements elements_;
+
+ // Minimum interval the timers run at.
+ base::TimeDelta min_timer_interval_;
+
+ base::RepeatingTimer<AnimationContainer> timer_;
+
+ AnimationContainerObserver* observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(AnimationContainer);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_ANIMATION_ANIMATION_CONTAINER_H_
diff --git a/ui/base/animation/animation_container_element.h b/ui/base/animation/animation_container_element.h
new file mode 100644
index 0000000..8ac63a5
--- /dev/null
+++ b/ui/base/animation/animation_container_element.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2011 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 UI_BASE_ANIMATION_ANIMATION_CONTAINER_ELEMENT_H_
+#define UI_BASE_ANIMATION_ANIMATION_CONTAINER_ELEMENT_H_
+#pragma once
+
+#include "base/time.h"
+
+namespace ui {
+
+// Interface for the elements the AnimationContainer contains. This is
+// implemented by Animation.
+class AnimationContainerElement {
+ public:
+ // Sets the start of the animation. This is invoked from
+ // AnimationContainer::Start.
+ virtual void SetStartTime(base::TimeTicks start_time) = 0;
+
+ // Invoked when the animation is to progress.
+ virtual void Step(base::TimeTicks time_now) = 0;
+
+ // Returns the time interval of the animation. If an Element needs to change
+ // this it should first invoke Stop, then Start.
+ virtual base::TimeDelta GetTimerInterval() const = 0;
+
+ protected:
+ virtual ~AnimationContainerElement() {}
+};
+
+} // namespace ui
+
+#endif // UI_BASE_ANIMATION_ANIMATION_CONTAINER_ELEMENT_H_
diff --git a/ui/base/animation/animation_container_observer.h b/ui/base/animation/animation_container_observer.h
new file mode 100644
index 0000000..b01a476
--- /dev/null
+++ b/ui/base/animation/animation_container_observer.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 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 UI_BASE_ANIMATION_ANIMATION_CONTAINER_OBSERVER_H_
+#define UI_BASE_ANIMATION_ANIMATION_CONTAINER_OBSERVER_H_
+#pragma once
+
+namespace ui {
+
+class AnimationContainer;
+
+// The observer is notified after every update of the animations managed by
+// the container.
+class AnimationContainerObserver {
+ public:
+ // Invoked on every tick of the timer managed by the container and after
+ // all the animations have updated.
+ virtual void AnimationContainerProgressed(
+ AnimationContainer* container) = 0;
+
+ // Invoked when no more animations are being managed by this container.
+ virtual void AnimationContainerEmpty(AnimationContainer* container) = 0;
+
+ protected:
+ virtual ~AnimationContainerObserver() {}
+};
+
+} // namespace ui
+
+#endif // UI_BASE_ANIMATION_ANIMATION_CONTAINER_OBSERVER_H_
diff --git a/ui/base/animation/animation_container_unittest.cc b/ui/base/animation/animation_container_unittest.cc
new file mode 100644
index 0000000..6345591
--- /dev/null
+++ b/ui/base/animation/animation_container_unittest.cc
@@ -0,0 +1,126 @@
+// Copyright (c) 2011 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 "base/scoped_ptr.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/animation/animation_container.h"
+#include "ui/base/animation/animation_container_observer.h"
+#include "ui/base/animation/linear_animation.h"
+#include "ui/base/animation/test_animation_delegate.h"
+
+using testing::AtLeast;
+
+namespace ui {
+
+namespace {
+
+class MockObserver : public AnimationContainerObserver {
+ public:
+ MockObserver() {}
+
+ MOCK_METHOD1(AnimationContainerProgressed, void(AnimationContainer*));
+ MOCK_METHOD1(AnimationContainerEmpty, void(AnimationContainer*));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockObserver);
+};
+
+class TestAnimation : public LinearAnimation {
+ public:
+ explicit TestAnimation(AnimationDelegate* delegate)
+ : LinearAnimation(20, 20, delegate) {
+ }
+
+ virtual void AnimateToState(double state) {
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestAnimation);
+};
+
+} // namespace
+
+class AnimationContainerTest: public testing::Test {
+ private:
+ MessageLoopForUI message_loop_;
+};
+
+// Makes sure the animation ups the ref count of the container and releases it
+// appropriately.
+TEST_F(AnimationContainerTest, Ownership) {
+ TestAnimationDelegate delegate;
+ scoped_refptr<AnimationContainer> container(new AnimationContainer());
+ scoped_ptr<Animation> animation(new TestAnimation(&delegate));
+ animation->SetContainer(container.get());
+ // Setting the container should up the ref count.
+ EXPECT_FALSE(container->HasOneRef());
+
+ animation.reset();
+
+ // Releasing the animation should decrement the ref count.
+ EXPECT_TRUE(container->HasOneRef());
+}
+
+// Makes sure multiple animations are managed correctly.
+TEST_F(AnimationContainerTest, Multi) {
+ TestAnimationDelegate delegate1;
+ TestAnimationDelegate delegate2;
+
+ scoped_refptr<AnimationContainer> container(new AnimationContainer());
+ TestAnimation animation1(&delegate1);
+ TestAnimation animation2(&delegate2);
+ animation1.SetContainer(container.get());
+ animation2.SetContainer(container.get());
+
+ // Start both animations.
+ animation1.Start();
+ EXPECT_TRUE(container->is_running());
+ animation2.Start();
+ EXPECT_TRUE(container->is_running());
+
+ // Run the message loop the delegate quits the message loop when notified.
+ MessageLoop::current()->Run();
+
+ // Both timers should have finished.
+ EXPECT_TRUE(delegate1.finished());
+ EXPECT_TRUE(delegate2.finished());
+
+ // And the container should no longer be runnings.
+ EXPECT_FALSE(container->is_running());
+}
+
+// Makes sure observer is notified appropriately.
+TEST_F(AnimationContainerTest, Observer) {
+ MockObserver observer;
+ TestAnimationDelegate delegate1;
+
+ scoped_refptr<AnimationContainer> container(new AnimationContainer());
+ container->set_observer(&observer);
+ TestAnimation animation1(&delegate1);
+ animation1.SetContainer(container.get());
+
+ // We expect to get these two calls: the animation progressed, and then when
+ // the animation completed the container went empty.
+ EXPECT_CALL(observer, AnimationContainerProgressed(container.get())).Times(
+ AtLeast(1));
+ EXPECT_CALL(observer, AnimationContainerEmpty(container.get())).Times(1);
+
+ // Start the animation.
+ animation1.Start();
+ EXPECT_TRUE(container->is_running());
+
+ // Run the message loop. The delegate quits the message loop when notified.
+ MessageLoop::current()->Run();
+
+ // The timer should have finished.
+ EXPECT_TRUE(delegate1.finished());
+
+ // And the container should no longer be running.
+ EXPECT_FALSE(container->is_running());
+
+ container->set_observer(NULL);
+}
+
+} // namespace ui
diff --git a/ui/base/animation/animation_delegate.h b/ui/base/animation/animation_delegate.h
new file mode 100644
index 0000000..958aa89
--- /dev/null
+++ b/ui/base/animation/animation_delegate.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2011 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 UI_BASE_ANIMATION_ANIMATION_DELEGATE_H_
+#define UI_BASE_ANIMATION_ANIMATION_DELEGATE_H_
+#pragma once
+
+namespace ui {
+
+class Animation;
+
+// AnimationDelegate
+//
+// Implement this interface when you want to receive notifications about the
+// state of an animation.
+class AnimationDelegate {
+ public:
+ // Called when an animation has completed.
+ virtual void AnimationEnded(const Animation* animation) {}
+
+ // Called when an animation has progressed.
+ virtual void AnimationProgressed(const Animation* animation) {}
+
+ // Called when an animation has been canceled.
+ virtual void AnimationCanceled(const Animation* animation) {}
+
+ protected:
+ virtual ~AnimationDelegate() {}
+};
+
+} // namespace ui
+
+#endif // UI_BASE_ANIMATION_ANIMATION_DELEGATE_H_
diff --git a/ui/base/animation/animation_unittest.cc b/ui/base/animation/animation_unittest.cc
new file mode 100644
index 0000000..7d87600
--- /dev/null
+++ b/ui/base/animation/animation_unittest.cc
@@ -0,0 +1,146 @@
+// Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/animation/animation_delegate.h"
+#include "ui/base/animation/linear_animation.h"
+#include "ui/base/animation/test_animation_delegate.h"
+
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
+namespace ui {
+
+class AnimationTest: public testing::Test {
+ private:
+ MessageLoopForUI message_loop_;
+};
+
+namespace {
+
+///////////////////////////////////////////////////////////////////////////////
+// RunAnimation
+
+class RunAnimation : public LinearAnimation {
+ public:
+ RunAnimation(int frame_rate, AnimationDelegate* delegate)
+ : LinearAnimation(frame_rate, delegate) {
+ }
+
+ virtual void AnimateToState(double state) {
+ EXPECT_LE(0.0, state);
+ EXPECT_GE(1.0, state);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CancelAnimation
+
+class CancelAnimation : public LinearAnimation {
+ public:
+ CancelAnimation(int duration, int frame_rate, AnimationDelegate* delegate)
+ : LinearAnimation(duration, frame_rate, delegate) {
+ }
+
+ virtual void AnimateToState(double state) {
+ if (state >= 0.5)
+ Stop();
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// EndAnimation
+
+class EndAnimation : public LinearAnimation {
+ public:
+ EndAnimation(int duration, int frame_rate, AnimationDelegate* delegate)
+ : LinearAnimation(duration, frame_rate, delegate) {
+ }
+
+ virtual void AnimateToState(double state) {
+ if (state >= 0.5)
+ End();
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// DeletingAnimationDelegate
+
+// AnimationDelegate implementation that deletes the animation in ended.
+class DeletingAnimationDelegate : public AnimationDelegate {
+ public:
+ virtual void AnimationEnded(const Animation* animation) {
+ delete animation;
+ MessageLoop::current()->Quit();
+ }
+};
+
+} // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// LinearCase
+
+TEST_F(AnimationTest, RunCase) {
+ TestAnimationDelegate ad;
+ RunAnimation a1(150, &ad);
+ a1.SetDuration(2000);
+ a1.Start();
+ MessageLoop::current()->Run();
+
+ EXPECT_TRUE(ad.finished());
+ EXPECT_FALSE(ad.canceled());
+}
+
+TEST_F(AnimationTest, CancelCase) {
+ TestAnimationDelegate ad;
+ CancelAnimation a2(2000, 150, &ad);
+ a2.Start();
+ MessageLoop::current()->Run();
+
+ EXPECT_TRUE(ad.finished());
+ EXPECT_TRUE(ad.canceled());
+}
+
+// Lets an animation run, invoking End part way through and make sure we get the
+// right delegate methods invoked.
+TEST_F(AnimationTest, EndCase) {
+ TestAnimationDelegate ad;
+ EndAnimation a2(2000, 150, &ad);
+ a2.Start();
+ MessageLoop::current()->Run();
+
+ EXPECT_TRUE(ad.finished());
+ EXPECT_FALSE(ad.canceled());
+}
+
+// Runs an animation with a delegate that deletes the animation in end.
+TEST_F(AnimationTest, DeleteFromEnd) {
+ DeletingAnimationDelegate delegate;
+ RunAnimation* animation = new RunAnimation(150, &delegate);
+ animation->Start();
+ MessageLoop::current()->Run();
+ // delegate should have deleted animation.
+}
+
+TEST_F(AnimationTest, ShouldRenderRichAnimation) {
+#if defined(OS_WIN)
+ if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
+ BOOL result;
+ ASSERT_NE(
+ 0, ::SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &result, 0));
+ // ShouldRenderRichAnimation() should check the SPI_GETCLIENTAREAANIMATION
+ // value on Vista.
+ EXPECT_EQ(!!result, Animation::ShouldRenderRichAnimation());
+ } else {
+ // On XP, the function should check the SM_REMOTESESSION value.
+ EXPECT_EQ(!::GetSystemMetrics(SM_REMOTESESSION),
+ Animation::ShouldRenderRichAnimation());
+ }
+#else
+ EXPECT_TRUE(Animation::ShouldRenderRichAnimation());
+#endif
+}
+
+} // namespace ui
diff --git a/ui/base/animation/linear_animation.cc b/ui/base/animation/linear_animation.cc
new file mode 100644
index 0000000..60054d9
--- /dev/null
+++ b/ui/base/animation/linear_animation.cc
@@ -0,0 +1,96 @@
+// Copyright (c) 2011 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 "ui/base/animation/linear_animation.h"
+
+#include <math.h>
+
+#include "ui/base/animation/animation_container.h"
+#include "ui/base/animation/animation_delegate.h"
+
+using base::Time;
+using base::TimeDelta;
+
+namespace ui {
+
+static TimeDelta CalculateInterval(int frame_rate) {
+ int timer_interval = 1000000 / frame_rate;
+ if (timer_interval < 10000)
+ timer_interval = 10000;
+ return TimeDelta::FromMicroseconds(timer_interval);
+}
+
+LinearAnimation::LinearAnimation(int frame_rate,
+ AnimationDelegate* delegate)
+ : Animation(CalculateInterval(frame_rate)),
+ state_(0.0),
+ in_end_(false) {
+ set_delegate(delegate);
+}
+
+LinearAnimation::LinearAnimation(int duration,
+ int frame_rate,
+ AnimationDelegate* delegate)
+ : Animation(CalculateInterval(frame_rate)),
+ duration_(TimeDelta::FromMilliseconds(duration)),
+ state_(0.0),
+ in_end_(false) {
+ set_delegate(delegate);
+ SetDuration(duration);
+}
+
+double LinearAnimation::GetCurrentValue() const {
+ // Default is linear relationship, subclass to adapt.
+ return state_;
+}
+
+void LinearAnimation::End() {
+ if (!is_animating())
+ return;
+
+ // NOTE: We don't use AutoReset here as Stop may end up deleting us (by way
+ // of the delegate).
+ in_end_ = true;
+ Stop();
+}
+
+void LinearAnimation::SetDuration(int duration) {
+ duration_ = TimeDelta::FromMilliseconds(duration);
+ if (duration_ < timer_interval())
+ duration_ = timer_interval();
+ if (is_animating())
+ SetStartTime(container()->last_tick_time());
+}
+
+void LinearAnimation::Step(base::TimeTicks time_now) {
+ TimeDelta elapsed_time = time_now - start_time();
+ state_ = static_cast<double>(elapsed_time.InMicroseconds()) /
+ static_cast<double>(duration_.InMicroseconds());
+ if (state_ >= 1.0)
+ state_ = 1.0;
+
+ AnimateToState(state_);
+
+ if (delegate())
+ delegate()->AnimationProgressed(this);
+
+ if (state_ == 1.0)
+ Stop();
+}
+
+void LinearAnimation::AnimationStopped() {
+ if (!in_end_)
+ return;
+
+ in_end_ = false;
+ // Set state_ to ensure we send ended to delegate and not canceled.
+ state_ = 1;
+ AnimateToState(1.0);
+}
+
+bool LinearAnimation::ShouldSendCanceledFromStop() {
+ return state_ != 1;
+}
+
+} // namespace ui
diff --git a/ui/base/animation/linear_animation.h b/ui/base/animation/linear_animation.h
new file mode 100644
index 0000000..38205ea
--- /dev/null
+++ b/ui/base/animation/linear_animation.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2011 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 UI_BASE_ANIMATION_LINEAR_ANIMATION_H_
+#define UI_BASE_ANIMATION_LINEAR_ANIMATION_H_
+#pragma once
+
+#include "base/time.h"
+#include "ui/base/animation/animation.h"
+
+namespace ui {
+
+class AnimationDelegate;
+
+// Linear time bounded animation. As the animation progresses AnimateToState is
+// invoked.
+class LinearAnimation : public Animation {
+ public:
+ // Initializes everything except the duration.
+ //
+ // Caller must make sure to call SetDuration() if they use this
+ // constructor; it is preferable to use the full one, but sometimes
+ // duration can change between calls to Start() and we need to
+ // expose this interface.
+ LinearAnimation(int frame_rate, AnimationDelegate* delegate);
+
+ // Initializes all fields.
+ LinearAnimation(int duration, int frame_rate, AnimationDelegate* delegate);
+
+ // Gets the value for the current state, according to the animation curve in
+ // use. This class provides only for a linear relationship, however subclasses
+ // can override this to provide others.
+ virtual double GetCurrentValue() const;
+
+ // Skip to the end of the current animation.
+ void End();
+
+ // Changes the length of the animation. This resets the current
+ // state of the animation to the beginning.
+ void SetDuration(int duration);
+
+ protected:
+ // Called when the animation progresses. Subclasses override this to
+ // efficiently update their state.
+ virtual void AnimateToState(double state) = 0;
+
+ // Invoked by the AnimationContainer when the animation is running to advance
+ // the animation. Use |time_now| rather than Time::Now to avoid multiple
+ // animations running at the same time diverging.
+ virtual void Step(base::TimeTicks time_now);
+
+ // Overriden to advance to the end (if End was invoked).
+ virtual void AnimationStopped();
+
+ // Overriden to return true if state is not 1.
+ virtual bool ShouldSendCanceledFromStop();
+
+ private:
+ base::TimeDelta duration_;
+
+ // Current state, on a scale from 0.0 to 1.0.
+ double state_;
+
+ // If true, we're in end. This is used to determine if the animation should
+ // be advanced to the end from AnimationStopped.
+ bool in_end_;
+
+ DISALLOW_COPY_AND_ASSIGN(LinearAnimation);
+};
+
+} // namespace ui
+
+#endif // APP_LINEAR_ANIMATION_H_
diff --git a/ui/base/animation/multi_animation.cc b/ui/base/animation/multi_animation.cc
new file mode 100644
index 0000000..5a0c1e1
--- /dev/null
+++ b/ui/base/animation/multi_animation.cc
@@ -0,0 +1,88 @@
+// Copyright (c) 2011 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 "ui/base/animation/multi_animation.h"
+
+#include "base/logging.h"
+#include "ui/base/animation/animation_delegate.h"
+
+namespace ui {
+
+// Default interval, in ms.
+static const int kDefaultInterval = 20;
+
+static int TotalTime(const MultiAnimation::Parts& parts) {
+ int time_ms = 0;
+ for (size_t i = 0; i < parts.size(); ++i) {
+ DCHECK(parts[i].end_time_ms - parts[i].start_time_ms >= parts[i].time_ms);
+ time_ms += parts[i].time_ms;
+ }
+ return time_ms;
+}
+
+MultiAnimation::MultiAnimation(const Parts& parts)
+ : Animation(base::TimeDelta::FromMilliseconds(kDefaultInterval)),
+ parts_(parts),
+ cycle_time_ms_(TotalTime(parts)),
+ current_value_(0),
+ current_part_index_(0),
+ continuous_(true) {
+ DCHECK(!parts_.empty());
+}
+
+MultiAnimation::~MultiAnimation() {}
+
+double MultiAnimation::GetCurrentValue() const {
+ return current_value_;
+}
+
+void MultiAnimation::Step(base::TimeTicks time_now) {
+ double last_value = current_value_;
+ size_t last_index = current_part_index_;
+
+ int delta = static_cast<int>((time_now - start_time()).InMilliseconds());
+ if (delta >= cycle_time_ms_ && !continuous_) {
+ current_part_index_ = parts_.size() - 1;
+ current_value_ = Tween::CalculateValue(parts_[current_part_index_].type, 1);
+ Stop();
+ return;
+ }
+ delta %= cycle_time_ms_;
+ const Part& part = GetPart(&delta, &current_part_index_);
+ double percent = static_cast<double>(delta + part.start_time_ms) /
+ static_cast<double>(part.end_time_ms);
+ DCHECK(percent <= 1);
+ current_value_ = Tween::CalculateValue(part.type, percent);
+
+ if ((current_value_ != last_value || current_part_index_ != last_index) &&
+ delegate()) {
+ delegate()->AnimationProgressed(this);
+ }
+}
+
+void MultiAnimation::SetStartTime(base::TimeTicks start_time) {
+ Animation::SetStartTime(start_time);
+ current_value_ = 0;
+ current_part_index_ = 0;
+}
+
+const MultiAnimation::Part& MultiAnimation::GetPart(int* time_ms,
+ size_t* part_index) {
+ DCHECK(*time_ms < cycle_time_ms_);
+
+ for (size_t i = 0; i < parts_.size(); ++i) {
+ if (*time_ms < parts_[i].time_ms) {
+ *part_index = i;
+ return parts_[i];
+ }
+
+ *time_ms -= parts_[i].time_ms;
+ }
+ NOTREACHED();
+ *time_ms = 0;
+ *part_index = 0;
+ return parts_[0];
+}
+
+} // namespace ui
diff --git a/ui/base/animation/multi_animation.h b/ui/base/animation/multi_animation.h
new file mode 100644
index 0000000..fbacde3
--- /dev/null
+++ b/ui/base/animation/multi_animation.h
@@ -0,0 +1,94 @@
+// Copyright (c) 2011 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 UI_BASE_ANIMATION_MULTI_ANIMATION_H_
+#define UI_BASE_ANIMATION_MULTI_ANIMATION_H_
+#pragma once
+
+#include <vector>
+
+#include "ui/base/animation/animation.h"
+#include "ui/base/animation/tween.h"
+
+namespace ui {
+
+// MultiAnimation is an animation that consists of a number of sub animations.
+// To create a MultiAnimation pass in the parts, invoke Start() and the delegate
+// is notified as the animation progresses. By default MultiAnimation runs until
+// Stop is invoked, see |set_continuous()| for details.
+class MultiAnimation : public Animation {
+ public:
+ // Defines part of the animation. Each part consists of the following:
+ //
+ // time_ms: the time of the part.
+ // start_time_ms: the amount of time to offset this part by when calculating
+ // the percented completed.
+ // end_time_ms: the end time used to calculate the percentange completed.
+ //
+ // In most cases |start_time_ms| = 0 and |end_time_ms| = |time_ms|. But you
+ // can adjust the start/end for different effects. For example, to run a part
+ // for 200ms with a % between .25 and .75 use the following three values: 200,
+ // 100, 400.
+ struct Part {
+ Part() : time_ms(0), start_time_ms(0), end_time_ms(0), type(Tween::ZERO) {}
+ Part(int time_ms, Tween::Type type)
+ : time_ms(time_ms),
+ start_time_ms(0),
+ end_time_ms(time_ms),
+ type(type) {}
+
+ int time_ms;
+ int start_time_ms;
+ int end_time_ms;
+ Tween::Type type;
+ };
+
+ typedef std::vector<Part> Parts;
+
+ explicit MultiAnimation(const Parts& parts);
+ virtual ~MultiAnimation();
+
+ // Sets whether the animation continues after it reaches the end. If true, the
+ // animation runs until explicitly stopped. The default is true.
+ void set_continuous(bool continuous) { continuous_ = continuous; }
+
+ // Returns the current value. The current value for a MultiAnimation is
+ // determined from the tween type of the current part.
+ virtual double GetCurrentValue() const;
+
+ // Returns the index of the current part.
+ size_t current_part_index() const { return current_part_index_; }
+
+ protected:
+ // Animation overrides.
+ virtual void Step(base::TimeTicks time_now);
+ virtual void SetStartTime(base::TimeTicks start_time);
+
+ private:
+ // Returns the part containing the specified time. |time_ms| is reset to be
+ // relative to the part containing the time and |part_index| the index of the
+ // part.
+ const Part& GetPart(int* time_ms, size_t* part_index);
+
+ // The parts that make up the animation.
+ const Parts parts_;
+
+ // Total time of all the parts.
+ const int cycle_time_ms_;
+
+ // Current value for the animation.
+ double current_value_;
+
+ // Index of the current part.
+ size_t current_part_index_;
+
+ // See description above setter.
+ bool continuous_;
+
+ DISALLOW_COPY_AND_ASSIGN(MultiAnimation);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_ANIMATION_MULTI_ANIMATION_H_
diff --git a/ui/base/animation/multi_animation_unittest.cc b/ui/base/animation/multi_animation_unittest.cc
new file mode 100644
index 0000000..dfc015d
--- /dev/null
+++ b/ui/base/animation/multi_animation_unittest.cc
@@ -0,0 +1,93 @@
+// Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/animation/animation_container_element.h"
+#include "ui/base/animation/multi_animation.h"
+
+namespace ui {
+
+typedef testing::Test MultiAnimationTest;
+
+TEST_F(MultiAnimationTest, Basic) {
+ // Create a MultiAnimation with two parts.
+ MultiAnimation::Parts parts;
+ parts.push_back(MultiAnimation::Part(100, Tween::LINEAR));
+ parts.push_back(MultiAnimation::Part(100, Tween::EASE_OUT));
+
+ MultiAnimation animation(parts);
+ AnimationContainerElement* as_element =
+ static_cast<AnimationContainerElement*>(&animation);
+ as_element->SetStartTime(base::TimeTicks());
+
+ // Step to 50, which is half way through the first part.
+ as_element->Step(base::TimeTicks() + base::TimeDelta::FromMilliseconds(50));
+ EXPECT_EQ(.5, animation.GetCurrentValue());
+
+ // Step to 120, which is 20% through the second part.
+ as_element->Step(base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(120));
+ EXPECT_EQ(Tween::CalculateValue(Tween::EASE_OUT, .2),
+ animation.GetCurrentValue());
+
+ // Step to 320, which is 20% through the second part.
+ as_element->Step(base::TimeTicks() +
+ base::TimeDelta::FromMilliseconds(320));
+ EXPECT_EQ(Tween::CalculateValue(Tween::EASE_OUT, .2),
+ animation.GetCurrentValue());
+}
+
+TEST_F(MultiAnimationTest, DifferingStartAndEnd) {
+ // Create a MultiAnimation with two parts.
+ MultiAnimation::Parts parts;
+ parts.push_back(MultiAnimation::Part(200, Tween::LINEAR));
+ parts[0].start_time_ms = 100;
+ parts[0].end_time_ms = 400;
+
+ MultiAnimation animation(parts);
+ AnimationContainerElement* as_element =
+ static_cast<AnimationContainerElement*>(&animation);
+ as_element->SetStartTime(base::TimeTicks());
+
+ // Step to 0. Because the start_time is 100, this should be 100ms into the
+ // animation
+ as_element->Step(base::TimeTicks());
+ EXPECT_EQ(.25, animation.GetCurrentValue());
+
+ // Step to 100, which is effectively 200ms into the animation.
+ as_element->Step(base::TimeTicks() + base::TimeDelta::FromMilliseconds(100));
+ EXPECT_EQ(.5, animation.GetCurrentValue());
+}
+
+// Makes sure multi-animation stops if cycles is false.
+TEST_F(MultiAnimationTest, DontCycle) {
+ MultiAnimation::Parts parts;
+ parts.push_back(MultiAnimation::Part(200, Tween::LINEAR));
+ MultiAnimation animation(parts);
+ AnimationContainerElement* as_element =
+ static_cast<AnimationContainerElement*>(&animation);
+ as_element->SetStartTime(base::TimeTicks());
+ animation.set_continuous(false);
+
+ // Step to 300, which is greater than the cycle time.
+ as_element->Step(base::TimeTicks() + base::TimeDelta::FromMilliseconds(300));
+ EXPECT_EQ(1.0, animation.GetCurrentValue());
+ EXPECT_FALSE(animation.is_animating());
+}
+
+// Makes sure multi-animation cycles correctly.
+TEST_F(MultiAnimationTest, Cycle) {
+ MultiAnimation::Parts parts;
+ parts.push_back(MultiAnimation::Part(200, Tween::LINEAR));
+ MultiAnimation animation(parts);
+ AnimationContainerElement* as_element =
+ static_cast<AnimationContainerElement*>(&animation);
+ as_element->SetStartTime(base::TimeTicks());
+
+ // Step to 300, which is greater than the cycle time.
+ as_element->Step(base::TimeTicks() + base::TimeDelta::FromMilliseconds(300));
+ EXPECT_EQ(.5, animation.GetCurrentValue());
+}
+
+} // namespace ui
diff --git a/ui/base/animation/slide_animation.cc b/ui/base/animation/slide_animation.cc
new file mode 100644
index 0000000..ec08334
--- /dev/null
+++ b/ui/base/animation/slide_animation.cc
@@ -0,0 +1,114 @@
+// Copyright (c) 2011 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 "ui/base/animation/slide_animation.h"
+
+#include <math.h>
+
+namespace ui {
+
+// How many frames per second to target.
+static const int kDefaultFramerateHz = 50;
+
+// How long animations should take by default.
+static const int kDefaultDurationMs = 120;
+
+SlideAnimation::SlideAnimation(AnimationDelegate* target)
+ : LinearAnimation(kDefaultFramerateHz, target),
+ target_(target),
+ tween_type_(Tween::EASE_OUT),
+ showing_(false),
+ value_start_(0),
+ value_end_(0),
+ value_current_(0),
+ slide_duration_(kDefaultDurationMs) {
+}
+
+SlideAnimation::~SlideAnimation() {
+}
+
+void SlideAnimation::Reset() {
+ Reset(0);
+}
+
+void SlideAnimation::Reset(double value) {
+ Stop();
+ showing_ = static_cast<bool>(value == 1);
+ value_current_ = value;
+}
+
+void SlideAnimation::Show() {
+ // If we're already showing (or fully shown), we have nothing to do.
+ if (showing_)
+ return;
+
+ showing_ = true;
+ value_start_ = value_current_;
+ value_end_ = 1.0;
+
+ // Make sure we actually have something to do.
+ if (slide_duration_ == 0) {
+ AnimateToState(1.0); // Skip to the end of the animation.
+ return;
+ } else if (value_current_ == value_end_) {
+ return;
+ }
+
+ // This will also reset the currently-occuring animation.
+ SetDuration(static_cast<int>(slide_duration_ * (1 - value_current_)));
+ Start();
+}
+
+void SlideAnimation::Hide() {
+ // If we're already hiding (or hidden), we have nothing to do.
+ if (!showing_)
+ return;
+
+ showing_ = false;
+ value_start_ = value_current_;
+ value_end_ = 0.0;
+
+ // Make sure we actually have something to do.
+ if (slide_duration_ == 0) {
+ AnimateToState(0.0); // Skip to the end of the animation.
+ return;
+ } else if (value_current_ == value_end_) {
+ return;
+ }
+
+ // This will also reset the currently-occuring animation.
+ SetDuration(static_cast<int>(slide_duration_ * value_current_));
+ Start();
+}
+
+void SlideAnimation::SetSlideDuration(int duration) {
+ slide_duration_ = duration;
+}
+
+double SlideAnimation::GetCurrentValue() const {
+ return value_current_;
+}
+
+void SlideAnimation::AnimateToState(double state) {
+ if (state > 1.0)
+ state = 1.0;
+
+ state = Tween::CalculateValue(tween_type_, state);
+
+ value_current_ = value_start_ + (value_end_ - value_start_) * state;
+
+ // Implement snapping.
+ if (tween_type_ == Tween::EASE_OUT_SNAP &&
+ fabs(value_current_ - value_end_) <= 0.06)
+ value_current_ = value_end_;
+
+ // Correct for any overshoot (while state may be capped at 1.0, let's not
+ // take any rounding error chances.
+ if ((value_end_ >= value_start_ && value_current_ > value_end_) ||
+ (value_end_ < value_start_ && value_current_ < value_end_)) {
+ value_current_ = value_end_;
+ }
+}
+
+} // namespace ui
diff --git a/ui/base/animation/slide_animation.h b/ui/base/animation/slide_animation.h
new file mode 100644
index 0000000..8f5e67c
--- /dev/null
+++ b/ui/base/animation/slide_animation.h
@@ -0,0 +1,100 @@
+// Copyright (c) 2011 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 UI_BASE_ANIMATION_SLIDE_ANIMATION_H_
+#define UI_BASE_ANIMATION_SLIDE_ANIMATION_H_
+#pragma once
+
+#include "ui/base/animation/linear_animation.h"
+#include "ui/base/animation/tween.h"
+
+namespace ui {
+
+// Slide Animation
+//
+// Used for reversible animations and as a general helper class. Typical usage:
+//
+// #include "ui/base/animation/slide_animation.h"
+//
+// class MyClass : public AnimationDelegate {
+// public:
+// MyClass() {
+// animation_.reset(new SlideAnimation(this));
+// animation_->SetSlideDuration(500);
+// }
+// void OnMouseOver() {
+// animation_->Show();
+// }
+// void OnMouseOut() {
+// animation_->Hide();
+// }
+// void AnimationProgressed(const Animation* animation) {
+// if (animation == animation_.get()) {
+// Layout();
+// SchedulePaint();
+// } else if (animation == other_animation_.get()) {
+// ...
+// }
+// }
+// void Layout() {
+// if (animation_->is_animating()) {
+// hover_image_.SetOpacity(animation_->GetCurrentValue());
+// }
+// }
+// private:
+// scoped_ptr<SlideAnimation> animation_;
+// }
+class SlideAnimation : public LinearAnimation {
+ public:
+ explicit SlideAnimation(AnimationDelegate* target);
+ virtual ~SlideAnimation();
+
+ // Set the animation back to the 0 state.
+ virtual void Reset();
+ virtual void Reset(double value);
+
+ // Begin a showing animation or reverse a hiding animation in progress.
+ virtual void Show();
+
+ // Begin a hiding animation or reverse a showing animation in progress.
+ virtual void Hide();
+
+ // Sets the time a slide will take. Note that this isn't actually
+ // the amount of time an animation will take as the current value of
+ // the slide is considered.
+ virtual void SetSlideDuration(int duration);
+ int GetSlideDuration() const { return slide_duration_; }
+ void SetTweenType(Tween::Type tween_type) { tween_type_ = tween_type; }
+
+ virtual double GetCurrentValue() const;
+ bool IsShowing() const { return showing_; }
+ bool IsClosing() const { return !showing_ && value_end_ < value_current_; }
+
+ private:
+ // Overridden from Animation.
+ virtual void AnimateToState(double state);
+
+ AnimationDelegate* target_;
+
+ Tween::Type tween_type_;
+
+ // Used to determine which way the animation is going.
+ bool showing_;
+
+ // Animation values. These are a layer on top of Animation::state_ to
+ // provide the reversability.
+ double value_start_;
+ double value_end_;
+ double value_current_;
+
+ // How long a hover in/out animation will last for. This defaults to
+ // kHoverFadeDurationMS, but can be overridden with SetDuration.
+ int slide_duration_;
+
+ DISALLOW_COPY_AND_ASSIGN(SlideAnimation);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_ANIMATION_SLIDE_ANIMATION_H_
diff --git a/ui/base/animation/slide_animation_unittest.cc b/ui/base/animation/slide_animation_unittest.cc
new file mode 100644
index 0000000..dcce5c0
--- /dev/null
+++ b/ui/base/animation/slide_animation_unittest.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2011 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 "base/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/base/animation/test_animation_delegate.h"
+
+namespace ui {
+
+class SlideAnimationTest: public testing::Test {
+ private:
+ MessageLoopForUI message_loop_;
+};
+
+// Tests that delegate is not notified when animation is running and is deleted.
+// (Such a scenario would cause problems for BoundsAnimator).
+TEST_F(SlideAnimationTest, DontNotifyOnDelete) {
+ TestAnimationDelegate delegate;
+ scoped_ptr<SlideAnimation> animation(new SlideAnimation(&delegate));
+
+ // Start the animation.
+ animation->Show();
+
+ // Delete the animation.
+ animation.reset();
+
+ // Make sure the delegate wasn't notified.
+ EXPECT_FALSE(delegate.finished());
+ EXPECT_FALSE(delegate.canceled());
+}
+
+} // namespace ui
diff --git a/ui/base/animation/test_animation_delegate.h b/ui/base/animation/test_animation_delegate.h
new file mode 100644
index 0000000..e6c4047
--- /dev/null
+++ b/ui/base/animation/test_animation_delegate.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 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 UI_BASE_ANIMATION_TEST_ANIMATION_DELEGATE_H_
+#define UI_BASE_ANIMATION_TEST_ANIMATION_DELEGATE_H_
+#pragma once
+
+#include "base/message_loop.h"
+#include "ui/base/animation/animation_delegate.h"
+
+namespace ui {
+
+// Trivial AnimationDelegate implementation. AnimationEnded/Canceled quit the
+// message loop.
+class TestAnimationDelegate : public AnimationDelegate {
+ public:
+ TestAnimationDelegate() : canceled_(false), finished_(false) {
+ }
+
+ virtual void AnimationEnded(const Animation* animation) {
+ finished_ = true;
+ MessageLoop::current()->Quit();
+ }
+
+ virtual void AnimationCanceled(const Animation* animation) {
+ finished_ = true;
+ canceled_ = true;
+ MessageLoop::current()->Quit();
+ }
+
+ bool finished() const {
+ return finished_;
+ }
+
+ bool canceled() const {
+ return canceled_;
+ }
+
+ private:
+ bool canceled_;
+ bool finished_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestAnimationDelegate);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_ANIMATION_TEST_ANIMATION_DELEGATE_H_
diff --git a/ui/base/animation/throb_animation.cc b/ui/base/animation/throb_animation.cc
new file mode 100644
index 0000000..95e9a65
--- /dev/null
+++ b/ui/base/animation/throb_animation.cc
@@ -0,0 +1,81 @@
+// Copyright (c) 2011 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 "ui/base/animation/throb_animation.h"
+
+#include <limits>
+
+namespace ui {
+
+static const int kDefaultThrobDurationMS = 400;
+
+ThrobAnimation::ThrobAnimation(AnimationDelegate* target)
+ : SlideAnimation(target),
+ slide_duration_(GetSlideDuration()),
+ throb_duration_(kDefaultThrobDurationMS),
+ cycles_remaining_(0),
+ throbbing_(false) {
+}
+
+void ThrobAnimation::StartThrobbing(int cycles_til_stop) {
+ cycles_til_stop = cycles_til_stop >= 0 ? cycles_til_stop :
+ std::numeric_limits<int>::max();
+ cycles_remaining_ = cycles_til_stop;
+ throbbing_ = true;
+ SlideAnimation::SetSlideDuration(throb_duration_);
+ if (is_animating())
+ return; // We're already running, we'll cycle when current loop finishes.
+
+ if (IsShowing())
+ SlideAnimation::Hide();
+ else
+ SlideAnimation::Show();
+ cycles_remaining_ = cycles_til_stop;
+}
+
+void ThrobAnimation::Reset() {
+ ResetForSlide();
+ SlideAnimation::Reset();
+}
+
+void ThrobAnimation::Show() {
+ ResetForSlide();
+ SlideAnimation::Show();
+}
+
+void ThrobAnimation::Hide() {
+ ResetForSlide();
+ SlideAnimation::Hide();
+}
+
+void ThrobAnimation::SetSlideDuration(int duration) {
+ slide_duration_ = duration;
+}
+
+void ThrobAnimation::Step(base::TimeTicks time_now) {
+ LinearAnimation::Step(time_now);
+
+ if (!is_animating() && throbbing_) {
+ // Were throbbing a finished a cycle. Start the next cycle unless we're at
+ // the end of the cycles, in which case we stop.
+ cycles_remaining_--;
+ if (IsShowing()) {
+ // We want to stop hidden, hence this doesn't check cycles_remaining_.
+ SlideAnimation::Hide();
+ } else if (cycles_remaining_ > 0) {
+ SlideAnimation::Show();
+ } else {
+ // We're done throbbing.
+ throbbing_ = false;
+ }
+ }
+}
+
+void ThrobAnimation::ResetForSlide() {
+ SlideAnimation::SetSlideDuration(slide_duration_);
+ cycles_remaining_ = 0;
+ throbbing_ = false;
+}
+
+} // namespace ui
diff --git a/ui/base/animation/throb_animation.h b/ui/base/animation/throb_animation.h
new file mode 100644
index 0000000..21dc03b
--- /dev/null
+++ b/ui/base/animation/throb_animation.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2011 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 UI_BASE_ANIMATION_THROB_ANIMATION_H_
+#define UI_BASE_ANIMATION_THROB_ANIMATION_H_
+#pragma once
+
+#include "ui/base/animation/slide_animation.h"
+
+namespace ui {
+
+// A subclass of SlideAnimation that can continually slide. All of the Animation
+// methods behave like that of SlideAnimation: transition to the next state.
+// The StartThrobbing method causes the ThrobAnimation to cycle between hidden
+// and shown for a set number of cycles.
+//
+// A ThrobAnimation has two durations: the duration used when behavior like
+// a SlideAnimation, and the duration used when throbbing.
+class ThrobAnimation : public SlideAnimation {
+ public:
+ explicit ThrobAnimation(AnimationDelegate* target);
+ virtual ~ThrobAnimation() {}
+
+ // Starts throbbing. cycles_til_stop gives the number of cycles to do before
+ // stopping. A negative value means "throb indefinitely".
+ void StartThrobbing(int cycles_til_stop);
+
+ // Sets the duration of the slide animation when throbbing.
+ void SetThrobDuration(int duration) { throb_duration_ = duration; }
+
+ // Overridden to reset to the slide duration.
+ virtual void Reset();
+ virtual void Show();
+ virtual void Hide();
+
+ // Overridden to maintain the slide duration.
+ virtual void SetSlideDuration(int duration);
+
+ // The number of cycles remaining until the animation stops.
+ void set_cycles_remaining(int value) { cycles_remaining_ = value; }
+ int cycles_remaining() const { return cycles_remaining_; }
+
+ protected:
+ // Overriden to continually throb (assuming we're throbbing).
+ virtual void Step(base::TimeTicks time_now);
+
+ private:
+ // Resets state such that we behave like SlideAnimation.
+ void ResetForSlide();
+
+ // Duration of the slide animation.
+ int slide_duration_;
+
+ // Duration of the slide animation when throbbing.
+ int throb_duration_;
+
+ // If throbbing, this is the number of cycles left.
+ int cycles_remaining_;
+
+ // Are we throbbing?
+ bool throbbing_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThrobAnimation);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_ANIMATION_THROB_ANIMATION_H_
diff --git a/ui/base/animation/tween.cc b/ui/base/animation/tween.cc
new file mode 100644
index 0000000..131e686
--- /dev/null
+++ b/ui/base/animation/tween.cc
@@ -0,0 +1,86 @@
+// Copyright (c) 2011 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 "ui/base/animation/tween.h"
+
+#include <math.h>
+
+#if defined(OS_WIN)
+#include <float.h>
+#endif
+
+#include "base/logging.h"
+#include "gfx/rect.h"
+
+namespace ui {
+
+// static
+double Tween::CalculateValue(Tween::Type type, double state) {
+ DCHECK_GE(state, 0);
+ DCHECK_LE(state, 1);
+
+ switch (type) {
+ case EASE_IN:
+ return pow(state, 2);
+
+ case EASE_IN_OUT:
+ if (state < 0.5)
+ return pow(state * 2, 2) / 2.0;
+ return 1.0 - (pow((state - 1.0) * 2, 2) / 2.0);
+
+ case FAST_IN_OUT:
+ return (pow(state - 0.5, 3) + 0.125) / 0.25;
+
+ case LINEAR:
+ return state;
+
+ case EASE_OUT_SNAP:
+ state = 0.95 * (1.0 - pow(1.0 - state, 2));
+ break;
+
+ case EASE_OUT:
+ return 1.0 - pow(1.0 - state, 2);
+
+ case ZERO:
+ return 0;
+ }
+
+ NOTREACHED();
+ return state;
+}
+
+// static
+double Tween::ValueBetween(double value, double start, double target) {
+ return start + (target - start) * value;
+}
+
+// static
+int Tween::ValueBetween(double value, int start, int target) {
+ if (start == target)
+ return start;
+ double delta = static_cast<double>(target - start);
+ if (delta < 0)
+ delta--;
+ else
+ delta++;
+#if defined(OS_WIN)
+ return start + static_cast<int>(value * _nextafter(delta, 0));
+#else
+ return start + static_cast<int>(value * nextafter(delta, 0));
+#endif
+}
+
+// static
+gfx::Rect Tween::ValueBetween(double value,
+ const gfx::Rect& start_bounds,
+ const gfx::Rect& target_bounds) {
+ return gfx::Rect(ValueBetween(value, start_bounds.x(), target_bounds.x()),
+ ValueBetween(value, start_bounds.y(), target_bounds.y()),
+ ValueBetween(value, start_bounds.width(),
+ target_bounds.width()),
+ ValueBetween(value, start_bounds.height(),
+ target_bounds.height()));
+}
+
+} // namespace ui
diff --git a/ui/base/animation/tween.h b/ui/base/animation/tween.h
new file mode 100644
index 0000000..873281f
--- /dev/null
+++ b/ui/base/animation/tween.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2011 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 UI_BASE_ANIMATION_TWEEN_H_
+#define UI_BASE_ANIMATION_TWEEN_H_
+#pragma once
+
+#include "base/basictypes.h"
+
+namespace gfx {
+class Rect;
+}
+
+namespace ui {
+
+class Tween {
+ public:
+ enum Type {
+ LINEAR, // Linear.
+ EASE_OUT, // Fast in, slow out (default).
+ EASE_IN, // Slow in, fast out.
+ EASE_IN_OUT, // Slow in and out, fast in the middle.
+ FAST_IN_OUT, // Fast in and out, slow in the middle.
+ EASE_OUT_SNAP, // Fast in, slow out, snap to final value.
+ ZERO, // Returns a value of 0 always.
+ };
+
+ // Returns the value based on the tween type. |state| is from 0-1.
+ static double CalculateValue(Type type, double state);
+
+ // Conveniences for getting a value between a start and end point.
+ static double ValueBetween(double value, double start, double target);
+ static int ValueBetween(double value, int start, int target);
+ static gfx::Rect ValueBetween(double value,
+ const gfx::Rect& start_bounds,
+ const gfx::Rect& target_bounds);
+
+ private:
+ Tween();
+ ~Tween();
+
+ DISALLOW_COPY_AND_ASSIGN(Tween);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_ANIMATION_TWEEN_H_
diff --git a/ui/base/run_all_unittests.cc b/ui/base/run_all_unittests.cc
new file mode 100644
index 0000000..3be8d08
--- /dev/null
+++ b/ui/base/run_all_unittests.cc
@@ -0,0 +1,9 @@
+// Copyright (c) 2011 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 "ui/base/test_suite.h"
+
+int main(int argc, char** argv) {
+ return UiBaseTestSuite(argc, argv).Run();
+}
diff --git a/ui/base/test_suite.h b/ui/base/test_suite.h
new file mode 100644
index 0000000..c548d6a
--- /dev/null
+++ b/ui/base/test_suite.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2011 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 UI_BASE_TEST_SUITE_H_
+#define UI_BASE_TEST_SUITE_H_
+#pragma once
+
+#include "build/build_config.h"
+
+#include "base/path_service.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/test/test_suite.h"
+#include "build/build_config.h"
+
+#if defined(OS_MACOSX)
+#include "base/mac/mac_util.h"
+#endif
+
+class UiBaseTestSuite : public base::TestSuite {
+ public:
+ UiBaseTestSuite(int argc, char** argv) : TestSuite(argc, argv) {
+ }
+
+ protected:
+
+ virtual void Initialize() {
+ base::mac::ScopedNSAutoreleasePool autorelease_pool;
+
+ TestSuite::Initialize();
+ }
+
+ virtual void Shutdown() {
+ TestSuite::Shutdown();
+ }
+};
+
+#endif // UI_BASE_TEST_SUITE_H_
diff --git a/ui/base/ui_base.gypi b/ui/base/ui_base.gypi
new file mode 100644
index 0000000..f441c6f
--- /dev/null
+++ b/ui/base/ui_base.gypi
@@ -0,0 +1,100 @@
+# Copyright (c) 2011 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.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'target_defaults': {
+ 'sources/': [
+ ['exclude', '/(cocoa|gtk|win)/'],
+ ['exclude', '_(cocoa|gtk|linux|mac|posix|skia|win|x)\\.(cc|mm?)$'],
+ ['exclude', '/(gtk|win|x11)_[^/]*\\.cc$'],
+ ],
+ 'conditions': [
+ ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {'sources/': [
+ ['include', '/gtk/'],
+ ['include', '_(gtk|linux|posix|skia|x)\\.cc$'],
+ ['include', '/(gtk|x11)_[^/]*\\.cc$'],
+ ]}],
+ ['OS=="mac"', {'sources/': [
+ ['include', '/cocoa/'],
+ ['include', '_(cocoa|mac|posix)\\.(cc|mm?)$'],
+ ]}, { # else: OS != "mac"
+ 'sources/': [
+ ['exclude', '\\.mm?$'],
+ ],
+ }],
+ ['OS=="win"', {'sources/': [
+ ['include', '_(win)\\.cc$'],
+ ['include', '/win/'],
+ ['include', '/win_[^/]*\\.cc$'],
+ ]}],
+ ['touchui==0', {'sources/': [
+ ['exclude', 'event_x.cc$'],
+ ['exclude', 'native_menu_x.cc$'],
+ ['exclude', 'native_menu_x.h$'],
+ ['exclude', 'touchui/'],
+ ['exclude', '_(touch)\\.cc$'],
+ ]}],
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'ui_base',
+ 'type': '<(library)',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../gfx/gfx.gyp:gfx',
+ '../skia/skia.gyp:skia',
+ '../third_party/icu/icu.gyp:icui18n',
+ '../third_party/icu/icu.gyp:icuuc',
+ ],
+ 'sources': [
+ 'animation/animation.cc',
+ 'animation/animation.h',
+ 'animation/animation_container.cc',
+ 'animation/animation_container.h',
+ 'animation/animation_container_element.h',
+ 'animation/animation_container_observer.h',
+ 'animation/animation_delegate.h',
+ 'animation/linear_animation.cc',
+ 'animation/linear_animation.h',
+ 'animation/multi_animation.cc',
+ 'animation/multi_animation.h',
+ 'animation/slide_animation.cc',
+ 'animation/slide_animation.h',
+ 'animation/throb_animation.cc',
+ 'animation/throb_animation.h',
+ 'animation/tween.cc',
+ 'animation/tween.h',
+ ],
+ },
+ {
+ 'target_name': 'ui_base_unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../base/base.gyp:test_support_base',
+ '../testing/gmock.gyp:gmock',
+ '../testing/gtest.gyp:gtest',
+ 'ui_base',
+ ],
+ 'sources': [
+ 'animation/animation_container_unittest.cc',
+ 'animation/animation_unittest.cc',
+ 'animation/multi_animation_unittest.cc',
+ 'animation/slide_animation_unittest.cc',
+ 'run_all_unittests.cc',
+ 'test_suite.h',
+ ],
+ },
+ ],
+}
+
+# Local Variables:
+# tab-width:2
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/ui/ui.gyp b/ui/ui.gyp
new file mode 100644
index 0000000..e289b0b
--- /dev/null
+++ b/ui/ui.gyp
@@ -0,0 +1,52 @@
+# Copyright (c) 2011 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.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'target_defaults': {
+ 'sources/': [
+ ['exclude', '/(cocoa|gtk|win)/'],
+ ['exclude', '_(cocoa|gtk|linux|mac|posix|skia|win|x)\\.(cc|mm?)$'],
+ ['exclude', '/(gtk|win|x11)_[^/]*\\.cc$'],
+ ],
+ 'conditions': [
+ ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {'sources/': [
+ ['include', '/gtk/'],
+ ['include', '_(gtk|linux|posix|skia|x)\\.cc$'],
+ ['include', '/(gtk|x11)_[^/]*\\.cc$'],
+ ]}],
+ ['OS=="mac"', {'sources/': [
+ ['include', '/cocoa/'],
+ ['include', '_(cocoa|mac|posix)\\.(cc|mm?)$'],
+ ]}, { # else: OS != "mac"
+ 'sources/': [
+ ['exclude', '\\.mm?$'],
+ ],
+ }],
+ ['OS=="win"', {'sources/': [
+ ['include', '_(win)\\.cc$'],
+ ['include', '/win/'],
+ ['include', '/win_[^/]*\\.cc$'],
+ ]}],
+ ['touchui==0', {'sources/': [
+ ['exclude', 'event_x.cc$'],
+ ['exclude', 'native_menu_x.cc$'],
+ ['exclude', 'native_menu_x.h$'],
+ ['exclude', 'touchui/'],
+ ['exclude', '_(touch)\\.cc$'],
+ ]}],
+ ],
+ },
+ 'includes': [
+ 'base/ui_base.gypi',
+ ],
+}
+
+# Local Variables:
+# tab-width:2
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=2 shiftwidth=2: