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