blob: 2f0245377ed3a52cef725d9f0206d1ac5e843f03 [file] [log] [blame]
// Copyright 2018 The Fuchsia 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:flutter/widgets.dart';
import 'package:lib.widgets/model.dart';
import 'package:lib.widgets/widgets.dart';
import 'package:meta/meta.dart';
import 'overlay_position_model.dart';
export 'package:lib.widgets/model.dart'
show ScopedModel, Model, ScopedModelDescendant;
const RK4SpringDescription _kSimulationDesc =
RK4SpringDescription(tension: 450.0, friction: 50.0);
/// Tracks any ongoing vertical drag that effects the overlay.
class OverlayDragModel extends TickingModel {
/// The overlay position model.
final OverlayPositionModel overlayPositionModel;
final double flingMinPixelsPerSecond;
final double resetDistance;
/// The current vertical drag offset.
double offset = 0.0;
RK4SpringSimulation _resetSimulation;
/// Constructor.
OverlayDragModel({
@required this.overlayPositionModel,
this.flingMinPixelsPerSecond = 100.0,
this.resetDistance = -32.0,
});
/// Wraps [ModelFinder.of] for this [Model]. See [ModelFinder.of] for more
/// details.
static OverlayDragModel of(BuildContext context) =>
ModelFinder<OverlayDragModel>().of(context);
/// Called when a vertical drag starts.
void start() {}
/// Called when a vertical drag updates.
void update({@required double delta}) {
if (delta == 0.0) {
return;
}
offset += delta;
notifyListeners();
}
/// Called when a vertical drag ends.
void end({@required double verticalPixelsPerSecond}) {
/// If offset greater than threshold or velocity is a fling downward, reset.
/// Otherwise fill.
if (overlayPositionModel.value == 0.0) {
if (offset <= resetDistance ||
verticalPixelsPerSecond <= -flingMinPixelsPerSecond) {
overlayPositionModel.show();
}
} else {
if (offset >= -resetDistance ||
verticalPixelsPerSecond >= flingMinPixelsPerSecond) {
overlayPositionModel.hide();
}
}
/// Spring offset to 0.0. Set effectedModel to null when 0.0.
_resetSimulation = RK4SpringSimulation(
initValue: offset,
desc: _kSimulationDesc,
)..target = 0.0;
startTicking();
}
@override
bool handleTick(double elapsedSeconds) {
if (_resetSimulation == null) {
return false;
}
if (!_resetSimulation.isDone) {
_resetSimulation.elapseTime(elapsedSeconds);
}
if (!_resetSimulation.isDone) {
offset = _resetSimulation.value;
return true;
}
_resetSimulation = null;
offset = 0.0;
return false;
}
}