| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 import '../animation/curves.dart'; | |
| 6 import '../animation/fling_curve.dart'; | |
| 7 import '../animation/generators.dart'; | 5 import '../animation/generators.dart'; |
| 6 import '../animation/mechanics.dart'; |
| 8 import '../animation/scroll_behavior.dart'; | 7 import '../animation/scroll_behavior.dart'; |
| 9 import '../animation/mechanics.dart'; | |
| 10 import '../fn.dart'; | 8 import '../fn.dart'; |
| 9 import '../theme/view-configuration.dart' as config; |
| 10 import 'dart:math' as math; |
| 11 import 'dart:sky' as sky; | 11 import 'dart:sky' as sky; |
| 12 | 12 |
| 13 const double _kMillisecondsPerSecond = 1000.0; |
| 14 |
| 15 double _velocityForFlingGesture(sky.GestureEvent event) { |
| 16 return math.max(-config.kMaxFlingVelocity, math.min(config.kMaxFlingVelocity, |
| 17 -event.velocityY)) / _kMillisecondsPerSecond; |
| 18 } |
| 19 |
| 13 abstract class Scrollable extends Component { | 20 abstract class Scrollable extends Component { |
| 14 ScrollBehavior scrollBehavior; | 21 ScrollBehavior scrollBehavior; |
| 15 double get scrollOffset => _scrollOffset; | 22 double get scrollOffset => _scrollOffset; |
| 16 | 23 |
| 17 double _scrollOffset = 0.0; | 24 double _scrollOffset = 0.0; |
| 18 FlingCurve _flingCurve; | |
| 19 int _flingAnimationId; | |
| 20 Simulation _simulation; | 25 Simulation _simulation; |
| 21 | 26 |
| 22 Scrollable({Object key, this.scrollBehavior}) : super(key: key) { | 27 Scrollable({Object key, this.scrollBehavior}) : super(key: key) { |
| 23 events.listen('pointerdown', _handlePointerDown); | 28 events.listen('pointerdown', _handlePointerDown); |
| 24 events.listen('pointerup', _handlePointerUpOrCancel); | 29 events.listen('pointerup', _handlePointerUpOrCancel); |
| 25 events.listen('pointercancel', _handlePointerUpOrCancel); | 30 events.listen('pointercancel', _handlePointerUpOrCancel); |
| 26 events.listen('gestureflingstart', _handleFlingStart); | 31 events.listen('gestureflingstart', _handleFlingStart); |
| 27 events.listen('gestureflingcancel', _handleFlingCancel); | 32 events.listen('gestureflingcancel', _handleFlingCancel); |
| 28 events.listen('gesturescrollupdate', _handleScrollUpdate); | 33 events.listen('gesturescrollupdate', _handleScrollUpdate); |
| 29 events.listen('wheel', _handleWheel); | 34 events.listen('wheel', _handleWheel); |
| 30 } | 35 } |
| 31 | 36 |
| 32 void didUnmount() { | 37 void didUnmount() { |
| 33 super.didUnmount(); | 38 super.didUnmount(); |
| 34 _stopFling(); | |
| 35 _stopSimulation(); | 39 _stopSimulation(); |
| 36 } | 40 } |
| 37 | 41 |
| 38 bool scrollBy(double scrollDelta) { | 42 bool scrollBy(double scrollDelta) { |
| 39 var newScrollOffset = scrollBehavior.applyCurve(_scrollOffset, scrollDelta); | 43 var newScrollOffset = scrollBehavior.applyCurve(_scrollOffset, scrollDelta); |
| 40 if (newScrollOffset == _scrollOffset) | 44 if (newScrollOffset == _scrollOffset) |
| 41 return false; | 45 return false; |
| 42 setState(() { | 46 setState(() { |
| 43 _scrollOffset = newScrollOffset; | 47 _scrollOffset = newScrollOffset; |
| 44 }); | 48 }); |
| 45 return true; | 49 return true; |
| 46 } | 50 } |
| 47 | 51 |
| 48 void _scheduleFlingUpdate() { | |
| 49 _flingAnimationId = sky.window.requestAnimationFrame(_updateFling); | |
| 50 } | |
| 51 | |
| 52 void _stopFling() { | |
| 53 if (_flingAnimationId == null) | |
| 54 return; | |
| 55 sky.window.cancelAnimationFrame(_flingAnimationId); | |
| 56 _flingCurve = null; | |
| 57 _flingAnimationId = null; | |
| 58 } | |
| 59 | |
| 60 void _stopSimulation() { | 52 void _stopSimulation() { |
| 61 if (_simulation == null) | 53 if (_simulation == null) |
| 62 return; | 54 return; |
| 63 _simulation.cancel(); | 55 _simulation.cancel(); |
| 64 _simulation = null; | 56 _simulation = null; |
| 65 } | 57 } |
| 66 | 58 |
| 67 void _updateFling(double timeStamp) { | 59 void _startSimulation(Particle particle) { |
| 68 double scrollDelta = _flingCurve.update(timeStamp); | 60 _stopSimulation(); |
| 69 if (!scrollBy(scrollDelta)) | |
| 70 return _settle(); | |
| 71 _scheduleFlingUpdate(); | |
| 72 } | |
| 73 | |
| 74 void _settle() { | |
| 75 _stopFling(); | |
| 76 Particle particle = new Particle(position: scrollOffset); | |
| 77 _simulation = scrollBehavior.release(particle); | 61 _simulation = scrollBehavior.release(particle); |
| 78 if (_simulation == null) | 62 if (_simulation == null) |
| 79 return; | 63 return; |
| 80 _simulation.onTick.listen((_) { | 64 _simulation.onTick.listen((_) { |
| 81 setState(() { | 65 setState(() { |
| 82 _scrollOffset = particle.position; | 66 _scrollOffset = particle.position; |
| 83 }); | 67 }); |
| 84 }); | 68 }); |
| 85 } | 69 } |
| 86 | 70 |
| 71 Particle _createParticle([double velocity = 0.0]) { |
| 72 return new Particle(position: _scrollOffset, velocity: velocity); |
| 73 } |
| 74 |
| 87 void _handlePointerDown(_) { | 75 void _handlePointerDown(_) { |
| 88 _stopFling(); | |
| 89 _stopSimulation(); | 76 _stopSimulation(); |
| 90 } | 77 } |
| 91 | 78 |
| 92 void _handlePointerUpOrCancel(_) { | 79 void _handlePointerUpOrCancel(_) { |
| 93 if (_flingCurve == null) | 80 if (_simulation == null) |
| 94 _settle(); | 81 _startSimulation(_createParticle()); |
| 95 } | 82 } |
| 96 | 83 |
| 97 void _handleScrollUpdate(sky.GestureEvent event) { | 84 void _handleScrollUpdate(sky.GestureEvent event) { |
| 98 scrollBy(-event.dy); | 85 scrollBy(-event.dy); |
| 99 } | 86 } |
| 100 | 87 |
| 101 void _handleFlingStart(sky.GestureEvent event) { | 88 void _handleFlingStart(sky.GestureEvent event) { |
| 102 _stopSimulation(); | 89 _startSimulation(_createParticle(_velocityForFlingGesture(event))); |
| 103 _flingCurve = new FlingCurve(-event.velocityY, event.timeStamp); | |
| 104 _scheduleFlingUpdate(); | |
| 105 } | 90 } |
| 106 | 91 |
| 107 void _handleFlingCancel(sky.GestureEvent event) { | 92 void _handleFlingCancel(sky.GestureEvent event) { |
| 108 _settle(); | 93 _startSimulation(_createParticle()); |
| 109 } | 94 } |
| 110 | 95 |
| 111 void _handleWheel(sky.WheelEvent event) { | 96 void _handleWheel(sky.WheelEvent event) { |
| 112 scrollBy(-event.offsetY); | 97 scrollBy(-event.offsetY); |
| 113 } | 98 } |
| 114 } | 99 } |
| OLD | NEW |