Added scroll view page path effect.
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit / utc-Dali-ScrollViewEffect.cpp
1 /*
2  * Copyright (c) 2014 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 <iostream>
19 #include <stdlib.h>
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.h>
26 #include <dali-toolkit/dali-toolkit.h>
27 #include <dali/integration-api/events/touch-event-integ.h>
28 #include <dali/integration-api/events/pan-gesture-event.h>
29
30 using namespace Dali;
31 using namespace Toolkit;
32
33 void utc_dali_toolkit_scroll_view_effect_startup(void)
34 {
35   test_return_value = TET_UNDEF;
36 }
37
38 void utc_dali_toolkit_scroll_view_effect_cleanup(void)
39 {
40   test_return_value = TET_PASS;
41 }
42
43 namespace
44 {
45
46 const int MILLISECONDS_PER_SECOND = 1000;
47 const int RENDER_FRAME_INTERVAL = 16;                           ///< Duration of each frame in ms. (at approx 60FPS)
48 const int RENDER_ANIMATION_TEST_DURATION_MS = 1000;             ///< 1000ms to test animation
49 const int RENDER_DELAY_SCROLL = 1000;                           ///< duration to wait for any scroll to complete.
50
51 /*
52  * Simulate time passed by.
53  *
54  * @note this will always process at least 1 frame (1/60 sec)
55  *
56  * @param application Test application instance
57  * @param duration Time to pass in milliseconds.
58  * @return The actual time passed in milliseconds
59  */
60 int Wait(ToolkitTestApplication& application, int duration = 0)
61 {
62   int time = 0;
63
64   for(int i = 0; i <= ( duration / RENDER_FRAME_INTERVAL); i++)
65   {
66     application.SendNotification();
67     application.Render(RENDER_FRAME_INTERVAL);
68     time += RENDER_FRAME_INTERVAL;
69   }
70
71   return time;
72 }
73
74 /**
75  * Creates a Ruler that snaps to a specified grid size.
76  * If that grid size is 0.0 then this ruler does not
77  * snap.
78  *
79  * @param[in] gridSize (optional) The grid size for the ruler,
80  * (Default = 0.0 i.e. no snapping)
81  * @return The ruler is returned.
82  */
83 RulerPtr CreateRuler(float gridSize = 0.0f)
84 {
85   if(gridSize <= Math::MACHINE_EPSILON_0)
86   {
87       return new DefaultRuler();
88   }
89   return new FixedRuler(gridSize);
90 }
91
92 // Callback probes.
93
94 static bool gOnScrollStartCalled;                       ///< Whether the OnScrollStart signal was invoked.
95 static bool gOnScrollUpdateCalled;                      ///< Whether the OnScrollUpdate signal was invoked.
96 static bool gOnScrollCompleteCalled;                    ///< Whether the OnScrollComplete signal was invoked.
97 static Vector3 gConstraintResult;                       ///< Result from constraint.
98
99 static std::vector< Actor > gPages;                                ///< Keeps track of all the pages for applying effects.
100 typedef std::vector< Actor >::iterator ActorIter;
101
102 static void ResetScrollCallbackResults()
103 {
104   gOnScrollStartCalled = false;
105   gOnScrollUpdateCalled = false;
106   gOnScrollCompleteCalled = false;
107 }
108
109 /**
110  * Invoked when scrolling starts.
111  *
112  * @param[in] position The current scroll position.
113  */
114 static void OnScrollStart( const Vector3& position )
115 {
116   gOnScrollStartCalled = true;
117 }
118
119 /**
120  * Invoked when scrolling updates (via dragging)
121  *
122  * @param[in] position The current scroll position.
123  */
124 static void OnScrollUpdate( const Vector3& position )
125 {
126   gOnScrollUpdateCalled = true;
127 }
128
129 /**
130  * Invoked when scrolling finishes
131  *
132  * @param[in] position The current scroll position.
133  */
134 static void OnScrollComplete( const Vector3& position )
135 {
136   gOnScrollCompleteCalled = true;
137 }
138
139 ScrollView SetupTestScrollView(int rows, int columns, Vector2 size)
140 {
141   Constraint constraint;
142
143   ScrollView scrollView = ScrollView::New();
144   scrollView.SetSize(size);
145   scrollView.SetAnchorPoint(AnchorPoint::CENTER);
146   scrollView.SetParentOrigin(ParentOrigin::CENTER);
147
148   constraint = Constraint::New<Dali::Vector3>( scrollView, Dali::Actor::Property::SIZE, Dali::EqualToConstraint() );
149   constraint.AddSource( Dali::ParentSource( Dali::Actor::Property::SIZE ) );
150   constraint.Apply();
151
152   scrollView.SetWrapMode(false);
153   scrollView.ScrollStartedSignal().Connect( &OnScrollStart );
154   scrollView.ScrollUpdatedSignal().Connect( &OnScrollUpdate );
155   scrollView.ScrollCompletedSignal().Connect( &OnScrollComplete );
156   Stage::GetCurrent().Add( scrollView );
157   RulerPtr rulerX = CreateRuler(size.width);
158   RulerPtr rulerY = CreateRuler(size.height);
159   if(columns > 1)
160   {
161     rulerX->SetDomain(RulerDomain(0.0f, size.width * columns));
162   }
163   else
164   {
165     rulerX->Disable();
166   }
167   if(rows > 1)
168   {
169     rulerY->SetDomain(RulerDomain(0.0f, size.width * rows));
170   }
171   else
172   {
173     rulerY->Disable();
174   }
175
176   scrollView.SetRulerX( rulerX );
177   scrollView.SetRulerY( rulerY );
178   Stage::GetCurrent().Add( scrollView );
179
180   Actor container = Actor::New();
181   container.SetParentOrigin(ParentOrigin::CENTER);
182   container.SetAnchorPoint(AnchorPoint::CENTER);
183   container.SetSize( size );
184   scrollView.Add( container );
185
186   constraint = Constraint::New<Vector3>( container, Actor::Property::SIZE, EqualToConstraint() );
187   constraint.AddSource( Dali::ParentSource( Dali::Actor::Property::SIZE ) );
188   constraint.Apply();
189
190   gPages.clear();
191   for(int row = 0;row<rows;row++)
192   {
193     for(int column = 0;column<columns;column++)
194     {
195       Actor page = Actor::New();
196
197       constraint = Constraint::New<Vector3>( page, Actor::Property::SIZE, EqualToConstraint() );
198       constraint.AddSource( Dali::ParentSource( Dali::Actor::Property::SIZE ) );
199       constraint.Apply();
200       page.SetParentOrigin( ParentOrigin::CENTER );
201       page.SetAnchorPoint( AnchorPoint::CENTER );
202       page.SetPosition( column * size.x, row * size.y );
203       container.Add(page);
204
205       gPages.push_back(page);
206     }
207   }
208
209   ResetScrollCallbackResults();
210   return scrollView;
211 }
212
213 void CleanupTest()
214 {
215   gPages.clear();
216   ResetScrollCallbackResults();
217 }
218
219 Actor AddActorToPage(Actor page, float x, float y, float cols, float rows)
220 {
221   Stage stage = Stage::GetCurrent();
222   Vector2 stageSize = stage.GetSize();
223
224   const float margin = 10.0f;
225   const Vector2 actorSize((stageSize.x / cols) - margin, (stageSize.y / rows) - margin);
226
227   Actor actor = Actor::New();
228   actor.SetParentOrigin( ParentOrigin::CENTER );
229   actor.SetAnchorPoint( AnchorPoint::CENTER );
230
231   Vector3 position( margin * 0.5f + (actorSize.x + margin) * x - stageSize.width * 0.5f,
232                     margin * 0.5f + (actorSize.y + margin) * y - stageSize.height * 0.5f,
233                     0.0f);
234   Vector3 positionEnd( margin * 0.5f + (actorSize.x + margin) * (x + cols) - stageSize.width * 0.5f - margin,
235                        margin * 0.5f + (actorSize.y + margin) * (y + rows) - stageSize.height * 0.5f - margin,
236                        0.0f);
237   Vector3 size(positionEnd - position);
238   actor.SetPosition( position + size * 0.5f);
239   actor.SetSize( positionEnd - position );
240   page.Add(actor);
241   return actor;
242 }
243
244 } // unnamed namespace
245
246
247 int UtcDaliScrollViewCubeEffectSetup(void)
248 {
249   tet_infoline(" UtcDaliScrollViewCubeEffectSetup");
250
251   ScrollViewCubeEffect effect;
252
253   DALI_TEST_CHECK( !effect );
254
255   BaseHandle handle = ScrollViewCubeEffect::New();
256
257   DALI_TEST_CHECK( handle );
258
259   effect = ScrollViewCubeEffect::DownCast(handle);
260
261   DALI_TEST_CHECK( effect );
262   END_TEST;
263 }
264
265 int UtcDaliScrollViewCubeEffectTest(void)
266 {
267   ToolkitTestApplication application;
268   tet_infoline(" UtcDaliScrollViewCubeEffectTest");
269
270   Vector2 size = Stage::GetCurrent().GetSize();
271
272   ScrollView scrollView = SetupTestScrollView(1, 3, size);
273   Actor page = gPages[1];
274   Wait(application, 500);
275
276   ScrollViewCubeEffect effect = ScrollViewCubeEffect::New();
277   scrollView.ApplyEffect(effect);
278
279   Actor actor = AddActorToPage(page, 0.5f, 0.5f, 3, 3);
280   Wait(application);
281   Vector3 actorPrePosition = actor.GetCurrentPosition();
282
283   effect.ApplyToActor(actor, page, Vector3(-105.0f, 30.0f, -240.0f), Vector2(Math::PI * 0.5f, Math::PI * 0.5f), Vector2(0.25f, 0.25f) * size);
284
285   Actor actor2 = AddActorToPage(page, 0.5f, 0.5f, 3, 3);
286   effect.ApplyToActor(actor2, Vector3(-105.0f, 30.0f, -240.0f), Vector2(Math::PI * 0.5f, Math::PI * 0.5f), Vector2(0.25f, 0.25f) * size);
287
288   scrollView.ScrollTo(1);
289   while(!gOnScrollCompleteCalled)
290   {
291     Wait(application);
292   }
293   // test that the first page has reached centre of screen
294   Vector3 actorPostPosition = actor.GetCurrentPosition();
295   // just check the actor has moved
296   DALI_TEST_CHECK((actorPostPosition - actorPrePosition).Length() > Math::MACHINE_EPSILON_1);
297   CleanupTest();
298   END_TEST;
299 }
300
301 int UtcDaliScrollViewCarouselEffectSetup(void)
302 {
303   tet_infoline(" UtcDaliScrollViewCarouselEffectSetup");
304
305   ScrollViewCarouselEffect effect;
306
307   DALI_TEST_CHECK( !effect );
308
309   BaseHandle handle = ScrollViewCarouselEffect::New();
310
311   DALI_TEST_CHECK( handle );
312
313   effect = ScrollViewCarouselEffect::DownCast(handle);
314
315   DALI_TEST_CHECK( effect );
316   END_TEST;
317 }
318
319 int UtcDaliScrollViewCarouselEffectTest(void)
320 {
321   ToolkitTestApplication application;
322   tet_infoline(" UtcDaliScrollViewCarouselEffectTest");
323
324   Vector2 size = Stage::GetCurrent().GetSize();
325
326   ScrollView scrollView = SetupTestScrollView(1, 3, size);
327   Actor testPage = gPages[1];
328   Wait(application, 500);
329
330   ScrollViewCarouselEffect effect = ScrollViewCarouselEffect::New();
331   scrollView.ApplyEffect(effect);
332
333   Actor actor = AddActorToPage(testPage, 0.5f, 0.5f, 3, 3);
334   Wait(application);
335   Vector3 actorPrePosition = actor.GetCurrentPosition();
336
337   effect.ApplyToActor( actor, Vector2(1.2f, 1.2f) );
338
339   scrollView.ScrollTo(Vector3(size.x, 0.0f, 0.0f), 0.5f, DirectionBiasNone, DirectionBiasNone);
340   while(!gOnScrollCompleteCalled)
341   {
342     Wait(application);
343   }
344   // test that the first page has reached centre of screen
345   Vector3 actorPostPosition = actor.GetCurrentPosition();
346   // just check the actor has moved
347   DALI_TEST_CHECK((actorPostPosition - actorPrePosition).Length() > Math::MACHINE_EPSILON_1);
348   CleanupTest();
349   END_TEST;
350 }
351
352 int UtcDaliScrollViewDepthEffectSetup(void)
353 {
354   tet_infoline(" UtcDaliScrollViewDepthEffectSetup");
355
356   ScrollViewDepthEffect effect;
357
358   DALI_TEST_CHECK( !effect );
359
360   BaseHandle handle = ScrollViewDepthEffect::New();
361
362   DALI_TEST_CHECK( handle );
363
364   effect = ScrollViewDepthEffect::DownCast(handle);
365
366   DALI_TEST_CHECK( effect );
367   END_TEST;
368 }
369
370 int UtcDaliScrollViewDepthEffectTest(void)
371 {
372   ToolkitTestApplication application;
373   tet_infoline(" UtcDaliScrollViewDepthEffectTest");
374
375   Vector2 size = Stage::GetCurrent().GetSize();
376
377   ScrollView scrollView = SetupTestScrollView(1, 3, size);
378   Actor testPage = gPages[1];
379   Wait(application, 500);
380
381   ScrollViewDepthEffect effect = ScrollViewDepthEffect::New();
382   scrollView.ApplyEffect(effect);
383
384   Actor actor = AddActorToPage(testPage, 0.5f, 0.5f, 3, 3);
385   Wait(application);
386   Vector3 actorPrePosition = actor.GetCurrentPosition();
387
388   const Vector2 positionExtent(0.5f, 2.5f);
389   const Vector2 offsetExtent(1.0f, 1.0f);
390   const float positionScale(1.5f);
391   const float scaleExtent(0.5f);
392
393   effect.ApplyToActor( actor, positionExtent, offsetExtent, positionScale, scaleExtent );
394
395   scrollView.ScrollTo(1);
396   while(!gOnScrollCompleteCalled)
397   {
398     Wait(application);
399   }
400   // test that the first page has reached centre of screen
401   Vector3 actorPostPosition = actor.GetCurrentPosition();
402   // just check the actor has moved
403   DALI_TEST_CHECK((actorPostPosition - actorPrePosition).Length() > Math::MACHINE_EPSILON_1);
404   CleanupTest();
405   END_TEST;
406 }
407
408
409 int UtcDaliScrollViewPagePathEffectSetup(void)
410 {
411   tet_infoline(" UtcDaliScrollViewPagePathEffectSetup");
412
413   ScrollViewPagePathEffect effect;
414
415   DALI_TEST_CHECK( !effect );
416
417   BaseHandle handle = ScrollViewPagePathEffect::New(Dali::Path::New(), Vector3::ZERO,Toolkit::ScrollView::Property::SCROLL_FINAL_X, Vector3::ZERO,0);
418
419   DALI_TEST_CHECK( handle );
420
421   effect = ScrollViewPagePathEffect::DownCast(handle);
422
423   DALI_TEST_CHECK( effect );
424   END_TEST;
425 }
426
427 int UtcDaliScrollViewPagePathEffectTest(void)
428 {
429   ToolkitTestApplication application;
430   tet_infoline(" UtcDaliScrollViewPagePathEffectTest");
431
432   Vector2 size = Stage::GetCurrent().GetSize();
433
434   ScrollView scrollView = SetupTestScrollView(1, 3, size);
435   Actor testPage = gPages[2];
436   Wait(application, 500);
437
438   //Create path
439   float xHalfSize( size.x * 0.5f);
440
441   Dali::Path path = Dali::Path::New();
442   Dali::Property::Array points;
443   points.resize(3);
444   points[0] = Vector3( xHalfSize, 0.0f,  -xHalfSize);
445   points[1] = Vector3( 0.0f, 0.0f, 0.0f );
446   points[2] = Vector3( -xHalfSize, 0.0f,  -xHalfSize);
447   path.SetProperty( Path::Property::POINTS, points );
448
449   Dali::Property::Array controlPoints;
450   controlPoints.resize(4);
451   controlPoints[0] = Vector3( xHalfSize, 0.0f, 0.0f );
452   controlPoints[1] = Vector3( xHalfSize, 0.0f, 0.0f );
453   controlPoints[2] = Vector3(-xHalfSize, 0.0f, 0.0f );
454   controlPoints[3] = Vector3(-xHalfSize, 0.0f, 0.0f );
455   path.SetProperty( Path::Property::CONTROL_POINTS, controlPoints );
456
457   ScrollViewPagePathEffect effect = ScrollViewPagePathEffect::New(path,
458                                                                   Vector3::ZERO,
459                                                                   Toolkit::ScrollView::Property::SCROLL_FINAL_X,
460                                                                   Vector3(size.x,size.y,0.0f),
461                                                                   3);
462   scrollView.ApplyEffect(effect);
463
464   unsigned int pageCounter(0);
465   for(ActorIter pageIter = gPages.begin(); pageIter != gPages.end(); ++pageIter)
466   {
467     Actor page = *pageIter;
468     page.RemoveConstraints();
469     Constraint constraint = Constraint::New<Vector3>( page, Actor::Property::SIZE, EqualToConstraint() );
470     constraint.AddSource( ParentSource( Actor::Property::SIZE ) );
471     constraint.Apply();
472     effect.ApplyToPage(page, pageCounter++);
473   }
474   Wait(application);
475
476   scrollView.ScrollTo(1);
477   while(!gOnScrollCompleteCalled)
478   {
479     Wait(application);
480   }
481
482   // test that the test page has reached centre of screen
483   Vector3 pagePos = testPage.GetCurrentPosition();
484   DALI_TEST_EQUALS(pagePos, Vector3::ZERO, Math::MACHINE_EPSILON_0, TEST_LOCATION);
485
486   CleanupTest();
487   END_TEST;
488 }
489