Merge "Tizen Directory Migration" into devel/master
[platform/core/uifw/dali-demo.git] / examples / scroll-view / scroll-view-example.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // EXTERNAL INCLUDES
19 #include <sstream>
20
21 // INTERNAL INCLUDES
22 #include "shared/view.h"
23 #include <dali/dali.h>
24 #include <dali-toolkit/dali-toolkit.h>
25
26 using namespace Dali;
27 using namespace Dali::Toolkit;
28
29 namespace
30 {
31 const char * const BACKGROUND_IMAGE( DEMO_IMAGE_DIR "background-default.png" );
32 const char * const TOOLBAR_IMAGE( DEMO_IMAGE_DIR "top-bar.png" );
33 const char * const APPLICATION_TITLE( "ScrollView" );
34 const char * const EFFECT_CAROUSEL_IMAGE( DEMO_IMAGE_DIR "icon-scroll-view-carousel.png" );
35 const char * const EFFECT_CAROUSEL_IMAGE_SELECTED( DEMO_IMAGE_DIR "icon-scroll-view-carousel-selected.png" );
36
37 const Vector3 ICON_SIZE(100.0f, 100.0f, 0.0f);
38
39 const char* EFFECT_MODE_NAME[] = {
40     "PageCarousel",
41     "PageCube",
42     "PageSpiral",
43     "PageWave"
44 };
45
46 const char * const IMAGE_PATHS[] = {
47     DEMO_IMAGE_DIR "gallery-medium-1.jpg",
48     DEMO_IMAGE_DIR "gallery-medium-2.jpg",
49     DEMO_IMAGE_DIR "gallery-medium-3.jpg",
50     DEMO_IMAGE_DIR "gallery-medium-4.jpg",
51     DEMO_IMAGE_DIR "gallery-medium-5.jpg",
52     DEMO_IMAGE_DIR "gallery-medium-6.jpg",
53     DEMO_IMAGE_DIR "gallery-medium-7.jpg",
54     DEMO_IMAGE_DIR "gallery-medium-8.jpg",
55     DEMO_IMAGE_DIR "gallery-medium-9.jpg",
56     DEMO_IMAGE_DIR "gallery-medium-10.jpg",
57     DEMO_IMAGE_DIR "gallery-medium-11.jpg",
58     DEMO_IMAGE_DIR "gallery-medium-12.jpg",
59     DEMO_IMAGE_DIR "gallery-medium-13.jpg",
60     DEMO_IMAGE_DIR "gallery-medium-14.jpg",
61     DEMO_IMAGE_DIR "gallery-medium-15.jpg",
62     DEMO_IMAGE_DIR "gallery-medium-16.jpg",
63     DEMO_IMAGE_DIR "gallery-medium-17.jpg",
64     DEMO_IMAGE_DIR "gallery-medium-18.jpg",
65     DEMO_IMAGE_DIR "gallery-medium-19.jpg",
66     DEMO_IMAGE_DIR "gallery-medium-20.jpg",
67     DEMO_IMAGE_DIR "gallery-medium-21.jpg",
68     DEMO_IMAGE_DIR "gallery-medium-22.jpg",
69     DEMO_IMAGE_DIR "gallery-medium-23.jpg",
70     DEMO_IMAGE_DIR "gallery-medium-24.jpg",
71     DEMO_IMAGE_DIR "gallery-medium-25.jpg",
72     DEMO_IMAGE_DIR "gallery-medium-26.jpg",
73     DEMO_IMAGE_DIR "gallery-medium-27.jpg",
74     DEMO_IMAGE_DIR "gallery-medium-28.jpg",
75     DEMO_IMAGE_DIR "gallery-medium-29.jpg",
76     DEMO_IMAGE_DIR "gallery-medium-30.jpg",
77     DEMO_IMAGE_DIR "gallery-medium-31.jpg",
78     DEMO_IMAGE_DIR "gallery-medium-32.jpg",
79     DEMO_IMAGE_DIR "gallery-medium-33.jpg",
80     DEMO_IMAGE_DIR "gallery-medium-34.jpg",
81     DEMO_IMAGE_DIR "gallery-medium-35.jpg",
82     DEMO_IMAGE_DIR "gallery-medium-36.jpg",
83     DEMO_IMAGE_DIR "gallery-medium-37.jpg",
84     DEMO_IMAGE_DIR "gallery-medium-38.jpg",
85     DEMO_IMAGE_DIR "gallery-medium-39.jpg",
86     DEMO_IMAGE_DIR "gallery-medium-40.jpg",
87     DEMO_IMAGE_DIR "gallery-medium-41.jpg",
88     DEMO_IMAGE_DIR "gallery-medium-42.jpg",
89     DEMO_IMAGE_DIR "gallery-medium-43.jpg",
90     DEMO_IMAGE_DIR "gallery-medium-44.jpg",
91     DEMO_IMAGE_DIR "gallery-medium-45.jpg",
92     DEMO_IMAGE_DIR "gallery-medium-46.jpg",
93     DEMO_IMAGE_DIR "gallery-medium-47.jpg",
94     DEMO_IMAGE_DIR "gallery-medium-48.jpg",
95     DEMO_IMAGE_DIR "gallery-medium-49.jpg",
96     DEMO_IMAGE_DIR "gallery-medium-50.jpg",
97     DEMO_IMAGE_DIR "gallery-medium-51.jpg",
98     DEMO_IMAGE_DIR "gallery-medium-52.jpg",
99     DEMO_IMAGE_DIR "gallery-medium-53.jpg",
100
101     NULL
102 };
103
104 const char * const GetNextImagePath()
105 {
106   static const char * const * imagePtr = &IMAGE_PATHS[0];
107
108   if ( *(++imagePtr) == NULL )
109   {
110     imagePtr = &IMAGE_PATHS[0];
111   }
112
113   return *imagePtr;
114 }
115
116 const int PAGE_COLUMNS = 10;                                                ///< Number of Pages going across (columns)
117 const int PAGE_ROWS = 1;                                                    ///< Number of Pages going down (rows)
118 const int IMAGE_ROWS = 5;                                                   ///< Number of Images going down (rows) with a Page
119
120 const unsigned int IMAGE_THUMBNAIL_WIDTH  = 256;                            ///< Width of Thumbnail Image in texels
121 const unsigned int IMAGE_THUMBNAIL_HEIGHT = 256;                            ///< Height of Thumbnail Image in texels
122
123 const float SPIN_DURATION = 1.0f;                                           ///< Times to spin an Image by upon touching, each spin taking a second.
124
125 const float EFFECT_SNAP_DURATION(0.66f);                                    ///< Scroll Snap Duration for Effects
126 const float EFFECT_FLICK_DURATION(0.5f);                                    ///< Scroll Flick Duration for Effects
127
128 } // unnamed namespace
129
130 /**
131  * This example shows how to do custom Scroll Effects
132  */
133 class ExampleController : public ConnectionTracker
134 {
135 public:
136
137   /**
138    * Constructor
139    * @param application class, stored as reference
140    */
141   ExampleController( Application& application )
142   : mApplication( application ),
143     mView(),
144     mScrolling(false),
145     mEffectMode(PageCarouselEffect)
146   {
147     // Connect to the Application's Init and orientation changed signal
148     mApplication.InitSignal().Connect(this, &ExampleController::OnInit);
149   }
150
151   ~ExampleController()
152   {
153     // Nothing to do here; everything gets deleted automatically
154   }
155
156   /**
157    * This method gets called once the main loop of application is up and running
158    */
159   void OnInit(Application& app)
160   {
161     Stage stage = Dali::Stage::GetCurrent();
162     stage.KeyEventSignal().Connect(this, &ExampleController::OnKeyEvent);
163
164     // Hide the indicator bar
165     mApplication.GetWindow().ShowIndicator(Dali::Window::INVISIBLE);
166
167     // Creates a default view with a default tool bar.
168     // The view is added to the stage.
169     mContentLayer = DemoHelper::CreateView( app,
170                                             mView,
171                                             mToolBar,
172                                             BACKGROUND_IMAGE,
173                                             TOOLBAR_IMAGE,
174                                             "" );
175
176     mEffectIcon[ PageCarouselEffect ] = EFFECT_CAROUSEL_IMAGE;
177     mEffectIconSelected[ PageCarouselEffect ] = EFFECT_CAROUSEL_IMAGE_SELECTED;
178     mEffectIcon[ PageCubeEffect ]     = EFFECT_CAROUSEL_IMAGE;
179     mEffectIconSelected[ PageCubeEffect ]     = EFFECT_CAROUSEL_IMAGE_SELECTED;
180     mEffectIcon[ PageSpiralEffect ]   = EFFECT_CAROUSEL_IMAGE;
181     mEffectIconSelected[ PageSpiralEffect ]   = EFFECT_CAROUSEL_IMAGE_SELECTED;
182     mEffectIcon[ PageWaveEffect ]     = EFFECT_CAROUSEL_IMAGE;
183     mEffectIconSelected[ PageWaveEffect ]     = EFFECT_CAROUSEL_IMAGE_SELECTED;
184
185     // Create a effect change button. (right of toolbar)
186     mEffectChangeButton = Toolkit::PushButton::New();
187     mEffectChangeButton.ClickedSignal().Connect( this, &ExampleController::OnEffectTouched );
188     mToolBar.AddControl( mEffectChangeButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING  );
189
190     // Create the content layer.
191     AddContentLayer();
192
193     // Hack to force screen refresh.
194     Animation animation = Animation::New(1.0f);
195     animation.AnimateTo(Property(mContentLayer, Actor::Property::POSITION), Vector3::ZERO );
196     animation.Play();
197   }
198
199 private:
200
201   /**
202    * Adds content to the ContentLayer. This is everything we see
203    * excluding the toolbar at the top.
204    */
205   void AddContentLayer()
206   {
207     Stage stage = Stage::GetCurrent();
208     Vector2 stageSize = stage.GetSize();
209
210     mScrollView = ScrollView::New();
211     mScrollView.SetAnchorPoint(AnchorPoint::CENTER);
212     mScrollView.SetParentOrigin(ParentOrigin::CENTER);
213     mContentLayer.Add( mScrollView );
214     mScrollView.SetSize( stageSize );
215     mScrollView.SetAxisAutoLock( true );
216     mScrollView.SetAxisAutoLockGradient( 1.0f );
217
218     mScrollView.ScrollStartedSignal().Connect( this, &ExampleController::OnScrollStarted );
219     mScrollView.ScrollCompletedSignal().Connect( this, &ExampleController::OnScrollCompleted );
220
221     for(int row = 0;row<PAGE_ROWS;row++)
222     {
223       for(int column = 0;column<PAGE_COLUMNS;column++)
224       {
225         Actor page = CreatePage();
226
227         page.SetPosition( column * stageSize.x, row * stageSize.y );
228         mScrollView.Add( page );
229
230         mPages.push_back(page);
231       }
232     }
233
234     Update();
235   }
236
237   /**
238    * Updates the ScrollView and it's children based
239    * on the current effect.
240    */
241   void Update()
242   {
243     std::stringstream ss(APPLICATION_TITLE);
244     ss << APPLICATION_TITLE << ": " << EFFECT_MODE_NAME[mEffectMode];
245     SetTitle(ss.str());
246
247     mEffectChangeButton.SetUnselectedImage( mEffectIcon[ mEffectMode ] );
248     mEffectChangeButton.SetSelectedImage( mEffectIconSelected[ mEffectMode ] );
249
250     // remove old Effect if exists.
251     if(mScrollViewEffect)
252     {
253       mScrollView.RemoveEffect(mScrollViewEffect);
254     }
255
256     // apply new Effect to ScrollView
257     ApplyEffectToScrollView();
258     unsigned int pageCount(0);
259     for( std::vector< Actor >::iterator pageIter = mPages.begin(); pageIter != mPages.end(); ++pageIter)
260     {
261       Actor page = *pageIter;
262       ApplyEffectToPage( page, pageCount++ );
263     }
264   }
265
266   /**
267    * Creates a page using a source of images.
268    */
269   Actor CreatePage()
270   {
271     Actor page = Actor::New();
272     page.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
273     page.SetParentOrigin( ParentOrigin::CENTER );
274     page.SetAnchorPoint( AnchorPoint::CENTER );
275
276     Stage stage = Stage::GetCurrent();
277     Vector2 stageSize = stage.GetSize();
278
279     const float margin = 10.0f;
280
281     // Calculate the number of images going across (columns) within a page, according to the screen resolution and dpi.
282     int imageColumns = round(IMAGE_ROWS * (stageSize.x / stage.GetDpi().x) / (stageSize.y / stage.GetDpi().y));
283     const Vector3 imageSize((stageSize.x / imageColumns) - margin, (stageSize.y / IMAGE_ROWS) - margin, 0.0f);
284
285     for(int row = 0;row<IMAGE_ROWS;row++)
286     {
287       for(int column = 0;column<imageColumns;column++)
288       {
289         ImageView image = CreateImage( GetNextImagePath(), imageSize.x, imageSize.y );
290
291         image.SetParentOrigin( ParentOrigin::CENTER );
292         image.SetAnchorPoint( AnchorPoint::CENTER );
293
294         Vector3 position( margin * 0.5f + (imageSize.x + margin) * column - stageSize.width * 0.5f,
295                          margin * 0.5f + (imageSize.y + margin) * row - stageSize.height * 0.5f,
296                           0.0f);
297         image.SetPosition( position + imageSize * 0.5f );
298         image.SetSize( imageSize );
299         page.Add(image);
300       }
301     }
302
303     return page;
304   }
305
306   /**
307    * [ScrollView]
308    * Applies effect to scrollView
309    */
310   void ApplyEffectToScrollView()
311   {
312     bool snap(true);
313
314     Stage stage = Stage::GetCurrent();
315     Vector2 stageSize = stage.GetSize();
316
317     RulerPtr rulerX = CreateRuler(snap ? stageSize.width : 0.0f);
318     RulerPtr rulerY = new DefaultRuler;
319     rulerX->SetDomain(RulerDomain(0.0f, stageSize.x * PAGE_COLUMNS, false));
320     rulerY->Disable();
321
322     Dali::Path path = Dali::Path::New();
323     Dali::Property::Array points;
324         points.Resize(3);
325     Dali::Property::Array controlPoints;
326         controlPoints.Resize(4);
327     Vector3 forward;
328     if( mEffectMode == PageCarouselEffect)
329     {
330
331       points[0] = Vector3( stageSize.x*0.75, 0.0f,  -stageSize.x*0.75f);
332       points[1] = Vector3( 0.0f, 0.0f, 0.0f );
333       points[2] = Vector3( -stageSize.x*0.75f, 0.0f,  -stageSize.x*0.75f);
334       path.SetProperty( Path::Property::POINTS, points );
335
336       controlPoints[0] = Vector3( stageSize.x*0.5f, 0.0f, 0.0f );
337       controlPoints[1] = Vector3( stageSize.x*0.5f, 0.0f, 0.0f );
338       controlPoints[2] = Vector3(-stageSize.x*0.5f, 0.0f, 0.0f );
339       controlPoints[3] = Vector3(-stageSize.x*0.5f, 0.0f, 0.0f );
340       path.SetProperty( Path::Property::CONTROL_POINTS, controlPoints );
341
342       forward = Vector3::ZERO;
343     }
344     else if( mEffectMode == PageCubeEffect)
345     {
346       points[0] = Vector3( stageSize.x*0.5, 0.0f,  stageSize.x*0.5f);
347       points[1] = Vector3( 0.0f, 0.0f, 0.0f );
348       points[2] = Vector3( -stageSize.x*0.5f, 0.0f, stageSize.x*0.5f);
349       path.SetProperty( Path::Property::POINTS, points );
350
351       controlPoints[0] = Vector3( stageSize.x*0.5f, 0.0f, stageSize.x*0.3f );
352       controlPoints[1] = Vector3( stageSize.x*0.3f, 0.0f, 0.0f );
353       controlPoints[2] = Vector3(-stageSize.x*0.3f, 0.0f, 0.0f );
354       controlPoints[3] = Vector3(-stageSize.x*0.5f, 0.0f,  stageSize.x*0.3f );
355       path.SetProperty( Path::Property::CONTROL_POINTS, controlPoints );
356
357       forward = Vector3(-1.0f,0.0f,0.0f);
358     }
359     else if( mEffectMode == PageSpiralEffect)
360     {
361       points[0] = Vector3( stageSize.x*0.5, 0.0f,  -stageSize.x*0.5f);
362       points[1] = Vector3( 0.0f, 0.0f, 0.0f );
363       points[2] = Vector3( -stageSize.x*0.5f, 0.0f, -stageSize.x*0.5f);
364       path.SetProperty( Path::Property::POINTS, points );
365
366       controlPoints[0] = Vector3( stageSize.x*0.5f, 0.0f, 0.0f );
367       controlPoints[1] = Vector3( stageSize.x*0.5f, 0.0f, 0.0f );
368       controlPoints[2] = Vector3(-stageSize.x*0.5f, 0.0f, 0.0f );
369       controlPoints[3] = Vector3(-stageSize.x*0.5f, 0.0f, 0.0f );
370       path.SetProperty( Path::Property::CONTROL_POINTS, controlPoints );
371
372       forward = Vector3(-1.0f,0.0f,0.0f);
373     }
374     else if( mEffectMode == PageWaveEffect)
375     {
376       points[0] = Vector3( stageSize.x, 0.0f,  -stageSize.x);
377       points[1] = Vector3( 0.0f, 0.0f, 0.0f );
378       points[2] = Vector3( -stageSize.x, 0.0f, -stageSize.x);
379       path.SetProperty( Path::Property::POINTS, points );
380
381       controlPoints[0] = Vector3( 0.0f, 0.0f, -stageSize.x );
382       controlPoints[1] = Vector3( stageSize.x*0.5f, 0.0f, 0.0f );
383       controlPoints[2] = Vector3( -stageSize.x*0.5f, 0.0f, 0.0f);
384       controlPoints[3] = Vector3(0.0f, 0.0f,-stageSize.x  );
385       path.SetProperty( Path::Property::CONTROL_POINTS, controlPoints );
386
387       forward = Vector3(-1.0f,0.0f,0.0f);
388     }
389
390     mScrollViewEffect = ScrollViewPagePathEffect::New(path, forward,Toolkit::ScrollView::Property::SCROLL_FINAL_X, Vector3(stageSize.x,stageSize.y,0.0f),PAGE_COLUMNS);
391     mScrollView.SetScrollSnapDuration(EFFECT_SNAP_DURATION);
392     mScrollView.SetScrollFlickDuration(EFFECT_FLICK_DURATION);
393     mScrollView.SetScrollSnapAlphaFunction(AlphaFunction::EASE_OUT);
394     mScrollView.SetScrollFlickAlphaFunction(AlphaFunction::EASE_OUT);
395     mScrollView.RemoveConstraintsFromChildren();
396
397     rulerX = CreateRuler(snap ? stageSize.width * 0.5f : 0.0f);
398     rulerX->SetDomain( RulerDomain( 0.0f, stageSize.x * 0.5f * PAGE_COLUMNS, false ) );
399
400     unsigned int currentPage = mScrollView.GetCurrentPage();
401     if( mScrollViewEffect )
402     {
403       mScrollView.ApplyEffect(mScrollViewEffect);
404     }
405
406     mScrollView.SetWrapMode( true );
407     mScrollView.SetRulerX( rulerX );
408     mScrollView.SetRulerY( rulerY );
409
410     mScrollView.ScrollTo( currentPage, 0.0f );
411   }
412
413   /**
414    * Creates a Ruler that snaps to a specified grid size.
415    * If that grid size is 0.0 then this ruler does not
416    * snap.
417    *
418    * @param[in] gridSize (optional) The grid size for the ruler,
419    * (Default = 0.0 i.e. no snapping)
420    * @return The ruler is returned.
421    */
422   RulerPtr CreateRuler(float gridSize = 0.0f)
423   {
424     if(gridSize <= Math::MACHINE_EPSILON_0)
425     {
426         return new DefaultRuler();
427     }
428     return new FixedRuler(gridSize);
429   }
430   // end switch
431   /**
432     * [Page]
433     * Applies effect to the pages within scroll view.
434     *
435     * @param[in] page The page Actor to apply effect to.
436     */
437    void ApplyEffectToPage(Actor page, unsigned int pageOrder )
438    {
439      page.RemoveConstraints();
440      page.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
441
442      ScrollViewPagePathEffect effect = ScrollViewPagePathEffect::DownCast( mScrollViewEffect );
443      effect.ApplyToPage( page, pageOrder );
444    }
445
446   /**
447    * Creates an Image (Helper)
448    *
449    * @param[in] filename the path of the image.
450    * @param[in] width the width of the image in texels
451    * @param[in] height the height of the image in texels.
452    */
453   ImageView CreateImage( const std::string& filename, int width = IMAGE_THUMBNAIL_WIDTH, int height = IMAGE_THUMBNAIL_HEIGHT )
454   {
455     ImageView actor = ImageView::New();
456     Property::Map map;
457     map["rendererType"] = "IMAGE";
458     map["url"] = filename;
459     map["desiredWidth"] = width;
460     map["desiredHeight"] = height;
461     map["fittingMode"] = "SCALE_TO_FILL";
462     map["samplingMode"] = "BOX_THEN_LINEAR";
463     actor.SetProperty( ImageView::Property::IMAGE, map );
464
465     actor.SetName( filename );
466     actor.SetParentOrigin(ParentOrigin::CENTER);
467     actor.SetAnchorPoint(AnchorPoint::CENTER);
468
469     actor.TouchSignal().Connect( this, &ExampleController::OnTouchImage );
470     return actor;
471   }
472
473   /**
474    * When scroll starts (i.e. user starts to drag scrollview),
475    * note this state (mScrolling = true)
476    * @param[in] position Current Scroll Position
477    */
478   void OnScrollStarted( const Vector2& position )
479   {
480     mScrolling = true;
481   }
482
483   /**
484    * When scroll starts (i.e. user stops dragging scrollview, and scrollview has snapped to destination),
485    * note this state (mScrolling = false)
486    * @param[in] position Current Scroll Position
487    */
488   void OnScrollCompleted( const Vector2& position )
489   {
490     mScrolling = false;
491   }
492
493   /**
494    * Upon Touching an image (Release), make it spin
495    * (provided we're not scrolling).
496    * @param[in] actor The actor touched
497    * @param[in] event The touch information.
498    */
499   bool OnTouchImage( Actor actor, const TouchData& event )
500   {
501     if( (event.GetPointCount() > 0) && (!mScrolling) )
502     {
503       if( event.GetState( 0 ) == PointState::UP )
504       {
505         // Spin the Image a few times.
506         Animation animation = Animation::New(SPIN_DURATION);
507         animation.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree(360.0f * SPIN_DURATION) ), Vector3::XAXIS ), AlphaFunction::EASE_OUT );
508         animation.Play();
509       }
510     }
511     return false;
512   }
513
514   /**
515    * Signal handler, called when the 'Effect' button has been touched.
516    *
517    * @param[in] button The button that was pressed.
518    */
519   bool OnEffectTouched(Button button)
520   {
521     mEffectMode = static_cast<EffectMode>((static_cast<int>(mEffectMode) + 1) % static_cast<int>(Total));
522     Update();
523     return true;
524   }
525
526   /**
527    * Sets/Updates the title of the View
528    * @param[in] title The new title for the view.
529    */
530   void SetTitle(const std::string& title)
531   {
532     if(!mTitleActor)
533     {
534       mTitleActor = DemoHelper::CreateToolBarLabel( "" );
535       // Add title to the tool bar.
536       mToolBar.AddControl( mTitleActor, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Alignment::HorizontalCenter );
537     }
538
539     mTitleActor.SetProperty( Toolkit::TextLabel::Property::TEXT, title );
540   }
541
542   /**
543    * Main key event handler
544    */
545   void OnKeyEvent(const KeyEvent& event)
546   {
547     if(event.state == KeyEvent::Down)
548     {
549       if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
550       {
551         mApplication.Quit();
552       }
553     }
554   }
555
556 private:
557
558   Application& mApplication;                            ///< Application instance
559   Toolkit::Control mView;                               ///< The View instance.
560   Toolkit::ToolBar mToolBar;                            ///< The View's Toolbar.
561   TextLabel mTitleActor;                                ///< The Toolbar's Title.
562   Layer mContentLayer;                                  ///< The content layer (contains game actors)
563   ScrollView mScrollView;                               ///< ScrollView UI Component
564   bool mScrolling;                                      ///< ScrollView scrolling state (true = scrolling, false = stationary)
565   ScrollViewEffect mScrollViewEffect;                   ///< ScrollView Effect instance.
566   std::vector< Actor > mPages;                          ///< Keeps track of all the pages for applying effects.
567
568   /**
569    * Enumeration of different effects this scrollview can operate under.
570    */
571   enum EffectMode
572   {
573     PageCarouselEffect,                                 ///< Page carousel effect
574     PageCubeEffect,                                     ///< Page cube effect
575     PageSpiralEffect,                                   ///< Page spiral effect
576     PageWaveEffect,                                     ///< Page wave effect
577
578     Total
579   };
580
581   EffectMode mEffectMode;                               ///< Current Effect mode
582
583   std::string mEffectIcon[Total];                       ///< Icons for the effect button
584   std::string mEffectIconSelected[Total];               ///< Icons for the effect button when its selected
585   Toolkit::PushButton mEffectChangeButton;              ///< Effect Change Button
586 };
587
588 int DALI_EXPORT_API main(int argc, char **argv)
589 {
590   Application app = Application::New(&argc, &argv, DEMO_THEME_PATH);
591   ExampleController test(app);
592   app.MainLoop();
593   return 0;
594 }