diff --git a/README.md b/README.md index 8e50741..907e16f 100644 --- a/README.md +++ b/README.md @@ -213,9 +213,16 @@ There are a bunch of signals to listen on each object... taken from AS3, and JS. - onMouseOver - onMouseOut - onMouseScroll +- onLongPress(Duration duration,double distance) They all emit a `MouseInputData` with all the needed info inside, like stage coordinates, or translated local coordinates, which "mouse" button is pressed, etc. +Specially on event `onLongPress`, the handler register function differcent others, it’s includes two params for configure the event, one of `Duration duration`, it’s mean keep press how long for trigg the event, another is `distance`. + +Why need `distance` ? + +Beacuse of human can not keep static on screen, so, we are always trigged event `MouseMove`, but event `LongPress` will be cancelled automaticlly other event happed. It’s also mean when I pressed screen and other event happed before `duration`, So, it’s NOT LONG PRESS. + --- ### Demos. diff --git a/lib/src/core/scene_painter.dart b/lib/src/core/scene_painter.dart index 1dbe1be..7370b45 100644 --- a/lib/src/core/scene_painter.dart +++ b/lib/src/core/scene_painter.dart @@ -41,6 +41,7 @@ class ScenePainter with EventDispatcherMixin { /// Runs on the first "render". bool _isReady = false; + bool get isReady => _isReady; /// Automatically manage the `tick()` and `render()` requests. diff --git a/lib/src/display/display_object.dart b/lib/src/display/display_object.dart index f0bfbaf..eedfca7 100644 --- a/lib/src/display/display_object.dart +++ b/lib/src/display/display_object.dart @@ -1,6 +1,8 @@ +import 'dart:async'; import 'dart:ui' as ui; import 'package:flutter/foundation.dart'; import 'package:flutter/painting.dart' as painting; +import 'package:graphx/src/events/events.dart'; import '../../graphx.dart'; abstract class GDisplayObject @@ -13,7 +15,7 @@ abstract class GDisplayObject static GDisplayObject $currentDrag; static GRect $currentDragBounds; GPoint _dragCenterOffset; - + MouseInputData _lastMouseInput; /// Lets the user drag the specified sprite. /// The sprite remains draggable until explicitly stopped through a call to /// the Sprite.stopDrag() method, or until another sprite is made draggable. @@ -75,6 +77,7 @@ abstract class GDisplayObject bool $debugBounds = false; bool mouseUseShape = false; + Timer _longPressTimer; List $filters; @@ -138,6 +141,15 @@ abstract class GDisplayObject $onMouseWheel?.dispatch(mouseInput); break; case MouseInputType.down: + if(_longPressTimer != null) { + _longPressTimer.cancel(); + } + if($onLongPress != null) { + _longPressTimer = Timer(Duration(milliseconds: + $onLongPress.configure[EventSignalConfKey.LongPressDuration]), () { + $onLongPress.dispatch(mouseInput); + }); + } $mouseDownObj = object; $onMouseDown?.dispatch(mouseInput); break; @@ -146,14 +158,27 @@ abstract class GDisplayObject // $onRightMouseDown?.dispatch(mouseInput); // break; case MouseInputType.move: + if(_lastMouseInput != null) { + // ignore: lines_longer_than_80_chars + if((_lastMouseInput.localX - input.localX).abs() > + // ignore: lines_longer_than_80_chars + $onLongPress.configure[EventSignalConfKey.LongPressShakingDistance] || + (_lastMouseInput.localY - input.localY).abs() > + // ignore: lines_longer_than_80_chars + $onLongPress.configure[EventSignalConfKey.LongPressShakingDistance] + ) { + _longPressTimer?.cancel(); + } + } $onMouseMove?.dispatch(mouseInput); break; case MouseInputType.up: + _longPressTimer?.cancel(); + if ($mouseDownObj == object && ($onMouseClick != null || $onMouseDoubleClick != null)) { var mouseClickInput = input.clone(this, object, MouseInputType.up); $onMouseClick?.dispatch(mouseClickInput); - if ($lastClickTime > 0 && input.time - $lastClickTime < MouseInputData.doubleClickTime) { $onMouseDoubleClick?.dispatch(mouseClickInput); @@ -166,6 +191,7 @@ abstract class GDisplayObject $onMouseUp?.dispatch(mouseInput); break; case MouseInputType.over: + _longPressTimer?.cancel(); $mouseOverObj = object; if (useCursor && GMouse.isShowing()) { GMouse.setClickCursor(); @@ -173,6 +199,7 @@ abstract class GDisplayObject $onMouseOver?.dispatch(mouseInput); break; case MouseInputType.out: + _longPressTimer?.cancel(); $mouseOverObj = null; if (useCursor && GMouse.isShowing()) { GMouse.cursor = null; @@ -184,6 +211,7 @@ abstract class GDisplayObject } } $parent?.$dispatchMouseCallback(type, object, input); + _lastMouseInput = input.clone(this, object, type); } /// todo: add caching to local bounds (Rect). diff --git a/lib/src/display/stage.dart b/lib/src/display/stage.dart index 7d2797f..cf78d18 100644 --- a/lib/src/display/stage.dart +++ b/lib/src/display/stage.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:ui' as ui; import '../../graphx.dart'; @@ -40,6 +41,7 @@ class Stage extends GDisplayObjectContainer ui.Paint _backgroundPaint; DisplayBoundsDebugger _boundsDebugger; + /// Shortcut to access the owner [SceneController]. SceneController get controller => scene.core; diff --git a/lib/src/events/mixins.dart b/lib/src/events/mixins.dart index d5c5753..94a59fc 100644 --- a/lib/src/events/mixins.dart +++ b/lib/src/events/mixins.dart @@ -125,6 +125,7 @@ mixin MouseSignalsMixin { EventSignal $onMouseOut; EventSignal $onMouseOver; EventSignal $onMouseWheel; + EventSignal $onLongPress; EventSignal get onMouseClick => $onMouseClick ??= EventSignal(); EventSignal get onMouseDoubleClick => @@ -136,6 +137,13 @@ mixin MouseSignalsMixin { EventSignal get onMouseOver => $onMouseOver ??= EventSignal(); EventSignal get onMouseOut => $onMouseOut ??= EventSignal(); EventSignal get onMouseScroll => $onMouseWheel ??= EventSignal(); + //EventSignal get onLongPress => $onLongPress ??= EventSignal(); + + EventSignal onLongPress([Duration duration = + const Duration(milliseconds: 600),double distance = 1]) { + $onLongPress = EventSignal.longPress(duration,distance); + return $onLongPress; + } void $disposePointerSignals() { $onRightMouseDown?.removeAll(); @@ -156,6 +164,8 @@ mixin MouseSignalsMixin { $onMouseOut = null; $onMouseWheel?.removeAll(); $onMouseWheel = null; + $onLongPress?.removeAll(); + $onLongPress = null; } } diff --git a/lib/src/events/signal.dart b/lib/src/events/signal.dart index 44c726f..8fa1083 100644 --- a/lib/src/events/signal.dart +++ b/lib/src/events/signal.dart @@ -64,7 +64,20 @@ class Signal { } } +enum EventSignalConfKey { + LongPressDuration, + LongPressShakingDistance, +} + class EventSignal { + Map configure = {}; + EventSignal(); + factory EventSignal.longPress(Duration duration,double distance) { + var signal = EventSignal(); + signal.configure[EventSignalConfKey.LongPressDuration] = duration; + signal.configure[EventSignalConfKey.LongPressShakingDistance] = distance; + return signal; + } void call(EventSignalCallback callback) { add(callback); } diff --git a/lib/src/render/graphics.dart b/lib/src/render/graphics.dart index a1a71a4..a6fadce 100644 --- a/lib/src/render/graphics.dart +++ b/lib/src/render/graphics.dart @@ -700,7 +700,6 @@ class Graphics with RenderUtilMixin implements GxRenderable { } _constrainAlpha(); if (!_isVisible) return; - // trace("en", _drawingQueue.length); for (var graph in _drawingQueue) { if (graph.hasPicture) { diff --git a/pubspec.lock b/pubspec.lock index b2b92c7..02abaed 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,63 +5,63 @@ packages: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.5.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" charcode: dependency: transitive description: name: charcode - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.15.0" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.1" effective_dart: dependency: "direct dev" description: name: effective_dart - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.1" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" flutter: @@ -78,49 +78,49 @@ packages: dependency: "direct main" description: name: http - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "0.13.1" + version: "0.13.3" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.0.0" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.12.10" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.8.0" pedantic: dependency: "direct dev" description: name: pedantic - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.11.0" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.0" sky_engine: @@ -132,63 +132,63 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.8.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.19" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" xml: dependency: "direct main" description: name: xml - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.5.1" sdks: