Merge "Updated demos to remove indicator where appropriate" into devel/master
[platform/core/uifw/dali-demo.git] / examples / primitive-shapes / primitive-shapes-example.cpp
1 #include <dali-toolkit/dali-toolkit.h>
2 #include <dali/public-api/object/property-map.h>
3 #include <dali-toolkit/public-api/controls/slider/slider.h>
4
5 using namespace Dali;
6 using namespace Dali::Toolkit;
7
8 namespace
9 {
10   //Button image urls
11   const char* BUTTON_IMAGE_URL[] =
12   {
13     DEMO_IMAGE_DIR "sphere-button.png",
14     DEMO_IMAGE_DIR "cone-button.png",
15     DEMO_IMAGE_DIR "conical-frustrum-button.png",
16     DEMO_IMAGE_DIR "cylinder-button.png",
17     DEMO_IMAGE_DIR "cube-button.png",
18     DEMO_IMAGE_DIR "bevelled-cube-button.png",
19     DEMO_IMAGE_DIR "octahedron-button.png"
20   };
21
22   //Shape property defaults
23   const int DEFAULT_SLICES = 32;
24   const int DEFAULT_STACKS = 32;
25   const float DEFAULT_SCALE_HEIGHT = 16.0f;
26   const float DEFAULT_SCALE_BOTTOM_RADIUS = 8.0f;
27   const float DEFAULT_SCALE_TOP_RADIUS = 4.0f;
28   const float DEFAULT_SCALE_RADIUS = 8.0f;
29   const float DEFAULT_BEVEL_PERCENTAGE = 0.3f;
30   const float DEFAULT_BEVEL_SMOOTHNESS = 0.0f;
31
32   //Shape property limits
33   const int SLICES_LOWER_BOUND = 3;
34   const int SLICES_UPPER_BOUND = 16;
35   const int STACKS_LOWER_BOUND = 2;
36   const int STACKS_UPPER_BOUND = 16;
37
38   //Used to the control rate of rotation when panning an object.
39   const float X_ROTATION_DISPLACEMENT_FACTOR = 60.0f;
40   const float Y_ROTATION_DISPLACEMENT_FACTOR = 60.0f;
41
42   const int NUM_MODELS = 7; //Total number of possible base shapes.
43   const int MAX_PROPERTIES = 3; //Maximum number of properties a shape may require. (For displaying sliders.)
44
45 } //End namespace
46
47 class PrimitiveShapesController : public ConnectionTracker
48 {
49 public:
50
51   PrimitiveShapesController( Application& application )
52   : mApplication( application ),
53     mColor( Vector4( 0.3f, 0.7f, 1.0f, 1.0f ) ),
54     mRotation( Vector2::ZERO )
55   {
56     // Connect to the Application's Init signal
57     mApplication.InitSignal().Connect( this, &PrimitiveShapesController::Create );
58   }
59
60   ~PrimitiveShapesController()
61   {
62   }
63
64   // The Init signal is received once (only) during the Application lifetime
65   void Create( Application& application )
66   {
67     // Get a handle to the stage
68     Stage stage = Stage::GetCurrent();
69     stage.SetBackgroundColor( Color::WHITE );
70
71     // Hide the indicator bar
72     application.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
73
74     //Set up layer to place UI on.
75     Layer layer = Layer::New();
76     layer.SetParentOrigin( ParentOrigin::CENTER );
77     layer.SetAnchorPoint( AnchorPoint::CENTER );
78     layer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
79     layer.SetBehavior( Layer::LAYER_2D ); //We use a 2D layer as this is closer to UI work than full 3D scene creation.
80     layer.SetDepthTestDisabled( false ); //Enable depth testing, as otherwise the 2D layer would not do so.
81     stage.Add( layer );
82
83     //Set up model selection buttons.
84     SetupButtons( layer );
85
86     //Set up model parameter sliders.
87     SetupSliders( layer );
88
89     //Set up 3D model.
90     SetupModel( layer );
91
92     //Allow for exiting of the application via key presses.
93     stage.KeyEventSignal().Connect( this, &PrimitiveShapesController::OnKeyEvent );
94   }
95
96   //Place buttons on the top of the screen, which allow for selection of the shape to be displayed.
97   //The buttons are laid out like so:
98   //
99   //      ^    +--------------------------------+
100   //      |    |                                |
101   //      |    | +----+ +----+ +----+ +----+    |
102   //      |    | |    | |    | |    | |    |    |
103   //  30% |    | +----+ +----+ +----+ +----+    |
104   //      |    |                                |
105   //      |    | +----+ +----+ +----+           |
106   //      |    | |    | |    | |    |           |
107   //      v    | +----+ +----+ +----+           |
108   //           |                                |
109   //           |                                |
110   //           |                                |
111   //           |                                |
112   //           |                                |
113   //           |                                |
114   //           |                                |
115   //           |                                |
116   //           |                                |
117   //           |                                |
118   //           |                                |
119   //           |                                |
120   //           |                                |
121   //           |                                |
122   //           |                                |
123   //           |                                |
124   //           |                                |
125   //           |                                |
126   //           |                                |
127   //           +--------------------------------+
128   //
129   void SetupButtons( Layer layer )
130   {
131     float containerPadding = 10.0f;
132     float buttonPadding = 5.0f;
133
134     //Create a variable-length container that can wrap buttons around as more are added.
135     FlexContainer buttonContainer = FlexContainer::New();
136     buttonContainer.SetParentOrigin( ParentOrigin::TOP_CENTER );
137     buttonContainer.SetAnchorPoint( AnchorPoint::TOP_CENTER );
138     buttonContainer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
139     buttonContainer.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::HEIGHT );
140     buttonContainer.SetSizeModeFactor( Vector3( 0.0, 0.3, 0.0 ) );  //30% of height.
141     buttonContainer.SetPadding( Padding( containerPadding, containerPadding, containerPadding, containerPadding ) );
142     buttonContainer.SetProperty( FlexContainer::Property::FLEX_DIRECTION, FlexContainer::ROW );
143     buttonContainer.SetProperty( FlexContainer::Property::FLEX_WRAP, FlexContainer::WRAP );
144
145     layer.Add( buttonContainer );
146
147     //Create buttons and place them in the container.
148     for( int modelNumber = 0; modelNumber < NUM_MODELS; modelNumber++ )
149     {
150       PushButton button = Toolkit::PushButton::New();
151       button.SetParentOrigin( ParentOrigin::CENTER );
152       button.SetAnchorPoint( AnchorPoint::CENTER );
153       button.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
154       button.SetPadding( Padding( buttonPadding, buttonPadding, buttonPadding, buttonPadding ) );
155       button.SetProperty( Button::Property::UNSELECTED_STATE_IMAGE, Property::Value( BUTTON_IMAGE_URL[modelNumber] ) );
156       button.SetProperty( Button::Property::SELECTED_STATE_IMAGE, Property::Value( BUTTON_IMAGE_URL[modelNumber] ) );
157       button.RegisterProperty( "modelNumber", Property::Value( modelNumber ) );
158       button.ClickedSignal().Connect( this, &PrimitiveShapesController::OnChangeShapeClicked );
159
160       buttonContainer.Add( button );
161     }
162   }
163
164   //Add sliders to the bottom of the screen, which allow for control of shape properties such as radius.
165   //Each slider is placed next to a label that states the property it affects.
166   //The sliders are laid out like so:
167   //
168   //           +--------------------------------+
169   //           |                                |
170   //           |                                |
171   //           |                                |
172   //           |                                |
173   //           |                                |
174   //           |                                |
175   //           |                                |
176   //           |                                |
177   //           |                                |
178   //           |                                |
179   //           |                                |
180   //           |                                |
181   //           |                                |
182   //           |                                |
183   //           |                                |
184   //           |                                |
185   //           |                                |
186   //           |                                |
187   //           |                                |
188   //      ^    | Label +----------O-----------+ |
189   //      |    |                                |
190   //      |    |                                |
191   //      |    | Label +--O-------------------+ |
192   //  30% |    |                                |
193   //      |    |                                |
194   //      |    | Label +----------------------O |
195   //      |    |                                |
196   //      v    +--------------------------------+
197   //
198   void SetupSliders( Layer layer )
199   {
200     //Create table to hold sliders and their corresponding labels.
201     mSliderTable = Toolkit::TableView::New( MAX_PROPERTIES, 2 );
202     mSliderTable.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
203     mSliderTable.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
204     mSliderTable.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
205     mSliderTable.SetSizeModeFactor( Vector3( 0.9, 0.3, 0.0 ) );  //90% of width, 30% of height.
206     mSliderTable.SetFitWidth( 0 );  //Label column should fit to natural size of label.
207     mSliderTable.SetRelativeWidth( 1, 1.0f );  //Slider column should fill remaining space.
208     mSliderTable.SetCellPadding( Vector2( 10.0f, 0.0f ) ); //Leave a gap between the slider and its label.
209     layer.Add( mSliderTable );
210
211     //Set up sliders, and place labels next to them.
212     for( int i = 0; i < MAX_PROPERTIES; i++ )
213     {
214       //Create slider
215       Slider slider = Slider::New();
216       slider.SetParentOrigin( ParentOrigin::CENTER );
217       slider.SetAnchorPoint( AnchorPoint::CENTER );
218       slider.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
219       slider.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
220       slider.ValueChangedSignal().Connect( this, &PrimitiveShapesController::OnSliderValueChanged );
221       mSliders.push_back( slider );
222
223       //Setup slider cell properties
224       mSliderTable.AddChild( slider, TableView::CellPosition( i, 1 ) );
225       mSliderTable.SetCellAlignment( TableView::CellPosition( i, 1 ), HorizontalAlignment::CENTER, VerticalAlignment::CENTER );
226
227       //Create slider label
228       TextLabel sliderLabel = TextLabel::New();
229       sliderLabel.SetParentOrigin( ParentOrigin::CENTER );
230       sliderLabel.SetAnchorPoint( AnchorPoint::CENTER );
231       sliderLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
232       mSliderLabels.push_back( sliderLabel );
233
234       //Setup slider-label cell properties
235       mSliderTable.AddChild( sliderLabel, TableView::CellPosition( i, 0 ) );
236       mSliderTable.SetCellAlignment( TableView::CellPosition( i, 0 ), HorizontalAlignment::LEFT, VerticalAlignment::CENTER );
237     }
238   }
239
240   //Adds a control to the centre of the stage to display the 3D shapes.
241   //The model is placed in the center of the screen, like so:
242   //
243   //           +--------------------------------+
244   //           |                                |
245   //           |                                |
246   //           |                                |
247   //           |                                |
248   //           |                                |
249   //           |                                |
250   //           |                                |
251   //           |                                |
252   //           |                                |
253   //       ^   |           ----------           |
254   //       |   |          /          \          |
255   //       |   |         /            \         |
256   //       |   |        |              |        |
257   //   30% |   |        |              |        |
258   //       |   |        |              |        |
259   //       |   |         \            /         |
260   //       |   |          \          /          |
261   //       v   |           ----------           |
262   //           |                                |
263   //           |                                |
264   //           |                                |
265   //           |                                |
266   //           |                                |
267   //           |                                |
268   //           |                                |
269   //           |                                |
270   //           |                                |
271   //           +--------------------------------+
272   //
273   void SetupModel( Layer layer )
274   {
275     //Create a container to house the visual-holding actor, to provide a constant hitbox.
276     Actor container = Actor::New();
277     container.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
278     container.SetSizeModeFactor( Vector3( 0.9, 0.3, 0.0 ) );  //90% of width, 30% of height.
279     container.SetParentOrigin( ParentOrigin::CENTER );
280     container.SetAnchorPoint( AnchorPoint::CENTER );
281     layer.Add( container );
282
283     //Create control to display the 3D primitive.
284     mModel = Control::New();
285     mModel.SetParentOrigin( ParentOrigin::CENTER );
286     mModel.SetAnchorPoint( AnchorPoint::CENTER);
287     mModel.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
288     container.Add( mModel );
289
290     //Load default shape.
291     LoadCube();
292
293     //Make model spin to demonstrate 3D.
294     mRotationAnimation = Animation::New(15.0f);
295     mRotationAnimation.AnimateBy( Property( mModel, Actor::Property::ORIENTATION ),
296                                  Quaternion( Degree( 0.0f ), Degree( 360.0f ), Degree( 0.0f ) ) );
297     mRotationAnimation.SetLooping(true);
298     mRotationAnimation.Play();
299
300     //Attach gesture detector to pan models when rotated.
301     mPanGestureDetector = PanGestureDetector::New();
302     mPanGestureDetector.Attach( container );
303     mPanGestureDetector.DetectedSignal().Connect( this, &PrimitiveShapesController::OnPan );
304   }
305
306   //Clears all sliders and resets the primitive visual property map.
307   void InitialiseSlidersAndModel()
308   {
309     //Sliders
310     for( unsigned i = 0; i < mSliders.size(); i++ )
311     {
312       mSliders.at( i ).SetProperty( Slider::Property::MARKS, Property::Value( 0 ) ); //Remove marks
313       mSliders.at( i ).SetVisible( false );
314       mSliderLabels.at( i ).SetProperty( TextLabel::Property::TEXT, Property::Value( "Default" ) );
315       mSliderLabels.at( i ).SetVisible( false );
316     }
317
318     //Visual map for model
319     mVisualMap.Clear();
320     mVisualMap[ Visual::Property::TYPE           ] = Visual::PRIMITIVE;
321     mVisualMap[ PrimitiveVisual::Property::COLOR ] = mColor;
322   }
323
324   //Sets the 3D model to a sphere and modifies the sliders appropriately.
325   void LoadSphere()
326   {
327     InitialiseSlidersAndModel();
328
329     //Set up specific visual properties.
330     mVisualMap[ PrimitiveVisual::Property::SHAPE  ] = PrimitiveVisual::Shape::SPHERE;
331     mVisualMap[ PrimitiveVisual::Property::SLICES ] = DEFAULT_SLICES;
332     mVisualMap[ PrimitiveVisual::Property::STACKS ] = DEFAULT_STACKS;
333
334     //Set up sliders.
335     SetupSlider( 0, SLICES_LOWER_BOUND, SLICES_UPPER_BOUND, DEFAULT_STACKS, PrimitiveVisual::Property::SLICES, "slices" );
336     SetupMarks( mSliders.at( 0 ), SLICES_LOWER_BOUND, SLICES_UPPER_BOUND );
337     SetupSlider( 1, STACKS_LOWER_BOUND, STACKS_UPPER_BOUND, DEFAULT_STACKS, PrimitiveVisual::Property::STACKS, "stacks" );
338     SetupMarks( mSliders.at( 1 ), STACKS_LOWER_BOUND, STACKS_UPPER_BOUND );
339
340     //Set model in control.
341     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
342   }
343
344   //Sets the 3D model to a cone and modifies the sliders appropriately.
345   void LoadCone()
346   {
347     InitialiseSlidersAndModel();
348
349     //Set up specific visual properties.
350     mVisualMap[ PrimitiveVisual::Property::SHAPE               ] = PrimitiveVisual::Shape::CONE;
351     mVisualMap[ PrimitiveVisual::Property::SCALE_HEIGHT        ] = DEFAULT_SCALE_HEIGHT;
352     mVisualMap[ PrimitiveVisual::Property::SCALE_BOTTOM_RADIUS ] = DEFAULT_SCALE_BOTTOM_RADIUS;
353     mVisualMap[ PrimitiveVisual::Property::SLICES              ] = DEFAULT_SLICES;
354
355     //Set up sliders.
356     SetupSlider( 0, 1.0f, 32.0f, DEFAULT_SCALE_HEIGHT, PrimitiveVisual::Property::SCALE_HEIGHT, "scaleHeight" );
357     SetupSlider( 1, 1.0f, 32.0f, DEFAULT_SCALE_BOTTOM_RADIUS, PrimitiveVisual::Property::SCALE_BOTTOM_RADIUS, "scaleBottomRadius" );
358     SetupSlider( 2, SLICES_LOWER_BOUND, SLICES_UPPER_BOUND, DEFAULT_STACKS, PrimitiveVisual::Property::SLICES, "slices" );
359     SetupMarks( mSliders.at( 2 ), SLICES_LOWER_BOUND, SLICES_UPPER_BOUND );
360
361     //Set model in control.
362     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
363   }
364
365   //Sets the 3D model to a conical frustrum and modifies the sliders appropriately.
366   void LoadConicalFrustrum()
367   {
368     InitialiseSlidersAndModel();
369
370     //Set up specific visual properties.
371     mVisualMap[ PrimitiveVisual::Property::SHAPE               ] = PrimitiveVisual::Shape::CONICAL_FRUSTRUM;
372     mVisualMap[ PrimitiveVisual::Property::SCALE_TOP_RADIUS    ] = DEFAULT_SCALE_TOP_RADIUS;
373     mVisualMap[ PrimitiveVisual::Property::SCALE_BOTTOM_RADIUS ] = DEFAULT_SCALE_BOTTOM_RADIUS;
374     mVisualMap[ PrimitiveVisual::Property::SCALE_HEIGHT        ] = DEFAULT_SCALE_HEIGHT;
375     mVisualMap[ PrimitiveVisual::Property::SLICES              ] = DEFAULT_SLICES;
376
377     //Set up used sliders.
378     SetupSlider( 0, 1.0f, 32.0f, DEFAULT_SCALE_HEIGHT, PrimitiveVisual::Property::SCALE_HEIGHT, "scaleHeight" );
379     SetupSlider( 1, 0.0f, 32.0f, DEFAULT_SCALE_BOTTOM_RADIUS, PrimitiveVisual::Property::SCALE_BOTTOM_RADIUS, "scaleBottomRadius" );
380     SetupSlider( 2, 0.0f, 32.0f, DEFAULT_SCALE_TOP_RADIUS, PrimitiveVisual::Property::SCALE_TOP_RADIUS, "scaleTopRadius" );
381
382     //Set model in control.
383     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
384   }
385
386   //Sets the 3D model to a cylinder and modifies the sliders appropriately.
387   void LoadCylinder()
388   {
389     InitialiseSlidersAndModel();
390
391     //Set up specific visual properties.
392     mVisualMap[ PrimitiveVisual::Property::SHAPE        ] = PrimitiveVisual::Shape::CYLINDER;
393     mVisualMap[ PrimitiveVisual::Property::SCALE_HEIGHT ] = DEFAULT_SCALE_HEIGHT;
394     mVisualMap[ PrimitiveVisual::Property::SCALE_RADIUS ] = DEFAULT_SCALE_RADIUS;
395     mVisualMap[ PrimitiveVisual::Property::SLICES       ] = DEFAULT_SLICES;
396
397     //Set up used sliders.
398     SetupSlider( 0, 1.0f, 32.0f, DEFAULT_SCALE_HEIGHT, PrimitiveVisual::Property::SCALE_HEIGHT, "scaleHeight" );
399     SetupSlider( 1, 1.0f, 32.0f, DEFAULT_SCALE_RADIUS, PrimitiveVisual::Property::SCALE_RADIUS, "scaleRadius" );
400     SetupSlider( 2, SLICES_LOWER_BOUND, SLICES_UPPER_BOUND, DEFAULT_STACKS, PrimitiveVisual::Property::SLICES, "slices" );
401     SetupMarks( mSliders.at( 2 ), SLICES_LOWER_BOUND, SLICES_UPPER_BOUND );
402
403     //Set model in control.
404     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
405   }
406
407   //Sets the 3D model to a cube and modifies the sliders appropriately.
408   void LoadCube()
409   {
410     InitialiseSlidersAndModel();
411
412     //Set up specific visual properties.
413     mVisualMap[ PrimitiveVisual::Property::SHAPE ] = PrimitiveVisual::Shape::CUBE;
414
415     //Set model in control.
416     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
417   }
418
419   //Sets the 3D model to a bevelled cube and modifies the sliders appropriately.
420   void LoadBevelledCube()
421   {
422     InitialiseSlidersAndModel();
423
424     //Set up specific visual properties.
425     mVisualMap[ PrimitiveVisual::Property::SHAPE            ] = PrimitiveVisual::Shape::BEVELLED_CUBE;
426     mVisualMap[ PrimitiveVisual::Property::BEVEL_PERCENTAGE ] = DEFAULT_BEVEL_PERCENTAGE;
427     mVisualMap[ PrimitiveVisual::Property::BEVEL_SMOOTHNESS ] = DEFAULT_BEVEL_SMOOTHNESS;
428
429     //Set up used sliders.
430     SetupSlider( 0, 0.0f, 1.0f, DEFAULT_BEVEL_PERCENTAGE, PrimitiveVisual::Property::BEVEL_PERCENTAGE, "bevelPercentage" );
431     SetupSlider( 1, 0.0f, 1.0f, DEFAULT_BEVEL_SMOOTHNESS, PrimitiveVisual::Property::BEVEL_SMOOTHNESS, "bevelSmoothness" );
432
433     //Set model in control.
434     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
435   }
436
437   //Sets the 3D model to an octahedron and modifies the sliders appropriately.
438   void LoadOctahedron()
439   {
440     InitialiseSlidersAndModel();
441
442     //Set up specific visual properties.
443     mVisualMap[ PrimitiveVisual::Property::SHAPE ] = PrimitiveVisual::Shape::OCTAHEDRON;
444
445     //Set model in control.
446     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
447   }
448
449   //Sets up the slider at the given index for the supplied property, and labels it appropriately.
450   // visualProperty is the property that will be set by this slider.
451   void SetupSlider( int sliderIndex, float lowerBound, float upperBound, float startPoint,
452                     Property::Index visualProperty, std::string visualPropertyLabel )
453   {
454     //Set up the slider itself.
455     mSliders.at( sliderIndex ).RegisterProperty( "visualProperty", Property::Value( visualProperty ), Property::READ_WRITE );
456     mSliders.at( sliderIndex ).SetProperty( Slider::Property::LOWER_BOUND, Property::Value( lowerBound ) );
457     mSliders.at( sliderIndex ).SetProperty( Slider::Property::UPPER_BOUND, Property::Value( upperBound ) );
458     mSliders.at( sliderIndex ).SetProperty( Slider::Property::VALUE, Property::Value( startPoint ) );
459     mSliders.at( sliderIndex ).SetVisible( true );
460
461     //Label the slider with the property.
462     //We reset the TextLabel to force a relayout of the table.
463     mSliderTable.RemoveChildAt( TableView::CellPosition(sliderIndex, 0) );
464
465     TextLabel sliderLabel = TextLabel::New( visualPropertyLabel );
466     sliderLabel.SetParentOrigin( ParentOrigin::CENTER );
467     sliderLabel.SetAnchorPoint( AnchorPoint::CENTER );
468     sliderLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
469
470     mSliderTable.AddChild( sliderLabel, TableView::CellPosition( sliderIndex, 0 ) );
471     mSliderTable.SetCellAlignment( TableView::CellPosition( sliderIndex, 0 ), HorizontalAlignment::LEFT, VerticalAlignment::CENTER );
472
473     mSliderLabels.at( sliderIndex ).SetVisible( true );
474     mSliderLabels.at( sliderIndex) = sliderLabel;
475   }
476
477   //Setup snapping to integer values between the two given values.
478   void SetupMarks( Slider& slider, int lower, int upper )
479   {
480     Property::Array marks;
481
482     for( int mark = lower; mark <= upper; mark++ )
483     {
484       marks.PushBack( Property::Value( mark ) );
485     }
486
487     slider.SetProperty( Slider::Property::MARKS, Property::Value( marks ) );
488     slider.SetProperty( Slider::Property::SNAP_TO_MARKS, Property::Value( true ) );
489   }
490
491   //When a shape button is tapped, switch to the corresponding shape.
492   bool OnChangeShapeClicked( Button button )
493   {
494     //Get the model number from the button.
495     int modelNumber;
496     button.GetProperty( button.GetPropertyIndex( "modelNumber" ) ).Get( modelNumber );
497
498     //Switch to the shape that corresponds to the model number.
499     switch( modelNumber )
500     {
501       case 0:
502       {
503         LoadSphere();
504         break;
505       }
506       case 1:
507       {
508         LoadCone();
509         break;
510       }
511       case 2:
512       {
513         LoadConicalFrustrum();
514         break;
515       }
516       case 3:
517       {
518         LoadCylinder();
519         break;
520       }
521       case 4:
522       {
523         LoadCube();
524         break;
525       }
526       case 5:
527       {
528         LoadBevelledCube();
529         break;
530       }
531       case 6:
532       {
533         LoadOctahedron();
534         break;
535       }
536     }
537
538     return true;
539   }
540
541   //When the slider is adjusted, change the corresponding shape property accordingly.
542   bool OnSliderValueChanged( Slider slider, float value )
543   {
544     //Update property map to reflect the change to the specific visual property.
545     int visualProperty;
546     slider.GetProperty( slider.GetPropertyIndex( "visualProperty" ) ).Get( visualProperty );
547     mVisualMap[ visualProperty ] = value;
548
549     //Reload the model to display the change.
550     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
551
552     return true;
553   }
554
555   //Panning around the shape rotates it.
556   void OnPan( Actor actor, const PanGesture& gesture )
557   {
558     switch( gesture.state )
559     {
560       case Gesture::Started:
561       {
562         //Pause animation, as the gesture will be used to manually rotate the model
563         mRotationAnimation.Pause();
564
565         break;
566       }
567       case Gesture::Continuing:
568       {
569         //Rotate based off the gesture.
570         mRotation.x -= gesture.displacement.y / X_ROTATION_DISPLACEMENT_FACTOR; // Y displacement rotates around X axis
571         mRotation.y += gesture.displacement.x / Y_ROTATION_DISPLACEMENT_FACTOR; // X displacement rotates around Y axis
572         Quaternion rotation = Quaternion( Radian( mRotation.x ), Vector3::XAXIS) *
573                               Quaternion( Radian( mRotation.y ), Vector3::YAXIS);
574
575         mModel.SetOrientation( rotation );
576
577         break;
578       }
579       case Gesture::Finished:
580       {
581         //Return to automatic animation
582         mRotationAnimation.Play();
583
584         break;
585       }
586       case Gesture::Cancelled:
587       {
588         //Return to automatic animation
589         mRotationAnimation.Play();
590
591         break;
592       }
593       default:
594       {
595         break;
596       }
597     }
598   }
599
600   //If escape or the back button is pressed, quit the application (and return to the launcher)
601   void OnKeyEvent( const KeyEvent& event )
602   {
603     if( event.state == KeyEvent::Down )
604     {
605       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
606       {
607         mApplication.Quit();
608       }
609     }
610   }
611
612 private:
613   Application& mApplication;
614
615   std::vector<Slider> mSliders; ///< Holds the sliders on screen that each shape accesses.
616   std::vector<TextLabel> mSliderLabels; ///< Holds the labels to each slider.
617   TableView mSliderTable; ///< A table to layout the sliders next to their labels.
618
619   Property::Map mVisualMap; ///< Property map to create a primitive visual.
620   Control mModel; ///< Control to house the primitive visual.
621
622   PanGestureDetector mPanGestureDetector; ///< Detects pan gestures for rotation of the model.
623   Animation mRotationAnimation; ///< Automatically rotates the model, unless it is being panned.
624
625   Vector4 mColor; ///< Color to set all shapes.
626   Vector2 mRotation; ///< Keeps track of model rotation.
627 };
628
629 void RunTest( Application& application )
630 {
631   PrimitiveShapesController test( application );
632
633   application.MainLoop();
634 }
635
636 // Entry point for Linux & Tizen applications
637 //
638 int main( int argc, char **argv )
639 {
640   Application application = Application::New( &argc, &argv );
641
642   RunTest( application );
643
644   return 0;
645 }