From 5318fad92367cc81422e8950acb97e9d0990ed27 Mon Sep 17 00:00:00 2001 From: Gabriel Moreyra Date: Thu, 6 Oct 2022 21:54:08 -0300 Subject: [PATCH 1/2] Mouse hover event detection implementation --- example/lib/main.dart | 1 - example/lib/screens/screen1.dart | 22 +++--- example/lib/screens/screen2.dart | 23 +++--- example/lib/screens/screen3.dart | 5 +- example/pubspec.lock | 51 ++++++------- example/test/widget_test.dart | 14 ---- lib/src/canvas_touch_detector.dart | 25 ++++++- lib/src/shape_handler.dart | 25 ++++--- lib/src/shapes/arc.dart | 23 ++++-- lib/src/shapes/clip.dart | 1 - lib/src/shapes/oval.dart | 14 +++- lib/src/shapes/path.dart | 7 +- lib/src/shapes/point.dart | 24 ++++-- lib/src/shapes/rectangle.dart | 17 +++-- lib/src/shapes/rounded_rectangle.dart | 31 +++++--- lib/src/shapes/shape.dart | 6 +- lib/src/shapes/util.dart | 27 ++++++- lib/src/touchy_canvas.dart | 73 +++++++++++++++++-- lib/src/types/types.dart | 3 + pubspec.lock | 49 ++++++------- pubspec.yaml | 2 +- .../hittest_test/defer_to_child.dart | 36 +++++---- test/shape_handler/hittest_test/opaque.dart | 36 +++++---- .../hittest_test/translucent.dart | 36 +++++---- test/shapes/arc.dart | 3 +- test/shapes/line.dart | 2 - test/shapes/point.dart | 2 +- test/shapes/rectangle.dart | 2 - 28 files changed, 346 insertions(+), 214 deletions(-) delete mode 100644 example/test/widget_test.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index 1ad901f..2e31a3f 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -2,7 +2,6 @@ import 'package:example/screens/screen1.dart'; import 'package:example/screens/screen2.dart'; import 'package:example/screens/screen3.dart'; import 'package:flutter/material.dart'; -import 'package:touchable/touchable.dart'; void main() { runApp(MaterialApp( diff --git a/example/lib/screens/screen1.dart b/example/lib/screens/screen1.dart index 7edd9c7..8f0a206 100644 --- a/example/lib/screens/screen1.dart +++ b/example/lib/screens/screen1.dart @@ -74,8 +74,9 @@ class MyPainter extends CustomPainter { void paint(Canvas _canvas, Size size) { TouchyCanvas canvas = TouchyCanvas(context, _canvas); - canvas.drawCircle(Offset(0, 0), 60, Paint()..color = Colors.deepOrange, onTapDown: (_) { - print("orange Circle touched"); + canvas.drawCircle(Offset(0, 0), 60, Paint()..color = Colors.deepOrange, + onTapDown: (_) { + print('orange Circle touched'); setState('orange'); }); @@ -87,7 +88,7 @@ class MyPainter extends CustomPainter { ..strokeWidth = 200 ..style = PaintingStyle.stroke, onTapDown: (detail) { setState('black'); - print("black line touched"); + print('black line touched'); }); canvas.drawOval( @@ -96,7 +97,7 @@ class MyPainter extends CustomPainter { ..color = Colors.deepPurple ..style = PaintingStyle.stroke ..strokeWidth = 70, onTapDown: (_) { - print("purple oval touched"); + print('purple oval touched'); setState('purple'); }); @@ -106,7 +107,7 @@ class MyPainter extends CustomPainter { ..color = Colors.deepOrange ..style = PaintingStyle.stroke ..strokeWidth = 50, onTapDown: (_) { - print("orange rect touched"); + print('orange rect touched'); setState('orange'); }); @@ -115,11 +116,13 @@ class MyPainter extends CustomPainter { ..style = PaintingStyle.stroke ..strokeWidth = 10; canvas.drawCircle(Offset(150, 50), 60, paint, onTapDown: (_) { - print("green Circle touched"); + print('green Circle touched'); setState('green'); }); - canvas.drawCircle(Offset(150, 250), 70, Paint()..color = Colors.lightBlueAccent, onTapDown: (_) { + canvas.drawCircle( + Offset(150, 250), 70, Paint()..color = Colors.lightBlueAccent, + onTapDown: (_) { print('light blue Circle tap down'); setState('white'); }, onTapUp: (detail) { @@ -145,11 +148,12 @@ class MyPainter extends CustomPainter { ..strokeWidth = 40 ..color = Colors.grey, onTapDown: (_) { setState('grey'); - print("grey RRect touched"); + print('grey RRect touched'); }); canvas.drawRRect( - RRect.fromLTRBR(100 - 20.0, 340 - 20.0, 300 + 20.0, 650 + 20.0, Radius.elliptical(100 + 20.0, 150 + 20.0)), + RRect.fromLTRBR(100 - 20.0, 340 - 20.0, 300 + 20.0, 650 + 20.0, + Radius.elliptical(100 + 20.0, 150 + 20.0)), Paint() ..strokeWidth = 1 ..style = PaintingStyle.stroke diff --git a/example/lib/screens/screen2.dart b/example/lib/screens/screen2.dart index b226d9d..edc923f 100644 --- a/example/lib/screens/screen2.dart +++ b/example/lib/screens/screen2.dart @@ -1,6 +1,4 @@ import 'dart:math'; -import 'dart:ui'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:touchable/touchable.dart'; @@ -106,7 +104,7 @@ class MyPainter extends CustomPainter { pi, false, Paint()..color = Colors.black, onTapDown: (detail) { - print("clicked"); + print('clicked'); if (smileAnimation.value == 90) { smileAnimationController.reverse(); } @@ -116,11 +114,11 @@ class MyPainter extends CustomPainter { void drawNose(TouchyCanvas canvas, Size size) { var center = Offset(size.width / 2, size.height / 2); var noseColor = - ColorTween(begin: Colors.blueGrey, end: Colors.lightBlueAccent).animate( - CurvedAnimation( - parent: noseAnimationController, curve: Curves.bounceOut)); + ColorTween(begin: Colors.blueGrey, end: Colors.lightBlueAccent).animate( + CurvedAnimation( + parent: noseAnimationController, curve: Curves.bounceOut)); var noseLength = - Tween(begin: 0, end: 100).animate(noseAnimationController); + Tween(begin: 0, end: 100).animate(noseAnimationController); var upperbound = noseAnimationController.upperBound; void drawNose(Color color, double extraLength) { @@ -132,12 +130,13 @@ class MyPainter extends CustomPainter { Offset(center.dx + 15, center.dy + 25 + extraLength) ], true), Paint()..color = color, onTapDown: (_) { - print("On Pan Down"); + print('On Pan Down'); if (noseAnimationController.value == upperbound || noseAnimationController.status == AnimationStatus.forward) { noseAnimationController.reverse(); - } else + } else { noseAnimationController.forward(); + } }); } @@ -161,8 +160,8 @@ class MyPainter extends CustomPainter { Offset(center.dx - xOffset, center.dy - 40), 10, Paint()); canvas.drawCircle(Offset(center.dx + xOffset, center.dy - 50), 20, Paint()..color = Colors.transparent, onTapDown: (_) { - eyeAnimationController.reverse(); - }); + eyeAnimationController.reverse(); + }); } void drawEyeLid(double xOffset) { @@ -186,4 +185,4 @@ class MyPainter extends CustomPainter { bool shouldRepaint(CustomPainter oldDelegate) { return true; } -} \ No newline at end of file +} diff --git a/example/lib/screens/screen3.dart b/example/lib/screens/screen3.dart index a581823..3cdd97d 100644 --- a/example/lib/screens/screen3.dart +++ b/example/lib/screens/screen3.dart @@ -1,5 +1,3 @@ -import 'dart:ui'; - import 'package:flutter/material.dart'; import 'package:touchable/touchable.dart'; @@ -73,7 +71,8 @@ class MyPainter extends CustomPainter { void paint(Canvas _canvas, Size size) { TouchyCanvas canvas = TouchyCanvas(context, _canvas); - canvas.drawRect(Rect.fromLTWH(0, 0, 100, 300), Paint()..color = Colors.blue, onTapDown: (_) { + canvas.drawRect(Rect.fromLTWH(0, 0, 100, 300), Paint()..color = Colors.blue, + onTapDown: (_) { setState('blue'); }); } diff --git a/example/pubspec.lock b/example/pubspec.lock index aecadfe..5da3a55 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.6.1" + version: "2.9.0" boolean_selector: dependency: transitive description: @@ -21,28 +21,21 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" + version: "1.2.1" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" cupertino_icons: dependency: "direct main" description: @@ -56,7 +49,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" flutter: dependency: "direct main" description: flutter @@ -73,21 +66,28 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.12" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.5" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.8.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.2" sky_engine: dependency: transitive description: flutter @@ -99,7 +99,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.9.0" stack_trace: dependency: transitive description: @@ -120,41 +120,34 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.3.0" + version: "0.4.12" touchable: dependency: "direct main" description: path: ".." relative: true source: path - version: "1.0.0" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" + version: "1.0.1" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.2" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=2.18.1 <3.0.0" diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart deleted file mode 100644 index a92c6d7..0000000 --- a/example/test/widget_test.dart +++ /dev/null @@ -1,14 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:example/main.dart'; - -void main() { -} diff --git a/lib/src/canvas_touch_detector.dart b/lib/src/canvas_touch_detector.dart index 03bd936..eedf858 100644 --- a/lib/src/canvas_touch_detector.dart +++ b/lib/src/canvas_touch_detector.dart @@ -39,7 +39,30 @@ class _CanvasTouchDetectorState extends State { behavior: HitTestBehavior.translucent, child: Builder( builder: (context) { - return widget.builder(context); + return MouseRegion( + hitTestBehavior: HitTestBehavior.translucent, + onEnter: !widget.gesturesToOverride + .contains(GestureType.onEnter) + ? null + : (mouseEnterDetail) { + touchController.add(Gesture( + GestureType.onEnter, mouseEnterDetail.original)); + }, + onExit: !widget.gesturesToOverride.contains(GestureType.onExit) + ? null + : (mouseExitDetail) { + touchController.add(Gesture( + GestureType.onExit, mouseExitDetail.original)); + }, + onHover: !widget.gesturesToOverride + .contains(GestureType.onHover) + ? null + : (mouseHoverDetail) { + touchController.add(Gesture( + GestureType.onHover, mouseHoverDetail.original)); + }, + child: widget.builder(context), + ); }, ), onTapDown: !widget.gesturesToOverride.contains(GestureType.onTapDown) diff --git a/lib/src/shape_handler.dart b/lib/src/shape_handler.dart index ac6a8fd..5fb0a06 100644 --- a/lib/src/shape_handler.dart +++ b/lib/src/shape_handler.dart @@ -1,5 +1,3 @@ -import 'dart:ui'; - import 'package:flutter/cupertino.dart'; import 'package:touchable/src/shapes/clip.dart'; import 'package:touchable/src/shapes/shape.dart'; @@ -31,7 +29,10 @@ class ShapeHandler { /// /// Looking at above diagram , given the stack position 3 , this function returns all ClipShapes that are pushed before 3 into the clip stack. List _getClipShapesBelowPosition(int position) { - return clipItems.where((element) => element.position <= position).map((e) => e.clipShape).toList(); + return clipItems + .where((element) => element.position <= position) + .map((e) => e.clipShape) + .toList(); } ///returns [true] if point lies inside all the clipShapes @@ -42,16 +43,17 @@ class ShapeHandler { return true; } - Offset _getActualOffsetFromScrollController( - Offset touchPoint, ScrollController? controller, AxisDirection direction) { + Offset _getActualOffsetFromScrollController(Offset touchPoint, + ScrollController? controller, AxisDirection direction) { if (controller == null) { return touchPoint; } final scrollPosition = controller.position; - final actualScrollPixels = direction == AxisDirection.left || direction == AxisDirection.up - ? scrollPosition.maxScrollExtent - scrollPosition.pixels - : scrollPosition.pixels; + final actualScrollPixels = + direction == AxisDirection.left || direction == AxisDirection.up + ? scrollPosition.maxScrollExtent - scrollPosition.pixels + : scrollPosition.pixels; if (direction == AxisDirection.left || direction == AxisDirection.right) { return Offset(touchPoint.dx + actualScrollPixels, touchPoint.dy); @@ -68,7 +70,8 @@ class ShapeHandler { continue; } if (shape.isInside(point)) { - if (_isPointInsideClipShapes(_getClipShapesBelowPosition(i), point) == false) { + if (_isPointInsideClipShapes(_getClipShapesBelowPosition(i), point) == + false) { if (shape.hitTestBehavior == HitTestBehavior.opaque) { return selectedShapes; } @@ -89,7 +92,9 @@ class ShapeHandler { AxisDirection direction = AxisDirection.down, }) async { var touchPoint = _getActualOffsetFromScrollController( - TouchCanvasUtil.getPointFromGestureDetail(gesture.gestureDetail), scrollController, direction); + TouchCanvasUtil.getPointFromGestureDetail(gesture.gestureDetail), + scrollController, + direction); if (!_registeredGestures.contains(gesture.gestureType)) return; var touchedShapes = _getTouchedShapes(touchPoint); diff --git a/lib/src/shapes/arc.dart b/lib/src/shapes/arc.dart index 87592a8..41913ba 100644 --- a/lib/src/shapes/arc.dart +++ b/lib/src/shapes/arc.dart @@ -1,5 +1,4 @@ import 'dart:math'; -import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:touchable/src/shapes/constant.dart'; @@ -32,7 +31,10 @@ class Arc extends Shape { Map? gestureMap, HitTestBehavior? hitTestBehavior, PaintingStyle? paintStyleForTouch}) - : super(hitTestBehavior: hitTestBehavior, paint: paint , gestureCallbackMap: gestureMap) { + : super( + hitTestBehavior: hitTestBehavior, + paint: paint, + gestureCallbackMap: gestureMap) { _oval = Oval(rect, paint: paint); if (sweepAngle < 0) { @@ -42,15 +44,17 @@ class Arc extends Shape { } var cosStartAngle = cos(startAngle); - var startPointPhi = atan2(_oval.a * sin(startAngle), _oval.b * cosStartAngle); + var startPointPhi = + atan2(_oval.a * sin(startAngle), _oval.b * cosStartAngle); var endAngle = startAngle + sweepAngle; var cosEndAngle = cos(endAngle); var endPointPhi = atan2(_oval.a * sin(endAngle), _oval.b * cosEndAngle); - _arcStartPoint = - Offset(rect.center.dx + _oval.a * cos(startPointPhi), rect.center.dy + _oval.b * sin(startPointPhi)); - _arcEndPoint = Offset(rect.center.dx + _oval.a * cos(endPointPhi), rect.center.dy + _oval.b * sin(endPointPhi)); + _arcStartPoint = Offset(rect.center.dx + _oval.a * cos(startPointPhi), + rect.center.dy + _oval.b * sin(startPointPhi)); + _arcEndPoint = Offset(rect.center.dx + _oval.a * cos(endPointPhi), + rect.center.dy + _oval.b * sin(endPointPhi)); _chordLine = Line(_arcStartPoint, _arcEndPoint, paint: paint); _originToArcStartLine = Line(rect.center, _arcStartPoint, paint: paint); @@ -61,7 +65,9 @@ class Arc extends Shape { bool isInside(Offset p) { if (useCenter) { if (paint.style == PaintingStyle.stroke) { - return (_oval.isOnTheOval(p) && (_isBetweenArcStartAndEndLines(p) || sweepAngle.abs() >= 2 * pi)) || + return (_oval.isOnTheOval(p) && + (_isBetweenArcStartAndEndLines(p) || + sweepAngle.abs() >= 2 * pi)) || (_originToArcStartLine.isInside(p)) || (_originToArcEndLine.isInside(p)); } else { @@ -83,7 +89,8 @@ class Arc extends Shape { /// Does [not] consider the [paint.strokeWidth] of the lines. bool _isBetweenArcStartAndEndLines(Offset p) { - var startLineSideValue = _originToArcStartLine.getPointLyingOnSideTestValue(p); + var startLineSideValue = + _originToArcStartLine.getPointLyingOnSideTestValue(p); var endLineSideValue = _originToArcEndLine.getPointLyingOnSideTestValue(p); var threshold = ShapeConstant.floatPrecision; if (sweepAngle <= pi) { diff --git a/lib/src/shapes/clip.dart b/lib/src/shapes/clip.dart index 37ebdf7..69a3119 100644 --- a/lib/src/shapes/clip.dart +++ b/lib/src/shapes/clip.dart @@ -1,6 +1,5 @@ import 'dart:ui'; -import 'package:flutter/cupertino.dart'; import 'package:touchable/src/shapes/shape.dart'; abstract class ClipShape extends Shape { diff --git a/lib/src/shapes/oval.dart b/lib/src/shapes/oval.dart index ec063a6..265b88d 100644 --- a/lib/src/shapes/oval.dart +++ b/lib/src/shapes/oval.dart @@ -1,5 +1,4 @@ import 'dart:math'; -import 'dart:ui'; import 'package:flutter/cupertino.dart'; import 'package:touchable/src/shapes/constant.dart'; @@ -19,13 +18,18 @@ class Oval extends Shape { PaintingStyle? paintStyleForTouch}) : a = rect.right - rect.center.dx, b = rect.center.dy - rect.top, - super(hitTestBehavior: hitTestBehavior, paint: paint ?? Paint(), gestureCallbackMap: gestureMap ?? {}); + super( + hitTestBehavior: hitTestBehavior, + paint: paint ?? Paint(), + gestureCallbackMap: gestureMap ?? {}); @override bool isInside(Offset p) { if (a == 0 || b == 0) return false; - var extraWidth = paint.style == PaintingStyle.stroke ? paint.strokeWidth / 2 : ShapeConstant.floatPrecision; + var extraWidth = paint.style == PaintingStyle.stroke + ? paint.strokeWidth / 2 + : ShapeConstant.floatPrecision; bool insideOuterOval = _isInsideOval(p, extraWidth); if (paint.style == PaintingStyle.stroke) { @@ -43,7 +47,9 @@ class Oval extends Shape { } bool isOnTheOval(Offset p) { - var extraWidth = paint.style == PaintingStyle.stroke ? paint.strokeWidth / 2 : ShapeConstant.floatPrecision; + var extraWidth = paint.style == PaintingStyle.stroke + ? paint.strokeWidth / 2 + : ShapeConstant.floatPrecision; bool insideOuterOval = _isInsideOval(p, extraWidth); bool outsideInnerOval = !_isInsideOval(p, -extraWidth); return insideOuterOval && outsideInnerOval; diff --git a/lib/src/shapes/path.dart b/lib/src/shapes/path.dart index 50fb6a8..971a2bf 100644 --- a/lib/src/shapes/path.dart +++ b/lib/src/shapes/path.dart @@ -1,5 +1,3 @@ -import 'dart:ui'; - import 'package:flutter/cupertino.dart'; import 'package:touchable/src/shapes/shape.dart'; import 'package:touchable/src/types/types.dart'; @@ -12,7 +10,10 @@ class PathShape extends Shape { required Paint paint, HitTestBehavior? hitTestBehavior, PaintingStyle? paintStyleForTouch}) - : super(hitTestBehavior: hitTestBehavior, paint: paint, gestureCallbackMap: gestureMap); + : super( + hitTestBehavior: hitTestBehavior, + paint: paint, + gestureCallbackMap: gestureMap); @override bool isInside(Offset p) { diff --git a/lib/src/shapes/point.dart b/lib/src/shapes/point.dart index d5c680e..632b87d 100644 --- a/lib/src/shapes/point.dart +++ b/lib/src/shapes/point.dart @@ -16,7 +16,10 @@ class Point extends Shape { Paint? paint, HitTestBehavior? hitTestBehavior, PaintingStyle? paintStyleForTouch}) - : super(hitTestBehavior: hitTestBehavior, paint: paint ?? Paint(), gestureCallbackMap: gestureMap ?? {}); + : super( + hitTestBehavior: hitTestBehavior, + paint: paint ?? Paint(), + gestureCallbackMap: gestureMap ?? {}); @override bool isInside(Offset p) { @@ -52,7 +55,9 @@ class Point extends Shape { if (paint.strokeCap == StrokeCap.round) { return Circle(center: point, radius: extraWidth).isInside(queryPoint); } else { - return Rect.fromCenter(center: point, width: extraWidth * 2, height: extraWidth * 2).contains(queryPoint); + return Rect.fromCenter( + center: point, width: extraWidth * 2, height: extraWidth * 2) + .contains(queryPoint); } } } @@ -76,14 +81,18 @@ class PolygonUtil { int dir4 = _direction(l2.p1, l2.p2, l1.p2); if (dir1 != dir2 && dir3 != dir4) return true; //they are intersecting - if (dir1 == 0 && l1.isInside(l2.p1)) //when p2 of line2 are on the line1 + if (dir1 == 0 && l1.isInside(l2.p1)) { return true; - if (dir2 == 0 && l1.isInside(l2.p2)) //when p1 of line2 are on the line1 + } + if (dir2 == 0 && l1.isInside(l2.p2)) { return true; - if (dir3 == 0 && l2.isInside(l1.p1)) //when p2 of line1 are on the line2 + } + if (dir3 == 0 && l2.isInside(l1.p1)) { return true; - if (dir4 == 0 && l2.isInside(l1.p2)) //when p1 of line1 are on the line2 + } + if (dir4 == 0 && l2.isInside(l1.p2)) { return true; + } return false; } @@ -92,7 +101,8 @@ class PolygonUtil { if (n < 3) { return false; } //when polygon has less than 3 edge, it is not polygon - Line exline = Line(p, Offset(9999, p.dy)); //create a point at infinity, y is same as point p + Line exline = Line(p, + Offset(9999, p.dy)); //create a point at infinity, y is same as point p int count = 0; int i = 0; do { diff --git a/lib/src/shapes/rectangle.dart b/lib/src/shapes/rectangle.dart index e271f13..bd1cc27 100644 --- a/lib/src/shapes/rectangle.dart +++ b/lib/src/shapes/rectangle.dart @@ -1,5 +1,3 @@ -import 'dart:ui'; - import 'package:flutter/cupertino.dart'; import 'package:touchable/src/shapes/shape.dart'; import 'package:touchable/src/types/types.dart'; @@ -12,7 +10,10 @@ class Rectangle extends Shape { Paint? paint, HitTestBehavior? hitTestBehavior, PaintingStyle? paintStyleForTouch}) - : super(hitTestBehavior: hitTestBehavior, paint: paint ?? Paint(), gestureCallbackMap: gestureMap ?? {}); + : super( + hitTestBehavior: hitTestBehavior, + paint: paint ?? Paint(), + gestureCallbackMap: gestureMap ?? {}); @override bool isInside(Offset p) { @@ -22,11 +23,17 @@ class Rectangle extends Shape { double extraWidth = paint.strokeWidth / 2; bool insideOuterRect = Rect.fromLTRB( - rect.left - extraWidth, rect.top - extraWidth, rect.right + extraWidth, rect.bottom + extraWidth) + rect.left - extraWidth, + rect.top - extraWidth, + rect.right + extraWidth, + rect.bottom + extraWidth) .contains(p); bool outsideInnerRect = !Rect.fromLTRB( - rect.left + extraWidth, rect.top + extraWidth, rect.right - extraWidth, rect.bottom - extraWidth) + rect.left + extraWidth, + rect.top + extraWidth, + rect.right - extraWidth, + rect.bottom - extraWidth) .contains(p); return insideOuterRect && outsideInnerRect; } diff --git a/lib/src/shapes/rounded_rectangle.dart b/lib/src/shapes/rounded_rectangle.dart index fe658e3..7d78d86 100644 --- a/lib/src/shapes/rounded_rectangle.dart +++ b/lib/src/shapes/rounded_rectangle.dart @@ -1,5 +1,3 @@ -import 'dart:ui'; - import 'package:flutter/cupertino.dart'; import 'package:touchable/src/shapes/shape.dart'; import 'package:touchable/src/types/types.dart'; @@ -12,7 +10,10 @@ class RoundedRectangle extends Shape { Map? gestureMap, HitTestBehavior? hitTestBehavior, PaintingStyle? paintStyleForTouch}) - : super(hitTestBehavior: hitTestBehavior, paint: paint ?? Paint(), gestureCallbackMap: gestureMap ?? {}); + : super( + hitTestBehavior: hitTestBehavior, + paint: paint ?? Paint(), + gestureCallbackMap: gestureMap ?? {}); @override bool isInside(Offset p) { @@ -25,20 +26,28 @@ class RoundedRectangle extends Shape { rRect.top - extraWidth, rRect.right + extraWidth, rRect.bottom + extraWidth, - topLeft: Radius.elliptical(rRect.tlRadiusX + extraWidth, rRect.tlRadiusY + extraWidth), - topRight: Radius.elliptical(rRect.trRadiusX + extraWidth, rRect.trRadiusY + extraWidth), - bottomLeft: Radius.elliptical(rRect.blRadiusX + extraWidth, rRect.blRadiusY + extraWidth), - bottomRight: Radius.elliptical(rRect.brRadiusX + extraWidth, rRect.brRadiusY + extraWidth), + topLeft: Radius.elliptical( + rRect.tlRadiusX + extraWidth, rRect.tlRadiusY + extraWidth), + topRight: Radius.elliptical( + rRect.trRadiusX + extraWidth, rRect.trRadiusY + extraWidth), + bottomLeft: Radius.elliptical( + rRect.blRadiusX + extraWidth, rRect.blRadiusY + extraWidth), + bottomRight: Radius.elliptical( + rRect.brRadiusX + extraWidth, rRect.brRadiusY + extraWidth), ).contains(p); bool outsideInnerRect = !RRect.fromLTRBAndCorners( rRect.left + extraWidth, rRect.top + extraWidth, rRect.right - extraWidth, rRect.bottom - extraWidth, - topLeft: Radius.elliptical(rRect.tlRadiusX - extraWidth, rRect.tlRadiusY - extraWidth), - topRight: Radius.elliptical(rRect.trRadiusX - extraWidth, rRect.trRadiusY - extraWidth), - bottomLeft: Radius.elliptical(rRect.blRadiusX - extraWidth, rRect.blRadiusY - extraWidth), - bottomRight: Radius.elliptical(rRect.brRadiusX - extraWidth, rRect.brRadiusY - extraWidth), + topLeft: Radius.elliptical( + rRect.tlRadiusX - extraWidth, rRect.tlRadiusY - extraWidth), + topRight: Radius.elliptical( + rRect.trRadiusX - extraWidth, rRect.trRadiusY - extraWidth), + bottomLeft: Radius.elliptical( + rRect.blRadiusX - extraWidth, rRect.blRadiusY - extraWidth), + bottomRight: Radius.elliptical( + rRect.brRadiusX - extraWidth, rRect.brRadiusY - extraWidth), ).contains(p); return insideOuterRect && outsideInnerRect; } diff --git a/lib/src/shapes/shape.dart b/lib/src/shapes/shape.dart index 0861cc9..925b8e7 100644 --- a/lib/src/shapes/shape.dart +++ b/lib/src/shapes/shape.dart @@ -1,6 +1,3 @@ -import 'dart:ui'; - -import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:touchable/src/shapes/constant.dart'; import 'package:touchable/touchable.dart'; @@ -31,7 +28,8 @@ abstract class Shape { Function getCallbackFromGesture(Gesture gesture) { if (gestureCallbackMap.containsKey(gesture.gestureType)) { - return () => gestureCallbackMap[gesture.gestureType]?.call(gesture.gestureDetail); + return () => + gestureCallbackMap[gesture.gestureType]?.call(gesture.gestureDetail); } else { return () {}; } diff --git a/lib/src/shapes/util.dart b/lib/src/shapes/util.dart index bcd96dc..f1a11bf 100644 --- a/lib/src/shapes/util.dart +++ b/lib/src/shapes/util.dart @@ -1,7 +1,7 @@ import 'dart:math'; -import 'dart:ui'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:touchable/src/types/types.dart'; class ShapeUtil { @@ -37,8 +37,15 @@ class TouchCanvasUtil { return (gestureDetail as ScaleUpdateDetails).localFocalPoint; case ForcePressDetails: return (gestureDetail as ForcePressDetails).localPosition; + case PointerEnterEvent: + return (gestureDetail as PointerEnterEvent).localPosition; + case PointerExitEvent: + return (gestureDetail as PointerExitEvent).localPosition; + case PointerHoverEvent: + return (gestureDetail as PointerHoverEvent).localPosition; default: - throw Exception("gestureDetail.runTimeType = ${gestureDetail.runtimeType} is not recognized ! "); + throw Exception( + 'gestureDetail.runTimeType = ${gestureDetail.runtimeType} is not recognized ! '); } } @@ -57,6 +64,9 @@ class TouchCanvasUtil { required GestureDragDownCallback? onPanDown, required GestureTapDownCallback? onSecondaryTapDown, required GestureTapUpCallback? onSecondaryTapUp, + required PointerEnterEventListener? onEnter, + required PointerExitEventListener? onExit, + required PointerHoverEventListener? onHover, }) { var map = {}; if (onTapDown != null) { @@ -68,7 +78,8 @@ class TouchCanvasUtil { map.putIfAbsent(GestureType.onLongPressStart, () => onLongPressStart); } if (onLongPressMoveUpdate != null) { - map.putIfAbsent(GestureType.onLongPressMoveUpdate, () => onLongPressMoveUpdate); + map.putIfAbsent( + GestureType.onLongPressMoveUpdate, () => onLongPressMoveUpdate); } if (onLongPressEnd != null) { map.putIfAbsent(GestureType.onLongPressEnd, () => onLongPressEnd); @@ -104,6 +115,16 @@ class TouchCanvasUtil { map.putIfAbsent(GestureType.onSecondaryTapUp, () => onSecondaryTapUp); } + if (onEnter != null) { + map.putIfAbsent(GestureType.onEnter, () => onEnter); + } + if (onExit != null) { + map.putIfAbsent(GestureType.onExit, () => onExit); + } + if (onHover != null) { + map.putIfAbsent(GestureType.onHover, () => onHover); + } + return map; } } diff --git a/lib/src/touchy_canvas.dart b/lib/src/touchy_canvas.dart index b674e06..85a8889 100644 --- a/lib/src/touchy_canvas.dart +++ b/lib/src/touchy_canvas.dart @@ -1,9 +1,8 @@ -import 'dart:math'; import 'dart:typed_data'; import 'dart:ui'; -import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart' hide Image; +import 'package:flutter/services.dart'; import 'package:touchable/src/canvas_touch_detector.dart'; import 'package:touchable/src/shape_handler.dart'; import 'package:touchable/src/shapes/arc.dart'; @@ -52,7 +51,8 @@ class TouchyCanvas { _shapeHandler.addShape(ClipRRectShape(rrect)); } - void clipRect(Rect rect, {ClipOp clipOp = ClipOp.intersect, bool doAntiAlias = true}) { + void clipRect(Rect rect, + {ClipOp clipOp = ClipOp.intersect, bool doAntiAlias = true}) { _canvas.clipRect(rect, clipOp: clipOp, doAntiAlias: doAntiAlias); _shapeHandler.addShape(ClipRectShape(rect, clipOp: clipOp)); } @@ -76,6 +76,9 @@ class TouchyCanvas { GestureDragDownCallback? onPanDown, GestureTapDownCallback? onSecondaryTapDown, GestureTapUpCallback? onSecondaryTapUp, + PointerEnterEventListener? onEnter, + PointerExitEventListener? onExit, + PointerHoverEventListener? onHover, }) { _canvas.drawCircle(c, radius, paint); _shapeHandler.addShape(Circle( @@ -98,6 +101,9 @@ class TouchyCanvas { onPanDown: onPanDown, onSecondaryTapDown: onSecondaryTapDown, onSecondaryTapUp: onSecondaryTapUp, + onEnter: onEnter, + onExit: onExit, + onHover: onHover, ))); } @@ -121,6 +127,9 @@ class TouchyCanvas { GestureDragDownCallback? onPanDown, GestureTapDownCallback? onSecondaryTapDown, GestureTapUpCallback? onSecondaryTapUp, + PointerEnterEventListener? onEnter, + PointerExitEventListener? onExit, + PointerHoverEventListener? onHover, }) { _canvas.drawLine(p1, p2, paint); _shapeHandler.addShape(Line(p1, p2, @@ -141,6 +150,9 @@ class TouchyCanvas { onPanDown: onPanDown, onSecondaryTapDown: onSecondaryTapDown, onSecondaryTapUp: onSecondaryTapUp, + onEnter: onEnter, + onExit: onExit, + onHover: onHover, ))); } @@ -163,6 +175,9 @@ class TouchyCanvas { GestureDragDownCallback? onPanDown, GestureTapDownCallback? onSecondaryTapDown, GestureTapUpCallback? onSecondaryTapUp, + PointerEnterEventListener? onEnter, + PointerExitEventListener? onExit, + PointerHoverEventListener? onHover, }) { _canvas.drawOval(rect, paint); _shapeHandler.addShape(Oval(rect, @@ -183,6 +198,9 @@ class TouchyCanvas { onPanDown: onPanDown, onSecondaryTapDown: onSecondaryTapDown, onSecondaryTapUp: onSecondaryTapUp, + onEnter: onEnter, + onExit: onExit, + onHover: onHover, ))); } @@ -211,6 +229,9 @@ class TouchyCanvas { GestureDragDownCallback? onPanDown, GestureTapDownCallback? onSecondaryTapDown, GestureTapUpCallback? onSecondaryTapUp, + PointerEnterEventListener? onEnter, + PointerExitEventListener? onExit, + PointerHoverEventListener? onHover, }) { _canvas.drawPath(path, paint); _shapeHandler.addShape(PathShape(path, @@ -231,6 +252,9 @@ class TouchyCanvas { onPanDown: onPanDown, onSecondaryTapDown: onSecondaryTapDown, onSecondaryTapUp: onSecondaryTapUp, + onEnter: onEnter, + onExit: onExit, + onHover: onHover, ))); } @@ -254,6 +278,9 @@ class TouchyCanvas { GestureDragDownCallback? onPanDown, GestureTapDownCallback? onSecondaryTapDown, GestureTapUpCallback? onSecondaryTapUp, + PointerEnterEventListener? onEnter, + PointerExitEventListener? onExit, + PointerHoverEventListener? onHover, }) { _canvas.drawPoints(pointMode, points, paint); _shapeHandler.addShape(Point(pointMode, points, @@ -274,6 +301,9 @@ class TouchyCanvas { onPanDown: onPanDown, onSecondaryTapDown: onSecondaryTapDown, onSecondaryTapUp: onSecondaryTapUp, + onEnter: onEnter, + onExit: onExit, + onHover: onHover, ))); } @@ -296,6 +326,9 @@ class TouchyCanvas { GestureDragDownCallback? onPanDown, GestureTapDownCallback? onSecondaryTapDown, GestureTapUpCallback? onSecondaryTapUp, + PointerEnterEventListener? onEnter, + PointerExitEventListener? onExit, + PointerHoverEventListener? onHover, }) { _canvas.drawRRect(rrect, paint); _shapeHandler.addShape(RoundedRectangle(rrect, @@ -316,6 +349,9 @@ class TouchyCanvas { onPanDown: onPanDown, onSecondaryTapDown: onSecondaryTapDown, onSecondaryTapUp: onSecondaryTapUp, + onEnter: onEnter, + onExit: onExit, + onHover: onHover, ))); } @@ -339,6 +375,9 @@ class TouchyCanvas { GestureDragDownCallback? onPanDown, GestureTapDownCallback? onSecondaryTapDown, GestureTapUpCallback? onSecondaryTapUp, + PointerEnterEventListener? onEnter, + PointerExitEventListener? onExit, + PointerHoverEventListener? onHover, }) { _canvas.drawRawPoints(pointMode, points, paint); List offsetPoints = []; @@ -363,6 +402,9 @@ class TouchyCanvas { onPanDown: onPanDown, onSecondaryTapDown: onSecondaryTapDown, onSecondaryTapUp: onSecondaryTapUp, + onEnter: onEnter, + onExit: onExit, + onHover: onHover, ))); } @@ -385,6 +427,9 @@ class TouchyCanvas { GestureDragDownCallback? onPanDown, GestureTapDownCallback? onSecondaryTapDown, GestureTapUpCallback? onSecondaryTapUp, + PointerEnterEventListener? onEnter, + PointerExitEventListener? onExit, + PointerHoverEventListener? onHover, }) { _canvas.drawRect(rect, paint); _shapeHandler.addShape(Rectangle(rect, @@ -405,10 +450,14 @@ class TouchyCanvas { onPanDown: onPanDown, onSecondaryTapDown: onSecondaryTapDown, onSecondaryTapUp: onSecondaryTapUp, + onEnter: onEnter, + onExit: onExit, + onHover: onHover, ))); } - void drawShadow(Path path, Color color, double elevation, bool transparentOccluder) { + void drawShadow( + Path path, Color color, double elevation, bool transparentOccluder) { _canvas.drawShadow(path, color, elevation, transparentOccluder); // _shapeHandler.addShape(PathShape(path)); } @@ -433,9 +482,14 @@ class TouchyCanvas { GestureDragDownCallback? onPanDown, GestureTapDownCallback? onSecondaryTapDown, GestureTapUpCallback? onSecondaryTapUp, + PointerEnterEventListener? onEnter, + PointerExitEventListener? onExit, + PointerHoverEventListener? onHover, }) { _canvas.drawImage(image, p, paint); - _shapeHandler.addShape(Rectangle(Rect.fromLTWH(p.dx, p.dy, image.width.toDouble(), image.height.toDouble()), + _shapeHandler.addShape(Rectangle( + Rect.fromLTWH( + p.dx, p.dy, image.width.toDouble(), image.height.toDouble()), paint: paint, hitTestBehavior: hitTestBehavior, gestureMap: TouchCanvasUtil.getGestureCallbackMap( @@ -453,6 +507,9 @@ class TouchyCanvas { onPanDown: onPanDown, onSecondaryTapDown: onSecondaryTapDown, onSecondaryTapUp: onSecondaryTapUp, + onEnter: onEnter, + onExit: onExit, + onHover: onHover, ))); } @@ -478,6 +535,9 @@ class TouchyCanvas { GestureDragDownCallback? onPanDown, GestureTapDownCallback? onSecondaryTapDown, GestureTapUpCallback? onSecondaryTapUp, + PointerEnterEventListener? onEnter, + PointerExitEventListener? onExit, + PointerHoverEventListener? onHover, }) { _canvas.drawArc(rect, startAngle, sweepAngle, useCenter, paint); var arc = Arc(rect, startAngle, sweepAngle, useCenter, @@ -498,6 +558,9 @@ class TouchyCanvas { onPanDown: onPanDown, onSecondaryTapDown: onSecondaryTapDown, onSecondaryTapUp: onSecondaryTapUp, + onEnter: onEnter, + onExit: onExit, + onHover: onHover, )); _shapeHandler.addShape(arc); } diff --git a/lib/src/types/types.dart b/lib/src/types/types.dart index ff2476a..c54c72f 100644 --- a/lib/src/types/types.dart +++ b/lib/src/types/types.dart @@ -41,4 +41,7 @@ enum GestureType { onPanDown, onSecondaryTapDown, onSecondaryTapUp, + onHover, + onEnter, + onExit, } diff --git a/pubspec.lock b/pubspec.lock index ad6d1df..8f7b7f5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.6.1" + version: "2.9.0" boolean_selector: dependency: transitive description: @@ -21,35 +21,28 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" + version: "1.2.1" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" flutter: dependency: "direct main" description: flutter @@ -66,21 +59,28 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.12" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.5" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.8.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.2" sky_engine: dependency: transitive description: flutter @@ -92,7 +92,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.9.0" stack_trace: dependency: transitive description: @@ -113,34 +113,27 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.3.0" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" + version: "0.4.12" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.2" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=2.18.1 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index e844d94..e19f98e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ repository: https://github.com/nateshmbhat/touchable homepage: https://github.com/nateshmbhat/touchable environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.18.1 <3.0.0" dependencies: flutter: diff --git a/test/shape_handler/hittest_test/defer_to_child.dart b/test/shape_handler/hittest_test/defer_to_child.dart index 1918a72..3ace1f9 100644 --- a/test/shape_handler/hittest_test/defer_to_child.dart +++ b/test/shape_handler/hittest_test/defer_to_child.dart @@ -21,22 +21,26 @@ void testDeferToChild() { Map getMap(Function function) { return TouchCanvasUtil.getGestureCallbackMap( - onTapDown: (detail) { - function(detail); - }, - onTapUp: null, - onLongPressStart: null, - onLongPressEnd: null, - onLongPressMoveUpdate: null, - onForcePressStart: null, - onForcePressEnd: null, - onForcePressPeak: null, - onForcePressUpdate: null, - onPanStart: null, - onPanUpdate: null, - onPanDown: null, - onSecondaryTapDown: null, - onSecondaryTapUp: null); + onTapDown: (detail) { + function(detail); + }, + onTapUp: null, + onLongPressStart: null, + onLongPressEnd: null, + onLongPressMoveUpdate: null, + onForcePressStart: null, + onForcePressEnd: null, + onForcePressPeak: null, + onForcePressUpdate: null, + onPanStart: null, + onPanUpdate: null, + onPanDown: null, + onSecondaryTapDown: null, + onSecondaryTapUp: null, + onEnter: null, + onExit: null, + onHover: null, + ); } void addAllShapes() { diff --git a/test/shape_handler/hittest_test/opaque.dart b/test/shape_handler/hittest_test/opaque.dart index 90e58c7..988dcf3 100644 --- a/test/shape_handler/hittest_test/opaque.dart +++ b/test/shape_handler/hittest_test/opaque.dart @@ -21,22 +21,26 @@ void testOpaque() { Map getMap(Function function) { return TouchCanvasUtil.getGestureCallbackMap( - onTapDown: (detail) { - function(detail); - }, - onTapUp: null, - onLongPressStart: null, - onLongPressEnd: null, - onLongPressMoveUpdate: null, - onForcePressStart: null, - onForcePressEnd: null, - onForcePressPeak: null, - onForcePressUpdate: null, - onPanStart: null, - onPanUpdate: null, - onPanDown: null, - onSecondaryTapDown: null, - onSecondaryTapUp: null); + onTapDown: (detail) { + function(detail); + }, + onTapUp: null, + onLongPressStart: null, + onLongPressEnd: null, + onLongPressMoveUpdate: null, + onForcePressStart: null, + onForcePressEnd: null, + onForcePressPeak: null, + onForcePressUpdate: null, + onPanStart: null, + onPanUpdate: null, + onPanDown: null, + onSecondaryTapDown: null, + onSecondaryTapUp: null, + onEnter: null, + onExit: null, + onHover: null, + ); } void addAllShapes() { diff --git a/test/shape_handler/hittest_test/translucent.dart b/test/shape_handler/hittest_test/translucent.dart index c9016e8..29b8011 100644 --- a/test/shape_handler/hittest_test/translucent.dart +++ b/test/shape_handler/hittest_test/translucent.dart @@ -21,22 +21,26 @@ void testTranslucent() { Map getMap(Function function) { return TouchCanvasUtil.getGestureCallbackMap( - onTapDown: (detail) { - function(detail); - }, - onTapUp: null, - onLongPressStart: null, - onLongPressEnd: null, - onLongPressMoveUpdate: null, - onForcePressStart: null, - onForcePressEnd: null, - onForcePressPeak: null, - onForcePressUpdate: null, - onPanStart: null, - onPanUpdate: null, - onPanDown: null, - onSecondaryTapDown: null, - onSecondaryTapUp: null); + onTapDown: (detail) { + function(detail); + }, + onTapUp: null, + onLongPressStart: null, + onLongPressEnd: null, + onLongPressMoveUpdate: null, + onForcePressStart: null, + onForcePressEnd: null, + onForcePressPeak: null, + onForcePressUpdate: null, + onPanStart: null, + onPanUpdate: null, + onPanDown: null, + onSecondaryTapDown: null, + onSecondaryTapUp: null, + onEnter: null, + onExit: null, + onHover: null, + ); } void addAllShapes() { diff --git a/test/shapes/arc.dart b/test/shapes/arc.dart index ff052f0..429fdf9 100644 --- a/test/shapes/arc.dart +++ b/test/shapes/arc.dart @@ -1,6 +1,5 @@ import 'dart:math'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:touchable/src/shapes/arc.dart'; @@ -45,7 +44,7 @@ void testArc() { expect(arc2.isInside(Offset(227.0, 113.1)), true); }); - test("Arc with sweep greather than 360 degree test", () { + test('Arc with sweep greather than 360 degree test', () { var arc3 = Arc(Rect.fromLTWH(100, 100, 200, 200), 3 * pi / 2, -10 * pi / 3, false, paint: Paint() diff --git a/test/shapes/line.dart b/test/shapes/line.dart index 96382c2..c5c266f 100644 --- a/test/shapes/line.dart +++ b/test/shapes/line.dart @@ -1,5 +1,3 @@ -import 'dart:ui'; - import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:touchable/src/shapes/line.dart'; diff --git a/test/shapes/point.dart b/test/shapes/point.dart index 2f43421..66601f3 100644 --- a/test/shapes/point.dart +++ b/test/shapes/point.dart @@ -1,6 +1,5 @@ import 'dart:ui'; -import 'package:flutter/cupertino.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:touchable/src/shapes/point.dart'; @@ -83,6 +82,7 @@ void testPoint() { expect(p1.isInside(Offset(252.6, 459.8)), true); expect(p1.isInside(Offset(190.5, 500.6)), true); expect(p1.isInside(Offset(150.1, 489.1)), true); + ///TODO : WARNING : MAKE THE BELOW TEST PASS // expect(p1.isInside(Offset(161.9, 526.9)), true); // expect(p1.isInside(Offset(144.0, 438.5)), true); diff --git a/test/shapes/rectangle.dart b/test/shapes/rectangle.dart index 37db25e..f07489d 100644 --- a/test/shapes/rectangle.dart +++ b/test/shapes/rectangle.dart @@ -1,5 +1,3 @@ -import 'dart:ui'; - import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:touchable/src/shapes/rectangle.dart'; From 75db50422b2ee8c8841d8dd94d41d4adccbff8ab Mon Sep 17 00:00:00 2001 From: Gabriel Moreyra Date: Fri, 7 Oct 2022 18:50:16 -0300 Subject: [PATCH 2/2] Fix simultaneous hover and tap detection --- lib/src/canvas_touch_detector.dart | 345 ++++++++++++++--------------- 1 file changed, 171 insertions(+), 174 deletions(-) diff --git a/lib/src/canvas_touch_detector.dart b/lib/src/canvas_touch_detector.dart index eedf858..1bf352e 100644 --- a/lib/src/canvas_touch_detector.dart +++ b/lib/src/canvas_touch_detector.dart @@ -34,188 +34,185 @@ class _CanvasTouchDetectorState extends State { @override Widget build(BuildContext context) { - return TouchDetectionController(touchController, addStreamListener, - child: GestureDetector( - behavior: HitTestBehavior.translucent, - child: Builder( - builder: (context) { - return MouseRegion( - hitTestBehavior: HitTestBehavior.translucent, - onEnter: !widget.gesturesToOverride - .contains(GestureType.onEnter) - ? null - : (mouseEnterDetail) { - touchController.add(Gesture( - GestureType.onEnter, mouseEnterDetail.original)); - }, - onExit: !widget.gesturesToOverride.contains(GestureType.onExit) - ? null - : (mouseExitDetail) { - touchController.add(Gesture( - GestureType.onExit, mouseExitDetail.original)); - }, - onHover: !widget.gesturesToOverride - .contains(GestureType.onHover) - ? null - : (mouseHoverDetail) { - touchController.add(Gesture( - GestureType.onHover, mouseHoverDetail.original)); - }, - child: widget.builder(context), - ); - }, - ), - onTapDown: !widget.gesturesToOverride.contains(GestureType.onTapDown) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onTapDown, tapDetail)); - }, - onTapUp: !widget.gesturesToOverride.contains(GestureType.onTapUp) - ? null - : (tapDetail) { - touchController.add(Gesture(GestureType.onTapUp, tapDetail)); - }, - onHorizontalDragDown: !widget.gesturesToOverride - .contains(GestureType.onHorizontalDragDown) - ? null - : (tapDetail) { + return TouchDetectionController( + touchController, + addStreamListener, + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onTapDown: !widget.gesturesToOverride.contains(GestureType.onTapDown) + ? null + : (tapDetail) { + touchController.add(Gesture(GestureType.onTapDown, tapDetail)); + }, + onTapUp: !widget.gesturesToOverride.contains(GestureType.onTapUp) + ? null + : (tapDetail) { + touchController.add(Gesture(GestureType.onTapUp, tapDetail)); + }, + onHorizontalDragDown: !widget.gesturesToOverride + .contains(GestureType.onHorizontalDragDown) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onHorizontalDragDown, tapDetail)); + }, + onHorizontalDragStart: !widget.gesturesToOverride + .contains(GestureType.onHorizontalDragStart) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onHorizontalDragStart, tapDetail)); + }, + onHorizontalDragUpdate: !widget.gesturesToOverride + .contains(GestureType.onHorizontalDragUpdate) + ? null + : (tapDetail) { + touchController.add( + Gesture(GestureType.onHorizontalDragUpdate, tapDetail)); + }, + onVerticalDragDown: !widget.gesturesToOverride + .contains(GestureType.onVerticalDragDown) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onVerticalDragDown, tapDetail)); + }, + onVerticalDragStart: !widget.gesturesToOverride + .contains(GestureType.onVerticalDragStart) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onVerticalDragStart, tapDetail)); + }, + onVerticalDragUpdate: !widget.gesturesToOverride + .contains(GestureType.onVerticalDragUpdate) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onVerticalDragUpdate, tapDetail)); + }, + onLongPressStart: + !widget.gesturesToOverride.contains(GestureType.onLongPressStart) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onLongPressStart, tapDetail)); + }, + onLongPressEnd: + !widget.gesturesToOverride.contains(GestureType.onLongPressEnd) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onLongPressEnd, tapDetail)); + }, + onLongPressMoveUpdate: !widget.gesturesToOverride + .contains(GestureType.onLongPressMoveUpdate) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onLongPressMoveUpdate, tapDetail)); + }, + onScaleStart: + !widget.gesturesToOverride.contains(GestureType.onScaleStart) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onScaleStart, tapDetail)); + }, + onScaleUpdate: + !widget.gesturesToOverride.contains(GestureType.onScaleUpdate) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onScaleUpdate, tapDetail)); + }, + onForcePressStart: + !widget.gesturesToOverride.contains(GestureType.onForcePressStart) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onForcePressStart, tapDetail)); + }, + onForcePressEnd: + !widget.gesturesToOverride.contains(GestureType.onForcePressEnd) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onForcePressEnd, tapDetail)); + }, + onForcePressPeak: + !widget.gesturesToOverride.contains(GestureType.onForcePressPeak) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onForcePressPeak, tapDetail)); + }, + onForcePressUpdate: !widget.gesturesToOverride + .contains(GestureType.onForcePressUpdate) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onForcePressUpdate, tapDetail)); + }, + onPanStart: !widget.gesturesToOverride.contains(GestureType.onPanStart) + ? null + : (tapDetail) { + touchController.add(Gesture(GestureType.onPanStart, tapDetail)); + }, + onPanUpdate: + !widget.gesturesToOverride.contains(GestureType.onPanUpdate) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onPanUpdate, tapDetail)); + }, + onPanDown: !widget.gesturesToOverride.contains(GestureType.onPanDown) + ? null + : (tapDetail) { + touchController.add(Gesture(GestureType.onPanDown, tapDetail)); + }, + onSecondaryTapDown: !widget.gesturesToOverride + .contains(GestureType.onSecondaryTapDown) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onSecondaryTapDown, tapDetail)); + }, + onSecondaryTapUp: + !widget.gesturesToOverride.contains(GestureType.onSecondaryTapUp) + ? null + : (tapDetail) { + touchController + .add(Gesture(GestureType.onSecondaryTapUp, tapDetail)); + }, + child: MouseRegion( + onEnter: !widget.gesturesToOverride.contains(GestureType.onEnter) + ? null + : (mouseEnterDetail) { + print('onEnter: ${mouseEnterDetail.original?.localPosition}'); touchController.add( - Gesture(GestureType.onHorizontalDragDown, tapDetail)); + Gesture(GestureType.onEnter, mouseEnterDetail.original)); }, - onHorizontalDragStart: !widget.gesturesToOverride - .contains(GestureType.onHorizontalDragStart) + onExit: !widget.gesturesToOverride.contains(GestureType.onExit) ? null - : (tapDetail) { + : (mouseExitDetail) { touchController.add( - Gesture(GestureType.onHorizontalDragStart, tapDetail)); + Gesture(GestureType.onExit, mouseExitDetail.original)); }, - onHorizontalDragUpdate: !widget.gesturesToOverride - .contains(GestureType.onHorizontalDragUpdate) + onHover: !widget.gesturesToOverride.contains(GestureType.onHover) ? null - : (tapDetail) { + : (mouseHoverDetail) { touchController.add( - Gesture(GestureType.onHorizontalDragUpdate, tapDetail)); + Gesture(GestureType.onHover, mouseHoverDetail.original)); }, - onVerticalDragDown: !widget.gesturesToOverride - .contains(GestureType.onVerticalDragDown) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onVerticalDragDown, tapDetail)); - }, - onVerticalDragStart: !widget.gesturesToOverride - .contains(GestureType.onVerticalDragStart) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onVerticalDragStart, tapDetail)); - }, - onVerticalDragUpdate: !widget.gesturesToOverride - .contains(GestureType.onVerticalDragUpdate) - ? null - : (tapDetail) { - touchController.add( - Gesture(GestureType.onVerticalDragUpdate, tapDetail)); - }, - onLongPressStart: !widget.gesturesToOverride - .contains(GestureType.onLongPressStart) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onLongPressStart, tapDetail)); - }, - onLongPressEnd: - !widget.gesturesToOverride.contains(GestureType.onLongPressEnd) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onLongPressEnd, tapDetail)); - }, - onLongPressMoveUpdate: !widget.gesturesToOverride - .contains(GestureType.onLongPressMoveUpdate) - ? null - : (tapDetail) { - touchController.add( - Gesture(GestureType.onLongPressMoveUpdate, tapDetail)); - }, - onScaleStart: - !widget.gesturesToOverride.contains(GestureType.onScaleStart) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onScaleStart, tapDetail)); - }, - onScaleUpdate: - !widget.gesturesToOverride.contains(GestureType.onScaleUpdate) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onScaleUpdate, tapDetail)); - }, - onForcePressStart: !widget.gesturesToOverride - .contains(GestureType.onForcePressStart) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onForcePressStart, tapDetail)); - }, - onForcePressEnd: - !widget.gesturesToOverride.contains(GestureType.onForcePressEnd) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onForcePressEnd, tapDetail)); - }, - onForcePressPeak: !widget.gesturesToOverride - .contains(GestureType.onForcePressPeak) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onForcePressPeak, tapDetail)); - }, - onForcePressUpdate: !widget.gesturesToOverride - .contains(GestureType.onForcePressUpdate) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onForcePressUpdate, tapDetail)); - }, - onPanStart: - !widget.gesturesToOverride.contains(GestureType.onPanStart) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onPanStart, tapDetail)); - }, - onPanUpdate: - !widget.gesturesToOverride.contains(GestureType.onPanUpdate) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onPanUpdate, tapDetail)); - }, - onPanDown: !widget.gesturesToOverride.contains(GestureType.onPanDown) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onPanDown, tapDetail)); - }, - onSecondaryTapDown: !widget.gesturesToOverride - .contains(GestureType.onSecondaryTapDown) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onSecondaryTapDown, tapDetail)); - }, - onSecondaryTapUp: !widget.gesturesToOverride - .contains(GestureType.onSecondaryTapUp) - ? null - : (tapDetail) { - touchController - .add(Gesture(GestureType.onSecondaryTapUp, tapDetail)); - }, - )); + child: Builder( + builder: (context) { + return widget.builder(context); + }, + ), + ), + ), + ); } @override