91202fcfee3dee02c79f9375447f3480fe114c2b
[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   {
62     // Connect to the Application's Init signal
63     mApplication.InitSignal().Connect( this, &DragAndDropExample::Create );
64   }
65
66   ~DragAndDropExample()
67   {
68     mDragAndDropDetector.DetachAll();
69   }
70
71   // The Init signal is received once (only) during the Application lifetime
72   void Create( Application& application )
73   {
74     Stage stage = Stage::GetCurrent();
75     stage.SetBackgroundColor( Color::WHITE );
76
77     mDragAndDropDetector = Dali::Toolkit::DragAndDropDetector::New();
78
79     // Respond to key events
80     stage.KeyEventSignal().Connect( this, &DragAndDropExample::OnKeyEvent );
81
82     TextLabel hintText = TextLabel::New("please drag one textlabel, move and drop on other textlabel");
83     hintText.SetPosition(0.0f, 700.0f);
84     hintText.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::TOP_LEFT);
85     hintText.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::TOP_LEFT);
86     hintText.SetProperty(TextLabel::Property::MULTI_LINE, true);
87     stage.Add(hintText);
88
89     for(unsigned int i = 0 ; i < TEXT_LABEL_NUM; i++)
90     {
91       std::string str = "textlabel ";
92       mTextLabel[i] = TextLabel::New(str + std::to_string(i));
93       mTextLabel[i].SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::TOP_LEFT);
94       mTextLabel[i].SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::TOP_LEFT);
95       mTextLabel[i].SetProperty( Dali::Actor::Property::NAME,"textlabel " + std::to_string(i));
96       mTextLabel[i].SetProperty( Actor::Property::LEAVE_REQUIRED,true);
97       mTextLabel[i].SetProperty(TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER");
98       mTextLabel[i].SetProperty(TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER");
99       mTextLabel[i].SetBackgroundColor(TEXT_LABEL_COLOR[i]);
100
101       mTextLabel[i].SetSize(TEXT_LABEL_WIDTH, TEXT_LABEL_HEIGHT);
102       mTextLabel[i].SetPosition(TEXT_LABEL_POSITION_X, TEXT_LABEL_POSITION_START_Y + TEXT_LABEL_HEIGHT * i);
103       mDragAndDropDetector.Attach(mTextLabel[i]);
104
105       mRect[i] = Rect<float>(TEXT_LABEL_POSITION_X, TEXT_LABEL_POSITION_START_Y + TEXT_LABEL_HEIGHT * i, TEXT_LABEL_WIDTH, TEXT_LABEL_HEIGHT);
106       mOrder[i] = i;
107
108       stage.Add(mTextLabel[i]);
109     }
110
111     mDragAndDropDetector.StartedSignal().Connect(this, &DragAndDropExample::OnStart);
112     mDragAndDropDetector.EnteredSignal().Connect(this, &DragAndDropExample::OnEnter);
113     mDragAndDropDetector.ExitedSignal().Connect(this, &DragAndDropExample::OnExit);
114     mDragAndDropDetector.MovedSignal().Connect(this, &DragAndDropExample::OnMoved);
115     mDragAndDropDetector.DroppedSignal().Connect(this, &DragAndDropExample::OnDropped);
116     mDragAndDropDetector.EndedSignal().Connect(this, &DragAndDropExample::OnEnd);
117   }
118
119   void OnKeyEvent( const KeyEvent& event )
120   {
121     if( event.state == KeyEvent::Down )
122     {
123       if ( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) )
124       {
125         mApplication.Quit();
126       }
127     }
128   }
129
130   void OnStart(Control control, Dali::Toolkit::DragAndDropDetector detector)
131   {
132     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---OnStart---\n");
133     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---control name is %s---\n", control.GetProperty< std::string >( Dali::Actor::Property::NAME ).c_str());
134
135     control.SetProperty( DevelActor::Property::OPACITY,0.1f);
136     Vector2 screenPos  = detector.GetCurrentScreenPosition();
137     control.ScreenToLocal(mDragLocalPos.x, mDragLocalPos.y,screenPos.x, screenPos.y );
138     Rect<float> targetRect(screenPos.x, screenPos.y, 0.0f, 0.0f);
139
140     for(unsigned int i = 0; i < TEXT_LABEL_NUM; i++)
141     {
142       if(mRect[i].Contains(targetRect))
143       {
144         mDragIndex = i;
145       }
146     }
147
148     mDragRealIndex = mOrder[mDragIndex];
149   }
150
151   void OnEnter(Control control, Dali::Toolkit::DragAndDropDetector detector)
152   {
153     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---OnEnter---\n");
154     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---control name is %s---\n", control.GetProperty< std::string >( Dali::Actor::Property::NAME ).c_str());
155   }
156
157   void OnExit(Control control, Dali::Toolkit::DragAndDropDetector detector)
158   {
159     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---OnExit---\n");
160     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---control name is %s---\n", control.GetProperty< std::string >( Dali::Actor::Property::NAME ).c_str());
161   }
162
163   void OnMoved(Control control, Dali::Toolkit::DragAndDropDetector detector)
164   {
165     DALI_LOG_INFO(gDragAndDropFilter, Debug::Verbose, "---OnMoved---\n");
166     DALI_LOG_INFO(gDragAndDropFilter, Debug::Verbose, "---control name is %s---\n", control.GetProperty< std::string >( Dali::Actor::Property::NAME ).c_str());
167     DALI_LOG_INFO(gDragAndDropFilter, Debug::Verbose, "---coordinate is (%f, %f)---\n", detector.GetCurrentScreenPosition().x, detector.GetCurrentScreenPosition().y);
168   }
169
170   void OnDropped(Control control, Dali::Toolkit::DragAndDropDetector detector)
171   {
172     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---OnDropped---\n");
173     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---control name is %s---\n", control.GetProperty< std::string >( Dali::Actor::Property::NAME ).c_str());
174
175     Vector2 screenPos  = detector.GetCurrentScreenPosition();
176     Rect<float> targetRect(screenPos.x, screenPos.y, 0.0f, 0.0f);
177     int droppedIndex = -1;
178     for(unsigned int i = 0; i < TEXT_LABEL_NUM; i++)
179     {
180       if(mRect[i].Contains(targetRect))
181       {
182         droppedIndex = i;
183       }
184     }
185
186     Animation mAnimation = Animation::New(0.5f);
187
188     if(droppedIndex > mDragIndex)
189     {
190       for(int i = mDragIndex + 1; i <= droppedIndex; i++)
191       {
192         float y = mTextLabel[mOrder[i]].GetCurrentProperty< Vector3 >( Actor::Property::POSITION ).y;
193         mAnimation.AnimateTo(Property(mTextLabel[mOrder[i]], Actor::Property::POSITION), Vector3(TEXT_LABEL_POSITION_X, y - TEXT_LABEL_HEIGHT, 0.0f), AlphaFunction::EASE_OUT);
194         mAnimation.Play();
195       }
196
197       int tmpId = mOrder[mDragIndex];
198       for(int i = mDragIndex; i < droppedIndex; i++)
199       {
200         mOrder[i] = mOrder[i+1];
201       }
202
203       mOrder[droppedIndex] = tmpId;
204     }
205     else if(droppedIndex < mDragIndex)
206     {
207
208       for(int i = mDragIndex - 1; i >= droppedIndex; i--)
209       {
210         float y = mTextLabel[mOrder[i]].GetCurrentProperty< Vector3 >( Actor::Property::POSITION ).y;
211         mAnimation.AnimateTo(Property(mTextLabel[mOrder[i]], Actor::Property::POSITION), Vector3(TEXT_LABEL_POSITION_X, y + TEXT_LABEL_HEIGHT, 0.0f), AlphaFunction::EASE_OUT);
212         mAnimation.Play();
213       }
214
215       int tmpId = mOrder[mDragIndex];
216       for(int i = mDragIndex; i > droppedIndex; i--)
217       {
218         mOrder[i] = mOrder[i-1];
219       }
220
221       mOrder[droppedIndex] = tmpId;
222
223     }
224
225
226     Vector2 pos = detector.GetCurrentScreenPosition();
227     Vector2 localPos;
228     control.GetParent().ScreenToLocal(localPos.x, localPos.y, pos.x, pos.y);
229
230     KeyFrames k0 = KeyFrames::New();
231     k0.Add(0.0f, Vector3(localPos.x - mDragLocalPos.x, localPos.y - mDragLocalPos.y, 0.0f));
232     k0.Add(1.0f, Vector3(control.GetCurrentProperty< Vector3 >( Actor::Property::POSITION ).x, control.GetCurrentProperty< Vector3 >( Actor::Property::POSITION ).y, 0.0f));
233
234     KeyFrames k1 = KeyFrames::New();
235     k1.Add(0.0f, 0.1f);
236     k1.Add(1.0f, 1.0f);
237
238     Animation dropAnimation = Animation::New(0.5f);
239     dropAnimation.AnimateBetween(Property(mTextLabel[mDragRealIndex], Actor::Property::POSITION), k0, AlphaFunction::EASE_OUT);
240     dropAnimation.AnimateBetween(Property(mTextLabel[mDragRealIndex], DevelActor::Property::OPACITY), k1, AlphaFunction::EASE_OUT);
241     dropAnimation.Play();
242   }
243
244   void DropAnimationFinished(Animation& animation)
245   {
246     for(unsigned int i = 0 ; i < TEXT_LABEL_NUM; i++)
247     {
248       mDragAndDropDetector.Attach(mTextLabel[i]);
249     }
250   }
251
252   void OnEnd(Control control, Dali::Toolkit::DragAndDropDetector detector)
253   {
254     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---OnEnd---\n");
255     DALI_LOG_INFO(gDragAndDropFilter, Debug::General, "---control name is %s---\n", control.GetProperty< std::string >( Dali::Actor::Property::NAME ).c_str());
256
257     control.SetProperty( DevelActor::Property::OPACITY,1.0f);
258   }
259
260 private:
261   Application&  mApplication;
262   Dali::Toolkit::DragAndDropDetector mDragAndDropDetector;
263
264   TextLabel mTextLabel[TEXT_LABEL_NUM];
265   Rect<float> mRect[TEXT_LABEL_NUM];
266
267   int mOrder[TEXT_LABEL_NUM];
268   int mDragIndex;
269   int mDragRealIndex;
270
271   Vector2 mDragLocalPos;
272
273 };
274
275 int DALI_EXPORT_API main( int argc, char **argv )
276 {
277   Application application = Application::New( &argc, &argv );
278   DragAndDropExample test( application );
279   application.MainLoop();
280   return 0;
281 }