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 |