f1aec26c51b278b6bf07b9a1236f180fa10c94d8
[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.GetProperty< int >( Actor::Property::ID ));
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.GetProperty< int >( Actor::Property::ID )));
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     mPointDown = true;
130     mDragControl = control;
131     mFirstEnter.clear();
132     for( auto&& control : mControls)
133     {
134       mFirstEnter.push_back(control.GetProperty< int >( Actor::Property::ID ));
135     }
136     float width = control.GetProperty<float>(Dali::Actor::Property::SIZE_WIDTH);
137     float height = control.GetProperty<float>(Dali::Actor::Property::SIZE_HEIGHT);
138     Vector3 actorPos = control.GetProperty<Vector3>(Dali::Actor::Property::POSITION);
139
140     mShadowControl = Dali::Toolkit::Control::New();
141     mShadowControl.SetProperty( Actor::Property::POSITION, actorPos );
142     mShadowControl.SetProperty( Actor::Property::SIZE, Vector2( width, height ) );
143     mShadowControl.SetBackgroundColor(Vector4(0.3f, 0.3f, 0.3f, 0.7f));
144     mShadowControl.SetProperty( Actor::Property::PARENT_ORIGIN, control.GetCurrentProperty< Vector3 >( Actor::Property::PARENT_ORIGIN ) );
145     mShadowControl.SetProperty( Actor::Property::ANCHOR_POINT,control.GetCurrentProperty< Vector3 >( Actor::Property::ANCHOR_POINT ));
146     control.GetParent().Add(mShadowControl);
147     SetPosition(gesture.screenPosition);
148     EmitStartedSignal(control);
149   }
150   if(gesture.state == Gesture::Continuing)
151   {
152       Vector2 screenPosition = gesture.screenPosition;
153       control.GetParent().ScreenToLocal(mLocalPosition.x, mLocalPosition.y, screenPosition.x, screenPosition.y);
154       mShadowControl.SetProperty( Actor::Property::POSITION, Vector2(mLocalPosition.x - mDragLocalPosition.x, mLocalPosition.y - mDragLocalPosition.y));
155   }
156   if(gesture.state == Gesture::Finished)
157   {
158     mDragControl.GetParent().Remove(mShadowControl);
159     EmitEndedSignal(control);
160   }
161 }
162
163 bool DragAndDropDetector::OnDrag(Dali::Actor actor, const Dali::TouchData& data)
164 {
165   Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
166   PointState::Type type = data.GetState(0);
167
168   if(type == PointState::MOTION)
169   {
170     if(mDragControl != control && mPointDown)
171     {
172       auto found = std::find(mFirstEnter.begin(), mFirstEnter.end(), control.GetProperty< int >( Actor::Property::ID ));
173       if(mFirstEnter.end() != found)
174       {
175         SetPosition(data.GetScreenPosition(0));
176         mFirstEnter.erase(found);
177         EmitEnteredSignal(control);
178       }
179       else
180       {
181         SetPosition(data.GetScreenPosition(0));
182         EmitMovedSignal(control);
183       }
184     }
185   }
186
187   if(type == PointState::LEAVE)
188   {
189     if(mDragControl != control && mPointDown)
190     {
191       mFirstEnter.push_back(control.GetProperty< int >( Actor::Property::ID ));
192       EmitExitedSignal(control);
193     }
194   }
195
196   if(type == PointState::UP)
197   {
198     if(mDragControl != control && mPointDown)
199     {
200       SetPosition(data.GetScreenPosition(0));
201       ClearContent();
202       SetContent(mDragControl.GetProperty< std::string >( Dali::Actor::Property::NAME ));
203       EmitDroppedSignal(control);
204     }
205
206     if(mShadowControl)
207     {
208     control.GetParent().Remove(mShadowControl);
209     }
210     mPointDown = false;
211   }
212   return true;
213 }
214
215 const std::string& DragAndDropDetector::GetContent() const
216 {
217   return mContent;
218 }
219
220 const Vector2& DragAndDropDetector::GetCurrentScreenPosition() const
221 {
222   return mScreenPosition;
223 }
224
225 void DragAndDropDetector::SetContent( const std::string& content )
226 {
227   mContent = content;
228 }
229
230 void DragAndDropDetector::ClearContent()
231 {
232   mContent.clear();
233 }
234
235 void DragAndDropDetector::SetPosition( const Vector2& screenPosition )
236 {
237   mScreenPosition = screenPosition;
238 }
239
240 void DragAndDropDetector::EmitStartedSignal(Dali::Toolkit::Control& control)
241 {
242   if( !mStartedSignal.Empty() )
243   {
244     Dali::Toolkit::DragAndDropDetector handle( this );
245     mStartedSignal.Emit( control, handle );
246   }
247 }
248 void DragAndDropDetector::EmitEnteredSignal(Dali::Toolkit::Control& control)
249 {
250   if ( !mEnteredSignal.Empty() )
251   {
252     Dali::Toolkit::DragAndDropDetector handle( this );
253     mEnteredSignal.Emit( control, handle );
254   }
255 }
256
257 void DragAndDropDetector::EmitExitedSignal(Dali::Toolkit::Control& control)
258 {
259   if ( !mExitedSignal.Empty() )
260   {
261     Dali::Toolkit::DragAndDropDetector handle( this );
262     mExitedSignal.Emit( control, handle );
263   }
264 }
265
266 void DragAndDropDetector::EmitMovedSignal(Dali::Toolkit::Control& control)
267 {
268   if ( !mMovedSignal.Empty() )
269   {
270     Dali::Toolkit::DragAndDropDetector handle( this );
271     mMovedSignal.Emit( control, handle );
272   }
273 }
274
275 void DragAndDropDetector::EmitDroppedSignal(Dali::Toolkit::Control& control)
276 {
277   if ( !mDroppedSignal.Empty() )
278   {
279     Dali::Toolkit::DragAndDropDetector handle( this );
280     mDroppedSignal.Emit( control, handle );
281   }
282 }
283
284 void DragAndDropDetector::EmitEndedSignal(Dali::Toolkit::Control& control)
285 {
286   if( !mEndedSignal.Empty() )
287   {
288     Dali::Toolkit::DragAndDropDetector handle( this );
289     mEndedSignal.Emit( control, handle );
290   }
291 }
292
293 DragAndDropDetector::DragAndDropDetector()
294 : mContent(),
295   mScreenPosition()
296 {
297   mPanGestureDetector = Dali::PanGestureDetector::New();
298   mPointDown = false;
299 }
300
301 DragAndDropDetector::~DragAndDropDetector()
302 {
303 }
304
305 } // namespace Internal
306
307 } //namespace Toolkit
308
309 } // namespace Dali