[dali_1.2.60] Merge branch 'devel/master'
[platform/core/uifw/dali-demo.git] / examples / text-label / text-label-example.cpp
1 /*
2  * Copyright (c) 2017 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 /**
19  * @file text-label-example.cpp
20  * @brief Basic usage of TextLabel control
21  */
22
23 // EXTERNAL INCLUDES
24 #include <dali/devel-api/object/handle-devel.h>
25 #include <dali/devel-api/actors/actor-devel.h>
26 #include <dali-toolkit/devel-api/controls/buttons/button-devel.h>
27 #include <dali-toolkit/dali-toolkit.h>
28 #include <iostream>
29
30 // INTERNAL INCLUDES
31 #include "shared/multi-language-strings.h"
32 #include "shared/view.h"
33
34 using namespace Dali;
35 using namespace Dali::Toolkit;
36 using namespace MultiLanguageStrings;
37
38 namespace
39 {
40 const char* const BACKGROUND_IMAGE = DEMO_IMAGE_DIR "grab-handle.png";
41 const char* const STYLES_IMAGE = DEMO_IMAGE_DIR "FontStyleButton_Main.png";
42 const char* const TICK_IMAGE_IMAGE = DEMO_IMAGE_DIR "FontStyleButton_OK_02.png";
43 const char* const STYLE_SELECTED_IMAGE = DEMO_IMAGE_DIR "FontStyleButton_OK_03.png";
44
45 const char* BUTTON_IMAGES[] =
46 {
47   DEMO_IMAGE_DIR "FontStyleButton_Colour.png",
48   DEMO_IMAGE_DIR "FontStyleButton_Outline.png",
49   DEMO_IMAGE_DIR "FontStyleButton_Shadow.png"
50 };
51
52 const unsigned int KEY_ZERO = 10;
53 const unsigned int KEY_ONE = 11;
54 const unsigned int KEY_A = 38;
55 const unsigned int KEY_F = 41;
56 const unsigned int KEY_H = 43;
57 const unsigned int KEY_U = 30;
58 const unsigned int KEY_V = 55;
59 const unsigned int KEY_M = 58;
60 const unsigned int KEY_L = 46;
61 const unsigned int KEY_S = 39;
62 const unsigned int KEY_PLUS = 21;
63 const unsigned int KEY_MINUS = 20;
64
65 const char* H_ALIGNMENT_STRING_TABLE[] =
66 {
67   "BEGIN",
68   "CENTER",
69   "END"
70 };
71
72 const unsigned int H_ALIGNMENT_STRING_COUNT = sizeof( H_ALIGNMENT_STRING_TABLE ) / sizeof( H_ALIGNMENT_STRING_TABLE[0u] );
73
74 const char* V_ALIGNMENT_STRING_TABLE[] =
75 {
76   "TOP",
77   "CENTER",
78   "BOTTOM"
79 };
80
81 const unsigned int V_ALIGNMENT_STRING_COUNT = sizeof( V_ALIGNMENT_STRING_TABLE ) / sizeof( V_ALIGNMENT_STRING_TABLE[0u] );
82
83 enum StyleType
84 {
85   TEXT_COLOR = 0,
86   OUTLINE,
87   SHADOW,
88   NUMBER_OF_STYLES
89 };
90
91 const Vector4 AVAILABLE_COLORS[] =
92 {
93   Color::GREEN,
94   Color::BLUE,
95   Color::RED,
96   Color::CYAN
97 };
98
99 const unsigned int NUMBER_OF_COLORS = sizeof( AVAILABLE_COLORS ) / sizeof( AVAILABLE_COLORS[0u] );
100
101 int ConvertToEven(int value)
102 {
103   return (value % 2 == 0) ? value : (value + 1);
104 }
105
106 struct HSVColorConstraint
107 {
108   HSVColorConstraint(float hue, float saturation, float value)
109   : hue(hue),
110     saturation(saturation),
111     value(value)
112   {
113   }
114
115   void operator()(Vector3& current, const PropertyInputContainer& inputs )
116   {
117     current = hsv2rgb(Vector3(inputs[0]->GetFloat(), saturation, value));
118   }
119
120   Vector3 hsv2rgb(Vector3 colorHSV)
121   {
122     float r=colorHSV.z*(1+colorHSV.y*(cos(colorHSV.x)-1));
123     float g=colorHSV.z*(1+colorHSV.y*(cos(colorHSV.x-2.09439)-1));
124     float b=colorHSV.z*(1+colorHSV.y*(cos(colorHSV.x+2.09439)-1));
125     return Vector3(r, g, b);
126   }
127   float hue;
128   float saturation;
129   float value;
130 };
131
132 const float STYLE_BUTTON_POSTION_RELATIVE_TO_STAGE = 0.9f;
133 const float BUTTON_SIZE_RATIO_TO_STAGE = 0.1f;
134 const float OUTLINE_WIDTH = 2.0f;
135 const Vector2 SHADOW_OFFSET = Vector2( 2.0f, 2.0f );
136
137
138 } // anonymous namespace
139
140 /**
141  * @brief The main class of the demo.
142  */
143 class TextLabelExample : public ConnectionTracker
144 {
145 public:
146
147   TextLabelExample( Application& application )
148   : mApplication( application ),
149     mLabel(),
150     mShadowActive( false ),
151     mOutlineActive( false ),
152     mSelectedColor(AVAILABLE_COLORS[0]),
153     mContainer(),
154     mGrabCorner(),
155     mBorder(),
156     mPanGestureDetector(),
157     mLayoutSize(),
158     mLanguageId( 0u ),
159     mAlignment( 0u ),
160     mHueAngleIndex( Property::INVALID_INDEX ),
161     mOverrideMixColorIndex( Property::INVALID_INDEX )
162
163   {
164     // Connect to the Application's Init signal
165     mApplication.InitSignal().Connect( this, &TextLabelExample::Create );
166   }
167
168   ~TextLabelExample()
169   {
170     // Nothing to do here.
171   }
172
173   /**
174    * One-time setup in response to Application InitSignal.
175    */
176   void Create( Application& application )
177   {
178     Stage stage = Stage::GetCurrent();
179
180     stage.KeyEventSignal().Connect(this, &TextLabelExample::OnKeyEvent);
181     mStageSize = stage.GetSize();
182
183     mButtonSize = Size( mStageSize.height * 0.1, mStageSize.height * 0.1 ); // Button size 1/10 of stage height
184
185     mContainer = Control::New();
186     mContainer.SetName( "Container" );
187     mContainer.SetParentOrigin( ParentOrigin::CENTER );
188     mLayoutSize = Vector2(mStageSize.width*0.6f, mStageSize.width*0.6f);
189     mContainer.SetSize( mLayoutSize );
190     mContainer.SetDrawMode( DrawMode::OVERLAY_2D );
191     stage.Add( mContainer );
192
193     // Resize the center layout when the corner is grabbed
194     mGrabCorner = ImageView::New( BACKGROUND_IMAGE );
195     mGrabCorner.SetName( "GrabCorner" );
196     mGrabCorner.SetAnchorPoint( AnchorPoint::TOP_CENTER );
197     mGrabCorner.SetParentOrigin( ParentOrigin::BOTTOM_RIGHT );
198     mGrabCorner.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
199     mContainer.Add( mGrabCorner );
200
201     mPanGestureDetector = PanGestureDetector::New();
202     mPanGestureDetector.Attach( mGrabCorner );
203     mPanGestureDetector.DetectedSignal().Connect( this, &TextLabelExample::OnPan );
204
205     mLabel = TextLabel::New( "\xF0\x9F\x98\x89 A Quick Brown Fox Jumps Over The Lazy Dog" );
206
207     mLabel.SetName( "TextLabel" );
208     mLabel.SetAnchorPoint( AnchorPoint::TOP_LEFT );
209     mLabel.SetSize(mLayoutSize);
210     mLabel.SetProperty( TextLabel::Property::MULTI_LINE, true );
211     mLabel.SetProperty( TextLabel::Property::TEXT_COLOR, Color::GREEN );
212     mLabel.SetBackgroundColor( Color::WHITE );
213     mContainer.Add( mLabel );
214
215     // Create style activate button
216     mStyleMenuButton = PushButton::New();
217     mStyleMenuButton.SetPosition( mButtonSize.width, mStageSize.height * STYLE_BUTTON_POSTION_RELATIVE_TO_STAGE );
218     mStyleMenuButton.SetSize( mButtonSize );
219     mStyleMenuButton.SetProperty( Button::Property::TOGGLABLE, true );
220     mStyleMenuButton.SetProperty( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, STYLES_IMAGE );
221     mStyleMenuButton.SetProperty( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, TICK_IMAGE_IMAGE );
222
223     mStyleMenuButton.ClickedSignal().Connect( this, &TextLabelExample::OnStyleButtonClicked );
224     stage.Add( mStyleMenuButton );
225
226     // Add a border for the container so you can see the container is being resized while grabbing the handle.
227     mBorder = Control::New();
228     mBorder.SetAnchorPoint( AnchorPoint::TOP_LEFT );
229     mBorder.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
230     mBorder.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
231
232     Dali::Property::Map border;
233     border.Insert( Toolkit::Visual::Property::TYPE,  Visual::BORDER );
234     border.Insert( BorderVisual::Property::COLOR,  Color::WHITE );
235     border.Insert( BorderVisual::Property::SIZE,  2.f );
236     mBorder.SetProperty( Control::Property::BACKGROUND, border );
237     mContainer.Add( mBorder );
238     mBorder.SetVisible(false);
239
240     mGrabCorner.RaiseToTop();
241
242     mHueAngleIndex = mLabel.RegisterProperty( "hue", 0.0f );
243     Renderer bgRenderer = mLabel.GetRendererAt(0);
244     mOverrideMixColorIndex = DevelHandle::GetPropertyIndex( bgRenderer, ColorVisual::Property::MIX_COLOR );
245
246     Constraint constraint = Constraint::New<Vector3>( bgRenderer, mOverrideMixColorIndex, HSVColorConstraint(0.0f, 0.5f, 0.8f));
247     constraint.AddSource( Source( mLabel, mHueAngleIndex ) );
248     constraint.SetRemoveAction( Constraint::Discard );
249     constraint.Apply();
250
251     Animation anim = Animation::New(50.0f);
252     anim.AnimateTo(Property(mLabel, mHueAngleIndex), 6.28318f);
253     anim.SetLooping(true);
254     anim.Play();
255
256     // Animate the text color 3 times from source color to Yellow
257     Animation animation = Animation::New( 2.f );
258     animation.AnimateTo( Property( mLabel, TextLabel::Property::TEXT_COLOR ), Color::YELLOW, AlphaFunction::SIN );
259     animation.SetLoopCount( 3 );
260     animation.Play();
261
262     Property::Value labelText = mLabel.GetProperty( TextLabel::Property::TEXT );
263     std::cout << "Displaying text: \"" << labelText.Get< std::string >() << "\"" << std::endl;
264   }
265
266   // Depending on button pressed, apply the style to the text label
267   bool OnStyleSelected( Toolkit::Button button )
268   {
269     if( button == mStyleButtons[ StyleType::TEXT_COLOR ] )
270     {
271       Animation animation = Animation::New( 2.f );
272       animation.AnimateTo( Property( mLabel, TextLabel::Property::TEXT_COLOR ), mSelectedColor, AlphaFunction::LINEAR );
273       animation.Play();
274     }
275     else if( button == mStyleButtons[ StyleType::OUTLINE ] )
276     {
277       Property::Map outlineMap;
278       float outlineWidth = OUTLINE_WIDTH;
279
280       if( mOutlineActive )
281       {
282         outlineWidth = ( mOutlineColor == mSelectedColor ) ? 0.0f : OUTLINE_WIDTH ;  // toggles outline on/off
283       }
284       mOutlineActive = ( outlineWidth > 0.0f ) ? true : false;
285
286       mOutlineColor = mSelectedColor;
287       outlineMap["color"] = mOutlineColor;
288       outlineMap["width"] = outlineWidth;
289       mLabel.SetProperty( TextLabel::Property::OUTLINE, outlineMap );
290     }
291     else if( button == mStyleButtons[ StyleType::SHADOW ] )
292     {
293       Vector2 shadowOffset( SHADOW_OFFSET ); // Will be set to zeros if color already set
294       Property::Value value = mLabel.GetProperty( TextLabel::Property::SHADOW_COLOR  );
295       Vector4 currentShadowColor;
296       value.Get( currentShadowColor );
297
298       if ( mShadowActive )
299       {
300         // toggle shadow off ( zero offset ) if color is already set
301         shadowOffset = ( currentShadowColor == mSelectedColor ) ? Vector2::ZERO : Vector2( SHADOW_OFFSET );
302       }
303
304       mShadowActive = ( shadowOffset == Vector2::ZERO ) ? false : true;
305
306       mLabel.SetProperty( TextLabel::Property::SHADOW_OFFSET, shadowOffset );
307       mLabel.SetProperty( TextLabel::Property::SHADOW_COLOR, mSelectedColor );
308     }
309     return true;
310   }
311
312   bool OnColorSelected( Toolkit::Button button )
313   {
314     for( unsigned int index = 0; index < NUMBER_OF_COLORS; index++)
315     {
316       if ( mColorButtons[index] == button )
317       {
318         mSelectedColor = AVAILABLE_COLORS[ index ];
319         return true;
320       }
321     }
322     return true;
323   }
324
325   void ShowColorButtons()
326   {
327     for( unsigned int index = 0; index < NUMBER_OF_COLORS; index++)
328     {
329       mColorButtons[index] = RadioButton::New();
330       mColorButtons[index].SetPosition( mButtonSize.width, mStageSize.height * STYLE_BUTTON_POSTION_RELATIVE_TO_STAGE - ( mButtonSize.width * (index+1) ) );
331       mColorButtons[index].SetSize( mButtonSize );
332       mColorButtons[index].ClickedSignal().Connect( this, &TextLabelExample::OnColorSelected );
333       mColorButtons[index].SetProperty( Button::Property::TOGGLABLE, true );
334       Property::Map propertyMap;
335       propertyMap.Insert(Visual::Property::TYPE,  Visual::COLOR);
336       propertyMap.Insert(ColorVisual::Property::MIX_COLOR, AVAILABLE_COLORS[ index ]);
337       mColorButtons[index].SetProperty( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, propertyMap );
338       mColorButtons[index].SetProperty( Toolkit::DevelButton::Property::UNSELECTED_VISUAL, propertyMap );
339
340       propertyMap.Insert(Visual::Property::TYPE,  Visual::COLOR);
341       propertyMap.Insert(ColorVisual::Property::MIX_COLOR, AVAILABLE_COLORS[ index ]);
342       mColorButtons[index].SetProperty( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, propertyMap );
343
344       mColorButtons[index].SetProperty( Toolkit::DevelButton::Property::SELECTED_VISUAL,
345                           Property::Map().Add( Toolkit::Visual::Property::TYPE, Visual::BORDER )
346                                          .Add( BorderVisual::Property::COLOR, Color::WHITE )
347                                          .Add( BorderVisual::Property::SIZE, 2.0f )
348                                          .Add( BorderVisual::Property::ANTI_ALIASING, true ) );
349
350       Stage::GetCurrent().Add( mColorButtons[index] );
351     }
352   }
353
354
355   void HideColorButtons()
356   {
357     for( unsigned int index = 0; index < NUMBER_OF_COLORS; index++)
358     {
359        UnparentAndReset( mColorButtons[index] );
360     }
361   }
362
363   void HideStyleButtons()
364   {
365     for( unsigned int index = 0; index < NUMBER_OF_STYLES; index++)
366     {
367        UnparentAndReset( mStyleButtons[index] );
368     }
369   }
370
371   bool OnStyleButtonClicked( Toolkit::Button button )
372   {
373     if ( button.GetProperty( Toolkit::Button::Property::SELECTED ).Get<bool>() )
374     {
375       for ( unsigned int index = 0; index < NUMBER_OF_STYLES; index++ )
376       {
377         mStyleButtons[index] = PushButton::New();
378         mStyleButtons[index].SetPosition( mButtonSize.width + ( mButtonSize.width * (index+1) ), mStageSize.height * STYLE_BUTTON_POSTION_RELATIVE_TO_STAGE );
379         mStyleButtons[index].SetSize( mButtonSize );
380         mStyleButtons[index].SetProperty( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, BUTTON_IMAGES[ index ] );
381         mStyleButtons[index].SetProperty( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, STYLE_SELECTED_IMAGE );
382         mStyleButtons[index].ClickedSignal().Connect( this, &TextLabelExample::OnStyleSelected );
383         Stage::GetCurrent().Add( mStyleButtons[index] );
384       }
385       ShowColorButtons();
386     }
387     else
388     {
389       // hide menu and colors
390       HideColorButtons();
391       HideStyleButtons();
392     }
393     return true;
394   }
395
396   // Resize the text-label with pan gesture
397   void OnPan( Actor actor, const PanGesture& gesture )
398   {
399     // Reset mLayoutSize when the pan starts
400     if( gesture.state == Gesture::Started )
401     {
402       if( mLayoutSize.x < 2.0f )
403       {
404         mLayoutSize.x = 2.0f;
405       }
406
407       if( mLayoutSize.y < 2.0f )
408       {
409         mLayoutSize.y = 2.0f;
410       }
411
412       // Only show the border during the panning
413       mBorder.SetVisible(true);
414     }
415
416     mLayoutSize.x += gesture.displacement.x * 2.0f;
417     mLayoutSize.y += gesture.displacement.y * 2.0f;
418
419     if( mLayoutSize.x >= 2.0f ||
420         mLayoutSize.y >= 2.0f )
421     {
422       mLayoutSize.x = std::min ( mLayoutSize.x, mStageSize.width );
423       mLayoutSize.y = std::min ( mLayoutSize.y, mStageSize.height*.9f );
424
425       // Avoid pixel mis-alignment issue
426       Vector2 clampedSize = Vector2( std::max( ConvertToEven( static_cast<int>( mLayoutSize.x )), 2 ),
427                                      std::max( ConvertToEven( static_cast<int>( mLayoutSize.y )), 2 ) );
428
429       mContainer.SetSize( clampedSize );
430     }
431
432     if( gesture.state == Gesture::Cancelled || gesture.state == Gesture::Finished )
433     {
434       // Resize the text label to match the container size when panning is finished
435       mLabel.SetSize(mLayoutSize);
436       mBorder.SetVisible(false);
437     }
438   }
439
440   /**
441    * Main key event handler
442    */
443   void OnKeyEvent(const KeyEvent& event)
444   {
445     if(event.state == KeyEvent::Down)
446     {
447       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
448       {
449         mApplication.Quit();
450       }
451       else if( event.IsCtrlModifier() )
452       {
453         switch( event.keyCode )
454         {
455           // Select rendering back-end
456           case KEY_ZERO: // fall through
457           case KEY_ONE:
458           {
459             mLabel.SetProperty( TextLabel::Property::RENDERING_BACKEND, event.keyCode - 10 );
460             break;
461           }
462           case KEY_A: // Animate text colour
463           {
464             Animation animation = Animation::New( 2.f );
465             animation.AnimateTo( Property( mLabel, TextLabel::Property::TEXT_COLOR ), Color::RED, AlphaFunction::SIN );
466             animation.SetLoopCount( 3 );
467             animation.Play();
468             break;
469           }
470           case KEY_F: // Fill vertically
471           {
472             if( ResizePolicy::DIMENSION_DEPENDENCY == mLabel.GetResizePolicy(Dimension::HEIGHT) )
473             {
474               mLabel.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
475             }
476             else
477             {
478               mLabel.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
479             }
480             break;
481           }
482           case KEY_H: // Horizontal alignment
483           {
484             if( ++mAlignment >= H_ALIGNMENT_STRING_COUNT )
485             {
486               mAlignment = 0u;
487             }
488
489             mLabel.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, H_ALIGNMENT_STRING_TABLE[ mAlignment ] );
490             break;
491           }
492           case KEY_V: // Vertical alignment
493           {
494             if( ++mAlignment >= V_ALIGNMENT_STRING_COUNT )
495             {
496               mAlignment = 0u;
497             }
498
499             mLabel.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, V_ALIGNMENT_STRING_TABLE[ mAlignment ] );
500             break;
501           }
502           case KEY_M: // Multi-line
503           {
504             bool multiLine = mLabel.GetProperty<bool>( TextLabel::Property::MULTI_LINE );
505             mLabel.SetProperty( TextLabel::Property::MULTI_LINE, !multiLine );
506             break;
507           }
508           case KEY_L: // Language
509           {
510             const Language& language = LANGUAGES[ mLanguageId ];
511
512             mLabel.SetProperty( TextLabel::Property::TEXT, language.text );
513
514             if( ++mLanguageId >= NUMBER_OF_LANGUAGES )
515             {
516               mLanguageId = 0u;
517             }
518             break;
519           }
520           case KEY_S: // Shadow color
521           {
522             if( Color::BLACK == mLabel.GetProperty<Vector4>( TextLabel::Property::SHADOW_COLOR ) )
523             {
524               mLabel.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::RED );
525             }
526             else
527             {
528               mLabel.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::BLACK );
529             }
530             break;
531           }
532           case KEY_U: // Markup
533           {
534             mLabel.SetProperty( TextLabel::Property::ENABLE_MARKUP, true );
535             mLabel.SetProperty( TextLabel::Property::TEXT, "<font family='DejaVuSerif' size='18'>H<color value='blue'>ello</color> <font weight='bold'>world</font> demo</font>" );
536             break;
537           }
538           case KEY_PLUS: // Increase shadow offset
539           {
540             mLabel.SetProperty( TextLabel::Property::SHADOW_OFFSET, mLabel.GetProperty<Vector2>( TextLabel::Property::SHADOW_OFFSET ) + Vector2( 1.0f, 1.0f ) );
541             break;
542           }
543           case KEY_MINUS: // Decrease shadow offset
544           {
545             mLabel.SetProperty( TextLabel::Property::SHADOW_OFFSET, mLabel.GetProperty<Vector2>( TextLabel::Property::SHADOW_OFFSET ) - Vector2( 1.0f, 1.0f ) );
546             break;
547           }
548
549         }
550       }
551     }
552   }
553
554 private:
555
556   Application& mApplication;
557
558   TextLabel mLabel;
559
560   PushButton mStyleMenuButton;
561   PushButton mStyleButtons[ NUMBER_OF_STYLES ];
562   bool mShadowActive;
563   bool mOutlineActive;
564   Vector4 mSelectedColor;
565   Vector4 mOutlineColor; // Store outline as Vector4 whilst TextLabel Outline Property returns a string when using GetProperty
566   Button mColorButtons[ NUMBER_OF_COLORS ];
567
568   Control mContainer;
569   Control mGrabCorner;
570   Control mBorder;
571
572   PanGestureDetector mPanGestureDetector;
573
574   Vector2 mLayoutSize;
575
576   Size mStageSize;
577   Size mButtonSize;
578
579   unsigned int mLanguageId;
580   unsigned int mAlignment;
581   Property::Index mHueAngleIndex;
582   Property::Index mOverrideMixColorIndex;
583 };
584
585 void RunTest( Application& application )
586 {
587   TextLabelExample test( application );
588
589   application.MainLoop();
590 }
591
592 /** Entry point for Linux & Tizen applications */
593 int DALI_EXPORT_API main( int argc, char **argv )
594 {
595   Application application = Application::New( &argc, &argv, DEMO_THEME_PATH );
596
597   RunTest( application );
598
599   return 0;
600 }