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