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