| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 import '../animation/generators.dart'; | |
| 6 import '../animation/mechanics.dart'; | |
| 7 import '../animation/scroll_behavior.dart'; | |
| 8 import '../fn2.dart'; | |
| 9 import '../theme/view_configuration.dart' as config; | |
| 10 import 'dart:math' as math; | |
| 11 import 'dart:sky' as sky; | |
| 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 | |
| 20 abstract class ScrollClient { | |
| 21 bool ancestorScrolled(Scrollable ancestor); | |
| 22 } | |
| 23 | |
| 24 abstract class Scrollable extends Component { | |
| 25 | |
| 26 Scrollable({Object key}) : super(key: key, stateful: true); | |
| 27 | |
| 28 void syncFields(Scrollable source) { } | |
| 29 | |
| 30 double _scrollOffset = 0.0; | |
| 31 double get scrollOffset => _scrollOffset; | |
| 32 | |
| 33 ScrollBehavior _scrollBehavior; | |
| 34 ScrollBehavior createScrollBehavior(); | |
| 35 ScrollBehavior get scrollBehavior { | |
| 36 if (_scrollBehavior == null) | |
| 37 _scrollBehavior = createScrollBehavior(); | |
| 38 return _scrollBehavior; | |
| 39 } | |
| 40 | |
| 41 Simulation _simulation; | |
| 42 | |
| 43 UINode buildContent(); | |
| 44 | |
| 45 UINode build() { | |
| 46 return new EventListenerNode( | |
| 47 buildContent(), | |
| 48 onPointerDown: _handlePointerDown, | |
| 49 onPointerUp: _handlePointerUpOrCancel, | |
| 50 onPointerCancel: _handlePointerUpOrCancel, | |
| 51 onGestureFlingStart: _handleFlingStart, | |
| 52 onGestureFlingCancel: _handleFlingCancel, | |
| 53 onGestureScrollUpdate: _handleScrollUpdate, | |
| 54 onWheel: _handleWheel | |
| 55 ); | |
| 56 } | |
| 57 | |
| 58 List<ScrollClient> _registeredScrollClients; | |
| 59 | |
| 60 void registerScrollClient(ScrollClient notifiee) { | |
| 61 if (_registeredScrollClients == null) | |
| 62 _registeredScrollClients = new List<ScrollClient>(); | |
| 63 setState(() { | |
| 64 _registeredScrollClients.add(notifiee); | |
| 65 }); | |
| 66 } | |
| 67 | |
| 68 void unregisterScrollClient(ScrollClient notifiee) { | |
| 69 if (_registeredScrollClients == null) | |
| 70 return; | |
| 71 setState(() { | |
| 72 _registeredScrollClients.remove(notifiee); | |
| 73 }); | |
| 74 } | |
| 75 | |
| 76 bool scrollTo(double newScrollOffset) { | |
| 77 if (newScrollOffset == _scrollOffset) | |
| 78 return false; | |
| 79 setState(() { | |
| 80 _scrollOffset = newScrollOffset; | |
| 81 }); | |
| 82 if (_registeredScrollClients != null) { | |
| 83 var newList = null; | |
| 84 _registeredScrollClients.forEach((target) { | |
| 85 if (target.ancestorScrolled(this)) { | |
| 86 if (newList == null) | |
| 87 newList = new List<ScrollClient>(); | |
| 88 newList.add(target); | |
| 89 } | |
| 90 }); | |
| 91 setState(() { | |
| 92 _registeredScrollClients = newList; | |
| 93 }); | |
| 94 } | |
| 95 return true; | |
| 96 } | |
| 97 | |
| 98 bool scrollBy(double scrollDelta) { | |
| 99 var newScrollOffset = scrollBehavior.applyCurve(_scrollOffset, scrollDelta); | |
| 100 return scrollTo(newScrollOffset); | |
| 101 } | |
| 102 | |
| 103 void didUnmount() { | |
| 104 _stopSimulation(); | |
| 105 super.didUnmount(); | |
| 106 } | |
| 107 | |
| 108 void _stopSimulation() { | |
| 109 if (_simulation == null) | |
| 110 return; | |
| 111 _simulation.cancel(); | |
| 112 _simulation = null; | |
| 113 } | |
| 114 | |
| 115 void _startSimulation(Particle particle) { | |
| 116 _stopSimulation(); | |
| 117 _simulation = scrollBehavior.release(particle); | |
| 118 if (_simulation == null) | |
| 119 return; | |
| 120 _simulation.onTick.listen((_) => scrollTo(particle.position)); | |
| 121 } | |
| 122 | |
| 123 Particle _createParticle([double velocity = 0.0]) { | |
| 124 return new Particle(position: _scrollOffset, velocity: velocity); | |
| 125 } | |
| 126 | |
| 127 void _handlePointerDown(_) { | |
| 128 _stopSimulation(); | |
| 129 } | |
| 130 | |
| 131 void _handlePointerUpOrCancel(_) { | |
| 132 if (_simulation == null) | |
| 133 _startSimulation(_createParticle()); | |
| 134 } | |
| 135 | |
| 136 void _handleScrollUpdate(sky.GestureEvent event) { | |
| 137 scrollBy(-event.dy); | |
| 138 } | |
| 139 | |
| 140 void _handleFlingStart(sky.GestureEvent event) { | |
| 141 _startSimulation(_createParticle(_velocityForFlingGesture(event))); | |
| 142 } | |
| 143 | |
| 144 void _handleFlingCancel(sky.GestureEvent event) { | |
| 145 _startSimulation(_createParticle()); | |
| 146 } | |
| 147 | |
| 148 void _handleWheel(sky.WheelEvent event) { | |
| 149 scrollBy(-event.offsetY); | |
| 150 } | |
| 151 | |
| 152 } | |
| OLD | NEW |