| 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 |