[NUI] Add New NUI DnD Class and Demo
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / DragAndDrop / DragAndDrop.cs
1 /*
2  * Copyright(c) 2022 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 using System;
18 using System.ComponentModel;
19 using System.Runtime.InteropServices;
20 using System.Collections.Generic;
21 using System.Diagnostics.CodeAnalysis;
22 using Tizen.NUI.BaseComponents;
23
24 namespace Tizen.NUI
25 {
26     /// <summary>
27     /// DragAndDrop controls the drag objet and data.
28     /// </summary>
29     [EditorBrowsable(EditorBrowsableState.Never)]
30     public class DragAndDrop : BaseHandle
31     {
32         [EditorBrowsable(EditorBrowsableState.Never)]
33         public delegate void DragAndDropEventHandler(View targetView, DragEvent dragEvent);
34         private delegate void InternalDragAndDropEventHandler(global::System.IntPtr dragEvent);
35         private Dictionary<View, InternalDragAndDropEventHandler> targetEventDictionary = new Dictionary<View, InternalDragAndDropEventHandler>();
36
37         [EditorBrowsable(EditorBrowsableState.Never)]
38         private DragAndDrop() : this(Interop.DragAndDrop.New(), true)
39         {
40             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
41         }
42
43         private DragAndDrop(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
44         {
45
46         }
47
48         [EditorBrowsable(EditorBrowsableState.Never)]
49         public static DragAndDrop Instance { get; } = new DragAndDrop();
50
51         /// <summary>
52         /// Starts drag and drop.
53         /// </summary>
54         /// <param name="sourceView">The soruce view</param>
55         /// <param name="shadowView">The shadow view for drag object</param>
56         /// <param name="dragData">The data to send</param>
57         [EditorBrowsable(EditorBrowsableState.Never)]
58         public void StartDragAndDrop(View sourceView, View shadowView, DragData dragData)
59         {
60             if (!Interop.DragAndDrop.StartDragAndDrop(SwigCPtr, View.getCPtr(sourceView), View.getCPtr(shadowView), dragData.MimeType, dragData.Data))
61             {
62                 throw new InvalidOperationException("Fail to StartDragAndDrop");
63             }
64         }
65
66         /// <summary>
67         /// Adds listener for drop targets
68         /// </summary>
69         /// <param name="targetView">The target view</param>
70         /// <param name="callback">The callback function to get drag event</param>
71         [EditorBrowsable(EditorBrowsableState.Never)]
72         public void AddListener(View targetView, DragAndDropEventHandler callback)
73         {
74             InternalDragAndDropEventHandler cb = (dragEvent) =>
75             {
76                 DragType type = (DragType)Interop.DragAndDrop.GetAction(dragEvent);
77                 DragEvent ev = new DragEvent();
78                 global::System.IntPtr cPtr = Interop.DragAndDrop.GetPosition(dragEvent);
79                 ev.Position = (cPtr == global::System.IntPtr.Zero) ? null : new Position(cPtr, false);
80
81                 if (type == DragType.Enter)
82                 {
83                     ev.DragType = type;
84                     callback(targetView, ev);
85                 }
86                 else if (type == DragType.Leave)
87                 {
88                     ev.DragType = type;
89                     callback(targetView, ev);
90                 }
91                 else if (type == DragType.Move)
92                 {
93                     ev.DragType = type;
94                     callback(targetView, ev);
95                 }
96                 else if (type == DragType.Drop)
97                 {
98                     ev.DragType = type;
99                     ev.MimeType = Interop.DragAndDrop.GetMimeType(dragEvent);
100                     ev.Data = Interop.DragAndDrop.GetData(dragEvent);
101                     callback(targetView, ev);
102                 }
103             };
104
105             targetEventDictionary.Add(targetView, cb);
106
107             if (!Interop.DragAndDrop.AddListener(SwigCPtr, View.getCPtr(targetView),
108                                                  new global::System.Runtime.InteropServices.HandleRef(this, Marshal.GetFunctionPointerForDelegate<Delegate>(cb))))
109             {
110                  throw new InvalidOperationException("Fail to AddListener");
111             }
112         }
113
114         /// <summary>
115         /// Removes listener for drop targets
116         /// </summary>
117         /// <param name="targetView">The target view</param>
118         /// <param name="callback">The callback function to remove</param>
119         [EditorBrowsable(EditorBrowsableState.Never)]
120         public void RemoveListener(View targetView, DragAndDropEventHandler callback)
121         {
122             if (!targetEventDictionary.ContainsKey(targetView))
123             {
124                  throw new InvalidOperationException("Fail to RemoveListener");
125             }
126
127             InternalDragAndDropEventHandler cb = targetEventDictionary[targetView];
128             targetEventDictionary.Remove(targetView);
129             if (!Interop.DragAndDrop.RemoveListener(SwigCPtr, View.getCPtr(targetView),
130                                                     new global::System.Runtime.InteropServices.HandleRef(this, Marshal.GetFunctionPointerForDelegate<Delegate>(cb))))
131             {
132                  throw new InvalidOperationException("Fail to RemoveListener");
133             }
134         }
135     }
136 }