Skip to content

Commit ef76db0

Browse files
sung-surookiejava
authored andcommitted
Add GestureManager (#96)
* Add GestureManager * Fix DragGestureHandler * Fix GestureManager * Check nullable enable
1 parent 054e389 commit ef76db0

File tree

11 files changed

+1485
-1
lines changed

11 files changed

+1485
-1
lines changed
Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,137 @@
11
#nullable enable
22

33
using System;
4+
using System.Collections.Specialized;
5+
using System.ComponentModel;
6+
using System.Linq;
47

58
namespace Microsoft.Maui.Controls.Platform
69
{
710
class GestureManager : IDisposable
811
{
12+
IViewHandler? _handler;
13+
GestureDetector? _gestureDetector;
14+
bool _disposed = false;
15+
16+
protected virtual VisualElement? Element => _handler?.VirtualView as VisualElement;
17+
918
public GestureManager(IViewHandler handler)
1019
{
11-
//TODO: Need to impl
20+
_handler = handler;
21+
_gestureDetector = null;
22+
SetupElement(null, Element);
23+
}
24+
25+
void SetupElement(VisualElement? oldElement, VisualElement? newElement)
26+
{
27+
if (oldElement != null)
28+
{
29+
if (oldElement is View ov &&
30+
ov.GestureRecognizers is INotifyCollectionChanged incc)
31+
{
32+
incc.CollectionChanged -= OnGestureRecognizerCollectionChanged;
33+
_gestureDetector?.Clear();
34+
}
35+
oldElement.PropertyChanged -= OnElementPropertyChanged;
36+
}
37+
38+
if (newElement != null)
39+
{
40+
if (newElement is View ov &&
41+
ov.GestureRecognizers is INotifyCollectionChanged incc)
42+
{
43+
incc.CollectionChanged += OnGestureRecognizerCollectionChanged;
44+
if (ov.GestureRecognizers.Count > 0)
45+
{
46+
_gestureDetector = new GestureDetector(_handler);
47+
_gestureDetector.AddGestures(ov.GestureRecognizers);
48+
}
49+
}
50+
newElement.PropertyChanged += OnElementPropertyChanged;
51+
}
52+
53+
UpdateInputTransparent();
54+
UpdateIsEnabled();
55+
}
56+
57+
void OnElementPropertyChanged(object? sender, PropertyChangedEventArgs e)
58+
{
59+
if (e.PropertyName == VisualElement.InputTransparentProperty.PropertyName)
60+
UpdateInputTransparent();
61+
else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
62+
UpdateIsEnabled();
1263
}
1364

1465
public void Dispose()
1566
{
67+
Dispose(true);
68+
GC.SuppressFinalize(this);
69+
}
70+
71+
public void Dispose(bool disposing)
72+
{
73+
if (_disposed)
74+
{
75+
return;
76+
}
77+
78+
_disposed = true;
79+
80+
if (disposing)
81+
{
82+
SetupElement(Element, null);
83+
if (_gestureDetector != null)
84+
{
85+
_gestureDetector.Dispose();
86+
_gestureDetector = null;
87+
}
88+
_handler = null;
89+
}
90+
}
91+
92+
void UpdateInputTransparent()
93+
{
94+
if (Element != null && _gestureDetector != null)
95+
{
96+
_gestureDetector.InputTransparent = Element.InputTransparent;
97+
}
98+
}
99+
100+
void UpdateIsEnabled()
101+
{
102+
if (Element != null && _gestureDetector != null)
103+
{
104+
_gestureDetector.IsEnabled = Element.IsEnabled;
105+
}
106+
}
107+
108+
void OnGestureRecognizerCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
109+
{
110+
if (_gestureDetector == null)
111+
{
112+
_gestureDetector = new GestureDetector(_handler);
113+
}
114+
115+
// Gestures will be registered/unregistered according to changes in the GestureRecognizers list
116+
switch (e.Action)
117+
{
118+
case NotifyCollectionChangedAction.Add:
119+
_gestureDetector.AddGestures(e.NewItems?.OfType<IGestureRecognizer>());
120+
break;
121+
122+
case NotifyCollectionChangedAction.Replace:
123+
_gestureDetector.RemoveGestures(e.OldItems?.OfType<IGestureRecognizer>());
124+
_gestureDetector.AddGestures(e.NewItems?.OfType<IGestureRecognizer>());
125+
break;
126+
127+
case NotifyCollectionChangedAction.Remove:
128+
_gestureDetector.RemoveGestures(e.OldItems?.OfType<IGestureRecognizer>());
129+
break;
130+
131+
case NotifyCollectionChangedAction.Reset:
132+
_gestureDetector.Clear();
133+
break;
134+
}
16135
}
17136
}
18137
}
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using ElmSharp;
4+
using Microsoft.Maui.Controls.Internals;
5+
using Tizen.UIExtensions.ElmSharp;
6+
using EGestureType = ElmSharp.GestureLayer.GestureType;
7+
using TImage = Tizen.UIExtensions.ElmSharp.Image;
8+
using TLabel = Tizen.UIExtensions.ElmSharp.Label;
9+
10+
namespace Microsoft.Maui.Controls.Platform
11+
{
12+
public class DragGestureHandler : GestureHandler
13+
{
14+
DragDropExtensions.Interop.DragIconCreateCallback _iconCallback;
15+
DragDropExtensions.Interop.DragStateCallback _dragDoneCallback;
16+
17+
static bool s_isDragging;
18+
static CustomDragStateData s_currentDragStateData;
19+
20+
protected virtual IView Element => Handler?.VirtualView as IView;
21+
22+
public DragGestureHandler(IGestureRecognizer recognizer, IViewHandler handler) : base(recognizer)
23+
{
24+
_iconCallback = OnIconCallback;
25+
_dragDoneCallback = OnDragDoneCallback;
26+
Handler = handler;
27+
}
28+
29+
public override EGestureType Type => EGestureType.LongTap;
30+
31+
public IViewHandler Handler { get; }
32+
33+
public static CustomDragStateData CurrentStateData
34+
{
35+
get
36+
{
37+
return s_currentDragStateData;
38+
}
39+
}
40+
41+
EvasObject NativeView
42+
{
43+
get
44+
{
45+
return Handler.NativeView as EvasObject;
46+
}
47+
}
48+
49+
public void ResetCurrentStateData()
50+
{
51+
s_currentDragStateData = null;
52+
}
53+
54+
protected override void OnStarted(View sender, object data)
55+
{
56+
}
57+
58+
protected override void OnMoved(View sender, object data)
59+
{
60+
//Workaround to prevent an error occuring by multiple StartDrag calling in Tizen 6.5
61+
if (!s_isDragging)
62+
{
63+
ResetCurrentStateData();
64+
StartDrag();
65+
}
66+
}
67+
68+
protected override void OnCompleted(View sender, object data)
69+
{
70+
}
71+
72+
protected override void OnCanceled(View sender, object data)
73+
{
74+
}
75+
76+
void StartDrag()
77+
{
78+
if (Recognizer is DragGestureRecognizer dragGestureRecognizer && dragGestureRecognizer.CanDrag)
79+
{
80+
if (Handler == null)
81+
return;
82+
83+
var arg = dragGestureRecognizer.SendDragStarting(Element);
84+
85+
if (arg.Cancel)
86+
return;
87+
88+
s_currentDragStateData = new CustomDragStateData();
89+
s_currentDragStateData.DataPackage = arg.Data;
90+
91+
var target = DragDropExtensions.DragDropContentType.Text;
92+
var strData = string.IsNullOrEmpty(arg.Data.Text) ? " " : arg.Data.Text;
93+
94+
s_isDragging = true;
95+
96+
DragDropExtensions.StartDrag(NativeView,
97+
target,
98+
strData,
99+
DragDropExtensions.DragDropActionType.Move,
100+
_iconCallback,
101+
null,
102+
null,
103+
_dragDoneCallback);
104+
}
105+
}
106+
107+
IntPtr OnIconCallback(IntPtr data, IntPtr window, ref int xoff, ref int yoff)
108+
{
109+
EvasObject icon = null;
110+
EvasObject parent = new CustomWindow(NativeView, window);
111+
112+
if (s_currentDragStateData.DataPackage.Image != null)
113+
{
114+
icon = GetImageIconAsync(parent).Result;
115+
}
116+
else if (NativeView is ShapeView)
117+
{
118+
icon = GetShapeView(parent);
119+
}
120+
else
121+
{
122+
icon = GetDefaultIcon(parent);
123+
}
124+
var bound = NativeView.Geometry;
125+
bound.X = 0;
126+
bound.Y = 0;
127+
icon.Geometry = bound;
128+
129+
if (icon is TLabel)
130+
{
131+
icon.Resized += (s, e) =>
132+
{
133+
var map = new EvasMap(4);
134+
map.PopulatePoints(icon.Geometry, 0);
135+
map.Zoom(0.5, 0.5, 0, 0);
136+
icon.IsMapEnabled = true;
137+
icon.EvasMap = map;
138+
};
139+
}
140+
else
141+
{
142+
var map = new EvasMap(4);
143+
map.PopulatePoints(icon.Geometry, 0);
144+
map.Zoom(0.5, 0.5, 0, 0);
145+
icon.IsMapEnabled = true;
146+
icon.EvasMap = map;
147+
}
148+
149+
150+
return icon;
151+
}
152+
153+
EvasObject GetDefaultIcon(EvasObject parent)
154+
{
155+
if (!string.IsNullOrEmpty(s_currentDragStateData.DataPackage.Text))
156+
{
157+
var label = new TLabel(parent);
158+
label.Text = s_currentDragStateData.DataPackage.Text;
159+
160+
if (Element is IFontElement fe)
161+
label.FontSize = fe.FontSize;
162+
163+
return label;
164+
}
165+
else
166+
{
167+
var box = new ElmSharp.Rectangle(parent);
168+
box.Color = new ElmSharp.Color(128, 128, 128, 128);
169+
return box;
170+
}
171+
}
172+
173+
async Task<EvasObject> GetImageIconAsync(EvasObject parent)
174+
{
175+
var image = new TImage(parent);
176+
var mImage = s_currentDragStateData.DataPackage.Image;
177+
var services = Handler.MauiContext?.Services;
178+
var provider = services.GetService(typeof(IImageSourceServiceProvider)) as IImageSourceServiceProvider;
179+
var service = provider?.GetImageSourceService(mImage);
180+
var result = await service.LoadImageAsync(mImage, image);
181+
if (result == null)
182+
return null;
183+
return image;
184+
}
185+
186+
EvasObject GetShapeView(EvasObject parent)
187+
{
188+
var copiedImg = new EvasImage(parent)
189+
{
190+
IsFilled = true
191+
};
192+
193+
if (NativeView is ShapeView shapeView)
194+
{
195+
var canvas = shapeView.SKCanvasView;
196+
var realHandle = DragDropExtensions.Interop.elm_object_part_content_get(canvas, "elm.swallow.content");
197+
198+
DragDropExtensions.Interop.evas_object_image_size_get(realHandle, out int w, out int h);
199+
DragDropExtensions.Interop.evas_object_image_size_set(copiedImg, w, h);
200+
201+
var imgData = DragDropExtensions.Interop.evas_object_image_data_get(realHandle, false);
202+
DragDropExtensions.Interop.evas_object_image_data_set(copiedImg, imgData);
203+
}
204+
205+
return copiedImg;
206+
}
207+
208+
void OnDragDoneCallback(IntPtr data, IntPtr obj)
209+
{
210+
s_isDragging = false;
211+
if (Recognizer is DragGestureRecognizer dragGestureRecognizer && dragGestureRecognizer.CanDrag)
212+
{
213+
dragGestureRecognizer.SendDropCompleted(new DropCompletedEventArgs());
214+
}
215+
}
216+
217+
public class CustomWindow : EvasObject
218+
{
219+
IntPtr _handle;
220+
221+
public CustomWindow(EvasObject parent, IntPtr handle) : base()
222+
{
223+
_handle = handle;
224+
Realize(parent);
225+
}
226+
227+
public CustomWindow(EvasObject handle) : base(handle)
228+
{
229+
}
230+
231+
protected override IntPtr CreateHandle(EvasObject parent)
232+
{
233+
return _handle;
234+
}
235+
}
236+
237+
public class CustomDragStateData
238+
{
239+
public DataPackage DataPackage { get; set; }
240+
public DataPackageOperation AcceptedOperation { get; set; } = DataPackageOperation.Copy;
241+
}
242+
}
243+
}

0 commit comments

Comments
 (0)