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