[dali_1.3.53] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / drag-drop-detector / drag-and-drop-detector-impl.cpp
1 /*
2  * Copyright (c) 2018 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
18 // CLASS HEADER
19 #include <dali-toolkit/internal/drag-drop-detector/drag-and-drop-detector-impl.h>
20
21 #include <dali/public-api/events/point-state.h>
22 #include <dali/public-api/events/touch-data.h>
23
24 namespace Dali
25 {
26
27 namespace Toolkit
28 {
29
30 namespace Internal
31 {
32
33 Dali::Toolkit::DragAndDropDetector DragAndDropDetector::New()
34 {
35   Dali::Toolkit::DragAndDropDetector detector = Dali::Toolkit::DragAndDropDetector(new DragAndDropDetector());
36
37   return detector;
38 }
39
40 void DragAndDropDetector::Attach(Dali::Toolkit::Control& control)
41 {
42   if(control)
43   {
44     if(!mControls.empty())
45     {
46       auto match = std::find(mControls.begin(), mControls.end(), control);
47       if(match != mControls.end())
48       {
49         return;
50       }
51     }
52     mControls.push_back(control);
53     control.TouchSignal().Connect(this, &DragAndDropDetector::OnDrag);
54     mFirstEnter.push_back(control.GetId());
55     mPanGestureDetector.Attach(control);
56     mPanGestureDetector.DetectedSignal().Connect(this, &DragAndDropDetector::OnPan);
57   }
58
59 }
60
61 void DragAndDropDetector::Detach(Dali::Toolkit::Control& control)
62 {
63   if(!mControls.empty())
64   {
65     if(!control)
66     {
67       return;
68     }
69
70     auto match = std::find(mControls.begin(), mControls.end(), control);
71
72     if(match != mControls.end())
73     {
74       match->TouchSignal().Disconnect(this, &DragAndDropDetector::OnDrag);
75       mPanGestureDetector.Detach(*match);
76       mFirstEnter.erase(std::find(mFirstEnter.begin(), mFirstEnter.end(), control.GetId()));
77       mControls.erase(match);
78     }
79   }
80 }
81
82 void DragAndDropDetector::DetachAll()
83 {
84   if(!mControls.empty())
85   {
86     auto iter = mControls.begin();
87     for(;iter != mControls.end();)
88     {
89       iter->TouchSignal().Disconnect(this, &DragAndDropDetector::OnDrag);
90       mPanGestureDetector.Detach(*iter);
91       iter = mControls.erase(iter);
92     }
93   }
94
95   if(!mFirstEnter.empty())
96   {
97     auto iter = mFirstEnter.begin();
98     for(;iter != mFirstEnter.end();)
99     {
100       iter = mFirstEnter.erase(iter);
101     }
102   }
103 }
104
105 uint32_t DragAndDropDetector::GetAttachedControlCount() const
106 {
107   return mControls.size();
108 }
109
110 Dali::Toolkit::Control DragAndDropDetector::GetAttachedControl(uint32_t index) const
111 {
112   Dali::Toolkit::Control control;
113
114   if(index < mControls.size())
115   {
116     control = mControls[index];
117   }
118
119   return control;
120 }
121
122 void DragAndDropDetector::OnPan(Dali::Actor actor, const PanGesture& gesture)
123 {
124   Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
125
126   if(gesture.state == Gesture::Started)
127   {
128     mDragLocalPosition = gesture.position;
129   }
130   if(gesture.state == Gesture::Continuing)
131   {
132       Vector2 screenPosition = gesture.screenPosition;
133       control.GetParent().ScreenToLocal(mLocalPosition.x, mLocalPosition.y, screenPosition.x, screenPosition.y);
134       mShadowControl.SetPosition(mLocalPosition.x - mDragLocalPosition.x, mLocalPosition.y - mDragLocalPosition.y);
135   }
136   if(gesture.state == Gesture::Finished)
137   {
138     mDragControl.GetParent().Remove(mShadowControl);
139     EmitEndedSignal(control);
140   }
141 }
142
143 bool DragAndDropDetector::OnDrag(Dali::Actor actor, const Dali::TouchData& data)
144 {
145   Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
146   PointState::Type type = data.GetState(0);
147   if(type == PointState::DOWN)
148   {
149     mPointDown = true;
150     mDragControl = control;
151     mFirstEnter.clear();
152     for( auto&& control : mControls)
153     {
154       mFirstEnter.push_back(control.GetId());
155     }
156     float width = control.GetProperty<float>(Dali::Actor::Property::SIZE_WIDTH);
157     float height = control.GetProperty<float>(Dali::Actor::Property::SIZE_HEIGHT);
158     Vector3 actorPos = control.GetProperty<Vector3>(Dali::Actor::Property::POSITION);
159
160     mShadowControl = Dali::Toolkit::Control::New();
161     mShadowControl.SetPosition(actorPos);
162     mShadowControl.SetSize(width, height);
163     mShadowControl.SetBackgroundColor(Vector4(0.3f, 0.3f, 0.3f, 0.7f));
164     mShadowControl.SetParentOrigin(control.GetCurrentParentOrigin());
165     mShadowControl.SetAnchorPoint(control.GetCurrentAnchorPoint());
166     control.GetParent().Add(mShadowControl);
167     SetPosition(data.GetScreenPosition(0));
168     EmitStartedSignal(control);
169   }
170
171   if(type == PointState::MOTION)
172   {
173     if(mDragControl != control && mPointDown)
174     {
175       auto found = std::find(mFirstEnter.begin(), mFirstEnter.end(), control.GetId());
176       if(mFirstEnter.end() != found)
177       {
178         SetPosition(data.GetScreenPosition(0));
179         mFirstEnter.erase(found);
180         EmitEnteredSignal(control);
181       }
182       else
183       {
184         SetPosition(data.GetScreenPosition(0));
185         EmitMovedSignal(control);
186       }
187     }
188   }
189
190   if(type == PointState::LEAVE)
191   {
192     if(mDragControl != control && mPointDown)
193     {
194       mFirstEnter.push_back(control.GetId());
195       EmitExitedSignal(control);
196     }
197   }
198
199   if(type == PointState::UP)
200   {
201     if(mDragControl != control && mPointDown)
202     {
203       SetPosition(data.GetScreenPosition(0));
204       ClearContent();
205       SetContent(mDragControl.GetName());
206       EmitDroppedSignal(control);
207     }
208
209     if(mShadowControl)
210     {
211     control.GetParent().Remove(mShadowControl);
212     }
213     mPointDown = false;
214   }
215   return true;
216 }
217
218 const std::string& DragAndDropDetector::GetContent() const
219 {
220   return mContent;
221 }
222
223 const Vector2& DragAndDropDetector::GetCurrentScreenPosition() const
224 {
225   return mScreenPosition;
226 }
227
228 void DragAndDropDetector::SetContent( const std::string& content )
229 {
230   mContent = content;
231 }
232
233 void DragAndDropDetector::ClearContent()
234 {
235   mContent.clear();
236 }
237
238 void DragAndDropDetector::SetPosition( const Vector2& screenPosition )
239 {
240   mScreenPosition = screenPosition;
241 }
242
243 void DragAndDropDetector::EmitStartedSignal(Dali::Toolkit::Control& control)
244 {
245   if( !mStartedSignal.Empty() )
246   {
247     Dali::Toolkit::DragAndDropDetector handle( this );
248     mStartedSignal.Emit( control, handle );
249   }
250 }
251 void DragAndDropDetector::EmitEnteredSignal(Dali::Toolkit::Control& control)
252 {
253   if ( !mEnteredSignal.Empty() )
254   {
255     Dali::Toolkit::DragAndDropDetector handle( this );
256     mEnteredSignal.Emit( control, handle );
257   }
258 }
259
260 void DragAndDropDetector::EmitExitedSignal(Dali::Toolkit::Control& control)
261 {
262   if ( !mExitedSignal.Empty() )
263   {
264     Dali::Toolkit::DragAndDropDetector handle( this );
265     mExitedSignal.Emit( control, handle );
266   }
267 }
268
269 void DragAndDropDetector::EmitMovedSignal(Dali::Toolkit::Control& control)
270 {
271   if ( !mMovedSignal.Empty() )
272   {
273     Dali::Toolkit::DragAndDropDetector handle( this );
274     mMovedSignal.Emit( control, handle );
275   }
276 }
277
278 void DragAndDropDetector::EmitDroppedSignal(Dali::Toolkit::Control& control)
279 {
280   if ( !mDroppedSignal.Empty() )
281   {
282     Dali::Toolkit::DragAndDropDetector handle( this );
283     mDroppedSignal.Emit( control, handle );
284   }
285 }
286
287 void DragAndDropDetector::EmitEndedSignal(Dali::Toolkit::Control& control)
288 {
289   if( !mEndedSignal.Empty() )
290   {
291     Dali::Toolkit::DragAndDropDetector handle( this );
292     mEndedSignal.Emit( control, handle );
293   }
294 }
295
296 DragAndDropDetector::DragAndDropDetector()
297 : mContent(),
298   mScreenPosition()
299 {
300   mPanGestureDetector = Dali::PanGestureDetector::New();
301   mPointDown = false;
302 }
303
304 DragAndDropDetector::~DragAndDropDetector()
305 {
306 }
307
308 } // namespace Internal
309
310 } //namespace Toolkit
311
312 } // namespace Dali