Updated demos to use DALi clang-format
[platform/core/uifw/dali-demo.git] / examples / drag-and-drop / drag-and-drop-example.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 #include <dali-toolkit/dali-toolkit.h>
19 #include <dali-toolkit/devel-api/drag-drop-detector/drag-and-drop-detector.h>
20 #include <dali/devel-api/actors/actor-devel.h>
21 #include <dali/integration-api/debug.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 const float        TEXT_LABEL_POSITION_X       = 100.0f;
41 const float        TEXT_LABEL_POSITION_START_Y = 50.0f;
42 const float        TEXT_LABEL_WIDTH            = 250.0f;
43 const float        TEXT_LABEL_HEIGHT           = 70.0f;
44 const unsigned int TEXT_LABEL_NUM              = sizeof(TEXT_LABEL_COLOR) / sizeof(TEXT_LABEL_COLOR[0]);
45
46 const float DROP_ANIMATION_DURATION_S = 0.5f;
47
48 #if defined(DEBUG_ENABLED)
49 Debug::Filter* gDragAndDropFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DRAG_AND_DROP_EXAMPLE");
50 #endif
51 } // namespace
52
53 //This example shows how to use drag and drop function by several simple TextActors
54 class DragAndDropExample : public ConnectionTracker
55 {
56 public:
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     auto window = application.GetWindow();
75     window.SetBackgroundColor(Color::WHITE);
76
77     mDragAndDropDetector = Dali::Toolkit::DragAndDropDetector::New();
78
79     // Respond to key events
80     window.KeyEventSignal().Connect(this, &DragAndDropExample::OnKeyEvent);
81
82     TextLabel hintText = TextLabel::New("please drag one textlabel, move and drop on other textlabel");
83     hintText.SetProperty(Actor::Property::POSITION, Vector2(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     window.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].SetProperty(Actor::Property::SIZE, Vector2(TEXT_LABEL_WIDTH, TEXT_LABEL_HEIGHT));
102       mTextLabel[i].SetProperty(Actor::Property::POSITION, Vector2(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       window.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.GetState() == 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(Actor::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(DROP_ANIMATION_DURATION_S);
187
188     if(droppedIndex > mDragIndex)
189     {
190       for(int i = mDragIndex + 1; i <= droppedIndex; i++)
191       {
192         mAnimation.AnimateTo(Property(mTextLabel[mOrder[i]], Actor::Property::POSITION),
193                              Vector3(TEXT_LABEL_POSITION_X, TEXT_LABEL_POSITION_START_Y + TEXT_LABEL_HEIGHT * (i - 1), 0.0f),
194                              AlphaFunction::EASE_OUT);
195         mAnimation.Play();
196       }
197
198       int tmpId = mOrder[mDragIndex];
199       for(int i = mDragIndex; i < droppedIndex; i++)
200       {
201         mOrder[i] = mOrder[i + 1];
202       }
203
204       mOrder[droppedIndex] = tmpId;
205     }
206     else if(droppedIndex < mDragIndex)
207     {
208       for(int i = mDragIndex - 1; i >= droppedIndex; i--)
209       {
210         mAnimation.AnimateTo(Property(mTextLabel[mOrder[i]], Actor::Property::POSITION),
211                              Vector3(TEXT_LABEL_POSITION_X, TEXT_LABEL_POSITION_START_Y + TEXT_LABEL_HEIGHT * (i + 1), 0.0f),
212                              AlphaFunction::EASE_OUT);
213         mAnimation.Play();
214       }
215
216       int tmpId = mOrder[mDragIndex];
217       for(int i = mDragIndex; i > droppedIndex; i--)
218       {
219         mOrder[i] = mOrder[i - 1];
220       }
221
222       mOrder[droppedIndex] = tmpId;
223     }
224
225     Vector2 pos = detector.GetCurrentScreenPosition();
226     Vector2 localPos;
227     control.GetParent().ScreenToLocal(localPos.x, localPos.y, pos.x, pos.y);
228
229     KeyFrames k0 = KeyFrames::New();
230     k0.Add(0.0f, Vector3(localPos.x - mDragLocalPos.x, localPos.y - mDragLocalPos.y, 0.0f));
231     k0.Add(1.0f, Vector3(TEXT_LABEL_POSITION_X, TEXT_LABEL_POSITION_START_Y + TEXT_LABEL_HEIGHT * droppedIndex, 0.0f));
232
233     KeyFrames k1 = KeyFrames::New();
234     k1.Add(0.0f, 0.1f);
235     k1.Add(1.0f, 1.0f);
236
237     Animation dropAnimation = Animation::New(DROP_ANIMATION_DURATION_S);
238     dropAnimation.AnimateBetween(Property(mTextLabel[mDragRealIndex], Actor::Property::POSITION), k0, AlphaFunction::EASE_OUT);
239     dropAnimation.AnimateBetween(Property(mTextLabel[mDragRealIndex], Actor::Property::OPACITY), k1, AlphaFunction::EASE_OUT);
240     dropAnimation.Play();
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.GetProperty<std::string>(Dali::Actor::Property::NAME).c_str());
255
256     control.SetProperty(Actor::Property::OPACITY, 1.0f);
257   }
258
259 private:
260   Application&                       mApplication;
261   Dali::Toolkit::DragAndDropDetector mDragAndDropDetector;
262
263   TextLabel   mTextLabel[TEXT_LABEL_NUM];
264   Rect<float> mRect[TEXT_LABEL_NUM];
265
266   int mOrder[TEXT_LABEL_NUM];
267   int mDragIndex;
268   int mDragRealIndex;
269
270   Vector2 mDragLocalPos;
271 };
272
273 int DALI_EXPORT_API main(int argc, char** argv)
274 {
275   Application        application = Application::New(&argc, &argv);
276   DragAndDropExample test(application);
277   application.MainLoop();
278   return 0;
279 }