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 '../fn.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 double _scrollOffset = 0.0; | |
27 double get scrollOffset => _scrollOffset; | |
28 | |
29 ScrollBehavior _scrollBehavior; | |
30 ScrollBehavior createScrollBehavior(); | |
31 ScrollBehavior get scrollBehavior { | |
32 if (_scrollBehavior == null) | |
33 _scrollBehavior = createScrollBehavior(); | |
34 return _scrollBehavior; | |
35 } | |
36 | |
37 Simulation _simulation; | |
38 | |
39 Scrollable({Object key}) : super(key: key) { | |
40 onDidUnmount(_stopSimulation); | |
41 } | |
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 _stopSimulation() { | |
104 if (_simulation == null) | |
105 return; | |
106 _simulation.cancel(); | |
107 _simulation = null; | |
108 } | |
109 | |
110 void _startSimulation(Particle particle) { | |
111 _stopSimulation(); | |
112 _simulation = scrollBehavior.release(particle); | |
113 if (_simulation == null) | |
114 return; | |
115 _simulation.onTick.listen((_) => scrollTo(particle.position)); | |
116 } | |
117 | |
118 Particle _createParticle([double velocity = 0.0]) { | |
119 return new Particle(position: _scrollOffset, velocity: velocity); | |
120 } | |
121 | |
122 void _handlePointerDown(_) { | |
123 _stopSimulation(); | |
124 } | |
125 | |
126 void _handlePointerUpOrCancel(_) { | |
127 if (_simulation == null) | |
128 _startSimulation(_createParticle()); | |
129 } | |
130 | |
131 void _handleScrollUpdate(sky.GestureEvent event) { | |
132 scrollBy(-event.dy); | |
133 } | |
134 | |
135 void _handleFlingStart(sky.GestureEvent event) { | |
136 _startSimulation(_createParticle(_velocityForFlingGesture(event))); | |
137 } | |
138 | |
139 void _handleFlingCancel(sky.GestureEvent event) { | |
140 _startSimulation(_createParticle()); | |
141 } | |
142 | |
143 void _handleWheel(sky.WheelEvent event) { | |
144 scrollBy(-event.offsetY); | |
145 } | |
146 } | |
OLD | NEW |