Commit 379b6a50 authored by Hixie's avatar Hixie

Replace AnimationTiming with CurvedPerformance

Also, replace places that use the term "create performance" with
"create performance controller".
parent d46aff8a
......@@ -20,16 +20,28 @@ enum AnimationDirection {
/// Animatable objects, by convention, must be cheap to create. This allows them
/// to be used in build functions in Widgets.
abstract class Animatable {
// TODO(ianh): replace mentions of this class with just mentioning AnimatedValue directly
/// Update the variable to a given time in an animation that is running in the given direction
void setProgress(double t, AnimationDirection direction);
String toString();
}
/// Used by [Performance] to convert the timing of a performance to a different timescale.
/// For example, by setting different values for the interval and reverseInterval, a performance
/// can be made to take longer in one direction that the other.
class AnimationTiming {
AnimationTiming({ this.curve, this.reverseCurve });
/// An animated variable with a concrete type.
class AnimatedValue<T extends dynamic> implements Animatable {
AnimatedValue(this.begin, { this.end, this.curve, this.reverseCurve }) {
value = begin;
}
/// The current value of this variable.
T value;
/// The value this variable has at the beginning of the animation.
T begin;
/// The value this variable has at the end of the animation.
T end;
/// Returns the value this variable has at the given animation clock value.
T lerp(double t) => begin + (end - begin) * t;
/// The curve to use in the forward direction
Curve curve;
......@@ -39,6 +51,12 @@ class AnimationTiming {
/// If this field is null, use [curve] in both directions.
Curve reverseCurve;
Curve _getActiveCurve(AnimationDirection direction) {
if (direction == AnimationDirection.forward || reverseCurve == null)
return curve;
return reverseCurve;
}
/// Applies this timing to the given animation clock value in the given direction
double transform(double t, AnimationDirection direction) {
Curve activeCurve = _getActiveCurve(direction);
......@@ -51,32 +69,6 @@ class AnimationTiming {
return activeCurve.transform(t);
}
Curve _getActiveCurve(AnimationDirection direction) {
if (direction == AnimationDirection.forward || reverseCurve == null)
return curve;
return reverseCurve;
}
}
/// An animated variable with a concrete type.
class AnimatedValue<T extends dynamic> extends AnimationTiming implements Animatable {
AnimatedValue(this.begin, { this.end, Curve curve, Curve reverseCurve })
: super(curve: curve, reverseCurve: reverseCurve) {
value = begin;
}
/// The current value of this variable.
T value;
/// The value this variable has at the beginning of the animation.
T begin;
/// The value this variable has at the end of the animation.
T end;
/// Returns the value this variable has at the given animation clock value.
T lerp(double t) => begin + (end - begin) * t;
/// Updates the value of this variable according to the given animation clock
/// value and direction.
void setProgress(double t, AnimationDirection direction) {
......
......@@ -8,9 +8,10 @@ import 'dart:ui' show VoidCallback, lerpDouble;
import 'package:newton/newton.dart';
import 'animated_value.dart';
import 'curves.dart';
import 'forces.dart';
import 'simulation_stepper.dart';
import 'listener_helpers.dart';
import 'simulation_stepper.dart';
/// An interface that is implemented by [Performance] that exposes a
/// read-only view of the underlying performance. This is used by classes that
......@@ -310,6 +311,62 @@ class ProxyPerformance extends PerformanceView
double get progress => _masterPerformance != null ? _masterPerformance.progress : _progress;
}
class CurvedPerformance extends PerformanceView {
CurvedPerformance(this._performance, { this.curve, this.reverseCurve });
final PerformanceView _performance;
/// The curve to use in the forward direction
Curve curve;
/// The curve to use in the reverse direction
///
/// If this field is null, use [curve] in both directions.
Curve reverseCurve;
void addListener(VoidCallback listener) {
_performance.addListener(listener);
}
void removeListener(VoidCallback listener) {
_performance.removeListener(listener);
}
void addStatusListener(PerformanceStatusListener listener) {
_performance.addStatusListener(listener);
}
void removeStatusListener(PerformanceStatusListener listener) {
_performance.removeStatusListener(listener);
}
void updateVariable(Animatable variable) {
variable.setProgress(progress, curveDirection);
}
PerformanceStatus get status => _performance.status;
AnimationDirection get direction => _performance.direction;
AnimationDirection get curveDirection => _performance.curveDirection;
double get progress {
Curve activeCurve;
if (curveDirection == AnimationDirection.forward || reverseCurve == null)
activeCurve = curve;
else
activeCurve = reverseCurve;
if (activeCurve == null)
return _performance.progress;
if (_performance.status == PerformanceStatus.dismissed) {
assert(_performance.progress == 0.0);
assert(activeCurve.transform(0.0).roundToDouble() == 0.0);
return 0.0;
}
if (_performance.status == PerformanceStatus.completed) {
assert(_performance.progress == 1.0);
assert(activeCurve.transform(1.0).roundToDouble() == 1.0);
return 1.0;
}
return activeCurve.transform(_performance.progress);
}
}
/// A timeline that can be reversed and used to update [Animatable]s.
///
/// For example, a performance may handle an animation of a menu opening by
......@@ -344,9 +401,6 @@ class Performance extends PerformanceView
AnimationDirection get curveDirection => _curveDirection;
AnimationDirection _curveDirection;
/// If non-null, animate with this timing instead of a linear timing
AnimationTiming timing;
/// The progress of this performance along the timeline
///
/// Note: Setting this value stops the current animation.
......@@ -357,10 +411,6 @@ class Performance extends PerformanceView
_checkStatusChanged();
}
double get _curvedProgress {
return timing != null ? timing.transform(progress, _curveDirection) : progress;
}
/// Whether this animation is currently animating in either the forward or reverse direction
bool get isAnimating => _timeline.isAnimating;
......@@ -376,7 +426,7 @@ class Performance extends PerformanceView
/// Update the given varaible according to the current progress of this performance
void updateVariable(Animatable variable) {
variable.setProgress(_curvedProgress, _curveDirection);
variable.setProgress(progress, _curveDirection);
}
/// Start running this animation forwards (towards the end)
......@@ -476,7 +526,7 @@ class ValuePerformance<T> extends Performance {
void didTick(double t) {
if (variable != null)
variable.setProgress(_curvedProgress, _curveDirection);
variable.setProgress(progress, _curveDirection);
super.didTick(t);
}
}
......
......@@ -37,7 +37,7 @@ class BottomSheet extends StatelessComponent {
final double childHeight;
final WidgetBuilder builder;
static Performance createPerformance() {
static Performance createPerformanceController() {
return new Performance(
duration: _kBottomSheetDuration,
debugLabel: 'BottomSheet'
......@@ -154,8 +154,8 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
bool get barrierDismissable => true;
Color get barrierColor => Colors.black54;
Performance createPerformance() {
return BottomSheet.createPerformance();
Performance createPerformanceController() {
return BottomSheet.createPerformanceController();
}
Widget buildPage(BuildContext context, PerformanceView performance, PerformanceView forwardPerformance) {
......
......@@ -97,12 +97,11 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
final List<PopupMenuItem<T>> items;
final int elevation;
Performance createPerformance() {
Performance result = super.createPerformance();
AnimationTiming timing = new AnimationTiming();
timing.reverseCurve = new Interval(0.0, _kMenuCloseIntervalEnd);
result.timing = timing;
return result;
PerformanceView createPerformance() {
return new CurvedPerformance(
super.createPerformance(),
reverseCurve: new Interval(0.0, _kMenuCloseIntervalEnd)
);
}
Duration get transitionDuration => _kMenuDuration;
......
......@@ -133,7 +133,7 @@ class ScaffoldState extends State<Scaffold> {
Timer _snackBarTimer;
ScaffoldFeatureController showSnackBar(SnackBar snackbar) {
_snackBarPerformance ??= SnackBar.createPerformance()
_snackBarPerformance ??= SnackBar.createPerformanceController()
..addStatusListener(_handleSnackBarStatusChange);
if (_snackBars.isEmpty) {
assert(_snackBarPerformance.isDismissed);
......@@ -201,7 +201,7 @@ class ScaffoldState extends State<Scaffold> {
}
Completer completer = new Completer();
GlobalKey<_PersistentBottomSheetState> bottomSheetKey = new GlobalKey<_PersistentBottomSheetState>();
Performance performance = BottomSheet.createPerformance()
Performance performance = BottomSheet.createPerformanceController()
..forward();
_PersistentBottomSheet bottomSheet;
LocalHistoryEntry entry = new LocalHistoryEntry(
......
......@@ -116,7 +116,7 @@ class SnackBar extends StatelessComponent {
// API for Scaffold.addSnackBar():
static Performance createPerformance() {
static Performance createPerformanceController() {
return new Performance(
duration: _kSnackBarTransitionDuration,
debugLabel: 'SnackBar'
......
......@@ -92,28 +92,40 @@ class _AnimatedContainerState extends State<AnimatedContainer> {
AnimatedValue<double> _width;
AnimatedValue<double> _height;
Performance _performance;
Performance _performanceController;
PerformanceView _performance;
void initState() {
super.initState();
_performance = new Performance(duration: config.duration, debugLabel: '${config.toStringShort()}')
..timing = new AnimationTiming(curve: config.curve)
..addListener(_updateAllVariables);
_performanceController = new Performance(
duration: config.duration,
debugLabel: '${config.toStringShort()}'
);
_updateCurve();
_configAllVariables();
}
void didUpdateConfig(AnimatedContainer oldConfig) {
_performance
..duration = config.duration
..timing.curve = config.curve;
if (config.curve != oldConfig.curve)
_updateCurve();
_performanceController.duration = config.duration;
if (_configAllVariables()) {
_performance.progress = 0.0;
_performance.play();
_performanceController.progress = 0.0;
_performanceController.play();
}
}
void _updateCurve() {
_performance?.removeListener(_updateAllVariables);
if (config.curve != null)
_performance = new CurvedPerformance(_performanceController, curve: config.curve);
else
_performance = _performanceController;
_performance.addListener(_updateAllVariables);
}
void dispose() {
_performance.stop();
_performanceController.stop();
super.dispose();
}
......
......@@ -81,15 +81,27 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
Duration get transitionDuration;
bool get opaque;
PerformanceView get performance => _performance?.view;
Performance _performance;
Performance createPerformance() {
PerformanceView get performance => _performance;
Performance _performanceController;
PerformanceView _performance;
/// Called to create the Performance object that will drive the transitions to
/// this route from the previous one, and back to the previous route from this
/// one.
Performance createPerformanceController() {
Duration duration = transitionDuration;
assert(duration != null && duration >= Duration.ZERO);
return new Performance(duration: duration, debugLabel: debugLabel);
}
/// Called to create the PerformanceView that exposes the current progress of
/// the transition controlled by the Performance object created by
/// [createPerformanceController()].
PerformanceView createPerformance() {
assert(_performanceController != null);
return _performanceController.view;
}
T _result;
void handleStatusChanged(PerformanceStatus status) {
......@@ -112,26 +124,29 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
}
void install(OverlayEntry insertionPoint) {
_performanceController = createPerformanceController();
assert(_performanceController != null);
_performance = createPerformance();
assert(_performance != null);
super.install(insertionPoint);
}
void didPush() {
_performance.addStatusListener(handleStatusChanged);
_performance.forward();
_performanceController.forward();
super.didPush();
}
void didReplace(Route oldRoute) {
if (oldRoute is TransitionRoute)
_performance.progress = oldRoute._performance.progress;
_performanceController.progress = oldRoute._performanceController.progress;
_performance.addStatusListener(handleStatusChanged);
super.didReplace(oldRoute);
}
bool didPop(T result) {
_result = result;
_performance.reverse();
_performanceController.reverse();
_popCompleter?.complete(_result);
return true;
}
......@@ -142,7 +157,7 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
}
void dispose() {
_performance.stop();
_performanceController.stop();
super.dispose();
}
......@@ -182,7 +197,7 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
bool canTransitionFrom(TransitionRoute nextRoute) => true;
String get debugLabel => '$runtimeType';
String toString() => '$runtimeType(performance: $_performance)';
String toString() => '$runtimeType(performance: $_performanceController)';
}
class LocalHistoryEntry {
......
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