ef80cedb0dcb0714e229fb7c6d66d9f4ee3bb250
[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       Property::Map shadowMap;
307       shadowMap.Insert( "offset", shadowOffset );
308       shadowMap.Insert( "color", mSelectedColor );
309       shadowMap.Insert( "blurRadius", 2.0f );
310       mLabel.SetProperty( TextLabel::Property::SHADOW, shadowMap );
311     }
312     return true;
313   }
314
315   bool OnColorSelected( Toolkit::Button button )
316   {
317     for( unsigned int index = 0; index < NUMBER_OF_COLORS; index++)
318     {
319       if ( mColorButtons[index] == button )
320       {
321         mSelectedColor = AVAILABLE_COLORS[ index ];
322         return true;
323       }
324     }
325     return true;
326   }
327
328   void ShowColorButtons()
329   {
330     for( unsigned int index = 0; index < NUMBER_OF_COLORS; index++)
331     {
332       mColorButtons[index] = RadioButton::New();
333       mColorButtons[index].SetPosition( mButtonSize.width, mStageSize.height * STYLE_BUTTON_POSTION_RELATIVE_TO_STAGE - ( mButtonSize.width * (index+1) ) );
334       mColorButtons[index].SetSize( mButtonSize );
335       mColorButtons[index].ClickedSignal().Connect( this, &TextLabelExample::OnColorSelected );
336       mColorButtons[index].SetProperty( Button::Property::TOGGLABLE, true );
337       Property::Map propertyMap;
338       propertyMap.Insert(Visual::Property::TYPE,  Visual::COLOR);
339       propertyMap.Insert(ColorVisual::Property::MIX_COLOR, AVAILABLE_COLORS[ index ]);
340       mColorButtons[index].SetProperty( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, propertyMap );
341       mColorButtons[index].SetProperty( Toolkit::DevelButton::Property::UNSELECTED_VISUAL, propertyMap );
342
343       propertyMap.Insert(Visual::Property::TYPE,  Visual::COLOR);
344       propertyMap.Insert(ColorVisual::Property::MIX_COLOR, AVAILABLE_COLORS[ index ]);
345       mColorButtons[index].SetProperty( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, propertyMap );
346
347       mColorButtons[index].SetProperty( Toolkit::DevelButton::Property::SELECTED_VISUAL,
348                           Property::Map().Add( Toolkit::Visual::Property::TYPE, Visual::BORDER )
349                                          .Add( BorderVisual::Property::COLOR, Color::WHITE )
350                                          .Add( BorderVisual::Property::SIZE, 2.0f )
351                                          .Add( BorderVisual::Property::ANTI_ALIASING, true ) );
352
353       Stage::GetCurrent().Add( mColorButtons[index] );
354     }
355   }
356
357
358   void HideColorButtons()
359   {
360     for( unsigned int index = 0; index < NUMBER_OF_COLORS; index++)
361     {
362        UnparentAndReset( mColorButtons[index] );
363     }
364   }
365
366   void HideStyleButtons()
367   {
368     for( unsigned int index = 0; index < NUMBER_OF_STYLES; index++)
369     {
370        UnparentAndReset( mStyleButtons[index] );
371     }
372   }
373
374   bool OnStyleButtonClicked( Toolkit::Button button )
375   {
376     if ( button.GetProperty( Toolkit::Button::Property::SELECTED ).Get<bool>() )
377     {
378       for ( unsigned int index = 0; index < NUMBER_OF_STYLES; index++ )
379       {
380         mStyleButtons[index] = PushButton::New();
381         mStyleButtons[index].SetPosition( mButtonSize.width + ( mButtonSize.width * (index+1) ), mStageSize.height * STYLE_BUTTON_POSTION_RELATIVE_TO_STAGE );
382         mStyleButtons[index].SetSize( mButtonSize );
383         mStyleButtons[index].SetProperty( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, BUTTON_IMAGES[ index ] );
384         mStyleButtons[index].SetProperty( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, STYLE_SELECTED_IMAGE );
385         mStyleButtons[index].ClickedSignal().Connect( this, &TextLabelExample::OnStyleSelected );
386         Stage::GetCurrent().Add( mStyleButtons[index] );
387       }
388       ShowColorButtons();
389     }
390     else
391     {
392       // hide menu and colors
393       HideColorButtons();
394       HideStyleButtons();
395     }
396     return true;
397   }
398
399   // Resize the text-label with pan gesture
400   void OnPan( Actor actor, const PanGesture& gesture )
401   {
402     // Reset mLayoutSize when the pan starts
403     if( gesture.state == Gesture::Started )
404     {
405       if( mLayoutSize.x < 2.0f )
406       {
407         mLayoutSize.x = 2.0f;
408       }
409
410       if( mLayoutSize.y < 2.0f )
411       {
412         mLayoutSize.y = 2.0f;
413       }
414
415       // Only show the border during the panning
416       mBorder.SetVisible(true);
417     }
418
419     mLayoutSize.x += gesture.displacement.x * 2.0f;
420     mLayoutSize.y += gesture.displacement.y * 2.0f;
421
422     if( mLayoutSize.x >= 2.0f ||
423         mLayoutSize.y >= 2.0f )
424     {
425       mLayoutSize.x = std::min ( mLayoutSize.x, mStageSize.width );
426       mLayoutSize.y = std::min ( mLayoutSize.y, mStageSize.height*.9f );
427
428       // Avoid pixel mis-alignment issue
429       Vector2 clampedSize = Vector2( std::max( ConvertToEven( static_cast<int>( mLayoutSize.x )), 2 ),
430                                      std::max( ConvertToEven( static_cast<int>( mLayoutSize.y )), 2 ) );
431
432       mContainer.SetSize( clampedSize );
433     }
434
435     if( gesture.state == Gesture::Cancelled || gesture.state == Gesture::Finished )
436     {
437       // Resize the text label to match the container size when panning is finished
438       mLabel.SetSize(mLayoutSize);
439       mBorder.SetVisible(false);
440     }
441   }
442
443   /**
444    * Main key event handler
445    */
446   void OnKeyEvent(const KeyEvent& event)
447   {
448     if(event.state == KeyEvent::Down)
449     {
450       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
451       {
452         mApplication.Quit();
453       }
454       else if( event.IsCtrlModifier() )
455       {
456         switch( event.keyCode )
457         {
458           // Select rendering back-end
459           case KEY_ZERO: // fall through
460           case KEY_ONE:
461           {
462             mLabel.SetProperty( TextLabel::Property::RENDERING_BACKEND, event.keyCode - 10 );
463             break;
464           }
465           case KEY_A: // Animate text colour
466           {
467             Animation animation = Animation::New( 2.f );
468             animation.AnimateTo( Property( mLabel, TextLabel::Property::TEXT_COLOR ), Color::RED, AlphaFunction::SIN );
469             animation.SetLoopCount( 3 );
470             animation.Play();
471             break;
472           }
473           case KEY_F: // Fill vertically
474           {
475             if( ResizePolicy::DIMENSION_DEPENDENCY == mLabel.GetResizePolicy(Dimension::HEIGHT) )
476             {
477               mLabel.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
478             }
479             else
480             {
481               mLabel.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
482             }
483             break;
484           }
485           case KEY_H: // Horizontal alignment
486           {
487             if( ++mAlignment >= H_ALIGNMENT_STRING_COUNT )
488             {
489               mAlignment = 0u;
490             }
491
492             mLabel.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, H_ALIGNMENT_STRING_TABLE[ mAlignment ] );
493             break;
494           }
495           case KEY_V: // Vertical alignment
496           {
497             if( ++mAlignment >= V_ALIGNMENT_STRING_COUNT )
498             {
499               mAlignment = 0u;
500             }
501
502             mLabel.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, V_ALIGNMENT_STRING_TABLE[ mAlignment ] );
503             break;
504           }
505           case KEY_M: // Multi-line
506           {
507             bool multiLine = mLabel.GetProperty<bool>( TextLabel::Property::MULTI_LINE );
508             mLabel.SetProperty( TextLabel::Property::MULTI_LINE, !multiLine );
509             break;
510           }
511           case KEY_L: // Language
512           {
513             const Language& language = LANGUAGES[ mLanguageId ];
514
515             mLabel.SetProperty( TextLabel::Property::TEXT, language.text );
516
517             if( ++mLanguageId >= NUMBER_OF_LANGUAGES )
518             {
519               mLanguageId = 0u;
520             }
521             break;
522           }
523           case KEY_S: // Shadow color
524           {
525             if( Color::BLACK == mLabel.GetProperty<Vector4>( TextLabel::Property::SHADOW_COLOR ) )
526             {
527               mLabel.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::RED );
528             }
529             else
530             {
531               mLabel.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::BLACK );
532             }
533             break;
534           }
535           case KEY_U: // Markup
536           {
537             mLabel.SetProperty( TextLabel::Property::ENABLE_MARKUP, true );
538             mLabel.SetProperty( TextLabel::Property::TEXT, "<font family='DejaVuSerif' size='18'>H<color value='blue'>ello</color> <font weight='bold'>world</font> demo</font>" );
539             break;
540           }
541           case KEY_PLUS: // Increase shadow offset
542           {
543             mLabel.SetProperty( TextLabel::Property::SHADOW_OFFSET, mLabel.GetProperty<Vector2>( TextLabel::Property::SHADOW_OFFSET ) + Vector2( 1.0f, 1.0f ) );
544             break;
545           }
546           case KEY_MINUS: // Decrease shadow offset
547           {
548             mLabel.SetProperty( TextLabel::Property::SHADOW_OFFSET, mLabel.GetProperty<Vector2>( TextLabel::Property::SHADOW_OFFSET ) - Vector2( 1.0f, 1.0f ) );
549             break;
550           }
551
552         }
553       }
554     }
555   }
556
557 private:
558
559   Application& mApplication;
560
561   TextLabel mLabel;
562
563   PushButton mStyleMenuButton;
564   PushButton mStyleButtons[ NUMBER_OF_STYLES ];
565   bool mShadowActive;
566   bool mOutlineActive;
567   Vector4 mSelectedColor;
568   Vector4 mOutlineColor; // Store outline as Vector4 whilst TextLabel Outline Property returns a string when using GetProperty
569   Button mColorButtons[ NUMBER_OF_COLORS ];
570
571   Control mContainer;
572   Control mGrabCorner;
573   Control mBorder;
574
575   PanGestureDetector mPanGestureDetector;
576
577   Vector2 mLayoutSize;
578
579   Size mStageSize;
580   Size mButtonSize;
581
582   unsigned int mLanguageId;
583   unsigned int mAlignment;
584   Property::Index mHueAngleIndex;
585   Property::Index mOverrideMixColorIndex;
586 };
587
588 int DALI_EXPORT_API main( int argc, char **argv )
589 {
590   Application application = Application::New( &argc, &argv, DEMO_THEME_PATH );
591   TextLabelExample test( application );
592   application.MainLoop();
593   return 0;
594 }