Rafael Weinstein e8318f65a7 Change how events are handled in Effen
This patch removes the mutable API to event handling (Nodes no longer have a events object with which to add listeners).

Instead, a new (non-Render) Node is introduced: EventTarget. This node represents a location in the Effen tree which can handle events as they bubble.

Note that this also changes the implementation to use event delegation (one set of listeners at the sky.document level) rather than direct listeners on leaf nodes.

R=abarth@chromium.org

Review URL: https://codereview.chromium.org/1019633004
2015-03-15 12:33:30 -07:00

107 lines
2.7 KiB
Dart

// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../animation/generators.dart';
import '../animation/mechanics.dart';
import '../animation/scroll_behavior.dart';
import '../fn.dart';
import '../theme/view-configuration.dart' as config;
import 'dart:math' as math;
import 'dart:sky' as sky;
const double _kMillisecondsPerSecond = 1000.0;
double _velocityForFlingGesture(sky.GestureEvent event) {
return math.max(-config.kMaxFlingVelocity, math.min(config.kMaxFlingVelocity,
-event.velocityY)) / _kMillisecondsPerSecond;
}
abstract class Scrollable extends Component {
ScrollBehavior scrollBehavior;
double get scrollOffset => _scrollOffset;
double _scrollOffset = 0.0;
Simulation _simulation;
Scrollable({Object key, this.scrollBehavior}) : super(key: key);
Node buildContent();
Node build() {
return new EventTarget(
buildContent(),
onPointerDown: _handlePointerDown,
onPointerUp: _handlePointerUpOrCancel,
onPointerCancel: _handlePointerUpOrCancel,
onGestureFlingStart: _handleFlingStart,
onGestureFlingCancel: _handleFlingCancel,
onGestureScrollUpdate: _handleScrollUpdate,
onWheel: _handleWheel
);
}
void didUnmount() {
super.didUnmount();
_stopSimulation();
}
bool scrollBy(double scrollDelta) {
var newScrollOffset = scrollBehavior.applyCurve(_scrollOffset, scrollDelta);
if (newScrollOffset == _scrollOffset)
return false;
setState(() {
_scrollOffset = newScrollOffset;
});
return true;
}
void _stopSimulation() {
if (_simulation == null)
return;
_simulation.cancel();
_simulation = null;
}
void _startSimulation(Particle particle) {
_stopSimulation();
_simulation = scrollBehavior.release(particle);
if (_simulation == null)
return;
_simulation.onTick.listen((_) {
setState(() {
_scrollOffset = particle.position;
});
});
}
Particle _createParticle([double velocity = 0.0]) {
return new Particle(position: _scrollOffset, velocity: velocity);
}
void _handlePointerDown(_) {
_stopSimulation();
}
void _handlePointerUpOrCancel(_) {
if (_simulation == null)
_startSimulation(_createParticle());
}
void _handleScrollUpdate(sky.GestureEvent event) {
scrollBy(-event.dy);
}
void _handleFlingStart(sky.GestureEvent event) {
_startSimulation(_createParticle(_velocityForFlingGesture(event)));
}
void _handleFlingCancel(sky.GestureEvent event) {
_startSimulation(_createParticle());
}
void _handleWheel(sky.WheelEvent event) {
scrollBy(-event.offsetY);
}
}