blob: f7ea3e027a84fee75fc06c942666c0bc6867bf55 [file] [log] [blame]
// Copyright 2015 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.
import 'package:sky/widgets/animated_component.dart';
import 'package:sky/animation/animation_performance.dart';
import 'package:sky/animation/animated_value.dart';
import 'package:sky/widgets/basic.dart';
import 'package:vector_math/vector_math.dart';
dynamic _maybe(AnimatedValue x) => x != null ? x.value : null;
abstract class TransitionBase extends AnimatedComponent {
TransitionBase({
Key key,
this.child,
this.direction,
this.duration,
this.performance,
this.onDismissed,
this.onCompleted
}) : super(key: key);
Widget child;
Direction direction;
Duration duration;
AnimationPerformance performance;
Function onDismissed;
Function onCompleted;
void initState() {
if (performance == null) {
assert(duration != null);
performance = new AnimationPerformance(duration: duration);
}
if (direction == Direction.reverse)
performance.progress = 1.0;
performance.addStatusListener(_checkStatusChanged);
watch(performance);
_start();
}
void syncFields(TransitionBase source) {
child = source.child;
onCompleted = source.onCompleted;
onDismissed = source.onDismissed;
duration = source.duration;
if (direction != source.direction) {
direction = source.direction;
_start();
}
super.syncFields(source);
}
void _start() {
performance.play(direction);
}
void _checkStatusChanged(AnimationStatus status) {
if (performance.isDismissed) {
if (onDismissed != null)
onDismissed();
} else if (performance.isCompleted) {
if (onCompleted != null)
onCompleted();
}
}
Widget build();
}
class SlideTransition extends TransitionBase {
// TODO(mpcomplete): this constructor is mostly boilerplate, passing values
// to super. Is there a simpler way?
SlideTransition({
Key key,
this.position,
Duration duration,
AnimationPerformance performance,
Direction direction,
Function onDismissed,
Function onCompleted,
Widget child
}) : super(key: key,
duration: duration,
performance: performance,
direction: direction,
onDismissed: onDismissed,
onCompleted: onCompleted,
child: child);
AnimatedValue<Point> position;
void syncFields(SlideTransition updated) {
position = updated.position;
super.syncFields(updated);
}
Widget build() {
position.setProgress(performance.progress);
Matrix4 transform = new Matrix4.identity()
..translate(position.value.x, position.value.y);
return new Transform(transform: transform, child: child);
}
}
class FadeTransition extends TransitionBase {
FadeTransition({
Key key,
this.opacity,
Duration duration,
AnimationPerformance performance,
Direction direction,
Function onDismissed,
Function onCompleted,
Widget child
}) : super(key: key,
duration: duration,
performance: performance,
direction: direction,
onDismissed: onDismissed,
onCompleted: onCompleted,
child: child);
AnimatedValue<double> opacity;
void syncFields(FadeTransition updated) {
opacity = updated.opacity;
super.syncFields(updated);
}
Widget build() {
opacity.setProgress(performance.progress);
return new Opacity(opacity: opacity.value, child: child);
}
}
class ColorTransition extends TransitionBase {
ColorTransition({
Key key,
this.color,
Duration duration,
AnimationPerformance performance,
Direction direction,
Function onDismissed,
Function onCompleted,
Widget child
}) : super(key: key,
duration: duration,
performance: performance,
direction: direction,
onDismissed: onDismissed,
onCompleted: onCompleted,
child: child);
AnimatedColorValue color;
void syncFields(ColorTransition updated) {
color = updated.color;
super.syncFields(updated);
}
Widget build() {
color.setProgress(performance.progress);
return new DecoratedBox(
decoration: new BoxDecoration(backgroundColor: color.value),
child: child
);
}
}
class SquashTransition extends TransitionBase {
SquashTransition({
Key key,
this.width,
this.height,
Duration duration,
AnimationPerformance performance,
Direction direction,
Function onDismissed,
Function onCompleted,
Widget child
}) : super(key: key,
duration: duration,
performance: performance,
direction: direction,
onDismissed: onDismissed,
onCompleted: onCompleted,
child: child);
AnimatedValue<double> width;
AnimatedValue<double> height;
void syncFields(SquashTransition updated) {
width = updated.width;
height = updated.height;
super.syncFields(updated);
}
Widget build() {
if (width != null)
width.setProgress(performance.progress);
if (height != null)
height.setProgress(performance.progress);
return new SizedBox(width: _maybe(width), height: _maybe(height), child: child);
}
}