Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NUI] Add multi-mimetype feature for Drag and Drop #6294

Merged
merged 3 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/Tizen.NUI/src/internal/Interop/Interop.DragAndDrop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,19 @@ internal enum DragType
public static extern global::System.IntPtr New();

[global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_DragAndDrop_StartDragAndDrop")]
public static extern bool StartDragAndDrop(global::System.Runtime.InteropServices.HandleRef dragAndDrop, global::System.Runtime.InteropServices.HandleRef sourceView, global::System.Runtime.InteropServices.HandleRef shadow, string mimeType, string data, global::System.Runtime.InteropServices.HandleRef callback);
public static extern bool StartDragAndDrop(global::System.Runtime.InteropServices.HandleRef dragAndDrop, global::System.Runtime.InteropServices.HandleRef sourceView, global::System.Runtime.InteropServices.HandleRef shadow, string [] mimeTypes, int mimeTypsSize, string [] dataSet, int dataSetSize, global::System.Runtime.InteropServices.HandleRef callback);

[global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_DragAndDrop_AddListener")]
[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
public static extern bool AddListener(global::System.Runtime.InteropServices.HandleRef dragAndDrop, global::System.Runtime.InteropServices.HandleRef targetView, global::System.Runtime.InteropServices.HandleRef callback);
public static extern bool AddListener(global::System.Runtime.InteropServices.HandleRef dragAndDrop, global::System.Runtime.InteropServices.HandleRef targetView, string mimeType, global::System.Runtime.InteropServices.HandleRef callback);

[global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_DragAndDrop_RemoveListener")]
[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
public static extern bool RemoveListener(global::System.Runtime.InteropServices.HandleRef dragAndDrop, global::System.Runtime.InteropServices.HandleRef targetView, global::System.Runtime.InteropServices.HandleRef callback);

[global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_DragAndDrop_Window_AddListener")]
[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
public static extern bool WindowAddListener(global::System.Runtime.InteropServices.HandleRef dragAndDrop, global::System.Runtime.InteropServices.HandleRef targetWindow, global::System.Runtime.InteropServices.HandleRef callback);
public static extern bool WindowAddListener(global::System.Runtime.InteropServices.HandleRef dragAndDrop, global::System.Runtime.InteropServices.HandleRef targetWindow, string mimeType, global::System.Runtime.InteropServices.HandleRef callback);

[global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_DragAndDrop_Window_RemoveListener")]
[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
Expand All @@ -57,8 +57,8 @@ internal enum DragType
[global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_DragEvent_GetPosition")]
public static extern global::System.IntPtr GetPosition(global::System.IntPtr dragAndDrop);

[global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_DragEvent_GetMimeType")]
public static extern string GetMimeType(global::System.IntPtr dragAndDrop);
[global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_DragEvent_GetMimeTypes")]
public static extern bool GetMimeTypes(global::System.IntPtr dragAndDrop, out global::System.IntPtr mimeTypes, out int count);

[global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_DragEvent_GetData")]
public static extern string GetData(global::System.IntPtr dragAndDrop);
Expand Down
243 changes: 163 additions & 80 deletions src/Tizen.NUI/src/public/DragAndDrop/DragAndDrop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics.CodeAnalysis;
using Tizen.NUI.BaseComponents;

Expand All @@ -32,10 +33,9 @@ public class DragAndDrop : BaseHandle
{
public delegate void SourceEventHandler(DragSourceEventType sourceEventType);
private delegate void InternalSourceEventHandler(int sourceEventType);
public delegate void DragAndDropEventHandler(View targetView, DragEvent dragEvent);
[EditorBrowsable(EditorBrowsableState.Never)]
public delegate void DragAndDropWindowEventHandler(Window targetWindow, DragEvent dragEvent);
private delegate void InternalDragAndDropEventHandler(global::System.IntPtr dragEvent);
public delegate void DragAndDropEventHandler(View targetView, DragEvent navtiveDragEvent);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public delegate void DragAndDropEventHandler(View targetView, DragEvent navtiveDragEvent);
[EditorBrowsable(EditorBrowsableState.Never)]
public delegate void DragAndDropEventHandler(View targetView, DragEvent navtiveDragEvent);

Copy link
Contributor Author

@taehyub taehyub Sep 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

감사합니다. ACR 안되도록 추가완료하였습니다 😄

public delegate void DragAndDropWindowEventHandler(Window targetWindow, DragEvent navtiveDragEvent);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public delegate void DragAndDropWindowEventHandler(Window targetWindow, DragEvent navtiveDragEvent);
[EditorBrowsable(EditorBrowsableState.Never)]
public delegate void DragAndDropWindowEventHandler(Window targetWindow, DragEvent navtiveDragEvent);

private delegate void InternalDragAndDropEventHandler(global::System.IntPtr navtiveDragEvent);
private InternalSourceEventHandler sourceEventCb;
private Dictionary<View, InternalDragAndDropEventHandler> targetEventDictionary = new Dictionary<View, InternalDragAndDropEventHandler>();
private Dictionary<Window, InternalDragAndDropEventHandler> targetWindowEventDictionary = new Dictionary<Window, InternalDragAndDropEventHandler>();
Expand All @@ -46,11 +46,107 @@ public class DragAndDrop : BaseHandle
private int dragWindowOffsetX = 0;
private int dragWindowOffsetY = 0;

private bool initDrag = false;

private const int MinDragWindowWidth = 100;
private const int MinDragWindowHeight = 100;

private void ProcessDragEventTargetCallback(IntPtr navtiveDragEvent, View targetView, DragAndDropEventHandler callback)
{
DragType type = (DragType)Interop.DragAndDrop.GetAction(navtiveDragEvent);
DragEvent dragEvent = new DragEvent();
global::System.IntPtr cPtr = Interop.DragAndDrop.GetPosition(navtiveDragEvent);
dragEvent.Position = (cPtr == global::System.IntPtr.Zero) ? null : new Position(cPtr, true);

IntPtr nativeMimeTypes;
int count;
Interop.DragAndDrop.GetMimeTypes(navtiveDragEvent, out nativeMimeTypes, out count);
if (count > 0)
{
IntPtr [] nativeMimeTypesArrary = new IntPtr[count];
Marshal.Copy(nativeMimeTypes, nativeMimeTypesArrary, 0, count);

string [] managedMimeTypes = new string[count];

for (int iterator = 0; iterator < count; iterator++)
{
managedMimeTypes[iterator] = Marshal.PtrToStringAnsi(nativeMimeTypesArrary[iterator]);
}

dragEvent.MimeType = managedMimeTypes[0];
dragEvent.MimeTypes = managedMimeTypes;
}

if (type == DragType.Enter)
{
dragEvent.DragType = type;
callback(targetView, dragEvent);
}
else if (type == DragType.Leave)
{
dragEvent.DragType = type;
callback(targetView, dragEvent);
}
else if (type == DragType.Move)
{
dragEvent.DragType = type;
callback(targetView, dragEvent);
}
else if (type == DragType.Drop)
{
dragEvent.DragType = type;
dragEvent.Data = Interop.DragAndDrop.GetData(navtiveDragEvent);
callback(targetView, dragEvent);
}
}

private void ProcessDragEventWindowCallback(IntPtr navtiveDragEvent, Window targetWindow, DragAndDropWindowEventHandler callback)
{
DragType type = (DragType)Interop.DragAndDrop.GetAction(navtiveDragEvent);
DragEvent dragEvent = new DragEvent();
global::System.IntPtr cPtr = Interop.DragAndDrop.GetPosition(navtiveDragEvent);
dragEvent.Position = (cPtr == global::System.IntPtr.Zero) ? null : new Position(cPtr, false);

IntPtr nativeMimeTypes;
int count;
Interop.DragAndDrop.GetMimeTypes(navtiveDragEvent, out nativeMimeTypes, out count);
if (count > 0)
{
IntPtr [] nativeMimeTypesArrary = new IntPtr[count];
Marshal.Copy(nativeMimeTypes, nativeMimeTypesArrary, 0, count);

string [] managedMimeTypes = new string[count];

for (int iterator = 0; iterator < count; iterator++)
{
managedMimeTypes[iterator] = Marshal.PtrToStringAnsi(nativeMimeTypesArrary[iterator]);
}

dragEvent.MimeType = managedMimeTypes[0];
dragEvent.MimeTypes = managedMimeTypes;
}

if (type == DragType.Enter)
{
dragEvent.DragType = type;
callback(targetWindow, dragEvent);
}
else if (type == DragType.Leave)
{
dragEvent.DragType = type;
callback(targetWindow, dragEvent);
}
else if (type == DragType.Move)
{
dragEvent.DragType = type;
callback(targetWindow, dragEvent);
}
else if (type == DragType.Drop)
{
dragEvent.DragType = type;
dragEvent.Data = Interop.DragAndDrop.GetData(navtiveDragEvent);
callback(targetWindow, dragEvent);
}
}

private DragAndDrop() : this(Interop.DragAndDrop.New(), true)
{
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
Expand Down Expand Up @@ -92,14 +188,7 @@ private void ReleaseDragWindow()
/// <param name="callback">The source event callback</param>
/// <since_tizen> 10 </since_tizen>
public void StartDragAndDrop(View sourceView, View shadowView, DragData dragData, SourceEventHandler callback)
{
if (initDrag)
{
Tizen.Log.Fatal("NUI", "Start Drag And Drop Initializing...");
return;
}
initDrag = true;

{
if (Window.IsSupportedMultiWindow() == false)
{
throw new NotSupportedException("This device does not support surfaceless_context. So Window cannot be created.");
Expand Down Expand Up @@ -155,7 +244,7 @@ public void StartDragAndDrop(View sourceView, View shadowView, DragData dragData
{
if ((DragSourceEventType)sourceEventType != DragSourceEventType.Start)
{
Tizen.Log.Fatal("NUI", "DnD Source Event is Called");
Tizen.Log.Fatal("NUI", "DnD Source Event is Called");
ReleaseDragWindow();
}

Expand All @@ -165,15 +254,29 @@ public void StartDragAndDrop(View sourceView, View shadowView, DragData dragData
//Show Drag Window before StartDragAndDrop
mDragWindow.Show();

if (!Interop.DragAndDrop.StartDragAndDrop(SwigCPtr, View.getCPtr(sourceView), Window.getCPtr(mDragWindow), dragData.MimeType, dragData.Data,
string [] mimeTypes;
string [] dataSet;

if (string.IsNullOrEmpty(dragData.MimeType))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (string.IsNullOrEmpty(dragData.MimeType))
if (string.IsNullOrEmpty(dragData.MimeType) && dragData.DataMap != null)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 의견 감사합니다 😄

{
mimeTypes = dragData.DataMap.Keys.ToArray();
dataSet = dragData.DataMap.Values.ToArray();
myroot marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
mimeTypes = new string[1];
mimeTypes[0] = dragData.MimeType;

dataSet = new string[1];
dataSet[0] = dragData.Data;
}

if (!Interop.DragAndDrop.StartDragAndDrop(SwigCPtr, View.getCPtr(sourceView), Window.getCPtr(mDragWindow), mimeTypes, mimeTypes.Length, dataSet, dataSet.Length,
new global::System.Runtime.InteropServices.HandleRef(this, Marshal.GetFunctionPointerForDelegate<Delegate>(sourceEventCb))))
{
throw new InvalidOperationException("Fail to StartDragAndDrop");
}

}

initDrag = false;
}
}

/// <summary>
Expand All @@ -184,42 +287,31 @@ public void StartDragAndDrop(View sourceView, View shadowView, DragData dragData
/// <since_tizen> 10 </since_tizen>
public void AddListener(View targetView, DragAndDropEventHandler callback)
{
InternalDragAndDropEventHandler cb = (dragEvent) =>
InternalDragAndDropEventHandler cb = (navtiveDragEvent) => ProcessDragEventTargetCallback(navtiveDragEvent, targetView, callback);

targetEventDictionary.Add(targetView, cb);

if (!Interop.DragAndDrop.AddListener(SwigCPtr, View.getCPtr(targetView), "*/*",
new global::System.Runtime.InteropServices.HandleRef(this, Marshal.GetFunctionPointerForDelegate<Delegate>(cb))))
{
DragType type = (DragType)Interop.DragAndDrop.GetAction(dragEvent);
DragEvent ev = new DragEvent();
global::System.IntPtr cPtr = Interop.DragAndDrop.GetPosition(dragEvent);
ev.Position = (cPtr == global::System.IntPtr.Zero) ? null : new Position(cPtr, true);
throw new InvalidOperationException("Fail to AddListener for View");
}
}

if (type == DragType.Enter)
{
ev.DragType = type;
ev.MimeType = Interop.DragAndDrop.GetMimeType(dragEvent);
callback(targetView, ev);
}
else if (type == DragType.Leave)
{
ev.DragType = type;
callback(targetView, ev);
}
else if (type == DragType.Move)
{
ev.DragType = type;
ev.MimeType = Interop.DragAndDrop.GetMimeType(dragEvent);
callback(targetView, ev);
}
else if (type == DragType.Drop)
{
ev.DragType = type;
ev.MimeType = Interop.DragAndDrop.GetMimeType(dragEvent);
ev.Data = Interop.DragAndDrop.GetData(dragEvent);
callback(targetView, ev);
}
};
/// <summary>
/// Adds listener for drop targets
/// </summary>
/// <param name="targetView">The target view</param>
/// <param name="mimeType">The mime type for target view</param>
/// <param name="callback">The callback function to get drag event when the drag source enters, moves, leaves and drops on the drop target</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public void AddListener(View targetView, string mimeType, DragAndDropEventHandler callback)
{
InternalDragAndDropEventHandler cb = (navtiveDragEvent) => ProcessDragEventTargetCallback(navtiveDragEvent, targetView, callback);

targetEventDictionary.Add(targetView, cb);

if (!Interop.DragAndDrop.AddListener(SwigCPtr, View.getCPtr(targetView),
if (!Interop.DragAndDrop.AddListener(SwigCPtr, View.getCPtr(targetView), mimeType,
new global::System.Runtime.InteropServices.HandleRef(this, Marshal.GetFunctionPointerForDelegate<Delegate>(cb))))
{
throw new InvalidOperationException("Fail to AddListener for View");
Expand Down Expand Up @@ -256,40 +348,31 @@ public void RemoveListener(View targetView, DragAndDropEventHandler _)
[EditorBrowsable(EditorBrowsableState.Never)]
public void AddListener(Window targetWindow, DragAndDropWindowEventHandler callback)
{
InternalDragAndDropEventHandler cb = (dragEvent) =>
InternalDragAndDropEventHandler cb = (navtiveDragEvent) => ProcessDragEventWindowCallback(navtiveDragEvent, targetWindow, callback);

targetWindowEventDictionary.Add(targetWindow, cb);

if (!Interop.DragAndDrop.WindowAddListener(SwigCPtr, Window.getCPtr(targetWindow), "*/*",
new global::System.Runtime.InteropServices.HandleRef(this, Marshal.GetFunctionPointerForDelegate<Delegate>(cb))))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
InternalDragAndDropEventHandler cb = (navtiveDragEvent) => ProcessDragEventWindowCallback(navtiveDragEvent, targetWindow, callback);
targetWindowEventDictionary.Add(targetWindow, cb);
if (!Interop.DragAndDrop.WindowAddListener(SwigCPtr, Window.getCPtr(targetWindow), "*/*",
new global::System.Runtime.InteropServices.HandleRef(this, Marshal.GetFunctionPointerForDelegate<Delegate>(cb))))
AddListener(targetWindow, "*/*", callback);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 기존 함수를 통해서 중복 코드를 없애면 코드가 훨씬 간결해지고 가독성이 올라가는 것 같습니다 😄

{
DragType type = (DragType)Interop.DragAndDrop.GetAction(dragEvent);
DragEvent ev = new DragEvent();
global::System.IntPtr cPtr = Interop.DragAndDrop.GetPosition(dragEvent);
ev.Position = (cPtr == global::System.IntPtr.Zero) ? null : new Position(cPtr, false);
throw new InvalidOperationException("Fail to AddListener for Window");
}
}

if (type == DragType.Enter)
{
ev.DragType = type;
callback(targetWindow, ev);
}
else if (type == DragType.Leave)
{
ev.DragType = type;
callback(targetWindow, ev);
}
else if (type == DragType.Move)
{
ev.DragType = type;
callback(targetWindow, ev);
}
else if (type == DragType.Drop)
{
ev.DragType = type;
ev.MimeType = Interop.DragAndDrop.GetMimeType(dragEvent);
ev.Data = Interop.DragAndDrop.GetData(dragEvent);
callback(targetWindow, ev);
}
};
/// <summary>
/// Adds listener for drop targets
/// </summary>
/// <param name="targetWindow">The target Window</param>
/// <param name="mimeType">The mime type for target view</param>
/// <param name="callback">The callback function to get drag event when the drag source enters, moves, leaves and drops on the drop target</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public void AddListener(Window targetWindow, string mimeType, DragAndDropWindowEventHandler callback)
{
InternalDragAndDropEventHandler cb = (navtiveDragEvent) => ProcessDragEventWindowCallback(navtiveDragEvent, targetWindow, callback);

targetWindowEventDictionary.Add(targetWindow, cb);

if (!Interop.DragAndDrop.WindowAddListener(SwigCPtr, Window.getCPtr(targetWindow),
if (!Interop.DragAndDrop.WindowAddListener(SwigCPtr, Window.getCPtr(targetWindow), mimeType,
new global::System.Runtime.InteropServices.HandleRef(this, Marshal.GetFunctionPointerForDelegate<Delegate>(cb))))
{
throw new InvalidOperationException("Fail to AddListener for Window");
Expand Down
Loading
Loading