MouseEventStream class
MouseEventStream
transforms the bare bone DOM events into a stream
of higher level MouseEvents
.
A MouseEventStream
originates at an DOM Element
which the stream is attached to.
class MouseEventStream { var _controler = new StreamController(); var _subscriptions = []; var _lastMouseDownPos = null; var _lastMouseDownTimestamp = 0; var _mouseDown = false; var _isDragging = false; /// Creates a new stream which isn't attached to any element MouseEventStream(); /// Creates a new stream which is attached to [source]. MouseEventStream.from(Element source) { attach(source); } var _deferredEvent = null; _fireDeferred() { if (_deferredEvent != null) { var e = _deferredEvent; _deferredEvent = null; _controler.sink.add(new MouseEvent(MouseEvent.CLICK, e)); } } void _rawMouseClick(html.MouseEvent evt) { if (_deferredEvent == null) { var ts = new DateTime.now().millisecondsSinceEpoch; if (ts - _lastMouseDownTimestamp > 150) { // a click generated at the end of a drag sequence // mouse down, mouse move, ..., mouse move, mouse up, click // Ignore it. return; } _deferredEvent = evt; new Timer(const Duration(milliseconds: 200), () => _fireDeferred()); } else { _deferredEvent = null; _controler.sink.add(new MouseEvent(MouseEvent.DOUBLE_CLICK,evt)); } } void _rawMouseMove(html.MouseEvent evt){ if (_mouseDown) { if (!_isDragging) { _controler.sink.add(new MouseEvent(MouseEvent.DRAG_START, evt)); } _isDragging = true; } if (_isDragging) { _controler.sink.add(new MouseEvent(MouseEvent.DRAG, evt)); } else { _controler.sink.add(new MouseEvent(MouseEvent.HOVER, evt)); } } void _rawMouseDown(html.MouseEvent evt) { if (evt.button != 0 /* left */) return; evt.preventDefault(); evt.stopPropagation(); _mouseDown = true; _lastMouseDownTimestamp = new DateTime.now().millisecondsSinceEpoch; _lastMouseDownPos = new Point2D(evt.offset.x, evt.offset.y); } void _rawMouseUp(html.MouseEvent evt) { if (evt.button != 0 /* left */) return; evt.preventDefault(); evt.stopPropagation(); if (_isDragging) { _controler.sink.add(new MouseEvent(MouseEvent.DRAG_END, evt)); } _mouseDown = false; _isDragging = false; } get stream => _controler.stream; /// Detach from source and cancel all event subsriptions void detach() { _subscriptions ..forEach((s) => s.cancel()) ..clear(); } /// Attach to [source] and process its raw mouse events. void attach(Element source) { _subscriptions.add(source.onClick.listen(_rawMouseClick)); _subscriptions.add(source.onMouseDown.listen(_rawMouseDown)); _subscriptions.add(source.onMouseUp.listen(_rawMouseUp)); _subscriptions.add(source.onMouseMove.listen(_rawMouseMove)); } }
Constructors
new MouseEventStream() #
Creates a new stream which isn't attached to any element
MouseEventStream();
Properties
final stream #
get stream => _controler.stream;
Methods
void attach(Element source) #
Attach to source and process its raw mouse events.
void attach(Element source) { _subscriptions.add(source.onClick.listen(_rawMouseClick)); _subscriptions.add(source.onMouseDown.listen(_rawMouseDown)); _subscriptions.add(source.onMouseUp.listen(_rawMouseUp)); _subscriptions.add(source.onMouseMove.listen(_rawMouseMove)); }
void detach() #
Detach from source and cancel all event subsriptions
void detach() { _subscriptions ..forEach((s) => s.cancel()) ..clear(); }