Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

Commit 020fc33

Browse files
authored
[Tizen] Add drag and drop gesture handlers (#13692)
1 parent c16c8c4 commit 020fc33

File tree

8 files changed

+525
-2
lines changed

8 files changed

+525
-2
lines changed
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;
3+
using ElmSharp;
4+
using Tizen.Common;
5+
using Xamarin.Forms.Platform.Tizen.SkiaSharp;
6+
using EGestureType = ElmSharp.GestureLayer.GestureType;
7+
8+
namespace Xamarin.Forms.Platform.Tizen
9+
{
10+
public class DragGestureHandler : GestureHandler
11+
{
12+
bool _isApi4;
13+
14+
DragDropExtensions.Interop.DragIconCreateCallback _iconCallback;
15+
DragDropExtensions.Interop.DragStateCallback _dragDoneCallback;
16+
17+
static bool s_isDragging;
18+
static CustomDragStateData s_currentDragStateData;
19+
20+
public DragGestureHandler(IGestureRecognizer recognizer, IVisualElementRenderer renderer) : base(recognizer)
21+
{
22+
_iconCallback = OnIconCallback;
23+
_dragDoneCallback = OnDragDoneCallback;
24+
_isApi4 = DotnetUtil.TizenAPIVersion <= 4;
25+
Renderer = renderer;
26+
}
27+
28+
public override EGestureType Type => EGestureType.LongTap;
29+
30+
public IVisualElementRenderer Renderer { get; }
31+
32+
public static CustomDragStateData CurrentStateData
33+
{
34+
get
35+
{
36+
return s_currentDragStateData;
37+
}
38+
}
39+
40+
EvasObject NativeView
41+
{
42+
get
43+
{
44+
var native = Renderer.NativeView;
45+
if (Renderer is SkiaSharp.ICanvasRenderer canvasRenderer)
46+
{
47+
native = canvasRenderer.RealNativeView;
48+
}
49+
return native;
50+
}
51+
}
52+
53+
public void ResetCurrentStateData()
54+
{
55+
s_currentDragStateData = null;
56+
}
57+
58+
protected override void OnStarted(View sender, object data)
59+
{
60+
}
61+
62+
protected override void OnMoved(View sender, object data)
63+
{
64+
//Workaround to prevent an error occuring by multiple StartDrag calling in Tizen 6.5
65+
if (!s_isDragging)
66+
{
67+
ResetCurrentStateData();
68+
StartDrag();
69+
}
70+
}
71+
72+
protected override void OnCompleted(View sender, object data)
73+
{
74+
}
75+
76+
protected override void OnCanceled(View sender, object data)
77+
{
78+
}
79+
80+
void StartDrag()
81+
{
82+
if (Recognizer is DragGestureRecognizer dragGestureRecognizer && dragGestureRecognizer.CanDrag)
83+
{
84+
if (Renderer == null)
85+
return;
86+
87+
var arg = dragGestureRecognizer.SendDragStarting(Renderer.Element);
88+
89+
if (arg.Cancel)
90+
return;
91+
92+
s_currentDragStateData = new CustomDragStateData();
93+
s_currentDragStateData.DataPackage = arg.Data;
94+
95+
var target = DragDropExtensions.DragDropContentType.Text;
96+
var strData = string.IsNullOrEmpty(arg.Data.Text) ? " " : arg.Data.Text;
97+
98+
s_isDragging = true;
99+
100+
DragDropExtensions.StartDrag(NativeView,
101+
target,
102+
strData,
103+
DragDropExtensions.DragDropActionType.Move,
104+
_iconCallback,
105+
null,
106+
null,
107+
_dragDoneCallback);
108+
}
109+
}
110+
111+
IntPtr OnIconCallback(IntPtr data, IntPtr window, ref int xoff, ref int yoff)
112+
{
113+
EvasObject icon = null;
114+
EvasObject parent = new CustomWindow(NativeView, window);
115+
116+
if (s_currentDragStateData.DataPackage.Image != null)
117+
{
118+
icon = GetImageIcon(parent);
119+
}
120+
else if (NativeView is ShapeView)
121+
{
122+
icon = GetShapeView(parent);
123+
}
124+
else
125+
{
126+
icon = GetDefaultIcon(parent);
127+
}
128+
var bound = NativeView.Geometry;
129+
bound.X = 0;
130+
bound.Y = 0;
131+
icon.Geometry = bound;
132+
133+
if (icon is Native.Label)
134+
{
135+
icon.Resized += (s, e) =>
136+
{
137+
var map = new EvasMap(4);
138+
map.PopulatePoints(icon.Geometry, 0);
139+
map.Zoom(0.5, 0.5, 0, 0);
140+
icon.IsMapEnabled = true;
141+
icon.EvasMap = map;
142+
};
143+
}
144+
else
145+
{
146+
var map = new EvasMap(4);
147+
map.PopulatePoints(icon.Geometry, 0);
148+
map.Zoom(0.5, 0.5, 0, 0);
149+
icon.IsMapEnabled = true;
150+
icon.EvasMap = map;
151+
}
152+
153+
154+
return icon;
155+
}
156+
157+
EvasObject GetDefaultIcon(EvasObject parent)
158+
{
159+
if (!string.IsNullOrEmpty(s_currentDragStateData.DataPackage.Text))
160+
{
161+
var label = new Native.Label(parent);
162+
label.Text = s_currentDragStateData.DataPackage.Text;
163+
164+
if (Renderer.Element is Label lb)
165+
label.FontSize = lb.FontSize;
166+
else if (Renderer.Element is Entry et)
167+
label.FontSize = et.FontSize;
168+
else if (Renderer.Element is Editor ed)
169+
label.FontSize = ed.FontSize;
170+
171+
return label;
172+
}
173+
else
174+
{
175+
var box = new ElmSharp.Rectangle(parent);
176+
box.Color = new ElmSharp.Color(128, 128, 128, 128);
177+
return box;
178+
}
179+
}
180+
181+
EvasObject GetImageIcon(EvasObject parent)
182+
{
183+
var image = new Native.Image(parent);
184+
_ = image.LoadFromImageSourceAsync(s_currentDragStateData.DataPackage.Image);
185+
return image;
186+
}
187+
188+
EvasObject GetShapeView(EvasObject parent)
189+
{
190+
var copiedImg = new EvasImage(parent);
191+
copiedImg.IsFilled = true;
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+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
using System;
2+
using System.Linq;
3+
using ElmSharp;
4+
using Tizen.Common;
5+
using EGestureType = ElmSharp.GestureLayer.GestureType;
6+
7+
namespace Xamarin.Forms.Platform.Tizen
8+
{
9+
public class DropGestureHandler : GestureHandler
10+
{
11+
bool _isApi4;
12+
13+
DragDropExtensions.Interop.DragStateCallback _dragEnterCallback;
14+
DragDropExtensions.Interop.DragStateCallback _dragLeaveCallback;
15+
DragDropExtensions.Interop.DropCallback _dropCallback;
16+
17+
public override EGestureType Type => default(EGestureType);
18+
19+
public DropGestureHandler(IGestureRecognizer recognizer, IVisualElementRenderer renderer) : base(recognizer)
20+
{
21+
_dragEnterCallback = OnEnterCallback;
22+
_dragLeaveCallback = OnLeaveCallback;
23+
_dropCallback = OnDropCallback;
24+
_isApi4 = DotnetUtil.TizenAPIVersion <= 4;
25+
Renderer = renderer;
26+
}
27+
28+
public IVisualElementRenderer Renderer { get; }
29+
30+
EvasObject NativeView
31+
{
32+
get
33+
{
34+
var native = Renderer.NativeView;
35+
if (Renderer is SkiaSharp.ICanvasRenderer canvasRenderer)
36+
{
37+
native = canvasRenderer.RealNativeView;
38+
}
39+
40+
if (native is Native.Canvas canvas)
41+
{
42+
var child = canvas.Children.LastOrDefault<EvasObject>();
43+
44+
if (child != null)
45+
{
46+
if (child.PassEvents)
47+
child.PassEvents = false;
48+
49+
return child;
50+
}
51+
}
52+
return native;
53+
}
54+
}
55+
56+
57+
public void AddDropGesture()
58+
{
59+
if (Renderer == null)
60+
return;
61+
62+
var target = DragDropExtensions.DragDropContentType.Targets;
63+
64+
DragDropExtensions.AddDropTarget(NativeView,
65+
target,
66+
_dragEnterCallback,
67+
_dragLeaveCallback, null,
68+
_dropCallback);
69+
}
70+
71+
void OnEnterCallback(IntPtr data, IntPtr obj)
72+
{
73+
var currentStateData = DragGestureHandler.CurrentStateData;
74+
if (currentStateData == null)
75+
return;
76+
77+
var arg = new DragEventArgs(currentStateData.DataPackage);
78+
79+
if (Recognizer is DropGestureRecognizer dropRecognizer && dropRecognizer.AllowDrop)
80+
dropRecognizer.SendDragOver(arg);
81+
82+
DragGestureHandler.CurrentStateData.AcceptedOperation = arg.AcceptedOperation;
83+
}
84+
85+
void OnLeaveCallback(IntPtr data, IntPtr obj)
86+
{
87+
var currentStateData = DragGestureHandler.CurrentStateData;
88+
if (currentStateData == null)
89+
return;
90+
91+
var arg = new DragEventArgs(currentStateData.DataPackage);
92+
93+
if (Recognizer is DropGestureRecognizer dropRecognizer && dropRecognizer.AllowDrop)
94+
dropRecognizer.SendDragLeave(arg);
95+
96+
DragGestureHandler.CurrentStateData.AcceptedOperation = arg.AcceptedOperation;
97+
}
98+
99+
bool OnDropCallback(IntPtr data, IntPtr obj, IntPtr selectionData)
100+
{
101+
var currentStateData = DragGestureHandler.CurrentStateData;
102+
103+
if (currentStateData.DataPackage == null || currentStateData.AcceptedOperation == DataPackageOperation.None)
104+
return false;
105+
106+
Device.BeginInvokeOnMainThread(async ()=>
107+
{
108+
if (Recognizer is DropGestureRecognizer dropRecognizer && dropRecognizer.AllowDrop)
109+
await dropRecognizer.SendDrop(new DropEventArgs(currentStateData.DataPackage.View));
110+
});
111+
112+
return true;
113+
}
114+
115+
#region GestureHandler
116+
protected override void OnStarted(View sender, object data)
117+
{
118+
}
119+
120+
protected override void OnMoved(View sender, object data)
121+
{
122+
}
123+
124+
protected override void OnCompleted(View sender, object data)
125+
{
126+
}
127+
128+
protected override void OnCanceled(View sender, object data)
129+
{
130+
}
131+
#endregion
132+
}
133+
}

0 commit comments

Comments
 (0)