Merge "fix issue in negative line spacing with key arrow down" into devel/master
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit / utc-Dali-ScrollViewEffect.cpp
1 /*
2  * Copyright (c) 2022 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 <stdlib.h>
19 #include <iostream>
20
21 // Need to override adaptor classes for toolkit test harness, so include
22 // test harness headers before dali headers.
23 #include <dali-toolkit-test-suite-utils.h>
24
25 #include <dali-toolkit/dali-toolkit.h>
26 #include <dali.h>
27 #include <dali/integration-api/events/touch-event-integ.h>
28
29 using namespace Dali;
30 using namespace Toolkit;
31
32 void utc_dali_toolkit_scroll_view_effect_startup(void)
33 {
34   test_return_value = TET_UNDEF;
35 }
36
37 void utc_dali_toolkit_scroll_view_effect_cleanup(void)
38 {
39   test_return_value = TET_PASS;
40 }
41
42 namespace
43 {
44 const int RENDER_FRAME_INTERVAL = 16; ///< Duration of each frame in ms. (at approx 60FPS)
45
46 /*
47  * Simulate time passed by.
48  *
49  * @note this will always process at least 1 frame (1/60 sec)
50  *
51  * @param application Test application instance
52  * @param duration Time to pass in milliseconds.
53  * @return The actual time passed in milliseconds
54  */
55 int Wait(ToolkitTestApplication& application, int duration = 0)
56 {
57   int time = 0;
58
59   for(int i = 0; i <= (duration / RENDER_FRAME_INTERVAL); i++)
60   {
61     application.SendNotification();
62     application.Render(RENDER_FRAME_INTERVAL);
63     time += RENDER_FRAME_INTERVAL;
64   }
65
66   return time;
67 }
68
69 /**
70  * Creates a Ruler that snaps to a specified grid size.
71  * If that grid size is 0.0 then this ruler does not
72  * snap.
73  *
74  * @param[in] gridSize (optional) The grid size for the ruler,
75  * (Default = 0.0 i.e. no snapping)
76  * @return The ruler is returned.
77  */
78 RulerPtr CreateRuler(float gridSize = 0.0f)
79 {
80   if(gridSize <= Math::MACHINE_EPSILON_0)
81   {
82     return new DefaultRuler();
83   }
84   return new FixedRuler(gridSize);
85 }
86
87 // Callback probes.
88
89 static bool    gOnScrollStartCalled;    ///< Whether the OnScrollStart signal was invoked.
90 static bool    gOnScrollUpdateCalled;   ///< Whether the OnScrollUpdate signal was invoked.
91 static bool    gOnScrollCompleteCalled; ///< Whether the OnScrollComplete signal was invoked.
92 static Vector3 gConstraintResult;       ///< Result from constraint.
93
94 static std::vector<Actor>            gPages; ///< Keeps track of all the pages for applying effects.
95 typedef std::vector<Actor>::iterator ActorIter;
96
97 static void ResetScrollCallbackResults()
98 {
99   gOnScrollStartCalled    = false;
100   gOnScrollUpdateCalled   = false;
101   gOnScrollCompleteCalled = false;
102 }
103
104 /**
105  * Invoked when scrolling starts.
106  *
107  * @param[in] position The current scroll position.
108  */
109 static void OnScrollStart(const Vector2& position)
110 {
111   gOnScrollStartCalled = true;
112 }
113
114 /**
115  * Invoked when scrolling updates (via dragging)
116  *
117  * @param[in] position The current scroll position.
118  */
119 static void OnScrollUpdate(const Vector2& position)
120 {
121   gOnScrollUpdateCalled = true;
122 }
123
124 /**
125  * Invoked when scrolling finishes
126  *
127  * @param[in] position The current scroll position.
128  */
129 static void OnScrollComplete(const Vector2& position)
130 {
131   gOnScrollCompleteCalled = true;
132 }
133
134 ScrollView SetupTestScrollView(Integration::Scene scene, int rows, int columns, Vector2 size)
135 {
136   Constraint constraint;
137
138   ScrollView scrollView = ScrollView::New();
139   scrollView.SetProperty(Actor::Property::SIZE, size);
140   scrollView.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
141   scrollView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
142
143   constraint = Constraint::New<Dali::Vector3>(scrollView, Dali::Actor::Property::SIZE, Dali::EqualToConstraint());
144   constraint.AddSource(Dali::ParentSource(Dali::Actor::Property::SIZE));
145   constraint.Apply();
146
147   scrollView.SetWrapMode(false);
148   scrollView.ScrollStartedSignal().Connect(&OnScrollStart);
149   scrollView.ScrollUpdatedSignal().Connect(&OnScrollUpdate);
150   scrollView.ScrollCompletedSignal().Connect(&OnScrollComplete);
151   scene.Add(scrollView);
152   RulerPtr rulerX = CreateRuler(size.width);
153   RulerPtr rulerY = CreateRuler(size.height);
154   if(columns > 1)
155   {
156     rulerX->SetDomain(RulerDomain(0.0f, size.width * columns));
157   }
158   else
159   {
160     rulerX->Disable();
161   }
162   if(rows > 1)
163   {
164     rulerY->SetDomain(RulerDomain(0.0f, size.width * rows));
165   }
166   else
167   {
168     rulerY->Disable();
169   }
170
171   scrollView.SetRulerX(rulerX);
172   scrollView.SetRulerY(rulerY);
173   scene.Add(scrollView);
174
175   Actor container = Actor::New();
176   container.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
177   container.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
178   container.SetProperty(Actor::Property::SIZE, size);
179   scrollView.Add(container);
180
181   constraint = Constraint::New<Vector3>(container, Actor::Property::SIZE, EqualToConstraint());
182   constraint.AddSource(Dali::ParentSource(Dali::Actor::Property::SIZE));
183   constraint.Apply();
184
185   gPages.clear();
186   for(int row = 0; row < rows; row++)
187   {
188     for(int column = 0; column < columns; column++)
189     {
190       Actor page = Actor::New();
191
192       constraint = Constraint::New<Vector3>(page, Actor::Property::SIZE, EqualToConstraint());
193       constraint.AddSource(Dali::ParentSource(Dali::Actor::Property::SIZE));
194       constraint.Apply();
195       page.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
196       page.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
197       page.SetProperty(Actor::Property::POSITION, Vector2(column * size.x, row * size.y));
198       container.Add(page);
199
200       gPages.push_back(page);
201     }
202   }
203
204   ResetScrollCallbackResults();
205   return scrollView;
206 }
207
208 void CleanupTest()
209 {
210   gPages.clear();
211   ResetScrollCallbackResults();
212 }
213
214 } // unnamed namespace
215
216 int UtcDaliScrollViewPagePathEffectSetup(void)
217 {
218   ToolkitTestApplication application;
219   tet_infoline(" UtcDaliScrollViewPagePathEffectSetup");
220
221   ScrollViewPagePathEffect effect;
222
223   DALI_TEST_CHECK(!effect);
224
225   BaseHandle handle = ScrollViewPagePathEffect::New(Dali::Path::New(), Vector3::ZERO, Toolkit::ScrollView::Property::SCROLL_FINAL_X, Vector3::ZERO, 0);
226
227   DALI_TEST_CHECK(handle);
228
229   effect = ScrollViewPagePathEffect::DownCast(handle);
230
231   DALI_TEST_CHECK(effect);
232   END_TEST;
233 }
234
235 int UtcDaliScrollViewPagePathEffectTest(void)
236 {
237   ToolkitTestApplication application;
238   tet_infoline(" UtcDaliScrollViewPagePathEffectTest");
239
240   Vector2 size = application.GetScene().GetSize();
241
242   ScrollView scrollView = SetupTestScrollView(application.GetScene(), 1, 3, size);
243   Actor      testPage   = gPages[2];
244   Wait(application, 500);
245
246   //Create path
247   float xHalfSize(size.x * 0.5f);
248
249   Dali::Path            path = Dali::Path::New();
250   Dali::Property::Array points;
251   points.Resize(3);
252   points[0] = Vector3(xHalfSize, 0.0f, -xHalfSize);
253   points[1] = Vector3(0.0f, 0.0f, 0.0f);
254   points[2] = Vector3(-xHalfSize, 0.0f, -xHalfSize);
255   path.SetProperty(Path::Property::POINTS, points);
256
257   Dali::Property::Array controlPoints;
258   controlPoints.Resize(4);
259   controlPoints[0] = Vector3(xHalfSize, 0.0f, 0.0f);
260   controlPoints[1] = Vector3(xHalfSize, 0.0f, 0.0f);
261   controlPoints[2] = Vector3(-xHalfSize, 0.0f, 0.0f);
262   controlPoints[3] = Vector3(-xHalfSize, 0.0f, 0.0f);
263   path.SetProperty(Path::Property::CONTROL_POINTS, controlPoints);
264
265   ScrollViewPagePathEffect effect = ScrollViewPagePathEffect::New(path,
266                                                                   Vector3::ZERO,
267                                                                   Toolkit::ScrollView::Property::SCROLL_FINAL_X,
268                                                                   Vector3(size.x, size.y, 0.0f),
269                                                                   3);
270   scrollView.ApplyEffect(effect);
271
272   unsigned int pageCounter(0);
273   for(ActorIter pageIter = gPages.begin(); pageIter != gPages.end(); ++pageIter)
274   {
275     Actor page = *pageIter;
276     page.RemoveConstraints();
277     Constraint constraint = Constraint::New<Vector3>(page, Actor::Property::SIZE, EqualToConstraint());
278     constraint.AddSource(ParentSource(Actor::Property::SIZE));
279     constraint.Apply();
280     effect.ApplyToPage(page, pageCounter++);
281   }
282   Wait(application);
283
284   scrollView.ScrollTo(1);
285   while(!gOnScrollCompleteCalled)
286   {
287     Wait(application);
288   }
289
290   // test that the test page has reached centre of screen
291   Vector3 pagePos = testPage.GetCurrentProperty<Vector3>(Actor::Property::POSITION);
292   DALI_TEST_EQUALS(pagePos, Vector3::ZERO, Math::MACHINE_EPSILON_0, TEST_LOCATION);
293
294   CleanupTest();
295   END_TEST;
296 }