Commit 29d1d2ee authored by Adam Barth's avatar Adam Barth

Add more dartdoc to animation.dart

After the refactoring of the animation library, we were missing some
dartdoc.
parent df8c9714
......@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// The Flutter animation engine.
/// The Flutter animation system.
///
/// See [https://flutter.io/animations/] for an overview.
///
/// This library depends only on core Dart libraries and the `newton` package.
library animation;
......
......@@ -30,15 +30,32 @@ enum AnimationStatus {
typedef void AnimationStatusListener(AnimationStatus status);
/// An animation with a value of type T
///
/// An animation consists of a value (of type T) together with a status. The
/// status indicates whether the animation is conceptually running from
/// beginning to end or from the end back to the beginning, although the actual
/// value of the animation might not change monotonically (e.g., if the
/// animation uses a curve that bounces).
///
/// Animations also let other objects listen for changes to either their value
/// or their status. These callbacks are called during the "animation" phase of
/// the pipeline, just prior to rebuilding widgets.
///
/// To create a new animation that you can run forward and backward, consider
/// using [AnimationController].
abstract class Animation<T> {
const Animation();
/// Calls the listener every time the value of the animation changes.
void addListener(VoidCallback listener);
/// Stop calling the listener every time the value of the animation changes.
void removeListener(VoidCallback listener);
/// Calls listener every time the status of the animation changes.
void addStatusListener(AnimationStatusListener listener);
/// Stops calling the listener every time the status of the animation changes.
void removeStatusListener(AnimationStatusListener listener);
......
......@@ -13,8 +13,22 @@ import 'forces.dart';
import 'listener_helpers.dart';
import 'ticker.dart';
/// A controller for an animation.
///
/// An animation controller can drive an animation forward or backward and can
/// set the animation to a particular value. The controller also defines the
/// bounds of the animation and can drive an animation using a physics
/// simulation.
class AnimationController extends Animation<double>
with EagerListenerMixin, LocalAnimationListenersMixin, LocalAnimationStatusListenersMixin {
with EagerListenerMixin, LocalListenersMixin, LocalAnimationStatusListenersMixin {
/// Creates an animation controller.
///
/// * value is the initial value of the animation.
/// * duration is the length of time this animation should last.
/// * debugLabel is a string to help identify this animation during debugging (used by toString).
/// * lowerBound is the smallest value this animation can obtain and the value at which this animation is deemed to be dismissed.
/// * upperBound is the largest value this animation can obtain and the value at which this animation is deemed to be completed.
AnimationController({
double value,
this.duration,
......@@ -22,10 +36,20 @@ class AnimationController extends Animation<double>
this.lowerBound: 0.0,
this.upperBound: 1.0
}) {
assert(upperBound >= lowerBound);
_value = (value ?? lowerBound).clamp(lowerBound, upperBound);
_ticker = new Ticker(_tick);
}
/// Creates an animation controller with no upper or lower bound for its value.
///
/// * value is the initial value of the animation.
/// * duration is the length of time this animation should last.
/// * debugLabel is a string to help identify this animation during debugging (used by toString).
///
/// This constructor is most useful for animations that will be driven using a
/// physics simulation, especially when the physics simulation as no
/// pre-determined bounds.
AnimationController.unbounded({
double value: 0.0,
this.duration,
......@@ -47,7 +71,7 @@ class AnimationController extends Animation<double>
/// identifying animation controller instances in debug output.
final String debugLabel;
/// Returns a [Animated<double>] for this animation controller,
/// Returns an [Animated<double>] for this animation controller,
/// so that a pointer to this object can be passed around without
/// allowing users of that pointer to mutate the AnimationController state.
Animation<double> get view => this;
......@@ -61,9 +85,9 @@ class AnimationController extends Animation<double>
Ticker _ticker;
Simulation _simulation;
/// The progress of this animation along the timeline.
/// The current value of the animation.
///
/// Note: Setting this value stops the current animation.
/// Setting this value stops the current animation.
double get value => _value.clamp(lowerBound, upperBound);
double _value;
void set value(double newValue) {
......@@ -110,6 +134,7 @@ class AnimationController extends Animation<double>
_ticker.stop();
}
/// Stops running this animation.
void dispose() {
stop();
}
......@@ -144,6 +169,7 @@ class AnimationController extends Animation<double>
_lastStatus = currentStatus;
}
/// Drives the animation from its current value to target.
Future animateTo(double target, { Duration duration, Curve curve: Curves.linear }) {
Duration simulationDuration = duration;
if (simulationDuration == null) {
......
......@@ -8,8 +8,8 @@ import 'animation.dart';
import 'curves.dart';
import 'listener_helpers.dart';
class AlwaysCompleteAnimation extends Animation<double> {
const AlwaysCompleteAnimation();
class _AlwaysCompleteAnimation extends Animation<double> {
const _AlwaysCompleteAnimation();
void addListener(VoidCallback listener) { }
void removeListener(VoidCallback listener) { }
......@@ -20,10 +20,15 @@ class AlwaysCompleteAnimation extends Animation<double> {
double get value => 1.0;
}
const AlwaysCompleteAnimation kAlwaysCompleteAnimation = const AlwaysCompleteAnimation();
/// An animation that is always complete.
///
/// Using this constant involves less overhead than building an
/// [AnimationController] with an initial value of 1.0. This is useful when an
/// API expects an animation but you don't actually want to animate anything.
const Animation<double> kAlwaysCompleteAnimation = const _AlwaysCompleteAnimation();
class AlwaysDismissedAnimation extends Animation<double> {
const AlwaysDismissedAnimation();
class _AlwaysDismissedAnimation extends Animation<double> {
const _AlwaysDismissedAnimation();
void addListener(VoidCallback listener) { }
void removeListener(VoidCallback listener) { }
......@@ -34,8 +39,14 @@ class AlwaysDismissedAnimation extends Animation<double> {
double get value => 0.0;
}
const AlwaysDismissedAnimation kAlwaysDismissedAnimation = const AlwaysDismissedAnimation();
/// An animation that is always dismissed.
///
/// Using this constant involves less overhead than building an
/// [AnimationController] with an initial value of 0.0. This is useful when an
/// API expects an animation but you don't actually want to animate anything.
const Animation<double> kAlwaysDismissedAnimation = const _AlwaysDismissedAnimation();
/// An animation that is always stopped at a given value.
class AlwaysStoppedAnimation extends Animation<double> {
const AlwaysStoppedAnimation(this.value);
......@@ -49,8 +60,16 @@ class AlwaysStoppedAnimation extends Animation<double> {
AnimationDirection get direction => AnimationDirection.forward;
}
abstract class ProxyAnimatedMixin {
Animation<double> get parent;
/// Implements most of the [Animation] interface, by deferring its behavior to a
/// given [parent] Animation. To implement an [Animation] that proxies to a
/// parent, this class plus implementing "T get value" is all that is necessary.
abstract class ProxyAnimatedMixin<T> {
/// The animation whose value this animation will proxy.
///
/// This animation must remain the same for the lifetime of this object. If
/// you wish to proxy a different animation at different times, conside using
/// [ProxyAnimation].
Animation<T> get parent;
void addListener(VoidCallback listener) => parent.addListener(listener);
void removeListener(VoidCallback listener) => parent.removeListener(listener);
......@@ -61,8 +80,14 @@ abstract class ProxyAnimatedMixin {
AnimationDirection get direction => parent.direction;
}
/// An animation that is a proxy for another animation.
///
/// A proxy animation is useful because the parent animation can be mutated. For
/// example, one object can create a proxy animation, hand the proxy to another
/// object, and then later change the animation from which the proxy receieves
/// its value.
class ProxyAnimation extends Animation<double>
with LazyListenerMixin, LocalAnimationListenersMixin, LocalAnimationStatusListenersMixin {
with LazyListenerMixin, LocalListenersMixin, LocalAnimationStatusListenersMixin {
ProxyAnimation([Animation<double> animation]) {
_parent = animation;
if (_parent == null) {
......@@ -76,6 +101,10 @@ class ProxyAnimation extends Animation<double>
AnimationDirection _direction;
double _value;
/// The animation whose value this animation will proxy.
///
/// This value is mutable. When mutated, the listeners on the proxy animation
/// will be transparently updated to be listening to the new parent animation.
Animation<double> get parent => _parent;
Animation<double> _parent;
void set parent(Animation<double> value) {
......@@ -121,10 +150,18 @@ class ProxyAnimation extends Animation<double>
double get value => _parent != null ? _parent.value : _value;
}
/// An animation that is the reverse of another animation.
///
/// If the parent animation is running forward from 0.0 to 1.0, this animation
/// is running in reverse from 1.0 to 0.0. Notice that using a ReverseAnimation
/// is different from simply using a [Tween] with a begin of 1.0 and an end of
/// 0.0 because the tween does not change the status or direction of the
/// animation.
class ReverseAnimation extends Animation<double>
with LazyListenerMixin, LocalAnimationStatusListenersMixin {
ReverseAnimation(this.parent);
/// The animation whose value and direction this animation is reversing.
final Animation<double> parent;
void addListener(VoidCallback listener) {
......@@ -169,7 +206,12 @@ class ReverseAnimation extends Animation<double>
}
}
class CurvedAnimation extends Animation<double> with ProxyAnimatedMixin {
/// An animation that applies a curve to another animation.
///
/// [CurvedAnimation] is useful when you wish to apply a [Curve] and you already
/// have the underlying animation object. If you don't yet have an animation and
/// want to apply a [Curve] to a [Tween], consider using [CurveTween].
class CurvedAnimation extends Animation<double> with ProxyAnimatedMixin<double> {
CurvedAnimation({
this.parent,
this.curve: Curves.linear,
......@@ -180,6 +222,7 @@ class CurvedAnimation extends Animation<double> with ProxyAnimatedMixin {
parent.addStatusListener(_handleStatusChanged);
}
/// The animation to which this animation applies a curve.
final Animation<double> parent;
/// The curve to use in the forward direction.
......@@ -240,7 +283,7 @@ enum _TrainHoppingMode { minimize, maximize }
/// removed, it exposes a [dispose()] method. Call this method to shut this
/// object down.
class TrainHoppingAnimation extends Animation<double>
with EagerListenerMixin, LocalAnimationListenersMixin, LocalAnimationStatusListenersMixin {
with EagerListenerMixin, LocalListenersMixin, LocalAnimationStatusListenersMixin {
TrainHoppingAnimation(this._currentTrain, this._nextTrain, { this.onSwitchedTrain }) {
assert(_currentTrain != null);
if (_nextTrain != null) {
......@@ -261,11 +304,13 @@ class TrainHoppingAnimation extends Animation<double>
assert(_mode != null);
}
/// The animation that is current driving this animation.
Animation<double> get currentTrain => _currentTrain;
Animation<double> _currentTrain;
Animation<double> _nextTrain;
_TrainHoppingMode _mode;
/// Called when this animation switches to be driven by a different animation.
VoidCallback onSwitchedTrain;
AnimationStatus _lastStatus;
......@@ -298,6 +343,9 @@ class TrainHoppingAnimation extends Animation<double>
_currentTrain.removeStatusListener(_statusChangeHandler);
_currentTrain.removeListener(_valueChangeHandler);
_currentTrain = _nextTrain;
// TODO(hixie): This should be setting a status listener on the next
// train, not a value listener, and it should pass in _statusChangeHandler,
// not _valueChangeHandler
_nextTrain.addListener(_valueChangeHandler);
_statusChangeHandler(_nextTrain.status);
}
......
......@@ -10,6 +10,7 @@ export 'package:newton/newton.dart' show SpringDescription;
abstract class Force {
const Force();
/// Creates a new physics simulation with the given initial conditions.
Simulation release(double position, double velocity);
}
......
......@@ -11,6 +11,7 @@ abstract class _ListenerMixin {
void didUnregisterListener();
}
/// A mixin that helps listen to another object only when this object has registered listeners.
abstract class LazyListenerMixin implements _ListenerMixin {
int _listenerCounter = 0;
void didRegisterListener() {
......@@ -30,6 +31,8 @@ abstract class LazyListenerMixin implements _ListenerMixin {
bool get isListening => _listenerCounter > 0;
}
/// A mixin that replaces the didRegisterListener/didUnregisterListener contract
/// with a dispose contract.
abstract class EagerListenerMixin implements _ListenerMixin {
void didRegisterListener() { }
void didUnregisterListener() { }
......@@ -38,7 +41,9 @@ abstract class EagerListenerMixin implements _ListenerMixin {
void dispose();
}
abstract class LocalAnimationListenersMixin extends _ListenerMixin {
/// A mixin that implements the addListener/removeListener protocol and notifies
/// all the registered listeners when notifyListeners is invoked.
abstract class LocalListenersMixin extends _ListenerMixin {
final List<VoidCallback> _listeners = <VoidCallback>[];
void addListener(VoidCallback listener) {
didRegisterListener();
......@@ -55,6 +60,9 @@ abstract class LocalAnimationListenersMixin extends _ListenerMixin {
}
}
/// A mixin that implements the addStatusListener/removeStatusListener protocol
/// and notifies all the registered listeners when notifyStatusListeners is
/// invoked.
abstract class LocalAnimationStatusListenersMixin extends _ListenerMixin {
final List<AnimationStatusListener> _statusListeners = <AnimationStatusListener>[];
void addStatusListener(AnimationStatusListener listener) {
......
......@@ -8,21 +8,27 @@ import 'animation.dart';
import 'animations.dart';
import 'curves.dart';
/// An object that can produce a value of type T given an [Animation] as input.
abstract class Animatable<T> {
const Animatable();
/// The current value of this object for the given animation.
T evaluate(Animation<double> animation);
/// Returns a new Animation that is driven by the given animation but that
/// takes on values determined by this object.
Animation<T> animate(Animation<double> parent) {
return new _AnimatedEvaluation<T>(parent, this);
}
/// Returns a new Animatable whose value is determined by first evaluating
/// the given parent and then evaluating this object.
Animatable<T> chain(Animatable<double> parent) {
return new _ChainedEvaluation<T>(parent, this);
}
}
class _AnimatedEvaluation<T> extends Animation<T> with ProxyAnimatedMixin {
class _AnimatedEvaluation<T> extends Animation<T> with ProxyAnimatedMixin<double> {
_AnimatedEvaluation(this.parent, this._evaluatable);
/// The animation from which this value is derived.
......@@ -45,6 +51,7 @@ class _ChainedEvaluation<T> extends Animatable<T> {
}
}
/// A linear interpolation between a beginning and ending value.
class Tween<T extends dynamic> extends Animatable<T> {
Tween({ this.begin, this.end });
......@@ -57,6 +64,7 @@ class Tween<T extends dynamic> extends Animatable<T> {
/// Returns the value this variable has at the given animation clock value.
T lerp(double t) => begin + (end - begin) * t;
/// Returns the interpolated value for the current value of the given animation.
T evaluate(Animation<double> animation) {
if (end == null)
return begin;
......@@ -69,7 +77,7 @@ class Tween<T extends dynamic> extends Animatable<T> {
}
}
/// An animated variable containing a color.
/// An interpolation between two colors.
///
/// This class specializes the interpolation of Tween<Color> to be
/// appropriate for colors.
......@@ -79,7 +87,7 @@ class ColorTween extends Tween<Color> {
Color lerp(double t) => Color.lerp(begin, end, t);
}
/// An animated variable containing a size.
/// An interpolation between two sizes.
///
/// This class specializes the interpolation of Tween<Size> to be
/// appropriate for rectangles.
......@@ -89,7 +97,7 @@ class SizeTween extends Tween<Size> {
Size lerp(double t) => Size.lerp(begin, end, t);
}
/// An animated variable containing a rectangle.
/// An interpolation between two rectangles.
///
/// This class specializes the interpolation of Tween<Rect> to be
/// appropriate for rectangles.
......@@ -99,7 +107,11 @@ class RectTween extends Tween<Rect> {
Rect lerp(double t) => Rect.lerp(begin, end, t);
}
/// An animated variable containing a int.
/// An interpolation between two integers.
///
/// This class specializes the interpolation of Tween<int> to be
/// appropriate for integers by interpolating between the given begin and end
/// values and then rounding the result to the nearest integer.
class IntTween extends Tween<int> {
IntTween({ int begin, int end }) : super(begin: begin, end: end);
......@@ -108,9 +120,15 @@ class IntTween extends Tween<int> {
int lerp(double t) => (begin + (end - begin) * t).round();
}
/// Transforms the value of the given animation by the given curve.
///
/// This class differs from [CurvedAnimation] in that [CurvedAnimation] applies
/// a curve to an existing [Animation] object whereas [CurveTween] can be
/// chained with another [Tween] prior to receiving the underlying [Animation].
class CurveTween extends Animatable<double> {
CurveTween({ this.curve });
/// The curve to use when transforming the value of the animation.
Curve curve;
double evaluate(Animation<double> animation) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment