add test example for drag&drop
[platform/core/uifw/dali-demo.git] / examples / drag-and-drop / drag-and-drop-example.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 #include <dali-toolkit/dali-toolkit.h>
19 #include <dali/integration-api/debug.h>
20 #include <dali/devel-api/actors/actor-devel.h>
21 #include <dali-toolkit/devel-api/drag-drop-detector/drag-and-drop-detector.h>
22
23 using namespace Dali;
24 using Dali::Toolkit::TextLabel;
25 using namespace Dali::Toolkit;
26
27 namespace
28 {
29 Vector4 TEXT_LABEL_COLOR[] =
30 {
31   Color::MAGENTA,
32   Color::YELLOW,
33   Color::CYAN,
34   Color::BLUE,
35   Color::MAGENTA,
36   Color::YELLOW,
37   Color::CYAN,
38   Color::BLUE
39 };
40
41 const float TEXT_LABEL_POSITION_X = 100.0f;
42 const float TEXT_LABEL_POSITION_START_Y = 50.0f;
43 const float TEXT_LABEL_WIDTH = 250.0f;
44 const float TEXT_LABEL_HEIGHT = 70.0f;
45 const unsigned int TEXT_LABEL_NUM = sizeof(TEXT_LABEL_COLOR) / sizeof(TEXT_LABEL_COLOR[0]);
46
47 #if defined(DEBUG_ENABLED)
48   Debug::Filter* gDragAndDropFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DRAG_AND_DROP_EXAMPLE");
49 #endif
50 }
51
52 //This example shows how to use drag and drop function by several simple TextActors
53 class DragAndDropExample : public ConnectionTracker
54 {
55 public:
56
57   DragAndDropExample( Application& application )
58   : mApplication( application ),
59     mDragIndex(-1),
60     mDragRealIndex(-1),
61     mDroppedFinished(false)
62   {
63     // Connect to the Application's Init signal
64     mApplication.InitSignal().Connect( this, &DragAndDropExample::Create );
65   }
66
67   // The Init signal is received once (only) during the Application lifetime
68   void Create( Application& application )
69   {
70     Stage stage = Stage::GetCurrent();
71     stage.SetBackgroundColor( Color::WHITE );
72
73     mDragAndDropDetector = Dali::Toolkit::DragAndDropDetector::New();
74
75     // Respond to key events
76     stage.KeyEventSignal().Connect( this, &DragAndDropExample::OnKeyEvent );
77
78     TextLabel hintText = TextLabel::New("please drag one textlabel, move and drop on other textlabel");
79     hintText.SetPosition(0.0f, 700.0f);
80     hintText.SetParentOrigin(ParentOrigin::TOP_LEFT);
81     hintText.SetAnchorPoint(AnchorPoint::TOP_LEFT);
82     hintText.SetProperty(TextLabel::Property::MULTI_LINE, true);
83     stage.Add(hintText);
84
85     for(unsigned int i = 0 ; i < TEXT_LABEL_NUM; i++)
86     {
87       std::string str = "textlabel ";
88       mTextLabel[i] = TextLabel::New(str + std::to_string(i));
89       mTextLabel[i].SetParentOrigin(ParentOrigin::TOP_LEFT);
90       mTextLabel[i].SetAnchorPoint(AnchorPoint::TOP_LEFT);
91       mTextLabel[i].SetName("textlabel " + std::to_string(i));
92       mTextLabel[i].SetLeaveRequired(true);
93       mTextLabel[i].SetProperty(TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER");
94       mTextLabel[i].SetProperty(TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER");
95       mTextLabel[i].SetBackgroundColor(TEXT_LABEL_COLOR[i]);
96
97       mTextLabel[i].SetSize(TEXT_LABEL_WIDTH, TEXT_LABEL_HEIGHT);
98       mTextLabel[i].SetPosition(TEXT_LABEL_POSITION_X, TEXT_LABEL_POSITION_START_Y + TEXT_LABEL_HEIGHT * i);
99       mDragAndDropDetector.Attach(mTextLabel[i]);
100
101       mRect[i] = Rect<float>(TEXT_LABEL_POSITION_X, TEXT_LABEL_POSITION_START_Y + TEXT_LABEL_HEIGHT * i, TEXT_LABEL_WIDTH, TEXT_LABEL_HEIGHT);
102       mOrder[i] = i;
103
104       stage.Add(mTextLabel[i]);
105     }
106
107     mDragAndDropDetector.StartedSignal().Connect(this, &DragAndDropExample::OnStart);
108     mDragAndDropDetector.EnteredSignal().Connect(this, &DragAndDropExample::OnEnter);
109     mDragAndDropDetector.ExitedSignal().Connect(this, &DragAndDropExample::OnExit);
110     mDragAndDropDetector.MovedSignal().Connect(this, &DragAndDropExample::OnMoved);
111     mDragAndDropDetector.DroppedSignal().Connect(this, &DragAndDropExample::OnDropped);
112     mDragAndDropDetector.EndedSignal().Connect(this, &DragAndDropExample::OnEnd);
113   }
114
115   void OnKeyEvent( const KeyEvent& event )
116   {
117     if( event.state == KeyEvent::Down )
118     {
119       if ( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) )
120       {
121         mApplication.Quit();
122       }
123     }
124   }
125
126   void OnStart(Control control, Dali::Toolkit::DragAndDropDetector detector)
127   {
128     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---OnStart---\n");
129     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---control name is %s---\n", control.GetName().c_str());
130
131     control.SetOpacity(0.1f);
132     Vector2 screenPos  = detector.GetCurrentScreenPosition();
133     control.ScreenToLocal(mDragLocalPos.x, mDragLocalPos.y,screenPos.x, screenPos.y );
134     Rect<float> targetRect(screenPos.x, screenPos.y, 0.0f, 0.0f);
135
136     for(unsigned int i = 0; i < TEXT_LABEL_NUM; i++)
137     {
138       if(mRect[i].Contains(targetRect))
139       {
140         mDragIndex = i;
141       }
142     }
143
144     mDragRealIndex = mOrder[mDragIndex];
145   }
146
147   void OnEnter(Control control, Dali::Toolkit::DragAndDropDetector detector)
148   {
149     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---OnEnter---\n");
150     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---control name is %s---\n", control.GetName().c_str());
151   }
152
153   void OnExit(Control control, Dali::Toolkit::DragAndDropDetector detector)
154   {
155     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---OnExit---\n");
156     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---control name is %s---\n", control.GetName().c_str());
157   }
158
159   void OnMoved(Control control, Dali::Toolkit::DragAndDropDetector detector)
160   {
161     DALI_LOG_INFO(gDragAndDropFilter, Debug::Verbose, "---OnMoved---\n");
162     DALI_LOG_INFO(gDragAndDropFilter, Debug::Verbose, "---control name is %s---\n", control.GetName().c_str());
163     DALI_LOG_INFO(gDragAndDropFilter, Debug::Verbose, "---coordinate is (%f, %f)---\n", detector.GetCurrentScreenPosition().x, detector.GetCurrentScreenPosition().y);
164   }
165
166   void OnDropped(Control control, Dali::Toolkit::DragAndDropDetector detector)
167   {
168     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---OnDropped---\n");
169     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---control name is %s---\n", control.GetName().c_str());
170
171     Vector2 screenPos  = detector.GetCurrentScreenPosition();
172     Rect<float> targetRect(screenPos.x, screenPos.y, 0.0f, 0.0f);
173     int droppedIndex = -1;
174     for(unsigned int i = 0; i < TEXT_LABEL_NUM; i++)
175     {
176       if(mRect[i].Contains(targetRect))
177       {
178         droppedIndex = i;
179       }
180     }
181
182     Animation mAnimation = Animation::New(0.5f);
183
184     if(droppedIndex > mDragIndex)
185     {
186       for(int i = mDragIndex + 1; i <= droppedIndex; i++)
187       {
188         float y = mTextLabel[mOrder[i]].GetCurrentPosition().y;
189         mAnimation.AnimateTo(Property(mTextLabel[mOrder[i]], Actor::Property::POSITION), Vector3(TEXT_LABEL_POSITION_X, y - TEXT_LABEL_HEIGHT, 0.0f), AlphaFunction::EASE_OUT);
190         mAnimation.Play();
191       }
192
193       int tmpId = mOrder[mDragIndex];
194       for(int i = mDragIndex; i < droppedIndex; i++)
195       {
196         mOrder[i] = mOrder[i+1];
197       }
198
199       mOrder[droppedIndex] = tmpId;
200     }
201     else if(droppedIndex < mDragIndex)
202     {
203
204       for(int i = mDragIndex - 1; i >= droppedIndex; i--)
205       {
206         float y = mTextLabel[mOrder[i]].GetCurrentPosition().y;
207         mAnimation.AnimateTo(Property(mTextLabel[mOrder[i]], Actor::Property::POSITION), Vector3(TEXT_LABEL_POSITION_X, y + TEXT_LABEL_HEIGHT, 0.0f), AlphaFunction::EASE_OUT);
208         mAnimation.Play();
209       }
210
211       int tmpId = mOrder[mDragIndex];
212       for(int i = mDragIndex; i > droppedIndex; i--)
213       {
214         mOrder[i] = mOrder[i-1];
215       }
216
217       mOrder[droppedIndex] = tmpId;
218
219     }
220
221
222     Vector2 pos = detector.GetCurrentScreenPosition();
223     Vector2 localPos;
224     control.GetParent().ScreenToLocal(localPos.x, localPos.y, pos.x, pos.y);
225
226     KeyFrames k0 = KeyFrames::New();
227     k0.Add(0.0f, Vector3(localPos.x - mDragLocalPos.x, localPos.y - mDragLocalPos.y, 0.0f));
228     k0.Add(1.0f, Vector3(control.GetCurrentPosition().x, control.GetCurrentPosition().y, 0.0f));
229
230     KeyFrames k1 = KeyFrames::New();
231     k1.Add(0.0f, 0.1f);
232     k1.Add(1.0f, 1.0f);
233
234     Animation dropAnimation = Animation::New(0.5f);
235     dropAnimation.FinishedSignal().Connect(this, &DragAndDropExample::DropAnimationFinished);
236     dropAnimation.AnimateBetween(Property(mTextLabel[mDragRealIndex], Actor::Property::POSITION), k0, AlphaFunction::EASE_OUT);
237     dropAnimation.AnimateBetween(Property(mTextLabel[mDragRealIndex], DevelActor::Property::OPACITY), k1, AlphaFunction::EASE_OUT);
238     dropAnimation.Play();
239
240     mDroppedFinished = true;
241   }
242
243   void DropAnimationFinished(Animation& animation)
244   {
245     for(unsigned int i = 0 ; i < TEXT_LABEL_NUM; i++)
246     {
247       mDragAndDropDetector.Attach(mTextLabel[i]);
248     }
249   }
250
251   void OnEnd(Control control, Dali::Toolkit::DragAndDropDetector detector)
252   {
253     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---OnEnd---\n");
254     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---control name is %s---\n", control.GetName().c_str());
255
256     control.SetOpacity(1.0f);
257
258     if(mDroppedFinished)
259     {
260       mDragAndDropDetector.DetachAll();
261     }
262
263     mDroppedFinished = false;
264   }
265
266 private:
267   Application&  mApplication;
268   Dali::Toolkit::DragAndDropDetector mDragAndDropDetector;
269
270   TextLabel mTextLabel[TEXT_LABEL_NUM];
271   Rect<float> mRect[TEXT_LABEL_NUM];
272
273   int mOrder[TEXT_LABEL_NUM];
274   int mDragIndex;
275   int mDragRealIndex;
276
277   Vector2 mDragLocalPos;
278
279   bool mDroppedFinished;
280
281 };
282
283 int DALI_EXPORT_API main( int argc, char **argv )
284 {
285   Application application = Application::New( &argc, &argv );
286   DragAndDropExample test( application );
287   application.MainLoop();
288   return 0;
289 }