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