您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

503 行
16 KiB

using System;
using RSG;
using UIWidgets.animation;
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 del) {
this._del = del;
}
public ScrollActivityDelegate del {
get { return this._del; }
}
ScrollActivityDelegate _del;
public void updateDelegate(ScrollActivityDelegate value) {
D.assert(this._del != value);
this._del = 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._del = null;
}
public override string ToString() {
return Diagnostics.describeIdentity(this);
}
}
public class IdleScrollActivity : ScrollActivity {
public IdleScrollActivity(ScrollActivityDelegate del) : base(del) {
}
public override void applyNewDimensions() {
this.del.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 del = null,
VoidCallback onHoldCanceled = null
) : base(del) {
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.del.goBallistic(0.0);
}
public override void dispose() {
if (this.onHoldCanceled != null)
this.onHoldCanceled();
base.dispose();
}
}
public class ScrollDragController : Drag {
public ScrollDragController(
ScrollActivityDelegate del = null,
DragStartDetails details = null,
VoidCallback onDragCanceled = null,
double? carriedVelocity = null,
double? motionStartDistanceThreshold = null
) {
D.assert(del != null);
D.assert(details != null);
D.assert(
motionStartDistanceThreshold == null || motionStartDistanceThreshold > 0.0,
"motionStartDistanceThreshold must be a positive number or null"
);
this._del = del;
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 del {
get { return this._del; }
}
ScrollActivityDelegate _del;
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.del.axisDirection); }
}
public void updateDelegate(ScrollActivityDelegate value) {
D.assert(this._del != value);
this._del = 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.del.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.del.goBallistic(velocity);
}
public void cancel() {
this.del.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 del,
ScrollDragController controller
) : base(del) {
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 as DragEndDetails
).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);
}
}
public class BallisticScrollActivity : ScrollActivity {
public BallisticScrollActivity(
ScrollActivityDelegate del,
Simulation simulation,
TickerProvider vsync
) : base(del) {
this._controller = AnimationController.unbounded(
debugLabel: this.GetType().ToString(),
vsync: vsync
);
this._controller.addListener(this._tick);
this._controller.animateWith(simulation).Then(() => this._end());
}
public override double velocity {
get { return this._controller.velocity; }
}
readonly AnimationController _controller;
public override void resetActivity() {
this.del.goBallistic(this.velocity);
}
public override void applyNewDimensions() {
this.del.goBallistic(this.velocity);
}
void _tick() {
if (!this.applyMoveTo(this._controller.value)) {
this.del.goIdle();
}
}
protected bool applyMoveTo(double value) {
return this.del.setPixels(value) == 0.0;
}
void _end() {
if (this.del != null) {
this.del.goBallistic(0.0);
}
}
public override void dispatchOverscrollNotification(
ScrollMetrics metrics, BuildContext context, double overscroll) {
new OverscrollNotification(metrics: metrics, context: context, overscroll: overscroll,
velocity: this.velocity).dispatch(context);
}
public override bool shouldIgnorePointer {
get { return true; }
}
public override bool isScrolling {
get { return true; }
}
public override void dispose() {
this._controller.dispose();
base.dispose();
}
public override string ToString() {
return string.Format("{0}({1})", Diagnostics.describeIdentity(this), this._controller);
}
}
public class DrivenScrollActivity : ScrollActivity {
public DrivenScrollActivity(
ScrollActivityDelegate del,
double from,
double to,
TimeSpan duration,
Curve curve,
TickerProvider vsync
) : base(del) {
D.assert(duration > TimeSpan.Zero);
D.assert(curve != null);
this._completer = new Promise();
this._controller = AnimationController.unbounded(
value: from,
debugLabel: this.GetType().ToString(),
vsync: vsync
);
this._controller.addListener(this._tick);
this._controller.animateTo(to, duration: duration, curve: curve)
.Then(() => this._end());
}
readonly Promise _completer;
readonly AnimationController _controller;
public IPromise done {
get { return this._completer; }
}
public override double velocity {
get { return this._controller.velocity; }
}
void _tick() {
if (this.del.setPixels(this._controller.value) != 0.0) {
this.del.goIdle();
}
}
void _end() {
if (this.del != null) {
this.del.goBallistic(this.velocity);
}
}
public override void dispatchOverscrollNotification(
ScrollMetrics metrics, BuildContext context, double overscroll) {
new OverscrollNotification(metrics: metrics, context: context, overscroll: overscroll,
velocity: this.velocity).dispatch(context);
}
public override bool shouldIgnorePointer {
get { return true; }
}
public override bool isScrolling {
get { return true; }
}
public override void dispose() {
this._completer.Resolve();
this._controller.dispose();
base.dispose();
}
public override string ToString() {
return string.Format("{0}({1})", Diagnostics.describeIdentity(this), this._controller);
}
}
}