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