kg
6 年前
当前提交
c845b230
共有 25 个文件被更改,包括 2338 次插入 和 1 次删除
-
314Assets/UIWidgets/animation/curves.cs
-
18Assets/UIWidgets/scheduler/binding.cs
-
63Assets/UIWidgets/animation/animation.cs
-
3Assets/UIWidgets/animation/animation.cs.meta
-
421Assets/UIWidgets/animation/animation_controller.cs
-
3Assets/UIWidgets/animation/animation_controller.cs.meta
-
272Assets/UIWidgets/animation/animations.cs
-
3Assets/UIWidgets/animation/animations.cs.meta
-
11Assets/UIWidgets/animation/curves.cs.meta
-
2Assets/UIWidgets/animation/listener_helpers.cs
-
3Assets/UIWidgets/animation/listener_helpers.cs.meta
-
245Assets/UIWidgets/animation/listener_helpers.mixin.gen.cs
-
11Assets/UIWidgets/animation/listener_helpers.mixin.gen.cs.meta
-
141Assets/UIWidgets/animation/listener_helpers.mixin.njk
-
3Assets/UIWidgets/animation/listener_helpers.mixin.njk.meta
-
127Assets/UIWidgets/animation/tween.cs
-
3Assets/UIWidgets/animation/tween.cs.meta
-
7Assets/UIWidgets/gestures/drag.cs
-
3Assets/UIWidgets/gestures/drag.cs.meta
-
298Assets/UIWidgets/scheduler/ticker.cs
-
3Assets/UIWidgets/scheduler/ticker.cs.meta
-
361Assets/UIWidgets/widgets/scroll_activity.cs
-
3Assets/UIWidgets/widgets/scroll_activity.cs.meta
-
18Assets/UIWidgets/widgets/scroll_context.cs
-
3Assets/UIWidgets/widgets/scroll_context.cs.meta
|
|||
using System; |
|||
using UIWidgets.foundation; |
|||
using UIWidgets.ui; |
|||
|
|||
public abstract double transform(double t); |
|||
|
|||
public Curve flipped { |
|||
get { return new FlippedCurve(this); } |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return this.GetType().ToString(); |
|||
} |
|||
} |
|||
|
|||
class _Linear : Curve { |
|||
public override double transform(double t) { |
|||
return t; |
|||
} |
|||
} |
|||
|
|||
public class SawTooth : Curve { |
|||
public SawTooth(int count) { |
|||
this.count = count; |
|||
} |
|||
|
|||
public readonly int count; |
|||
|
|||
public override double transform(double t) { |
|||
D.assert(t >= 0.0 && t <= 1.0); |
|||
if (t == 1.0) { |
|||
return 1.0; |
|||
} |
|||
|
|||
t *= this.count; |
|||
return t - (int) t; |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return string.Format("{0}({1})", this.GetType(), this.count); |
|||
} |
|||
} |
|||
|
|||
public class Interval : Curve { |
|||
public Interval(double begin, double end, Curve curve = null) { |
|||
this.begin = begin; |
|||
this.end = end; |
|||
this.curve = curve ?? Curves.linear; |
|||
} |
|||
|
|||
public readonly double begin; |
|||
|
|||
public readonly double end; |
|||
|
|||
public readonly Curve curve; |
|||
|
|||
public override double transform(double t) { |
|||
D.assert(t >= 0.0 && t <= 1.0); |
|||
D.assert(this.begin >= 0.0); |
|||
D.assert(this.begin <= 1.0); |
|||
D.assert(this.end >= 0.0); |
|||
D.assert(this.end <= 1.0); |
|||
D.assert(this.end >= this.begin); |
|||
if (t == 0.0 || t == 1.0) { |
|||
return t; |
|||
} |
|||
|
|||
t = ((t - this.begin) / (this.end - this.begin)).clamp(0.0, 1.0); |
|||
if (t == 0.0 || t == 1.0) { |
|||
return t; |
|||
} |
|||
|
|||
return this.curve.transform(t); |
|||
} |
|||
|
|||
public override string ToString() { |
|||
if (!(this.curve is _Linear)) { |
|||
return string.Format("{0}({1}\u22EF{2}\u27A9{3}", this.GetType(), this.begin, this.end, this.curve); |
|||
} |
|||
|
|||
return string.Format("{0}({1}\u22EF{2})", this.GetType(), this.begin, this.end); |
|||
} |
|||
} |
|||
|
|||
public class Threshold : Curve { |
|||
public Threshold(double threshold) { |
|||
this.threshold = threshold; |
|||
} |
|||
|
|||
public readonly double threshold; |
|||
|
|||
public override double transform(double t) { |
|||
D.assert(t >= 0.0 && t <= 1.0); |
|||
D.assert(this.threshold >= 0.0); |
|||
D.assert(this.threshold <= 1.0); |
|||
if (t == 0.0 || t == 1.0) { |
|||
return t; |
|||
} |
|||
|
|||
return t < this.threshold ? 0.0 : 1.0; |
|||
} |
|||
} |
|||
|
|||
public class Cubic : Curve { |
|||
public Cubic(double a, double b, double c, double d) { |
|||
this.a = a; |
|||
this.b = b; |
|||
this.c = c; |
|||
this.d = d; |
|||
} |
|||
|
|||
public readonly double a; |
|||
|
|||
public readonly double b; |
|||
|
|||
public readonly double c; |
|||
|
|||
public readonly double d; |
|||
|
|||
const double _cubicErrorBound = 0.001; |
|||
|
|||
double _evaluateCubic(double a, double b, double m) { |
|||
return 3 * a * (1 - m) * (1 - m) * m + |
|||
3 * b * (1 - m) * m * m + |
|||
m * m * m; |
|||
} |
|||
|
|||
public override double transform(double t) { |
|||
D.assert(t >= 0.0 && t <= 1.0); |
|||
double start = 0.0; |
|||
double end = 1.0; |
|||
while (true) { |
|||
double midpoint = (start + end) / 2; |
|||
double estimate = this._evaluateCubic(this.a, this.c, midpoint); |
|||
if ((t - estimate).abs() < _cubicErrorBound) { |
|||
return this._evaluateCubic(this.b, this.d, midpoint); |
|||
} |
|||
|
|||
if (estimate < t) { |
|||
start = midpoint; |
|||
} else { |
|||
end = midpoint; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return string.Format("{0}({1:F2}, {2:F2}, {3:F2}, {4:F2})", this.GetType(), this.a, this.b, this.c, this.d); |
|||
} |
|||
} |
|||
|
|||
public class FlippedCurve : Curve { |
|||
public FlippedCurve(Curve curve) { |
|||
D.assert(curve != null); |
|||
this.curve = curve; |
|||
} |
|||
|
|||
public readonly Curve curve; |
|||
|
|||
public override double transform(double t) { |
|||
return 1.0 - this.curve.transform(1.0 - t); |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return string.Format("{0}({1})", this.GetType(), this.curve); |
|||
} |
|||
} |
|||
|
|||
class _DecelerateCurve : Curve { |
|||
internal _DecelerateCurve() { |
|||
} |
|||
|
|||
public override double transform(double t) { |
|||
D.assert(t >= 0.0 && t <= 1.0); |
|||
t = 1.0 - t; |
|||
return 1.0 - t * t; |
|||
} |
|||
} |
|||
|
|||
class _BounceInCurve : Curve { |
|||
internal _BounceInCurve() { |
|||
} |
|||
|
|||
public override double transform(double t) { |
|||
D.assert(t >= 0.0 && t <= 1.0); |
|||
return 1.0 - Curves._bounce(1.0 - t); |
|||
} |
|||
} |
|||
|
|||
class _BounceOutCurve : Curve { |
|||
internal _BounceOutCurve() { |
|||
} |
|||
|
|||
public override double transform(double t) { |
|||
D.assert(t >= 0.0 && t <= 1.0); |
|||
return Curves._bounce(t); |
|||
} |
|||
} |
|||
|
|||
class _BounceInOutCurve : Curve { |
|||
internal _BounceInOutCurve() { |
|||
} |
|||
|
|||
public override double transform(double t) { |
|||
D.assert(t >= 0.0 && t <= 1.0); |
|||
if (t < 0.5) { |
|||
return (1.0 - Curves._bounce(1.0 - t)) * 0.5; |
|||
} else { |
|||
return Curves._bounce(t * 2.0 - 1.0) * 0.5 + 0.5; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public class ElasticInCurve : Curve { |
|||
public ElasticInCurve(double period = 0.4) { |
|||
this.period = period; |
|||
} |
|||
|
|||
public readonly double period; |
|||
|
|||
public override double transform(double t) { |
|||
D.assert(t >= 0.0 && t <= 1.0); |
|||
double s = this.period / 4.0; |
|||
t = t - 1.0; |
|||
return -Math.Pow(2.0, 10.0 * t) * Math.Sin((t - s) * (Math.PI * 2.0) / this.period); |
|||
} |
|||
|
|||
public override String ToString() { |
|||
return string.Format("{0}({1})", this.GetType(), this.period); |
|||
} |
|||
} |
|||
|
|||
public class ElasticOutCurve : Curve { |
|||
public ElasticOutCurve(double period = 0.4) { |
|||
this.period = period; |
|||
} |
|||
|
|||
public readonly double period; |
|||
|
|||
public override double transform(double t) { |
|||
D.assert(t >= 0.0 && t <= 1.0); |
|||
double s = this.period / 4.0; |
|||
return Math.Pow(2.0, -10.0 * t) * Math.Sin((t - s) * (Math.PI * 2.0) / this.period) + 1.0; |
|||
} |
|||
|
|||
public override String ToString() { |
|||
return string.Format("{0}({1})", this.GetType(), this.period); |
|||
} |
|||
} |
|||
|
|||
public class ElasticInOutCurve : Curve { |
|||
public ElasticInOutCurve(double period = 0.4) { |
|||
this.period = period; |
|||
} |
|||
|
|||
public readonly double period; |
|||
|
|||
public override double transform(double t) { |
|||
D.assert(t >= 0.0 && t <= 1.0); |
|||
double s = this.period / 4.0; |
|||
t = 2.0 * t - 1.0; |
|||
if (t < 0.0) { |
|||
return -0.5 * Math.Pow(2.0, 10.0 * t) * Math.Sin((t - s) * (Math.PI * 2.0) / this.period); |
|||
} else { |
|||
return Math.Pow(2.0, -10.0 * t) * Math.Sin((t - s) * (Math.PI * 2.0) / this.period) * 0.5 + 1.0; |
|||
} |
|||
} |
|||
|
|||
public override String ToString() { |
|||
return string.Format("{0}({1})", this.GetType(), this.period); |
|||
} |
|||
} |
|||
|
|||
public static class Curves { |
|||
public static readonly Curve linear = new _Linear(); |
|||
|
|||
public static readonly Curve decelerate = new _DecelerateCurve(); |
|||
|
|||
public static readonly Curve ease = new Cubic(0.25, 0.1, 0.25, 1.0); |
|||
|
|||
public static readonly Curve easeIn = new Cubic(0.42, 0.0, 1.0, 1.0); |
|||
|
|||
public static readonly Curve easeOut = new Cubic(0.0, 0.0, 0.58, 1.0); |
|||
|
|||
public static readonly Curve easeInOut = new Cubic(0.42, 0.0, 0.58, 1.0); |
|||
|
|||
public static readonly Curve fastOutSlowIn = new Cubic(0.4, 0.0, 0.2, 1.0); |
|||
|
|||
public static readonly Curve bounceIn = new _BounceInCurve(); |
|||
|
|||
public static readonly Curve bounceOut = new _BounceOutCurve(); |
|||
|
|||
public static readonly Curve bounceInOut = new _BounceInOutCurve(); |
|||
|
|||
public static readonly Curve elasticIn = new ElasticInCurve(); |
|||
|
|||
public static readonly Curve elasticOut = new ElasticOutCurve(); |
|||
|
|||
public static readonly Curve elasticInOut = new ElasticInOutCurve(); |
|||
|
|||
internal static double _bounce(double t) { |
|||
if (t < 1.0 / 2.75) { |
|||
return 7.5625 * t * t; |
|||
} else if (t < 2 / 2.75) { |
|||
t -= 1.5 / 2.75; |
|||
return 7.5625 * t * t + 0.75; |
|||
} else if (t < 2.5 / 2.75) { |
|||
t -= 2.25 / 2.75; |
|||
return 7.5625 * t * t + 0.9375; |
|||
} |
|||
|
|||
t -= 2.625 / 2.75; |
|||
return 7.5625 * t * t + 0.984375; |
|||
} |
|||
} |
|||
} |
|
|||
using UIWidgets.foundation; |
|||
using UIWidgets.ui; |
|||
|
|||
namespace UIWidgets.animation { |
|||
public enum AnimationStatus { |
|||
dismissed, |
|||
|
|||
forward, |
|||
|
|||
reverse, |
|||
|
|||
completed, |
|||
} |
|||
|
|||
public delegate void AnimationStatusListener(AnimationStatus status); |
|||
|
|||
public abstract class Animation<T> : ValueListenable<T> { |
|||
public abstract void addListener(VoidCallback listener); |
|||
|
|||
public abstract void removeListener(VoidCallback listener); |
|||
|
|||
public abstract void addStatusListener(AnimationStatusListener listener); |
|||
|
|||
public abstract void removeStatusListener(AnimationStatusListener listener); |
|||
|
|||
public abstract AnimationStatus status { get; } |
|||
|
|||
public abstract T value { get; } |
|||
|
|||
public bool isDismissed { |
|||
get { return this.status == AnimationStatus.dismissed; } |
|||
} |
|||
|
|||
public bool isCompleted { |
|||
get { return this.status == AnimationStatus.completed; } |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return string.Format("{0}({1})", Diagnostics.describeIdentity(this), this.toStringDetails()); |
|||
} |
|||
|
|||
public virtual string toStringDetails() { |
|||
string icon = null; |
|||
switch (this.status) { |
|||
case AnimationStatus.forward: |
|||
icon = "\u25B6"; // >
|
|||
break; |
|||
case AnimationStatus.reverse: |
|||
icon = "\u25C0"; // <
|
|||
break; |
|||
case AnimationStatus.completed: |
|||
icon = "\u23ED"; // >>|
|
|||
break; |
|||
case AnimationStatus.dismissed: |
|||
icon = "\u23EE"; // |<<
|
|||
break; |
|||
} |
|||
|
|||
D.assert(icon != null); |
|||
return icon; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: dacb0a58278b41d585c256badb6f6a5c |
|||
timeCreated: 1536727284 |
|
|||
using System; |
|||
using UIWidgets.foundation; |
|||
using UIWidgets.physics; |
|||
using UIWidgets.scheduler; |
|||
using UIWidgets.ui; |
|||
|
|||
namespace UIWidgets.animation { |
|||
enum _AnimationDirection { |
|||
forward, |
|||
reverse, |
|||
} |
|||
|
|||
public class AnimationController : |
|||
AnimationLocalStatusListenersMixinAnimationLocalListenersMixinAnimationEagerListenerMixinAnimationDouble { |
|||
public AnimationController( |
|||
double? value = null, |
|||
TimeSpan? duration = null, |
|||
string debugLabel = null, |
|||
double lowerBound = 0.0, |
|||
double upperBound = 1.0, |
|||
TickerProvider vsync = null |
|||
) { |
|||
D.assert(upperBound >= lowerBound); |
|||
D.assert(vsync != null); |
|||
this._direction = _AnimationDirection.forward; |
|||
|
|||
this.duration = duration; |
|||
this.debugLabel = debugLabel; |
|||
this.lowerBound = lowerBound; |
|||
this.upperBound = upperBound; |
|||
|
|||
this._ticker = vsync.createTicker(this._tick); |
|||
this._internalSetValue(value ?? lowerBound); |
|||
} |
|||
|
|||
private AnimationController( |
|||
double value = 0.0, |
|||
TimeSpan? duration = null, |
|||
string debugLabel = null, |
|||
TickerProvider vsync = null |
|||
) { |
|||
D.assert(vsync != null); |
|||
this.lowerBound = double.NegativeInfinity; |
|||
this.upperBound = double.PositiveInfinity; |
|||
this._direction = _AnimationDirection.forward; |
|||
|
|||
this.duration = duration; |
|||
this.debugLabel = debugLabel; |
|||
|
|||
this._ticker = vsync.createTicker(this._tick); |
|||
this._internalSetValue(value); |
|||
} |
|||
|
|||
public static AnimationController unbounded( |
|||
double value = 0.0, |
|||
TimeSpan? duration = null, |
|||
string debugLabel = null, |
|||
TickerProvider vsync = null |
|||
) { |
|||
return new AnimationController(value, duration, debugLabel, vsync); |
|||
} |
|||
|
|||
public readonly double lowerBound; |
|||
|
|||
public readonly double upperBound; |
|||
|
|||
public readonly string debugLabel; |
|||
|
|||
public Animation<double> view { |
|||
get { return this; } |
|||
} |
|||
|
|||
public TimeSpan? duration; |
|||
|
|||
Ticker _ticker; |
|||
|
|||
public void resync(TickerProvider vsync) { |
|||
Ticker oldTicker = this._ticker; |
|||
this._ticker = vsync.createTicker(_tick); |
|||
this._ticker.absorbTicker(oldTicker); |
|||
} |
|||
|
|||
Simulation _simulation; |
|||
|
|||
public override double value { |
|||
get { return this._value; } |
|||
} |
|||
|
|||
double _value; |
|||
|
|||
public void setValue(double newValue) { |
|||
this.stop(); |
|||
this._internalSetValue(newValue); |
|||
this.notifyListeners(); |
|||
this._checkStatusChanged(); |
|||
} |
|||
|
|||
|
|||
public void reset() { |
|||
this.setValue(this.lowerBound); |
|||
} |
|||
|
|||
public double velocity { |
|||
get { |
|||
if (!this.isAnimating) { |
|||
return 0.0; |
|||
} |
|||
|
|||
return this._simulation.dx((double) this.lastElapsedDuration.Value.Ticks / TimeSpan.TicksPerSecond); |
|||
} |
|||
} |
|||
|
|||
void _internalSetValue(double newValue) { |
|||
this._value = newValue.clamp(this.lowerBound, this.upperBound); |
|||
if (this._value == this.lowerBound) { |
|||
this._status = AnimationStatus.dismissed; |
|||
} else if (this._value == this.upperBound) { |
|||
this._status = AnimationStatus.completed; |
|||
} else { |
|||
this._status = (this._direction == _AnimationDirection.forward) |
|||
? AnimationStatus.forward |
|||
: AnimationStatus.reverse; |
|||
} |
|||
} |
|||
|
|||
TimeSpan? lastElapsedDuration { |
|||
get { return this._lastElapsedDuration; } |
|||
} |
|||
|
|||
TimeSpan? _lastElapsedDuration; |
|||
|
|||
public bool isAnimating { |
|||
get { return this._ticker != null && this._ticker.isActive; } |
|||
} |
|||
|
|||
_AnimationDirection _direction; |
|||
|
|||
public override AnimationStatus status { |
|||
get { return this._status; } |
|||
} |
|||
|
|||
AnimationStatus _status; |
|||
|
|||
public TickerFuture forward(double? from = null) { |
|||
D.assert(() => { |
|||
if (this.duration == null) { |
|||
throw new UIWidgetsError( |
|||
"AnimationController.forward() called with no default Duration.\n" + |
|||
"The \"duration\" property should be set, either in the constructor or later, before " + |
|||
"calling the forward() function." |
|||
); |
|||
} |
|||
|
|||
return true; |
|||
}); |
|||
this._direction = _AnimationDirection.forward; |
|||
if (from != null) { |
|||
this.setValue(from.Value); |
|||
} |
|||
|
|||
return this._animateToInternal(this.upperBound); |
|||
} |
|||
|
|||
public TickerFuture reverse(double? from = null) { |
|||
D.assert(() => { |
|||
if (this.duration == null) { |
|||
throw new UIWidgetsError( |
|||
"AnimationController.reverse() called with no default Duration.\n" + |
|||
"The \"duration\" property should be set, either in the constructor or later, before " + |
|||
"calling the reverse() function." |
|||
); |
|||
} |
|||
|
|||
return true; |
|||
}); |
|||
this._direction = _AnimationDirection.reverse; |
|||
if (from != null) { |
|||
this.setValue(from.Value); |
|||
} |
|||
|
|||
return this._animateToInternal(this.lowerBound); |
|||
} |
|||
|
|||
public TickerFuture animateTo(double target, TimeSpan? duration = null, Curve curve = null) { |
|||
curve = curve ?? Curves.linear; |
|||
|
|||
this._direction = _AnimationDirection.forward; |
|||
return this._animateToInternal(target, duration: duration, curve: curve); |
|||
} |
|||
|
|||
TickerFuture _animateToInternal(double target, TimeSpan? duration = null, Curve curve = null) { |
|||
curve = curve ?? Curves.linear; |
|||
|
|||
TimeSpan? simulationDuration = duration; |
|||
if (simulationDuration == null) { |
|||
D.assert(() => { |
|||
if (this.duration == null) { |
|||
throw new UIWidgetsError( |
|||
"AnimationController.animateTo() called with no explicit Duration and no default Duration.\n" + |
|||
"Either the \"duration\" argument to the animateTo() method should be provided, or the " + |
|||
"\"duration\" property should be set, either in the constructor or later, before " + |
|||
"calling the animateTo() function." |
|||
); |
|||
} |
|||
|
|||
return true; |
|||
}); |
|||
double range = this.upperBound - this.lowerBound; |
|||
double remainingFraction = range.isFinite() ? (target - this._value).abs() / range : 1.0; |
|||
simulationDuration = TimeSpan.FromTicks((long) (this.duration.Value.Ticks * remainingFraction)); |
|||
} else if (target == this.value) { |
|||
simulationDuration = TimeSpan.Zero; |
|||
} |
|||
|
|||
this.stop(); |
|||
|
|||
if (simulationDuration == TimeSpan.Zero) { |
|||
if (this._value != target) { |
|||
this._value = target.clamp(this.lowerBound, this.upperBound); |
|||
this.notifyListeners(); |
|||
} |
|||
|
|||
this._status = (this._direction == _AnimationDirection.forward) |
|||
? AnimationStatus.completed |
|||
: AnimationStatus.dismissed; |
|||
this._checkStatusChanged(); |
|||
return TickerFutureImpl.complete(); |
|||
} |
|||
|
|||
D.assert(simulationDuration > TimeSpan.Zero); |
|||
D.assert(!this.isAnimating); |
|||
return this._startSimulation( |
|||
new _InterpolationSimulation(this._value, target, simulationDuration.Value, curve)); |
|||
} |
|||
|
|||
public TickerFuture repeat(double? min = null, double? max = null, TimeSpan? period = null) { |
|||
min = min ?? this.lowerBound; |
|||
max = max ?? this.upperBound; |
|||
period = period ?? this.duration; |
|||
D.assert(() => { |
|||
if (period == null) { |
|||
throw new UIWidgetsError( |
|||
"AnimationController.repeat() called without an explicit period and with no default Duration.\n" + |
|||
"Either the \"period\" argument to the repeat() method should be provided, or the " + |
|||
"\"duration\" property should be set, either in the constructor or later, before " + |
|||
"calling the repeat() function." |
|||
); |
|||
} |
|||
|
|||
return true; |
|||
}); |
|||
return this.animateWith(new _RepeatingSimulation(min.Value, max.Value, period.Value)); |
|||
} |
|||
|
|||
public TickerFuture fling(double velocity = 1.0) { |
|||
this._direction = velocity < 0.0 ? _AnimationDirection.reverse : _AnimationDirection.forward; |
|||
double target = velocity < 0.0 |
|||
? this.lowerBound - _kFlingTolerance.distance |
|||
: this.upperBound + _kFlingTolerance.distance; |
|||
Simulation simulation = new SpringSimulation(_kFlingSpringDescription, this.value, target, velocity); |
|||
simulation.tolerance = _kFlingTolerance; |
|||
return this.animateWith(simulation); |
|||
} |
|||
|
|||
|
|||
public TickerFuture animateWith(Simulation simulation) { |
|||
this.stop(); |
|||
return this._startSimulation(simulation); |
|||
} |
|||
|
|||
TickerFuture _startSimulation(Simulation simulation) { |
|||
D.assert(simulation != null); |
|||
D.assert(!this.isAnimating); |
|||
this._simulation = simulation; |
|||
this._lastElapsedDuration = TimeSpan.Zero; |
|||
this._value = simulation.x(0.0).clamp(this.lowerBound, this.upperBound); |
|||
var result = this._ticker.start(); |
|||
this._status = (this._direction == _AnimationDirection.forward) |
|||
? AnimationStatus.forward |
|||
: AnimationStatus.reverse; |
|||
this._checkStatusChanged(); |
|||
return result; |
|||
} |
|||
|
|||
public void stop(bool canceled = true) { |
|||
this._simulation = null; |
|||
this._lastElapsedDuration = null; |
|||
this._ticker.stop(canceled: canceled); |
|||
} |
|||
|
|||
public override void dispose() { |
|||
D.assert(() => { |
|||
if (this._ticker == null) { |
|||
throw new UIWidgetsError( |
|||
"AnimationController.dispose() called more than once.\n" + |
|||
"A given " + this.GetType() + " cannot be disposed more than once.\n" + |
|||
"The following " + this.GetType() + " object was disposed multiple times:\n" + |
|||
" " + this); |
|||
} |
|||
|
|||
return true; |
|||
}); |
|||
this._ticker.dispose(); |
|||
this._ticker = null; |
|||
base.dispose(); |
|||
} |
|||
|
|||
AnimationStatus _lastReportedStatus = AnimationStatus.dismissed; |
|||
|
|||
void _checkStatusChanged() { |
|||
AnimationStatus newStatus = this.status; |
|||
if (this._lastReportedStatus != newStatus) { |
|||
this._lastReportedStatus = newStatus; |
|||
this.notifyStatusListeners(newStatus); |
|||
} |
|||
} |
|||
|
|||
void _tick(TimeSpan elapsed) { |
|||
this._lastElapsedDuration = elapsed; |
|||
double elapsedInSeconds = (double) elapsed.Ticks / TimeSpan.TicksPerSecond; |
|||
D.assert(elapsedInSeconds >= 0.0); |
|||
this._value = this._simulation.x(elapsedInSeconds).clamp(this.lowerBound, this.upperBound); |
|||
if (this._simulation.isDone(elapsedInSeconds)) { |
|||
this._status = (this._direction == _AnimationDirection.forward) |
|||
? AnimationStatus.completed |
|||
: AnimationStatus.dismissed; |
|||
this.stop(canceled: false); |
|||
} |
|||
|
|||
this.notifyListeners(); |
|||
this._checkStatusChanged(); |
|||
} |
|||
|
|||
public override string toStringDetails() { |
|||
string paused = this.isAnimating ? "" : "; paused"; |
|||
string ticker = this._ticker == null ? "; DISPOSED" : (this._ticker.muted ? "; silenced" : ""); |
|||
string label = this.debugLabel == null ? "" : "; for " + this.debugLabel; |
|||
string more = string.Format("{0} {1:F3}", base.toStringDetails(), this.value); |
|||
return more + paused + ticker + label; |
|||
} |
|||
|
|||
static readonly SpringDescription _kFlingSpringDescription = SpringDescription.withDampingRatio( |
|||
mass: 1.0, |
|||
stiffness: 500.0, |
|||
ratio: 1.0 |
|||
); |
|||
|
|||
static readonly Tolerance _kFlingTolerance = new Tolerance( |
|||
velocity: double.PositiveInfinity, |
|||
distance: 0.01 |
|||
); |
|||
} |
|||
|
|||
|
|||
class _InterpolationSimulation : Simulation { |
|||
internal _InterpolationSimulation(double _begin, double _end, TimeSpan duration, Curve _curve) { |
|||
this._begin = _begin; |
|||
this._end = _end; |
|||
this._curve = _curve; |
|||
|
|||
D.assert(duration.Ticks > 0); |
|||
this._durationInSeconds = (double) duration.Ticks / TimeSpan.TicksPerSecond; |
|||
} |
|||
|
|||
readonly double _durationInSeconds; |
|||
readonly double _begin; |
|||
readonly double _end; |
|||
readonly Curve _curve; |
|||
|
|||
public override double x(double timeInSeconds) { |
|||
double t = (timeInSeconds / this._durationInSeconds).clamp(0.0, 1.0); |
|||
if (t == 0.0) { |
|||
return this._begin; |
|||
} else if (t == 1.0) { |
|||
return this._end; |
|||
} else { |
|||
return this._begin + (this._end - this._begin) * this._curve.transform(t); |
|||
} |
|||
} |
|||
|
|||
public override double dx(double timeInSeconds) { |
|||
double epsilon = this.tolerance.time; |
|||
return (this.x(timeInSeconds + epsilon) - this.x(timeInSeconds - epsilon)) / (2 * epsilon); |
|||
} |
|||
|
|||
public override bool isDone(double timeInSeconds) { |
|||
return timeInSeconds > this._durationInSeconds; |
|||
} |
|||
} |
|||
|
|||
class _RepeatingSimulation : Simulation { |
|||
internal _RepeatingSimulation(double min, double max, TimeSpan period) { |
|||
this.min = min; |
|||
this.max = max; |
|||
this._periodInSeconds = (double) period.Ticks / TimeSpan.TicksPerSecond; |
|||
D.assert(this._periodInSeconds > 0.0); |
|||
} |
|||
|
|||
readonly double min; |
|||
readonly double max; |
|||
readonly double _periodInSeconds; |
|||
|
|||
public override double x(double timeInSeconds) { |
|||
D.assert(timeInSeconds >= 0.0); |
|||
double t = (timeInSeconds / this._periodInSeconds) % 1.0; |
|||
return this.lerpDouble(this.min, this.max, t); |
|||
} |
|||
|
|||
public override double dx(double timeInSeconds) { |
|||
return (this.max - this.min) / this._periodInSeconds; |
|||
} |
|||
|
|||
public override bool isDone(double timeInSeconds) { |
|||
return false; |
|||
} |
|||
|
|||
private double lerpDouble(double a, double b, double t) { |
|||
return a + (b - a) * t; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f1417c6a32c94895b551503b8ea7a464 |
|||
timeCreated: 1536734209 |
|
|||
using UIWidgets.foundation; |
|||
using UIWidgets.ui; |
|||
|
|||
namespace UIWidgets.animation { |
|||
class _AlwaysCompleteAnimation : Animation<double> { |
|||
internal _AlwaysCompleteAnimation() { |
|||
} |
|||
|
|||
public override void addListener(VoidCallback listener) { |
|||
} |
|||
|
|||
public override void removeListener(VoidCallback listener) { |
|||
} |
|||
|
|||
public override void addStatusListener(AnimationStatusListener listener) { |
|||
} |
|||
|
|||
public override void removeStatusListener(AnimationStatusListener listener) { |
|||
} |
|||
|
|||
public override AnimationStatus status { |
|||
get { return AnimationStatus.completed; } |
|||
} |
|||
|
|||
|
|||
public override double value { |
|||
get { return 1.0; } |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return "kAlwaysCompleteAnimation"; |
|||
} |
|||
} |
|||
|
|||
class _AlwaysDismissedAnimation : Animation<double> { |
|||
internal _AlwaysDismissedAnimation() { |
|||
} |
|||
|
|||
public override void addListener(VoidCallback listener) { |
|||
} |
|||
|
|||
public override void removeListener(VoidCallback listener) { |
|||
} |
|||
|
|||
public override void addStatusListener(AnimationStatusListener listener) { |
|||
} |
|||
|
|||
public override void removeStatusListener(AnimationStatusListener listener) { |
|||
} |
|||
|
|||
public override AnimationStatus status { |
|||
get { return AnimationStatus.dismissed; } |
|||
} |
|||
|
|||
|
|||
public override double value { |
|||
get { return 0.0; } |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return "kAlwaysDismissedAnimation"; |
|||
} |
|||
} |
|||
|
|||
public class AlwaysStoppedAnimation<T> : Animation<T> { |
|||
public AlwaysStoppedAnimation(T value) { |
|||
this._value = value; |
|||
} |
|||
|
|||
public override T value { |
|||
get { return this._value; } |
|||
} |
|||
|
|||
readonly T _value; |
|||
|
|||
public override void addListener(VoidCallback listener) { |
|||
} |
|||
|
|||
public override void removeListener(VoidCallback listener) { |
|||
} |
|||
|
|||
public override void addStatusListener(AnimationStatusListener listener) { |
|||
} |
|||
|
|||
public override void removeStatusListener(AnimationStatusListener listener) { |
|||
} |
|||
|
|||
public override AnimationStatus status { |
|||
get { return AnimationStatus.forward; } |
|||
} |
|||
|
|||
public override string toStringDetails() { |
|||
return string.Format("{0} {1}; paused", base.toStringDetails(), this.value); |
|||
} |
|||
} |
|||
|
|||
public abstract class AnimationWithParentMixin<TParent, T> : Animation<T> { |
|||
public abstract Animation<TParent> parent { get; } |
|||
|
|||
public override void addListener(VoidCallback listener) { |
|||
this.parent.addListener(listener); |
|||
} |
|||
|
|||
public override void removeListener(VoidCallback listener) { |
|||
this.parent.removeListener(listener); |
|||
} |
|||
|
|||
public override void addStatusListener(AnimationStatusListener listener) { |
|||
this.parent.addStatusListener(listener); |
|||
} |
|||
|
|||
public override void removeStatusListener(AnimationStatusListener listener) { |
|||
this.parent.removeStatusListener(listener); |
|||
} |
|||
|
|||
public override AnimationStatus status { |
|||
get { return this.parent.status; } |
|||
} |
|||
} |
|||
|
|||
public abstract class AnimationDouble : Animation<double> { |
|||
} |
|||
|
|||
public class ProxyAnimation : |
|||
AnimationLocalStatusListenersMixinAnimationLocalListenersMixinAnimationLazyListenerMixinAnimationDouble { |
|||
public ProxyAnimation(Animation<double> animation = null) { |
|||
this._parent = animation; |
|||
if (this._parent == null) { |
|||
this._status = AnimationStatus.dismissed; |
|||
this._value = 0.0; |
|||
} |
|||
} |
|||
|
|||
AnimationStatus _status; |
|||
|
|||
double _value; |
|||
|
|||
public Animation<double> parent { |
|||
get { return this._parent; } |
|||
set { |
|||
if (value == this._parent) { |
|||
return; |
|||
} |
|||
|
|||
if (this._parent != null) { |
|||
this._status = this._parent.status; |
|||
this._value = this._parent.value; |
|||
if (this.isListening) { |
|||
this.didStopListening(); |
|||
} |
|||
} |
|||
|
|||
this._parent = value; |
|||
if (this._parent != null) { |
|||
if (this.isListening) { |
|||
this.didStartListening(); |
|||
} |
|||
|
|||
if (this._value != this._parent.value) { |
|||
this.notifyListeners(); |
|||
} |
|||
|
|||
if (this._status != this._parent.status) { |
|||
this.notifyStatusListeners(this._parent.status); |
|||
} |
|||
|
|||
this._status = AnimationStatus.dismissed; |
|||
this._value = 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
Animation<double> _parent; |
|||
|
|||
protected override void didStartListening() { |
|||
if (this._parent != null) { |
|||
this._parent.addListener(this.notifyListeners); |
|||
this._parent.addStatusListener(this.notifyStatusListeners); |
|||
} |
|||
} |
|||
|
|||
protected override void didStopListening() { |
|||
if (this._parent != null) { |
|||
this._parent.removeListener(this.notifyListeners); |
|||
this._parent.removeStatusListener(this.notifyStatusListeners); |
|||
} |
|||
} |
|||
|
|||
public override AnimationStatus status { |
|||
get { return this._parent != null ? this._parent.status : this._status; } |
|||
} |
|||
|
|||
public override double value { |
|||
get { return this._parent != null ? this._parent.value : this._value; } |
|||
} |
|||
|
|||
public override string ToString() { |
|||
if (this.parent == null) { |
|||
return string.Format("{0}(null; {1} {2:F3}", this.GetType(), this.toStringDetails(), this.value); |
|||
} |
|||
|
|||
return string.Format("{0}\u27A9{1}", this.parent, this.GetType()); |
|||
} |
|||
} |
|||
|
|||
|
|||
public class ReverseAnimation : AnimationLocalStatusListenersMixinAnimationLazyListenerMixinAnimationDouble { |
|||
public ReverseAnimation(Animation<double> parent) { |
|||
D.assert(parent != null); |
|||
this._parent = parent; |
|||
} |
|||
|
|||
public Animation<double> parent { |
|||
get { return this._parent; } |
|||
} |
|||
|
|||
readonly Animation<double> _parent; |
|||
|
|||
public override void addListener(VoidCallback listener) { |
|||
this.didRegisterListener(); |
|||
this.parent.addListener(listener); |
|||
} |
|||
|
|||
public override void removeListener(VoidCallback listener) { |
|||
this.parent.removeListener(listener); |
|||
this.didUnregisterListener(); |
|||
} |
|||
|
|||
protected override void didStartListening() { |
|||
this.parent.addStatusListener(this._statusChangeHandler); |
|||
} |
|||
|
|||
protected override void didStopListening() { |
|||
this.parent.removeStatusListener(this._statusChangeHandler); |
|||
} |
|||
|
|||
void _statusChangeHandler(AnimationStatus status) { |
|||
this.notifyStatusListeners(this._reverseStatus(status)); |
|||
} |
|||
|
|||
public override AnimationStatus status { |
|||
get { return this._reverseStatus(this.parent.status); } |
|||
} |
|||
|
|||
public override double value { |
|||
get { return 1.0 - this.parent.value; } |
|||
} |
|||
|
|||
AnimationStatus _reverseStatus(AnimationStatus status) { |
|||
switch (status) { |
|||
case AnimationStatus.forward: return AnimationStatus.reverse; |
|||
case AnimationStatus.reverse: return AnimationStatus.forward; |
|||
case AnimationStatus.completed: return AnimationStatus.dismissed; |
|||
case AnimationStatus.dismissed: return AnimationStatus.completed; |
|||
} |
|||
|
|||
D.assert(false); |
|||
return default(AnimationStatus); |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return this.parent + "\u27AA" + this.GetType(); |
|||
} |
|||
} |
|||
|
|||
public static class Animations { |
|||
|
|||
public static readonly Animation<double> kAlwaysCompleteAnimation = new _AlwaysCompleteAnimation(); |
|||
|
|||
public static readonly Animation<double> kAlwaysDismissedAnimation = new _AlwaysDismissedAnimation(); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6a1fb4f1aff742c98f8e4e27a03e45f2 |
|||
timeCreated: 1536728596 |
|
|||
fileFormatVersion: 2 |
|||
guid: 020ec64cb65c14f6493309339667afee |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace UIWidgets.animation { |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 904fcf341bef44a191cf4674c42334a8 |
|||
timeCreated: 1536731860 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UIWidgets.foundation; |
|||
using UIWidgets.ui; |
|||
|
|||
namespace UIWidgets.animation { |
|||
|
|||
|
|||
public abstract class AnimationLazyListenerMixinAnimationDouble : AnimationDouble { |
|||
int _listenerCounter = 0; |
|||
|
|||
protected void didRegisterListener() { |
|||
D.assert(this._listenerCounter >= 0); |
|||
if (this._listenerCounter == 0) { |
|||
this.didStartListening(); |
|||
} |
|||
|
|||
this._listenerCounter += 1; |
|||
} |
|||
|
|||
protected void didUnregisterListener() { |
|||
D.assert(this._listenerCounter >= 1); |
|||
this._listenerCounter -= 1; |
|||
if (this._listenerCounter == 0) { |
|||
this.didStopListening(); |
|||
} |
|||
} |
|||
|
|||
protected abstract void didStartListening(); |
|||
|
|||
protected abstract void didStopListening(); |
|||
|
|||
public bool isListening { |
|||
get { return this._listenerCounter > 0; } |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
public abstract class AnimationEagerListenerMixinAnimationDouble : AnimationDouble { |
|||
protected void didRegisterListener() { |
|||
} |
|||
|
|||
protected void didUnregisterListener() { |
|||
} |
|||
|
|||
public virtual void dispose() { |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
public abstract class AnimationLocalListenersMixinAnimationLazyListenerMixinAnimationDouble : AnimationLazyListenerMixinAnimationDouble { |
|||
readonly ObserverList<VoidCallback> _listeners = new ObserverList<VoidCallback>(); |
|||
|
|||
public override void addListener(VoidCallback listener) { |
|||
this.didRegisterListener(); |
|||
this._listeners.Add(listener); |
|||
} |
|||
|
|||
public override void removeListener(VoidCallback listener) { |
|||
this._listeners.Remove(listener); |
|||
this.didUnregisterListener(); |
|||
} |
|||
|
|||
public void notifyListeners() { |
|||
var localListeners = new List<VoidCallback>(this._listeners); |
|||
foreach (VoidCallback listener in localListeners) { |
|||
try { |
|||
if (this._listeners.Contains(listener)) { |
|||
listener(); |
|||
} |
|||
} |
|||
catch (Exception exception) { |
|||
UIWidgetsError.reportError(new UIWidgetsErrorDetails( |
|||
exception: exception, |
|||
library: "animation library", |
|||
context: "while notifying listeners for " + this.GetType(), |
|||
informationCollector: information => { |
|||
information.AppendLine("The " + this.GetType() + " notifying listeners was:"); |
|||
information.Append(" " + this); |
|||
} |
|||
)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
public abstract class AnimationLocalListenersMixinAnimationEagerListenerMixinAnimationDouble : AnimationEagerListenerMixinAnimationDouble { |
|||
readonly ObserverList<VoidCallback> _listeners = new ObserverList<VoidCallback>(); |
|||
|
|||
public override void addListener(VoidCallback listener) { |
|||
this.didRegisterListener(); |
|||
this._listeners.Add(listener); |
|||
} |
|||
|
|||
public override void removeListener(VoidCallback listener) { |
|||
this._listeners.Remove(listener); |
|||
this.didUnregisterListener(); |
|||
} |
|||
|
|||
public void notifyListeners() { |
|||
var localListeners = new List<VoidCallback>(this._listeners); |
|||
foreach (VoidCallback listener in localListeners) { |
|||
try { |
|||
if (this._listeners.Contains(listener)) { |
|||
listener(); |
|||
} |
|||
} |
|||
catch (Exception exception) { |
|||
UIWidgetsError.reportError(new UIWidgetsErrorDetails( |
|||
exception: exception, |
|||
library: "animation library", |
|||
context: "while notifying listeners for " + this.GetType(), |
|||
informationCollector: information => { |
|||
information.AppendLine("The " + this.GetType() + " notifying listeners was:"); |
|||
information.Append(" " + this); |
|||
} |
|||
)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
public abstract class AnimationLocalStatusListenersMixinAnimationLocalListenersMixinAnimationLazyListenerMixinAnimationDouble : AnimationLocalListenersMixinAnimationLazyListenerMixinAnimationDouble { |
|||
readonly ObserverList<AnimationStatusListener> _statusListeners = new ObserverList<AnimationStatusListener>(); |
|||
|
|||
public override void addStatusListener(AnimationStatusListener listener) { |
|||
this.didRegisterListener(); |
|||
this._statusListeners.Add(listener); |
|||
} |
|||
|
|||
public override void removeStatusListener(AnimationStatusListener listener) { |
|||
this._statusListeners.Remove(listener); |
|||
this.didUnregisterListener(); |
|||
} |
|||
|
|||
public void notifyStatusListeners(AnimationStatus status) { |
|||
var localListeners = new List<AnimationStatusListener>(this._statusListeners); |
|||
foreach (AnimationStatusListener listener in localListeners) { |
|||
try { |
|||
if (this._statusListeners.Contains(listener)) { |
|||
listener(status); |
|||
} |
|||
} |
|||
catch (Exception exception) { |
|||
UIWidgetsError.reportError(new UIWidgetsErrorDetails( |
|||
exception: exception, |
|||
library: "animation library", |
|||
context: "while notifying status listeners for " + this.GetType(), |
|||
informationCollector: information => { |
|||
information.AppendLine("The " + this.GetType() + " notifying status listeners was:"); |
|||
information.Append(" " + this); |
|||
} |
|||
)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
public abstract class AnimationLocalStatusListenersMixinAnimationLazyListenerMixinAnimationDouble : AnimationLazyListenerMixinAnimationDouble { |
|||
readonly ObserverList<AnimationStatusListener> _statusListeners = new ObserverList<AnimationStatusListener>(); |
|||
|
|||
public override void addStatusListener(AnimationStatusListener listener) { |
|||
this.didRegisterListener(); |
|||
this._statusListeners.Add(listener); |
|||
} |
|||
|
|||
public override void removeStatusListener(AnimationStatusListener listener) { |
|||
this._statusListeners.Remove(listener); |
|||
this.didUnregisterListener(); |
|||
} |
|||
|
|||
public void notifyStatusListeners(AnimationStatus status) { |
|||
var localListeners = new List<AnimationStatusListener>(this._statusListeners); |
|||
foreach (AnimationStatusListener listener in localListeners) { |
|||
try { |
|||
if (this._statusListeners.Contains(listener)) { |
|||
listener(status); |
|||
} |
|||
} |
|||
catch (Exception exception) { |
|||
UIWidgetsError.reportError(new UIWidgetsErrorDetails( |
|||
exception: exception, |
|||
library: "animation library", |
|||
context: "while notifying status listeners for " + this.GetType(), |
|||
informationCollector: information => { |
|||
information.AppendLine("The " + this.GetType() + " notifying status listeners was:"); |
|||
information.Append(" " + this); |
|||
} |
|||
)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
public abstract class AnimationLocalStatusListenersMixinAnimationLocalListenersMixinAnimationEagerListenerMixinAnimationDouble : AnimationLocalListenersMixinAnimationEagerListenerMixinAnimationDouble { |
|||
readonly ObserverList<AnimationStatusListener> _statusListeners = new ObserverList<AnimationStatusListener>(); |
|||
|
|||
public override void addStatusListener(AnimationStatusListener listener) { |
|||
this.didRegisterListener(); |
|||
this._statusListeners.Add(listener); |
|||
} |
|||
|
|||
public override void removeStatusListener(AnimationStatusListener listener) { |
|||
this._statusListeners.Remove(listener); |
|||
this.didUnregisterListener(); |
|||
} |
|||
|
|||
public void notifyStatusListeners(AnimationStatus status) { |
|||
var localListeners = new List<AnimationStatusListener>(this._statusListeners); |
|||
foreach (AnimationStatusListener listener in localListeners) { |
|||
try { |
|||
if (this._statusListeners.Contains(listener)) { |
|||
listener(status); |
|||
} |
|||
} |
|||
catch (Exception exception) { |
|||
UIWidgetsError.reportError(new UIWidgetsErrorDetails( |
|||
exception: exception, |
|||
library: "animation library", |
|||
context: "while notifying status listeners for " + this.GetType(), |
|||
informationCollector: information => { |
|||
information.AppendLine("The " + this.GetType() + " notifying status listeners was:"); |
|||
information.Append(" " + this); |
|||
} |
|||
)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: fc158b938e74644e0ba73d8e95247892 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UIWidgets.foundation; |
|||
using UIWidgets.ui; |
|||
|
|||
namespace UIWidgets.animation { |
|||
{% macro AnimationLazyListenerMixin(with) %} |
|||
public abstract class AnimationLazyListenerMixin{{with}} : {{with}} { |
|||
int _listenerCounter = 0; |
|||
|
|||
protected void didRegisterListener() { |
|||
D.assert(this._listenerCounter >= 0); |
|||
if (this._listenerCounter == 0) { |
|||
this.didStartListening(); |
|||
} |
|||
|
|||
this._listenerCounter += 1; |
|||
} |
|||
|
|||
protected void didUnregisterListener() { |
|||
D.assert(this._listenerCounter >= 1); |
|||
this._listenerCounter -= 1; |
|||
if (this._listenerCounter == 0) { |
|||
this.didStopListening(); |
|||
} |
|||
} |
|||
|
|||
protected abstract void didStartListening(); |
|||
|
|||
protected abstract void didStopListening(); |
|||
|
|||
public bool isListening { |
|||
get { return this._listenerCounter > 0; } |
|||
} |
|||
} |
|||
{% endmacro %} |
|||
|
|||
{{ AnimationLazyListenerMixin('AnimationDouble') }} |
|||
|
|||
{% macro AnimationEagerListenerMixin(with) %} |
|||
public abstract class AnimationEagerListenerMixin{{with}} : {{with}} { |
|||
protected void didRegisterListener() { |
|||
} |
|||
|
|||
protected void didUnregisterListener() { |
|||
} |
|||
|
|||
public virtual void dispose() { |
|||
} |
|||
} |
|||
{% endmacro %} |
|||
|
|||
{{ AnimationEagerListenerMixin('AnimationDouble') }} |
|||
|
|||
{% macro AnimationLocalListenersMixin(with) %} |
|||
public abstract class AnimationLocalListenersMixin{{with}} : {{with}} { |
|||
readonly ObserverList<VoidCallback> _listeners = new ObserverList<VoidCallback>(); |
|||
|
|||
public override void addListener(VoidCallback listener) { |
|||
this.didRegisterListener(); |
|||
this._listeners.Add(listener); |
|||
} |
|||
|
|||
public override void removeListener(VoidCallback listener) { |
|||
this._listeners.Remove(listener); |
|||
this.didUnregisterListener(); |
|||
} |
|||
|
|||
public void notifyListeners() { |
|||
var localListeners = new List<VoidCallback>(this._listeners); |
|||
foreach (VoidCallback listener in localListeners) { |
|||
try { |
|||
if (this._listeners.Contains(listener)) { |
|||
listener(); |
|||
} |
|||
} |
|||
catch (Exception exception) { |
|||
UIWidgetsError.reportError(new UIWidgetsErrorDetails( |
|||
exception: exception, |
|||
library: "animation library", |
|||
context: "while notifying listeners for " + this.GetType(), |
|||
informationCollector: information => { |
|||
information.AppendLine("The " + this.GetType() + " notifying listeners was:"); |
|||
information.Append(" " + this); |
|||
} |
|||
)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
{% endmacro %} |
|||
|
|||
{{ AnimationLocalListenersMixin('AnimationLazyListenerMixinAnimationDouble') }} |
|||
|
|||
{{ AnimationLocalListenersMixin('AnimationEagerListenerMixinAnimationDouble') }} |
|||
|
|||
{% macro AnimationLocalStatusListenersMixin(with) %} |
|||
public abstract class AnimationLocalStatusListenersMixin{{with}} : {{with}} { |
|||
readonly ObserverList<AnimationStatusListener> _statusListeners = new ObserverList<AnimationStatusListener>(); |
|||
|
|||
public override void addStatusListener(AnimationStatusListener listener) { |
|||
this.didRegisterListener(); |
|||
this._statusListeners.Add(listener); |
|||
} |
|||
|
|||
public override void removeStatusListener(AnimationStatusListener listener) { |
|||
this._statusListeners.Remove(listener); |
|||
this.didUnregisterListener(); |
|||
} |
|||
|
|||
public void notifyStatusListeners(AnimationStatus status) { |
|||
var localListeners = new List<AnimationStatusListener>(this._statusListeners); |
|||
foreach (AnimationStatusListener listener in localListeners) { |
|||
try { |
|||
if (this._statusListeners.Contains(listener)) { |
|||
listener(status); |
|||
} |
|||
} |
|||
catch (Exception exception) { |
|||
UIWidgetsError.reportError(new UIWidgetsErrorDetails( |
|||
exception: exception, |
|||
library: "animation library", |
|||
context: "while notifying status listeners for " + this.GetType(), |
|||
informationCollector: information => { |
|||
information.AppendLine("The " + this.GetType() + " notifying status listeners was:"); |
|||
information.Append(" " + this); |
|||
} |
|||
)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
{% endmacro %} |
|||
|
|||
{{ AnimationLocalStatusListenersMixin('AnimationLocalListenersMixinAnimationLazyListenerMixinAnimationDouble') }} |
|||
|
|||
{{ AnimationLocalStatusListenersMixin('AnimationLazyListenerMixinAnimationDouble') }} |
|||
|
|||
{{ AnimationLocalStatusListenersMixin('AnimationLocalListenersMixinAnimationEagerListenerMixinAnimationDouble') }} |
|||
|
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 3bad423f035f41e0a5dbb75dc244a06b |
|||
timeCreated: 1536731953 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UIWidgets.foundation; |
|||
|
|||
namespace UIWidgets.animation { |
|||
public abstract class Animatable<T> { |
|||
public abstract T evaluate(Animation<double> animation); |
|||
|
|||
public Animation<T> animate(Animation<double> parent) { |
|||
return new _AnimatedEvaluation<T>(parent, this); |
|||
} |
|||
|
|||
public Animatable<T> chain(Animatable<double> parent) { |
|||
return new _ChainedEvaluation<T>(parent, this); |
|||
} |
|||
} |
|||
|
|||
class _AnimatedEvaluation<T> : AnimationWithParentMixin<double, T> { |
|||
internal _AnimatedEvaluation(Animation<double> _parent, Animatable<T> _evaluatable) { |
|||
this._parent = parent; |
|||
this._evaluatable = _evaluatable; |
|||
} |
|||
|
|||
public override Animation<double> parent { |
|||
get { return this._parent; } |
|||
} |
|||
|
|||
readonly Animation<double> _parent; |
|||
|
|||
readonly Animatable<T> _evaluatable; |
|||
|
|||
public override T value { |
|||
get { return this._evaluatable.evaluate(this.parent); } |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return string.Format("{0}\u27A9{1}\u27A9{2}", this.parent, this._evaluatable, this.value); |
|||
} |
|||
|
|||
public override string toStringDetails() { |
|||
return base.toStringDetails() + " " + this._evaluatable; |
|||
} |
|||
} |
|||
|
|||
|
|||
class _ChainedEvaluation<T> : Animatable<T> { |
|||
internal _ChainedEvaluation(Animatable<double> _parent, Animatable<T> _evaluatable) { |
|||
this._parent = _parent; |
|||
this._evaluatable = _evaluatable; |
|||
} |
|||
|
|||
readonly Animatable<double> _parent; |
|||
|
|||
readonly Animatable<T> _evaluatable; |
|||
|
|||
public override T evaluate(Animation<double> animation) { |
|||
double value = this._parent.evaluate(animation); |
|||
return this._evaluatable.evaluate(new AlwaysStoppedAnimation<double>(value)); |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return string.Format("{0}\u27A9{1}", this._parent, this._evaluatable); |
|||
} |
|||
} |
|||
|
|||
public abstract class Tween<T> : Animatable<T>, IEquatable<Tween<T>> { |
|||
protected Tween(T begin, T end) { |
|||
D.assert(begin != null); |
|||
D.assert(end != null); |
|||
|
|||
this.begin = begin; |
|||
this.end = end; |
|||
} |
|||
|
|||
public readonly T begin; |
|||
|
|||
public readonly T end; |
|||
|
|||
public abstract T lerp(double t); |
|||
|
|||
public override T evaluate(Animation<double> animation) { |
|||
double t = animation.value; |
|||
if (t == 0.0) { |
|||
return this.begin; |
|||
} |
|||
|
|||
if (t == 1.0) { |
|||
return this.end; |
|||
} |
|||
|
|||
return this.lerp(t); |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return string.Format("{0}({1} \u2192 {2})", this.GetType(), this.begin, this.end); |
|||
} |
|||
|
|||
public bool Equals(Tween<T> other) { |
|||
if (object.ReferenceEquals(null, other)) return false; |
|||
if (object.ReferenceEquals(this, other)) return true; |
|||
return EqualityComparer<T>.Default.Equals(this.begin, other.begin) && |
|||
EqualityComparer<T>.Default.Equals(this.end, other.end); |
|||
} |
|||
|
|||
public override bool Equals(object obj) { |
|||
if (object.ReferenceEquals(null, obj)) return false; |
|||
if (object.ReferenceEquals(this, obj)) return true; |
|||
if (obj.GetType() != this.GetType()) return false; |
|||
return this.Equals((Tween<T>) obj); |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
unchecked { |
|||
return (EqualityComparer<T>.Default.GetHashCode(this.begin) * 397) ^ |
|||
EqualityComparer<T>.Default.GetHashCode(this.end); |
|||
} |
|||
} |
|||
|
|||
public static bool operator ==(Tween<T> left, Tween<T> right) { |
|||
return object.Equals(left, right); |
|||
} |
|||
|
|||
public static bool operator !=(Tween<T> left, Tween<T> right) { |
|||
return !object.Equals(left, right); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: ca9370be0eef47e2aa0fcc3a9d4b4c46 |
|||
timeCreated: 1536728064 |
|
|||
namespace UIWidgets.gestures { |
|||
public interface Drag { |
|||
void update(DragUpdateDetails details); |
|||
void end(DragEndDetails details); |
|||
void cancel(); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2f59e34cb2654a9c9b2ce3b7df07ab22 |
|||
timeCreated: 1536665218 |
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Text; |
|||
using RSG; |
|||
using RSG.Promises; |
|||
using UIWidgets.foundation; |
|||
using UIWidgets.ui; |
|||
|
|||
namespace UIWidgets.scheduler { |
|||
public delegate void TickerCallback(TimeSpan elapsed); |
|||
|
|||
public interface TickerProvider { |
|||
Ticker createTicker(TickerCallback onTick); |
|||
} |
|||
|
|||
public class Ticker { |
|||
public Ticker(SchedulerBinding binding, TickerCallback onTick, string debugLabel = null) { |
|||
D.assert(() => { |
|||
this._debugCreationStack = new StackTrace(); |
|||
return true; |
|||
}); |
|||
|
|||
this._binding = binding; |
|||
this._onTick = onTick; |
|||
this.debugLabel = debugLabel; |
|||
} |
|||
|
|||
readonly SchedulerBinding _binding; |
|||
|
|||
TickerFutureImpl _future; |
|||
|
|||
public bool muted { |
|||
get { return this._muted; } |
|||
set { |
|||
if (value == this._muted) { |
|||
return; |
|||
} |
|||
|
|||
this._muted = value; |
|||
if (value) { |
|||
this.unscheduleTick(); |
|||
} else if (this.shouldScheduleTick) { |
|||
this.scheduleTick(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
bool _muted = false; |
|||
|
|||
public bool isTicking { |
|||
get { |
|||
if (this._future == null) { |
|||
return false; |
|||
} |
|||
|
|||
if (this.muted) { |
|||
return false; |
|||
} |
|||
|
|||
if (this._binding.framesEnabled) { |
|||
return true; |
|||
} |
|||
|
|||
if (this._binding.schedulerPhase != SchedulerPhase.idle) { |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
} |
|||
|
|||
public bool isActive { |
|||
get { return this._future != null; } |
|||
} |
|||
|
|||
TimeSpan? _startTime; |
|||
|
|||
public TickerFuture start() { |
|||
D.assert(() => { |
|||
if (this.isActive) { |
|||
throw new UIWidgetsError( |
|||
"A ticker that is already active cannot be started again without first stopping it.\n" + |
|||
"The affected ticker was: " + this.toString(debugIncludeStack: true)); |
|||
} |
|||
|
|||
return true; |
|||
}); |
|||
|
|||
D.assert(this._startTime == null); |
|||
this._future = new TickerFutureImpl(); |
|||
if (this.shouldScheduleTick) { |
|||
this.scheduleTick(); |
|||
} |
|||
|
|||
if (this._binding.schedulerPhase > SchedulerPhase.idle && |
|||
this._binding.schedulerPhase < SchedulerPhase.postFrameCallbacks) { |
|||
this._startTime = this._binding.currentFrameTimeStamp; |
|||
} |
|||
|
|||
return this._future; |
|||
} |
|||
|
|||
public void stop(bool canceled = false) { |
|||
if (!this.isActive) { |
|||
return; |
|||
} |
|||
|
|||
var localFuture = this._future; |
|||
this._future = null; |
|||
this._startTime = null; |
|||
D.assert(!this.isActive); |
|||
|
|||
this.unscheduleTick(); |
|||
if (canceled) { |
|||
localFuture._cancel(this); |
|||
} else { |
|||
localFuture._complete(); |
|||
} |
|||
} |
|||
|
|||
readonly TickerCallback _onTick; |
|||
|
|||
int? _animationId; |
|||
|
|||
protected bool scheduled { |
|||
get { return this._animationId != null; } |
|||
} |
|||
|
|||
protected bool shouldScheduleTick { |
|||
get { return !this.muted && this.isActive && !this.scheduled; } |
|||
} |
|||
|
|||
void _tick(TimeSpan timeStamp) { |
|||
D.assert(this.isTicking); |
|||
D.assert(this.scheduled); |
|||
this._animationId = null; |
|||
|
|||
this._startTime = this._startTime ?? timeStamp; |
|||
|
|||
this._onTick(timeStamp - this._startTime.Value); |
|||
|
|||
if (this.shouldScheduleTick) { |
|||
this.scheduleTick(rescheduling: true); |
|||
} |
|||
} |
|||
|
|||
protected void scheduleTick(bool rescheduling = false) { |
|||
D.assert(!this.scheduled); |
|||
D.assert(this.shouldScheduleTick); |
|||
this._animationId = this._binding.scheduleFrameCallback(this._tick, rescheduling: rescheduling); |
|||
} |
|||
|
|||
protected void unscheduleTick() { |
|||
if (this.scheduled) { |
|||
this._binding.cancelFrameCallbackWithId(this._animationId.Value); |
|||
this._animationId = null; |
|||
} |
|||
|
|||
D.assert(!this.shouldScheduleTick); |
|||
} |
|||
|
|||
public void absorbTicker(Ticker originalTicker) { |
|||
D.assert(!this.isActive); |
|||
D.assert(this._future == null); |
|||
D.assert(this._startTime == null); |
|||
D.assert(this._animationId == null); |
|||
D.assert((originalTicker._future == null) == (originalTicker._startTime == null), |
|||
"Cannot absorb Ticker after it has been disposed."); |
|||
if (originalTicker._future != null) { |
|||
this._future = originalTicker._future; |
|||
this._startTime = originalTicker._startTime; |
|||
if (this.shouldScheduleTick) { |
|||
this.scheduleTick(); |
|||
} |
|||
|
|||
originalTicker._future = null; |
|||
originalTicker.unscheduleTick(); |
|||
} |
|||
|
|||
originalTicker.dispose(); |
|||
} |
|||
|
|||
public virtual void dispose() { |
|||
if (this._future != null) { |
|||
var localFuture = this._future; |
|||
this._future = null; |
|||
D.assert(!this.isActive); |
|||
this.unscheduleTick(); |
|||
localFuture._cancel(this); |
|||
} |
|||
|
|||
D.assert(() => { |
|||
this._startTime = default(TimeSpan); |
|||
return true; |
|||
}); |
|||
} |
|||
|
|||
public readonly String debugLabel; |
|||
|
|||
StackTrace _debugCreationStack; |
|||
|
|||
public override string ToString() { |
|||
return this.toString(debugIncludeStack: false); |
|||
} |
|||
|
|||
public string toString(bool debugIncludeStack = false) { |
|||
var buffer = new StringBuilder(); |
|||
buffer.Append(this.GetType() + "("); |
|||
D.assert(() => { |
|||
buffer.Append(this.debugLabel ?? ""); |
|||
return true; |
|||
}); |
|||
buffer.Append(')'); |
|||
D.assert(() => { |
|||
if (debugIncludeStack) { |
|||
buffer.AppendLine(); |
|||
buffer.AppendLine("The stack trace when the " + this.GetType() + " was actually created was:"); |
|||
UIWidgetsError.defaultStackFilter(this._debugCreationStack.ToString().TrimEnd().Split('\n')) |
|||
.Each(line => buffer.AppendLine(line)); |
|||
} |
|||
|
|||
return true; |
|||
}); |
|||
return buffer.ToString(); |
|||
} |
|||
} |
|||
|
|||
public interface TickerFuture : IPromise { |
|||
void whenCompleteOrCancel(VoidCallback callback); |
|||
|
|||
IPromise orCancel { get; } |
|||
} |
|||
|
|||
public class TickerFutureImpl : Promise, TickerFuture { |
|||
public static TickerFuture complete() { |
|||
var result = new TickerFutureImpl(); |
|||
result._complete(); |
|||
return result; |
|||
} |
|||
|
|||
Promise _secondaryCompleter; |
|||
bool? _completed; |
|||
|
|||
internal void _complete() { |
|||
D.assert(this._completed == null); |
|||
this._completed = true; |
|||
this.Resolve(); |
|||
if (this._secondaryCompleter != null) { |
|||
this._secondaryCompleter.Resolve(); |
|||
} |
|||
} |
|||
|
|||
internal void _cancel(Ticker ticker) { |
|||
D.assert(this._completed == null); |
|||
this._completed = false; |
|||
if (this._secondaryCompleter != null) { |
|||
this._secondaryCompleter.Reject(new TickerCanceled(ticker)); |
|||
} |
|||
} |
|||
|
|||
public void whenCompleteOrCancel(VoidCallback callback) { |
|||
this.orCancel.Then(() => callback(), ex => callback()); |
|||
} |
|||
|
|||
public IPromise orCancel { |
|||
get { |
|||
if (this._secondaryCompleter == null) { |
|||
this._secondaryCompleter = new Promise(); |
|||
if (this._completed != null) { |
|||
if (this._completed.Value) { |
|||
this._secondaryCompleter.Resolve(); |
|||
} else { |
|||
this._secondaryCompleter.Reject(new TickerCanceled()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return this._secondaryCompleter; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public class TickerCanceled : Exception { |
|||
public TickerCanceled(Ticker ticker = null) { |
|||
this.ticker = ticker; |
|||
} |
|||
|
|||
public readonly Ticker ticker; |
|||
|
|||
public override string ToString() { |
|||
if (this.ticker != null) { |
|||
return "This ticker was canceled: " + this.ticker; |
|||
} |
|||
|
|||
return "The ticker was canceled before the \"orCancel\" property was first used."; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 3fb425debd2a441cadf8ad4a4fed3aa1 |
|||
timeCreated: 1536717302 |
|
|||
using System; |
|||
using UIWidgets.foundation; |
|||
using UIWidgets.gestures; |
|||
using UIWidgets.painting; |
|||
using UIWidgets.physics; |
|||
using UIWidgets.scheduler; |
|||
using UIWidgets.ui; |
|||
|
|||
namespace UIWidgets.widgets { |
|||
public interface ScrollActivityDelegate { |
|||
AxisDirection axisDirection { get; } |
|||
|
|||
double setPixels(double pixels); |
|||
|
|||
void applyUserOffset(double delta); |
|||
|
|||
void goIdle(); |
|||
|
|||
void goBallistic(double velocity); |
|||
} |
|||
|
|||
public abstract class ScrollActivity { |
|||
public ScrollActivity(ScrollActivityDelegate @delegate) { |
|||
this._delegate = @delegate; |
|||
} |
|||
|
|||
public ScrollActivityDelegate @delegate { |
|||
get { return this._delegate; } |
|||
} |
|||
|
|||
ScrollActivityDelegate _delegate; |
|||
|
|||
public void updateDelegate(ScrollActivityDelegate value) { |
|||
D.assert(this._delegate != value); |
|||
this._delegate = value; |
|||
} |
|||
|
|||
public virtual void resetActivity() { |
|||
} |
|||
|
|||
public virtual void dispatchScrollStartNotification(ScrollMetrics metrics, BuildContext context) { |
|||
new ScrollStartNotification(metrics: metrics, context: context).dispatch(context); |
|||
} |
|||
|
|||
public virtual void dispatchScrollUpdateNotification(ScrollMetrics metrics, BuildContext context, |
|||
double scrollDelta) { |
|||
new ScrollUpdateNotification(metrics: metrics, context: context, scrollDelta: scrollDelta) |
|||
.dispatch(context); |
|||
} |
|||
|
|||
public virtual void dispatchOverscrollNotification(ScrollMetrics metrics, BuildContext context, |
|||
double overscroll) { |
|||
new OverscrollNotification(metrics: metrics, context: context, overscroll: overscroll).dispatch(context); |
|||
} |
|||
|
|||
public virtual void dispatchScrollEndNotification(ScrollMetrics metrics, BuildContext context) { |
|||
new ScrollEndNotification(metrics: metrics, context: context).dispatch(context); |
|||
} |
|||
|
|||
public virtual void applyNewDimensions() { |
|||
} |
|||
|
|||
public abstract bool shouldIgnorePointer { get; } |
|||
|
|||
public abstract bool isScrolling { get; } |
|||
|
|||
public abstract double velocity { get; } |
|||
|
|||
public virtual void dispose() { |
|||
this._delegate = null; |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return Diagnostics.describeIdentity(this); |
|||
} |
|||
} |
|||
|
|||
public class IdleScrollActivity : ScrollActivity { |
|||
public IdleScrollActivity(ScrollActivityDelegate @delegate) : base(@delegate) { |
|||
} |
|||
|
|||
public override void applyNewDimensions() { |
|||
this.@delegate.goBallistic(0.0); |
|||
} |
|||
|
|||
public override bool shouldIgnorePointer { |
|||
get { return false; } |
|||
} |
|||
|
|||
public override bool isScrolling { |
|||
get { return false; } |
|||
} |
|||
|
|||
public override double velocity { |
|||
get { return 0.0; } |
|||
} |
|||
} |
|||
|
|||
public interface ScrollHoldController { |
|||
void cancel(); |
|||
} |
|||
|
|||
public class HoldScrollActivity : ScrollActivity, ScrollHoldController { |
|||
public HoldScrollActivity( |
|||
ScrollActivityDelegate @delegate = null, |
|||
VoidCallback onHoldCanceled = null |
|||
) : base(@delegate) { |
|||
this.onHoldCanceled = onHoldCanceled; |
|||
} |
|||
|
|||
public readonly VoidCallback onHoldCanceled; |
|||
|
|||
public override bool shouldIgnorePointer { |
|||
get { return false; } |
|||
} |
|||
|
|||
public override bool isScrolling { |
|||
get { return false; } |
|||
} |
|||
|
|||
public override double velocity { |
|||
get { return 0.0; } |
|||
} |
|||
|
|||
public void cancel() { |
|||
this.@delegate.goBallistic(0.0); |
|||
} |
|||
|
|||
public override void dispose() { |
|||
if (this.onHoldCanceled != null) |
|||
this.onHoldCanceled(); |
|||
base.dispose(); |
|||
} |
|||
} |
|||
|
|||
public class ScrollDragController : Drag { |
|||
public ScrollDragController( |
|||
ScrollActivityDelegate @delegate = null, |
|||
DragStartDetails details = null, |
|||
VoidCallback onDragCanceled = null, |
|||
double? carriedVelocity = null, |
|||
double? motionStartDistanceThreshold = null |
|||
) { |
|||
D.assert(@delegate != null); |
|||
D.assert(details != null); |
|||
D.assert( |
|||
motionStartDistanceThreshold == null || motionStartDistanceThreshold > 0.0, |
|||
"motionStartDistanceThreshold must be a positive number or null" |
|||
); |
|||
|
|||
this._delegate = @delegate; |
|||
this._lastDetails = details; |
|||
this._retainMomentum = carriedVelocity != null && carriedVelocity != 0.0; |
|||
this._lastNonStationaryTimestamp = details.sourceTimeStamp; |
|||
this._offsetSinceLastStop = motionStartDistanceThreshold == null ? (double?) null : 0.0; |
|||
|
|||
this.onDragCanceled = onDragCanceled; |
|||
this.carriedVelocity = carriedVelocity; |
|||
this.motionStartDistanceThreshold = motionStartDistanceThreshold; |
|||
} |
|||
|
|||
public ScrollActivityDelegate @delegate { |
|||
get { return this._delegate; } |
|||
} |
|||
|
|||
ScrollActivityDelegate _delegate; |
|||
|
|||
public readonly VoidCallback onDragCanceled; |
|||
|
|||
public readonly double? carriedVelocity; |
|||
|
|||
public readonly double? motionStartDistanceThreshold; |
|||
|
|||
DateTime _lastNonStationaryTimestamp; |
|||
|
|||
bool _retainMomentum; |
|||
|
|||
double? _offsetSinceLastStop; |
|||
|
|||
public static readonly TimeSpan momentumRetainStationaryDurationThreshold = new TimeSpan(0, 0, 0, 0, 20); |
|||
|
|||
public static readonly TimeSpan motionStoppedDurationThreshold = new TimeSpan(0, 0, 0, 0, 50); |
|||
|
|||
const double _bigThresholdBreakDistance = 24.0; |
|||
|
|||
bool _reversed { |
|||
get { return AxisUtils.axisDirectionIsReversed(this.@delegate.axisDirection); } |
|||
} |
|||
|
|||
public void updateDelegate(ScrollActivityDelegate value) { |
|||
D.assert(this._delegate != value); |
|||
this._delegate = value; |
|||
} |
|||
|
|||
void _maybeLoseMomentum(double offset, DateTime? timestamp) { |
|||
if (this._retainMomentum && |
|||
offset == 0.0 && |
|||
(timestamp == null || |
|||
timestamp - this._lastNonStationaryTimestamp > momentumRetainStationaryDurationThreshold)) { |
|||
this._retainMomentum = false; |
|||
} |
|||
} |
|||
|
|||
double _adjustForScrollStartThreshold(double offset, DateTime? timestamp) { |
|||
if (timestamp == null) { |
|||
return offset; |
|||
} |
|||
|
|||
if (offset == 0.0) { |
|||
if (this.motionStartDistanceThreshold != null && |
|||
this._offsetSinceLastStop == null && |
|||
timestamp - this._lastNonStationaryTimestamp > motionStoppedDurationThreshold) { |
|||
this._offsetSinceLastStop = 0.0; |
|||
} |
|||
|
|||
return 0.0; |
|||
} else { |
|||
if (this._offsetSinceLastStop == null) { |
|||
return offset; |
|||
} else { |
|||
this._offsetSinceLastStop += offset; |
|||
if (this._offsetSinceLastStop.Value.abs() > this.motionStartDistanceThreshold) { |
|||
this._offsetSinceLastStop = null; |
|||
if (offset.abs() > _bigThresholdBreakDistance) { |
|||
return offset; |
|||
} else { |
|||
return Math.Min( |
|||
this.motionStartDistanceThreshold.Value / 3.0, |
|||
offset.abs() |
|||
) * offset.sign(); |
|||
} |
|||
} else { |
|||
return 0.0; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
public void update(DragUpdateDetails details) { |
|||
D.assert(details.primaryDelta != null); |
|||
this._lastDetails = details; |
|||
double offset = details.primaryDelta.Value; |
|||
if (offset != 0.0) { |
|||
this._lastNonStationaryTimestamp = details.sourceTimeStamp; |
|||
} |
|||
|
|||
this._maybeLoseMomentum(offset, details.sourceTimeStamp); |
|||
offset = this._adjustForScrollStartThreshold(offset, details.sourceTimeStamp); |
|||
if (offset == 0.0) { |
|||
return; |
|||
} |
|||
|
|||
if (this._reversed) { |
|||
offset = -offset; |
|||
} |
|||
|
|||
this.@delegate.applyUserOffset(offset); |
|||
} |
|||
|
|||
public void end(DragEndDetails details) { |
|||
D.assert(details.primaryVelocity != null); |
|||
double velocity = -details.primaryVelocity.Value; |
|||
if (this._reversed) { |
|||
velocity = -velocity; |
|||
} |
|||
|
|||
this._lastDetails = details; |
|||
|
|||
if (this._retainMomentum && velocity.sign() == this.carriedVelocity.Value.sign()) { |
|||
velocity += this.carriedVelocity.Value; |
|||
} |
|||
|
|||
this.@delegate.goBallistic(velocity); |
|||
} |
|||
|
|||
public void cancel() { |
|||
this.@delegate.goBallistic(0.0); |
|||
} |
|||
|
|||
public virtual void dispose() { |
|||
this._lastDetails = null; |
|||
if (this.onDragCanceled != null) { |
|||
this.onDragCanceled(); |
|||
} |
|||
} |
|||
|
|||
public object lastDetails { |
|||
get { return this._lastDetails; } |
|||
} |
|||
|
|||
object _lastDetails; |
|||
|
|||
public override string ToString() { |
|||
return Diagnostics.describeIdentity(this); |
|||
} |
|||
} |
|||
|
|||
public class DragScrollActivity : ScrollActivity { |
|||
public DragScrollActivity( |
|||
ScrollActivityDelegate @delegate, |
|||
ScrollDragController controller |
|||
) : base(@delegate) { |
|||
this._controller = controller; |
|||
} |
|||
|
|||
ScrollDragController _controller; |
|||
|
|||
public override void dispatchScrollStartNotification(ScrollMetrics metrics, BuildContext context) { |
|||
object lastDetails = this._controller.lastDetails; |
|||
D.assert(lastDetails is DragStartDetails); |
|||
new ScrollStartNotification(metrics: metrics, context: context, dragDetails: (DragStartDetails) lastDetails) |
|||
.dispatch(context); |
|||
} |
|||
|
|||
public override void dispatchScrollUpdateNotification(ScrollMetrics metrics, BuildContext context, |
|||
double scrollDelta) { |
|||
object lastDetails = this._controller.lastDetails; |
|||
D.assert(lastDetails is DragUpdateDetails); |
|||
new ScrollUpdateNotification(metrics: metrics, context: context, scrollDelta: scrollDelta, |
|||
dragDetails: (DragUpdateDetails) lastDetails).dispatch(context); |
|||
} |
|||
|
|||
public override void dispatchOverscrollNotification(ScrollMetrics metrics, BuildContext context, |
|||
double overscroll) { |
|||
object lastDetails = this._controller.lastDetails; |
|||
D.assert(lastDetails is DragUpdateDetails); |
|||
new OverscrollNotification(metrics: metrics, context: context, overscroll: overscroll, |
|||
dragDetails: (DragUpdateDetails) lastDetails).dispatch(context); |
|||
} |
|||
|
|||
public override void dispatchScrollEndNotification(ScrollMetrics metrics, BuildContext context) { |
|||
object lastDetails = this._controller.lastDetails; |
|||
new ScrollEndNotification( |
|||
metrics: metrics, |
|||
context: context, |
|||
dragDetails: lastDetails is DragEndDetails ? (DragEndDetails) lastDetails : null |
|||
).dispatch(context); |
|||
} |
|||
|
|||
public override bool shouldIgnorePointer { |
|||
get { return true; } |
|||
} |
|||
|
|||
public override bool isScrolling { |
|||
get { return true; } |
|||
} |
|||
|
|||
public override double velocity { |
|||
get { return 0.0; } |
|||
} |
|||
|
|||
public override void dispose() { |
|||
this._controller = null; |
|||
base.dispose(); |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return string.Format("{0}({1})", Diagnostics.describeIdentity(this), this._controller); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6f4554d0588f42cfbef25f404ead887a |
|||
timeCreated: 1536667809 |
|
|||
using UIWidgets.painting; |
|||
using UIWidgets.scheduler; |
|||
|
|||
namespace UIWidgets.widgets { |
|||
public interface ScrollContext { |
|||
BuildContext notificationContext { get; } |
|||
|
|||
BuildContext storageContext { get; } |
|||
|
|||
TickerProvider vsync { get; } |
|||
|
|||
AxisDirection axisDirection { get; } |
|||
|
|||
void setIgnorePointer(bool value); |
|||
|
|||
void setCanDrag(bool value); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: ffa0043fe4ac45479630806085f547a9 |
|||
timeCreated: 1536670059 |
撰写
预览
正在加载...
取消
保存
Reference in new issue