1+ using CoreGraphics ;
2+ using Foundation ;
3+ using Microsoft . Maui . Controls . Platform ;
4+ using OxyPlot . Maui . Skia . Effects ;
5+ using UIKit ;
6+
7+ namespace OxyPlot . Maui . Skia . macOS . Effects ;
8+
9+ public class PlatformTouchEffect : PlatformEffect
10+ {
11+ private UIView _view ;
12+ private TouchRecognizer _touchRecognizer ;
13+ private MyTouchEffect _touchEffect ;
14+ protected override void OnAttached ( )
15+ {
16+ _view = Control ?? Container ;
17+ _touchEffect = Element . Effects . OfType < MyTouchEffect > ( ) . FirstOrDefault ( ) ;
18+
19+ if ( _touchEffect == null || _view == null ) return ;
20+
21+ _touchRecognizer = new TouchRecognizer ( Element , _touchEffect ) ;
22+ _view . AddGestureRecognizer ( _touchRecognizer ) ;
23+ _view . AddGestureRecognizer ( GetMouseWheelRecognizer ( _view ) ) ;
24+ }
25+
26+ protected override void OnDetached ( )
27+ {
28+ if ( _touchRecognizer != null )
29+ {
30+ _touchRecognizer . Detach ( ) ;
31+ _view . RemoveGestureRecognizer ( _touchRecognizer ) ;
32+ }
33+ }
34+
35+ // https://github.com/dotnet/maui/issues/16130
36+ private UIPanGestureRecognizer GetMouseWheelRecognizer ( UIView v )
37+ {
38+ return new UIPanGestureRecognizer ( ( e ) =>
39+ {
40+ if ( e . State == UIGestureRecognizerState . Ended )
41+ return ;
42+
43+ var isZoom = e . NumberOfTouches == 0 ;
44+ if ( ! isZoom ) return ;
45+
46+ var l = e . LocationInView ( v ) ;
47+ var t = e . TranslationInView ( v ) ;
48+ var deltaX = t . X / 2 ;
49+ var deltaY = t . Y / 2 ;
50+ var delta = deltaY != 0 ? deltaY : deltaX ;
51+
52+ var tolerance = 5 ;
53+ if ( Math . Abs ( delta ) < tolerance ) return ;
54+
55+ var pointerX = l . X - t . X ;
56+ var pointerY = l . Y - t . Y ;
57+ var locations = new [ ] { new Point ( pointerX , pointerY ) } ;
58+
59+ var eventArgs = new TouchActionEventArgs ( 0 , TouchActionType . MouseWheel , locations , false )
60+ {
61+ MouseWheelDelta = ( int ) delta
62+ } ;
63+
64+ _touchEffect . OnTouchAction ( Element , eventArgs ) ;
65+ } )
66+ {
67+ AllowedScrollTypesMask = UIScrollTypeMask . Discrete | UIScrollTypeMask . Continuous ,
68+ MinimumNumberOfTouches = 0 ,
69+ ShouldRecognizeSimultaneously = ( _ , _ ) => true
70+ } ;
71+ }
72+ }
73+
74+ internal class TouchRecognizer : UIGestureRecognizer
75+ {
76+ private readonly Microsoft . Maui . Controls . Element _element ;
77+ private readonly MyTouchEffect _touchEffect ;
78+ private uint _activeTouchesCount = 0 ;
79+
80+ public TouchRecognizer ( Microsoft . Maui . Controls . Element element , MyTouchEffect touchEffect )
81+ {
82+ this . _element = element ;
83+ this . _touchEffect = touchEffect ;
84+ ShouldRecognizeSimultaneously = ( _ , _ ) => true ;
85+ }
86+
87+ public void Detach ( )
88+ {
89+ ShouldRecognizeSimultaneously = null ;
90+ }
91+
92+ public override void TouchesBegan ( NSSet touches , UIEvent evt )
93+ {
94+ base . TouchesBegan ( touches , evt ) ;
95+ _activeTouchesCount += touches . Count . ToUInt32 ( ) ;
96+ FireEvent ( touches , TouchActionType . Pressed , true ) ;
97+ }
98+
99+ public override void TouchesMoved ( NSSet touches , UIEvent evt )
100+ {
101+ base . TouchesMoved ( touches , evt ) ;
102+
103+ if ( _activeTouchesCount == touches . Count . ToUInt32 ( ) )
104+ {
105+ FireEvent ( touches , TouchActionType . Moved , true ) ;
106+ }
107+ }
108+
109+ public override void TouchesEnded ( NSSet touches , UIEvent evt )
110+ {
111+ base . TouchesEnded ( touches , evt ) ;
112+ _activeTouchesCount -= touches . Count . ToUInt32 ( ) ;
113+ FireEvent ( touches , TouchActionType . Released , false ) ;
114+ }
115+
116+ private void FireEvent ( NSSet touches , TouchActionType actionType , bool isInContact )
117+ {
118+ UITouch [ ] uiTouches = touches . Cast < UITouch > ( ) . ToArray ( ) ;
119+ long id = ( ( IntPtr ) uiTouches . First ( ) . Handle ) . ToInt64 ( ) ;
120+ Point [ ] points = new Point [ uiTouches . Length ] ;
121+
122+ for ( int i = 0 ; i < uiTouches . Length ; i ++ )
123+ {
124+ CGPoint cgPoint = uiTouches [ i ] . LocationInView ( View ) ;
125+ points [ i ] = new ( cgPoint . X , cgPoint . Y ) ;
126+ }
127+ _touchEffect . OnTouchAction ( _element , new ( id , actionType , points , isInContact ) ) ;
128+ }
129+ }
0 commit comments