Merge "Added PropertyValue Array as a class" into tizen
[platform/core/uifw/dali-demo.git] / examples / scroll-view / scroll-view-example.cpp
1 /*
2  * Copyright (c) 2015 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 // EXTERNAL INCLUDES
19 #include <sstream>
20
21 // INTERNAL INCLUDES
22 #include "shared/view.h"
23 #include <dali/dali.h>
24 #include <dali-toolkit/dali-toolkit.h>
25
26 using namespace Dali;
27 using namespace Dali::Toolkit;
28
29 namespace
30 {
31 const char * const BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-default.png" );
32 const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
33 const char * const APPLICATION_TITLE( "ScrollView" );
34 const char * const EFFECT_DEPTH_IMAGE( DALI_IMAGE_DIR "icon-scroll-view-depth.png" );
35 const char * const EFFECT_INNER_CUBE_IMAGE( DALI_IMAGE_DIR "icon-scroll-view-inner-cube.png" );
36 const char * const EFFECT_CAROUSEL_IMAGE( DALI_IMAGE_DIR "icon-scroll-view-carousel.png" );
37
38 const Vector3 ICON_SIZE(100.0f, 100.0f, 0.0f);
39
40 const char* EFFECT_MODE_NAME[] = {
41     "Depth",
42     "Cube",
43     "PageCarousel",
44     "PageCube",
45     "PageSpiral",
46     "PageWave"
47 };
48
49 const char * const IMAGE_PATHS[] = {
50     DALI_IMAGE_DIR "gallery-medium-1.jpg",
51     DALI_IMAGE_DIR "gallery-medium-2.jpg",
52     DALI_IMAGE_DIR "gallery-medium-3.jpg",
53     DALI_IMAGE_DIR "gallery-medium-4.jpg",
54     DALI_IMAGE_DIR "gallery-medium-5.jpg",
55     DALI_IMAGE_DIR "gallery-medium-6.jpg",
56     DALI_IMAGE_DIR "gallery-medium-7.jpg",
57     DALI_IMAGE_DIR "gallery-medium-8.jpg",
58     DALI_IMAGE_DIR "gallery-medium-9.jpg",
59     DALI_IMAGE_DIR "gallery-medium-10.jpg",
60     DALI_IMAGE_DIR "gallery-medium-11.jpg",
61     DALI_IMAGE_DIR "gallery-medium-12.jpg",
62     DALI_IMAGE_DIR "gallery-medium-13.jpg",
63     DALI_IMAGE_DIR "gallery-medium-14.jpg",
64     DALI_IMAGE_DIR "gallery-medium-15.jpg",
65     DALI_IMAGE_DIR "gallery-medium-16.jpg",
66     DALI_IMAGE_DIR "gallery-medium-17.jpg",
67     DALI_IMAGE_DIR "gallery-medium-18.jpg",
68     DALI_IMAGE_DIR "gallery-medium-19.jpg",
69     DALI_IMAGE_DIR "gallery-medium-20.jpg",
70     DALI_IMAGE_DIR "gallery-medium-21.jpg",
71     DALI_IMAGE_DIR "gallery-medium-22.jpg",
72     DALI_IMAGE_DIR "gallery-medium-23.jpg",
73     DALI_IMAGE_DIR "gallery-medium-24.jpg",
74     DALI_IMAGE_DIR "gallery-medium-25.jpg",
75     DALI_IMAGE_DIR "gallery-medium-26.jpg",
76     DALI_IMAGE_DIR "gallery-medium-27.jpg",
77     DALI_IMAGE_DIR "gallery-medium-28.jpg",
78     DALI_IMAGE_DIR "gallery-medium-29.jpg",
79     DALI_IMAGE_DIR "gallery-medium-30.jpg",
80     DALI_IMAGE_DIR "gallery-medium-31.jpg",
81     DALI_IMAGE_DIR "gallery-medium-32.jpg",
82     DALI_IMAGE_DIR "gallery-medium-33.jpg",
83     DALI_IMAGE_DIR "gallery-medium-34.jpg",
84     DALI_IMAGE_DIR "gallery-medium-35.jpg",
85     DALI_IMAGE_DIR "gallery-medium-36.jpg",
86     DALI_IMAGE_DIR "gallery-medium-37.jpg",
87     DALI_IMAGE_DIR "gallery-medium-38.jpg",
88     DALI_IMAGE_DIR "gallery-medium-39.jpg",
89     DALI_IMAGE_DIR "gallery-medium-40.jpg",
90     DALI_IMAGE_DIR "gallery-medium-41.jpg",
91     DALI_IMAGE_DIR "gallery-medium-42.jpg",
92     DALI_IMAGE_DIR "gallery-medium-43.jpg",
93     DALI_IMAGE_DIR "gallery-medium-44.jpg",
94     DALI_IMAGE_DIR "gallery-medium-45.jpg",
95     DALI_IMAGE_DIR "gallery-medium-46.jpg",
96     DALI_IMAGE_DIR "gallery-medium-47.jpg",
97     DALI_IMAGE_DIR "gallery-medium-48.jpg",
98     DALI_IMAGE_DIR "gallery-medium-49.jpg",
99     DALI_IMAGE_DIR "gallery-medium-50.jpg",
100     DALI_IMAGE_DIR "gallery-medium-51.jpg",
101     DALI_IMAGE_DIR "gallery-medium-52.jpg",
102     DALI_IMAGE_DIR "gallery-medium-53.jpg",
103
104     NULL
105 };
106
107 const char * const GetNextImagePath()
108 {
109   static const char * const * imagePtr = &IMAGE_PATHS[0];
110
111   if ( *(++imagePtr) == NULL )
112   {
113     imagePtr = &IMAGE_PATHS[0];
114   }
115
116   return *imagePtr;
117 }
118
119 const int PAGE_COLUMNS = 10;                                                ///< Number of Pages going across (columns)
120 const int PAGE_ROWS = 1;                                                    ///< Number of Pages going down (rows)
121 const int IMAGE_ROWS = 5;                                                   ///< Number of Images going down (rows) with a Page
122
123 // 3D Effect constants
124 const Vector3 ANGLE_CUBE_PAGE_ROTATE(Math::PI * 0.2f, Math::PI * 0.2f, 0.0f); ///< Cube page rotates as if it has ten sides with the camera positioned inside
125 const Vector2 ANGLE_CUSTOM_CUBE_SWING(-Math::PI * 0.45f, -Math::PI * 0.45f);  ///< outer cube pages swing 90 degrees as they pan offscreen
126 const Vector2 ANGLE_SPIRAL_SWING_IN(Math::PI * 0.45f, Math::PI * 0.45f);
127 const Vector2 ANGLE_SPIRAL_SWING_OUT(Math::PI * 0.3f, Math::PI * 0.3f);
128
129 // Depth Effect constants
130 const Vector2 POSITION_EXTENT_DEPTH_EFFECT(0.5f, 2.5f);                     ///< Extent of X & Y position to alter function exponent.
131 const Vector2 OFFSET_EXTENT_DEPTH_EFFECT(1.0f, 1.0f);                       ///< Function exponent offset constant.
132 const float POSITION_SCALE_DEPTH_EFFECT(1.5f);                              ///< Position scaling.
133 const float SCALE_EXTENT_DEPTH_EFFECT(0.5f);                                ///< Maximum scale factor when Actors scrolled one page away (50% size)
134
135 // 3D Effect constants
136 const Vector2 ANGLE_SWING_3DEFFECT(Math::PI_2 * 0.75, Math::PI_2 * 0.75f); ///< Angle Swing in radians
137 const Vector2 POSITION_SWING_3DEFFECT(0.25f, 0.25f); ///< Position Swing relative to stage size.
138 const Vector3 ANCHOR_3DEFFECT_STYLE0(-105.0f, 30.0f, -240.0f); ///< Rotation Anchor position for 3D Effect (Style 0)
139 const Vector3 ANCHOR_3DEFFECT_STYLE1(65.0f, -70.0f, -300.0f); ///< Rotation Anchor position for 3D Effect (Style 1)
140
141
142 const unsigned int IMAGE_THUMBNAIL_WIDTH  = 256;                            ///< Width of Thumbnail Image in texels
143 const unsigned int IMAGE_THUMBNAIL_HEIGHT = 256;                            ///< Height of Thumbnail Image in texels
144
145 const float SPIN_DURATION = 1.0f;                                           ///< Times to spin an Image by upon touching, each spin taking a second.
146
147 const float EFFECT_SNAP_DURATION(0.66f);                                    ///< Scroll Snap Duration for Effects
148 const float EFFECT_FLICK_DURATION(0.5f);                                    ///< Scroll Flick Duration for Effects
149
150 } // unnamed namespace
151
152 /**
153  * This example shows how to do custom Scroll Effects
154  */
155 class ExampleController : public ConnectionTracker
156 {
157 public:
158
159   /**
160    * Constructor
161    * @param application class, stored as reference
162    */
163   ExampleController( Application& application )
164   : mApplication( application ),
165     mView(),
166     mScrolling(false),
167     mEffectMode(CubeEffect)
168   {
169     // Connect to the Application's Init and orientation changed signal
170     mApplication.InitSignal().Connect(this, &ExampleController::OnInit);
171   }
172
173   ~ExampleController()
174   {
175     // Nothing to do here; everything gets deleted automatically
176   }
177
178   /**
179    * This method gets called once the main loop of application is up and running
180    */
181   void OnInit(Application& app)
182   {
183     DemoHelper::RequestThemeChange();
184
185     Stage stage = Dali::Stage::GetCurrent();
186     stage.KeyEventSignal().Connect(this, &ExampleController::OnKeyEvent);
187
188     // Hide the indicator bar
189     mApplication.GetWindow().ShowIndicator(Dali::Window::INVISIBLE);
190
191     // Creates a default view with a default tool bar.
192     // The view is added to the stage.
193     mContentLayer = DemoHelper::CreateView( app,
194                                             mView,
195                                             mToolBar,
196                                             BACKGROUND_IMAGE,
197                                             TOOLBAR_IMAGE,
198                                             "" );
199
200     mEffectIcon[ DepthEffect ]     = ResourceImage::New( EFFECT_DEPTH_IMAGE );
201     mEffectIcon[ CubeEffect ]      = ResourceImage::New( EFFECT_INNER_CUBE_IMAGE );
202     mEffectIcon[ PageCarouselEffect ] = ResourceImage::New( EFFECT_CAROUSEL_IMAGE );
203     mEffectIcon[ PageCubeEffect ]     = ResourceImage::New( EFFECT_CAROUSEL_IMAGE );
204     mEffectIcon[ PageSpiralEffect ]   = ResourceImage::New( EFFECT_CAROUSEL_IMAGE );
205     mEffectIcon[ PageWaveEffect ]     = ResourceImage::New( EFFECT_CAROUSEL_IMAGE );
206
207     // Create a effect change button. (right of toolbar)
208     mEffectChangeButton = Toolkit::PushButton::New();
209     mEffectChangeButton.ClickedSignal().Connect( this, &ExampleController::OnEffectTouched );
210     mToolBar.AddControl( mEffectChangeButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING  );
211
212     // Create the content layer.
213     AddContentLayer();
214
215     // Hack to force screen refresh.
216     Animation animation = Animation::New(1.0f);
217     animation.AnimateTo(Property(mContentLayer, Actor::Property::POSITION), Vector3::ZERO );
218     animation.Play();
219   }
220
221 private:
222
223   /**
224    * Adds content to the ContentLayer. This is everything we see
225    * excluding the toolbar at the top.
226    */
227   void AddContentLayer()
228   {
229     Stage stage = Stage::GetCurrent();
230     Vector2 stageSize = stage.GetSize();
231
232     mScrollView = ScrollView::New();
233     mScrollView.SetAnchorPoint(AnchorPoint::CENTER);
234     mScrollView.SetParentOrigin(ParentOrigin::CENTER);
235     mContentLayer.Add( mScrollView );
236     mScrollView.SetSize( stageSize );
237     mScrollView.SetAxisAutoLock( true );
238     mScrollView.SetAxisAutoLockGradient( 1.0f );
239
240     mScrollView.ScrollStartedSignal().Connect( this, &ExampleController::OnScrollStarted );
241     mScrollView.ScrollCompletedSignal().Connect( this, &ExampleController::OnScrollCompleted );
242
243     for(int row = 0;row<PAGE_ROWS;row++)
244     {
245       for(int column = 0;column<PAGE_COLUMNS;column++)
246       {
247         Actor page = CreatePage();
248
249         page.SetPosition( column * stageSize.x, row * stageSize.y );
250         mScrollView.Add( page );
251
252         mPages.push_back(page);
253       }
254     }
255
256     Update();
257   }
258
259   /**
260    * Updates the ScrollView and it's children based
261    * on the current effect.
262    */
263   void Update()
264   {
265     std::stringstream ss(APPLICATION_TITLE);
266     ss << APPLICATION_TITLE << ": " << EFFECT_MODE_NAME[mEffectMode];
267     SetTitle(ss.str());
268
269     mEffectChangeButton.SetBackgroundImage( mEffectIcon[ mEffectMode ] );
270
271     // remove old Effect if exists.
272     if(mScrollViewEffect)
273     {
274       mScrollView.RemoveEffect(mScrollViewEffect);
275     }
276
277     // apply new Effect to ScrollView
278     ApplyEffectToScrollView();
279     unsigned int pageCount(0);
280     for( std::vector< Actor >::iterator pageIter = mPages.begin(); pageIter != mPages.end(); ++pageIter)
281     {
282       Actor page = *pageIter;
283       ApplyEffectToPage( page, pageCount++ );
284
285       unsigned int numChildren = (*pageIter).GetChildCount();
286       for(unsigned int i=0; i<numChildren; ++i)
287       {
288         Actor image = (*pageIter).GetChildAt(i);
289
290         // Remove old effect's manual constraints.
291         image.RemoveConstraints();
292
293         // Apply new effect's manual constraints.
294         ApplyEffectToActor( image, page );
295       }
296     }
297   }
298
299   /**
300    * Creates a page using a source of images.
301    */
302   Actor CreatePage()
303   {
304     Actor page = Actor::New();
305     page.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
306     page.SetParentOrigin( ParentOrigin::CENTER );
307     page.SetAnchorPoint( AnchorPoint::CENTER );
308
309     Stage stage = Stage::GetCurrent();
310     Vector2 stageSize = stage.GetSize();
311
312     const float margin = 10.0f;
313
314     // Calculate the number of images going across (columns) within a page, according to the screen resolution and dpi.
315     int imageColumns = round(IMAGE_ROWS * (stageSize.x / stage.GetDpi().x) / (stageSize.y / stage.GetDpi().y));
316     const Vector3 imageSize((stageSize.x / imageColumns) - margin, (stageSize.y / IMAGE_ROWS) - margin, 0.0f);
317
318     for(int row = 0;row<IMAGE_ROWS;row++)
319     {
320       for(int column = 0;column<imageColumns;column++)
321       {
322         ImageActor image = CreateImage( GetNextImagePath(), imageSize.x, imageSize.y );
323
324         image.SetParentOrigin( ParentOrigin::CENTER );
325         image.SetAnchorPoint( AnchorPoint::CENTER );
326
327         Vector3 position( margin * 0.5f + (imageSize.x + margin) * column - stageSize.width * 0.5f,
328                          margin * 0.5f + (imageSize.y + margin) * row - stageSize.height * 0.5f,
329                           0.0f);
330         image.SetPosition( position + imageSize * 0.5f );
331         image.SetSize( imageSize );
332         page.Add(image);
333       }
334     }
335
336     return page;
337   }
338
339   /**
340    * [ScrollView]
341    * Applies effect to scrollView
342    */
343   void ApplyEffectToScrollView()
344   {
345     bool wrap(true);
346     bool snap(true);
347
348     Stage stage = Stage::GetCurrent();
349     Vector2 stageSize = stage.GetSize();
350
351     RulerPtr rulerX = CreateRuler(snap ? stageSize.width : 0.0f);
352     RulerPtr rulerY = new DefaultRuler;
353     rulerX->SetDomain(RulerDomain(0.0f, stageSize.x * PAGE_COLUMNS, !wrap));
354     rulerY->Disable();
355
356     switch( mEffectMode )
357     {
358       case DepthEffect:
359       {
360         mScrollViewEffect = ScrollViewDepthEffect::New();
361         mScrollView.SetScrollSnapDuration(EFFECT_SNAP_DURATION);
362         mScrollView.SetScrollFlickDuration(EFFECT_FLICK_DURATION);
363         mScrollView.SetScrollSnapAlphaFunction(AlphaFunction::EASE_OUT);
364         mScrollView.SetScrollFlickAlphaFunction(AlphaFunction::EASE_OUT);
365         mScrollView.RemoveConstraintsFromChildren();
366         break;
367       }
368
369       case CubeEffect:
370       {
371         mScrollViewEffect = ScrollViewCubeEffect::New();
372         mScrollView.SetScrollSnapDuration(EFFECT_SNAP_DURATION);
373         mScrollView.SetScrollFlickDuration(EFFECT_FLICK_DURATION);
374         mScrollView.SetScrollSnapAlphaFunction(AlphaFunction::EASE_OUT_BACK);
375         mScrollView.SetScrollFlickAlphaFunction(AlphaFunction::EASE_OUT_BACK);
376         mScrollView.RemoveConstraintsFromChildren();
377         break;
378       }
379
380       case PageCarouselEffect:
381       case PageCubeEffect:
382       case PageSpiralEffect:
383       case PageWaveEffect:
384       {
385         Dali::Path path = Dali::Path::New();
386         Dali::Property::Array points;
387         points.Resize(3);
388         Dali::Property::Array controlPoints;
389         controlPoints.Resize(4);
390         Vector3 forward;
391         if( mEffectMode == PageCarouselEffect)
392         {
393
394           points[0] = Vector3( stageSize.x*0.75, 0.0f,  -stageSize.x*0.75f);
395           points[1] = Vector3( 0.0f, 0.0f, 0.0f );
396           points[2] = Vector3( -stageSize.x*0.75f, 0.0f,  -stageSize.x*0.75f);
397           path.SetProperty( Path::Property::POINTS, points );
398
399           controlPoints[0] = Vector3( stageSize.x*0.5f, 0.0f, 0.0f );
400           controlPoints[1] = Vector3( stageSize.x*0.5f, 0.0f, 0.0f );
401           controlPoints[2] = Vector3(-stageSize.x*0.5f, 0.0f, 0.0f );
402           controlPoints[3] = Vector3(-stageSize.x*0.5f, 0.0f, 0.0f );
403           path.SetProperty( Path::Property::CONTROL_POINTS, controlPoints );
404
405           forward = Vector3::ZERO;
406         }
407         else if( mEffectMode == PageCubeEffect)
408         {
409           points[0] = Vector3( stageSize.x*0.5, 0.0f,  stageSize.x*0.5f);
410           points[1] = Vector3( 0.0f, 0.0f, 0.0f );
411           points[2] = Vector3( -stageSize.x*0.5f, 0.0f, stageSize.x*0.5f);
412           path.SetProperty( Path::Property::POINTS, points );
413
414           controlPoints[0] = Vector3( stageSize.x*0.5f, 0.0f, stageSize.x*0.3f );
415           controlPoints[1] = Vector3( stageSize.x*0.3f, 0.0f, 0.0f );
416           controlPoints[2] = Vector3(-stageSize.x*0.3f, 0.0f, 0.0f );
417           controlPoints[3] = Vector3(-stageSize.x*0.5f, 0.0f,  stageSize.x*0.3f );
418           path.SetProperty( Path::Property::CONTROL_POINTS, controlPoints );
419
420           forward = Vector3(-1.0f,0.0f,0.0f);
421         }
422         else if( mEffectMode == PageSpiralEffect)
423         {
424           points[0] = Vector3( stageSize.x*0.5, 0.0f,  -stageSize.x*0.5f);
425           points[1] = Vector3( 0.0f, 0.0f, 0.0f );
426           points[2] = Vector3( -stageSize.x*0.5f, 0.0f, -stageSize.x*0.5f);
427           path.SetProperty( Path::Property::POINTS, points );
428
429           controlPoints[0] = Vector3( stageSize.x*0.5f, 0.0f, 0.0f );
430           controlPoints[1] = Vector3( stageSize.x*0.5f, 0.0f, 0.0f );
431           controlPoints[2] = Vector3(-stageSize.x*0.5f, 0.0f, 0.0f );
432           controlPoints[3] = Vector3(-stageSize.x*0.5f, 0.0f, 0.0f );
433           path.SetProperty( Path::Property::CONTROL_POINTS, controlPoints );
434
435           forward = Vector3(-1.0f,0.0f,0.0f);
436         }
437         else if( mEffectMode == PageWaveEffect)
438         {
439           points[0] = Vector3( stageSize.x, 0.0f,  -stageSize.x);
440           points[1] = Vector3( 0.0f, 0.0f, 0.0f );
441           points[2] = Vector3( -stageSize.x, 0.0f, -stageSize.x);
442           path.SetProperty( Path::Property::POINTS, points );
443
444           controlPoints[0] = Vector3( 0.0f, 0.0f, -stageSize.x );
445           controlPoints[1] = Vector3( stageSize.x*0.5f, 0.0f, 0.0f );
446           controlPoints[2] = Vector3( -stageSize.x*0.5f, 0.0f, 0.0f);
447           controlPoints[3] = Vector3(0.0f, 0.0f,-stageSize.x  );
448           path.SetProperty( Path::Property::CONTROL_POINTS, controlPoints );
449
450           forward = Vector3(-1.0f,0.0f,0.0f);
451         }
452
453         mScrollViewEffect = ScrollViewPagePathEffect::New(path, forward,Toolkit::ScrollView::Property::SCROLL_FINAL_X, Vector3(stageSize.x,stageSize.y,0.0f),PAGE_COLUMNS);
454         mScrollView.SetScrollSnapDuration(EFFECT_SNAP_DURATION);
455         mScrollView.SetScrollFlickDuration(EFFECT_FLICK_DURATION);
456         mScrollView.SetScrollSnapAlphaFunction(AlphaFunction::EASE_OUT);
457         mScrollView.SetScrollFlickAlphaFunction(AlphaFunction::EASE_OUT);
458         mScrollView.RemoveConstraintsFromChildren();
459
460         rulerX = CreateRuler(snap ? stageSize.width * 0.5f : 0.0f);
461         if( wrap )
462         {
463           rulerX->SetDomain(RulerDomain(0.0f, stageSize.x * 0.5f * PAGE_COLUMNS, !wrap));
464         }
465         else
466         {
467           rulerX->SetDomain(RulerDomain(0.0f, stageSize.x*0.5f* (PAGE_COLUMNS+1), !wrap));
468         }
469
470         break;
471       }
472
473       default:
474       {
475         break;
476       }
477     }
478
479     unsigned int currentPage = mScrollView.GetCurrentPage();
480     if( mScrollViewEffect )
481     {
482       mScrollView.ApplyEffect(mScrollViewEffect);
483     }
484
485     mScrollView.SetWrapMode(wrap);
486     mScrollView.SetRulerX( rulerX );
487     mScrollView.SetRulerY( rulerY );
488
489     mScrollView.ScrollTo( currentPage, 0.0f );
490   }
491
492   /**
493    * Creates a Ruler that snaps to a specified grid size.
494    * If that grid size is 0.0 then this ruler does not
495    * snap.
496    *
497    * @param[in] gridSize (optional) The grid size for the ruler,
498    * (Default = 0.0 i.e. no snapping)
499    * @return The ruler is returned.
500    */
501   RulerPtr CreateRuler(float gridSize = 0.0f)
502   {
503     if(gridSize <= Math::MACHINE_EPSILON_0)
504     {
505         return new DefaultRuler();
506     }
507     return new FixedRuler(gridSize);
508   }
509   // end switch
510   /**
511     * [Page]
512     * Applies effect to the pages within scroll view.
513     *
514     * @param[in] page The page Actor to apply effect to.
515     */
516    void ApplyEffectToPage(Actor page, unsigned int pageOrder )
517    {
518      page.RemoveConstraints();
519      page.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
520
521      switch( mEffectMode )
522      {
523        case PageCarouselEffect:
524        case PageCubeEffect:
525        case PageSpiralEffect:
526        case PageWaveEffect:
527        {
528          ScrollViewPagePathEffect effect = ScrollViewPagePathEffect::DownCast( mScrollViewEffect );
529          effect.ApplyToPage( page, pageOrder );
530          break;
531        }
532
533        default:
534        {
535          break;
536        }
537      }
538    }
539
540   /**
541    * [Actor]
542    * Applies effect to child which resides in page (which in turn resides in scrollview)
543    *
544    * @note Page is typically the Parent of child, although in
545    * some scenarios Page is simply a container which has a child as
546    * a descendent.
547    *
548    * @param[in] child The child actor to apply effect to
549    * @param[in] page The page which this child is inside
550    */
551   void ApplyEffectToActor( Actor child, Actor page )
552   {
553     switch( mEffectMode )
554     {
555       case DepthEffect:
556       {
557         ApplyDepthEffectToActor( child );
558         break;
559       }
560
561       case CubeEffect:
562       {
563         ApplyCubeEffectToActor( child );
564         break;
565       }
566
567       default:
568       {
569         break;
570       }
571     }
572   }
573
574   /**
575    * Applies depth effect to the child which resides in page (which in turn resides in scrollview)
576    *
577    * @param[in] child The child actor to apply depth effect to
578    */
579   void ApplyDepthEffectToActor( Actor child )
580   {
581     ScrollViewDepthEffect depthEffect = ScrollViewDepthEffect::DownCast(mScrollViewEffect);
582     depthEffect.ApplyToActor( child,
583                               POSITION_EXTENT_DEPTH_EFFECT,
584                               OFFSET_EXTENT_DEPTH_EFFECT,
585                               POSITION_SCALE_DEPTH_EFFECT,
586                               SCALE_EXTENT_DEPTH_EFFECT );
587   }
588
589   void ApplyCubeEffectToActor( Actor child )
590   {
591     Vector3 anchor;
592     if(rand()&1)
593     {
594       anchor = ANCHOR_3DEFFECT_STYLE0;
595     }
596     else
597     {
598       anchor = ANCHOR_3DEFFECT_STYLE1;
599     }
600
601     ScrollViewCubeEffect cubeEffect = ScrollViewCubeEffect::DownCast(mScrollViewEffect);
602     cubeEffect.ApplyToActor( child,
603                              anchor,
604                              ANGLE_SWING_3DEFFECT,
605                              POSITION_SWING_3DEFFECT * Vector2(Stage::GetCurrent().GetSize()));
606   }
607
608   /**
609    * Creates an Image (Helper)
610    *
611    * @param[in] filename the path of the image.
612    * @param[in] width the width of the image in texels
613    * @param[in] height the height of the image in texels.
614    */
615   ImageActor CreateImage( const std::string& filename, unsigned int width = IMAGE_THUMBNAIL_WIDTH, unsigned int height = IMAGE_THUMBNAIL_HEIGHT )
616   {
617     Image img = ResourceImage::New(filename, ImageDimensions( width, height ), Dali::FittingMode::SCALE_TO_FILL, Dali::SamplingMode::BOX_THEN_LINEAR );
618
619     ImageActor actor = ImageActor::New(img);
620     actor.SetName( filename );
621     actor.SetParentOrigin(ParentOrigin::CENTER);
622     actor.SetAnchorPoint(AnchorPoint::CENTER);
623
624     actor.TouchedSignal().Connect( this, &ExampleController::OnTouchImage );
625     return actor;
626   }
627
628   /**
629    * When scroll starts (i.e. user starts to drag scrollview),
630    * note this state (mScrolling = true)
631    * @param[in] position Current Scroll Position
632    */
633   void OnScrollStarted( const Vector2& position )
634   {
635     mScrolling = true;
636   }
637
638   /**
639    * When scroll starts (i.e. user stops dragging scrollview, and scrollview has snapped to destination),
640    * note this state (mScrolling = false)
641    * @param[in] position Current Scroll Position
642    */
643   void OnScrollCompleted( const Vector2& position )
644   {
645     mScrolling = false;
646   }
647
648   /**
649    * Upon Touching an image (Release), make it spin
650    * (provided we're not scrolling).
651    * @param[in] actor The actor touched
652    * @param[in] event The TouchEvent.
653    */
654   bool OnTouchImage( Actor actor, const TouchEvent& event )
655   {
656     if( (event.points.size() > 0) && (!mScrolling) )
657     {
658       TouchPoint point = event.points[0];
659       if(point.state == TouchPoint::Up)
660       {
661         // Spin the Image a few times.
662         Animation animation = Animation::New(SPIN_DURATION);
663         animation.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree(360.0f * SPIN_DURATION) ), Vector3::XAXIS ), AlphaFunction::EASE_OUT );
664         animation.Play();
665       }
666     }
667     return false;
668   }
669
670   /**
671    * Signal handler, called when the 'Effect' button has been touched.
672    *
673    * @param[in] button The button that was pressed.
674    */
675   bool OnEffectTouched(Button button)
676   {
677     mEffectMode = static_cast<EffectMode>((static_cast<int>(mEffectMode) + 1) % static_cast<int>(Total));
678     Update();
679     return true;
680   }
681
682   /**
683    * Sets/Updates the title of the View
684    * @param[in] title The new title for the view.
685    */
686   void SetTitle(const std::string& title)
687   {
688     if(!mTitleActor)
689     {
690       mTitleActor = DemoHelper::CreateToolBarLabel( "" );
691       // Add title to the tool bar.
692       mToolBar.AddControl( mTitleActor, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Alignment::HorizontalCenter );
693     }
694
695     mTitleActor.SetProperty( Toolkit::TextLabel::Property::TEXT, title );
696   }
697
698   /**
699    * Main key event handler
700    */
701   void OnKeyEvent(const KeyEvent& event)
702   {
703     if(event.state == KeyEvent::Down)
704     {
705       if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
706       {
707         mApplication.Quit();
708       }
709     }
710   }
711
712 private:
713
714   Application& mApplication;                            ///< Application instance
715   Toolkit::Control mView;                               ///< The View instance.
716   Toolkit::ToolBar mToolBar;                            ///< The View's Toolbar.
717   TextLabel mTitleActor;                                ///< The Toolbar's Title.
718   Layer mContentLayer;                                  ///< The content layer (contains game actors)
719   ScrollView mScrollView;                               ///< ScrollView UI Component
720   bool mScrolling;                                      ///< ScrollView scrolling state (true = scrolling, false = stationary)
721   ScrollViewEffect mScrollViewEffect;                   ///< ScrollView Effect instance.
722   std::vector< Actor > mPages;                          ///< Keeps track of all the pages for applying effects.
723
724   /**
725    * Enumeration of different effects this scrollview can operate under.
726    */
727   enum EffectMode
728   {
729     DepthEffect,                                        ///< Depth Effect
730     CubeEffect,                                         ///< Cube effect
731     PageCarouselEffect,                                 ///< Page carousel effect
732     PageCubeEffect,                                     ///< Page cube effect
733     PageSpiralEffect,                                   ///< Page spiral effect
734     PageWaveEffect,                                     ///< Page wave effect
735
736     Total
737   };
738
739   EffectMode mEffectMode;                               ///< Current Effect mode
740
741   Image mEffectIcon[Total];                             ///< Icons for the effect button
742   Toolkit::PushButton mEffectChangeButton;              ///< Effect Change Button
743 };
744
745 int main(int argc, char **argv)
746 {
747   Application app = Application::New(&argc, &argv);
748   ExampleController test(app);
749   app.MainLoop();
750   return 0;
751 }