blob: 9164898843f776324f66a1e6bc55c54cb88f9029 [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 '../animation/generators.dart';
import '../animation/mechanics.dart';
import '../animation/scroll_behavior.dart';
import '../fn.dart';
import '../theme/view-configuration.dart' as config;
import 'dart:math' as math;
import 'dart:sky' as sky;
const double _kMillisecondsPerSecond = 1000.0;
double _velocityForFlingGesture(sky.GestureEvent event) {
return math.max(-config.kMaxFlingVelocity, math.min(config.kMaxFlingVelocity,
-event.velocityY)) / _kMillisecondsPerSecond;
}
abstract class Scrollable extends Component {
ScrollBehavior scrollBehavior;
double get scrollOffset => _scrollOffset;
double _scrollOffset = 0.0;
Simulation _simulation;
Scrollable({Object key, this.scrollBehavior}) : super(key: key) {
events.listen('pointerdown', _handlePointerDown);
events.listen('pointerup', _handlePointerUpOrCancel);
events.listen('pointercancel', _handlePointerUpOrCancel);
events.listen('gestureflingstart', _handleFlingStart);
events.listen('gestureflingcancel', _handleFlingCancel);
events.listen('gesturescrollupdate', _handleScrollUpdate);
events.listen('wheel', _handleWheel);
}
void didUnmount() {
super.didUnmount();
_stopSimulation();
}
bool scrollBy(double scrollDelta) {
var newScrollOffset = scrollBehavior.applyCurve(_scrollOffset, scrollDelta);
if (newScrollOffset == _scrollOffset)
return false;
setState(() {
_scrollOffset = newScrollOffset;
});
return true;
}
void _stopSimulation() {
if (_simulation == null)
return;
_simulation.cancel();
_simulation = null;
}
void _startSimulation(Particle particle) {
_stopSimulation();
_simulation = scrollBehavior.release(particle);
if (_simulation == null)
return;
_simulation.onTick.listen((_) {
setState(() {
_scrollOffset = particle.position;
});
});
}
Particle _createParticle([double velocity = 0.0]) {
return new Particle(position: _scrollOffset, velocity: velocity);
}
void _handlePointerDown(_) {
_stopSimulation();
}
void _handlePointerUpOrCancel(_) {
if (_simulation == null)
_startSimulation(_createParticle());
}
void _handleScrollUpdate(sky.GestureEvent event) {
scrollBy(-event.dy);
}
void _handleFlingStart(sky.GestureEvent event) {
_startSimulation(_createParticle(_velocityForFlingGesture(event)));
}
void _handleFlingCancel(sky.GestureEvent event) {
_startSimulation(_createParticle());
}
void _handleWheel(sky.WheelEvent event) {
scrollBy(-event.offsetY);
}
}