Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-demo.git] / examples / text-label / text-label-example.cpp
1 /*
2  * Copyright (c) 2018 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 Usage of TextLabel control with style application.
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 #include "expanding-buttons.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 STYLE_SELECTED_IMAGE = DEMO_IMAGE_DIR "FontStyleButton_OK_03.png";
43
44 const char* BUTTON_IMAGES[] =
45 {
46   DEMO_IMAGE_DIR "FontStyleButton_Colour.png",
47   DEMO_IMAGE_DIR "FontStyleButton_Outline.png",
48   DEMO_IMAGE_DIR "FontStyleButton_Shadow.png"
49 };
50
51 const unsigned int KEY_ZERO = 10;
52 const unsigned int KEY_ONE = 11;
53 const unsigned int KEY_A = 38;
54 const unsigned int KEY_F = 41;
55 const unsigned int KEY_H = 43;
56 const unsigned int KEY_U = 30;
57 const unsigned int KEY_V = 55;
58 const unsigned int KEY_M = 58;
59 const unsigned int KEY_L = 46;
60 const unsigned int KEY_S = 39;
61 const unsigned int KEY_PLUS = 21;
62 const unsigned int KEY_MINUS = 20;
63
64 const char* H_ALIGNMENT_STRING_TABLE[] =
65 {
66   "BEGIN",
67   "CENTER",
68   "END"
69 };
70
71 const unsigned int H_ALIGNMENT_STRING_COUNT = sizeof( H_ALIGNMENT_STRING_TABLE ) / sizeof( H_ALIGNMENT_STRING_TABLE[0u] );
72
73 const char* V_ALIGNMENT_STRING_TABLE[] =
74 {
75   "TOP",
76   "CENTER",
77   "BOTTOM"
78 };
79
80 const unsigned int V_ALIGNMENT_STRING_COUNT = sizeof( V_ALIGNMENT_STRING_TABLE ) / sizeof( V_ALIGNMENT_STRING_TABLE[0u] );
81
82 enum StyleType
83 {
84   TEXT_COLOR = 0,
85   OUTLINE,
86   SHADOW,
87   NUMBER_OF_STYLES
88 };
89
90 const Vector4 AVAILABLE_COLORS[] =
91 {
92   Color::GREEN,
93   Color::BLUE,
94   Color::RED,
95   Color::CYAN,
96   Color::WHITE // Used as clear
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 const int GAP_BETWEEN_BUTTONS = 3;
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     mSelectedColor(AVAILABLE_COLORS[0]),
152     mStyleActivatedForColor( NUMBER_OF_STYLES ),
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     mColorButtonsHidden( true ),
163     mCollapseColorsAndStyles( false )
164   {
165     // Connect to the Application's Init signal
166     mApplication.InitSignal().Connect( this, &TextLabelExample::Create );
167
168     // Set Style flags to inactive
169     for ( unsigned int i = OUTLINE; i < NUMBER_OF_STYLES; i++ )
170     {
171       mStyleActiveState[ i ] = false;
172       mCurrentStyleColor[i] = AVAILABLE_COLORS[ NUMBER_OF_COLORS - 1 ];
173     }
174   }
175
176   ~TextLabelExample()
177   {
178     // Nothing to do here.
179   }
180
181   // Clicking the expanding button shows the registered style buttons.
182   void SetUpExpandingStyleButtons( Vector2 position )
183   {
184     mExpandingButtons = Demo::ExpandingButtons::New();
185     mExpandingButtons.SetPosition( mButtonSize.width, mStageSize.height * STYLE_BUTTON_POSTION_RELATIVE_TO_STAGE );
186     mExpandingButtons.CollapsingSignal().Connect( this, &TextLabelExample::OnExpandingButtonCollapsing );
187     mExpandingButtons.SetSize( mButtonSize );
188     // Creates the buttons to be expanded
189     CreateStyleButtons();
190
191     // Register the created buttons with the ExpandingButtons.
192     for ( unsigned int index = 0; index < NUMBER_OF_STYLES; index++ )
193     {
194       mExpandingButtons.RegisterButton( mStyleButtons[index] );
195     }
196   }
197
198   /**
199    * One-time setup in response to Application InitSignal.
200    */
201   void Create( Application& application )
202   {
203     Stage stage = Stage::GetCurrent();
204
205     stage.KeyEventSignal().Connect(this, &TextLabelExample::OnKeyEvent);
206     mStageSize = stage.GetSize();
207     mButtonSize = Size( mStageSize.height * 0.12, mStageSize.height * 0.12 ); // Button size 1/12 of stage height
208
209     mContainer = Control::New();
210     mContainer.SetName( "Container" );
211     mContainer.SetParentOrigin( ParentOrigin::CENTER );
212     mLayoutSize = Vector2(mStageSize.width*0.6f, mStageSize.width*0.6f);
213     mContainer.SetSize( mLayoutSize );
214     stage.Add( mContainer );
215
216     // Resize the center layout when the corner is grabbed
217     mGrabCorner = ImageView::New( BACKGROUND_IMAGE );
218     mGrabCorner.SetName( "GrabCorner" );
219     mGrabCorner.SetAnchorPoint( AnchorPoint::TOP_CENTER );
220     mGrabCorner.SetParentOrigin( ParentOrigin::BOTTOM_RIGHT );
221     mGrabCorner.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
222     mContainer.Add( mGrabCorner );
223
224     mPanGestureDetector = PanGestureDetector::New();
225     mPanGestureDetector.Attach( mGrabCorner );
226     mPanGestureDetector.DetectedSignal().Connect( this, &TextLabelExample::OnPan );
227
228     mLabel = TextLabel::New( "\xF0\x9F\x98\x89 A Quick Brown Fox Jumps Over The Lazy Dog" );
229
230     mLabel.SetName( "TextLabel" );
231     mLabel.SetAnchorPoint( AnchorPoint::TOP_LEFT );
232     mLabel.SetSize(mLayoutSize);
233     mLabel.SetProperty( TextLabel::Property::MULTI_LINE, true );
234     mLabel.SetProperty( TextLabel::Property::TEXT_COLOR, Color::GREEN );
235     mLabel.SetBackgroundColor( Color::WHITE );
236     mContainer.Add( mLabel );
237
238     // Clicking ExpandingButton shows the Registered Style buttons, clicking again hides them.
239     Vector2 expandingButtonPosition( mButtonSize.width, mStageSize.height * STYLE_BUTTON_POSTION_RELATIVE_TO_STAGE );
240     SetUpExpandingStyleButtons( expandingButtonPosition );
241     stage.Add( mExpandingButtons );
242
243     // Add a border for the container so you can see the container is being resized while grabbing the handle.
244     mBorder = Control::New();
245     mBorder.SetAnchorPoint( AnchorPoint::TOP_LEFT );
246     mBorder.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
247     mBorder.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
248
249     Dali::Property::Map border;
250     border.Insert( Toolkit::Visual::Property::TYPE,  Visual::BORDER );
251     border.Insert( BorderVisual::Property::COLOR,  Color::WHITE );
252     border.Insert( BorderVisual::Property::SIZE,  3.f );
253     mBorder.SetProperty( Control::Property::BACKGROUND, border );
254     mContainer.Add( mBorder );
255     mBorder.SetVisible(false);
256     mGrabCorner.RaiseToTop();
257
258     mHueAngleIndex = mLabel.RegisterProperty( "hue", 0.0f );
259     Renderer bgRenderer = mLabel.GetRendererAt(0);
260     mOverrideMixColorIndex = DevelHandle::GetPropertyIndex( bgRenderer, ColorVisual::Property::MIX_COLOR );
261
262     Constraint constraint = Constraint::New<Vector3>( bgRenderer, mOverrideMixColorIndex, HSVColorConstraint(0.0f, 0.5f, 0.8f));
263     constraint.AddSource( Source( mLabel, mHueAngleIndex ) );
264     constraint.SetRemoveAction( Constraint::Discard );
265     constraint.Apply();
266
267     Animation anim = Animation::New(50.0f);
268     anim.AnimateTo(Property(mLabel, mHueAngleIndex), 6.28318f);
269     anim.SetLooping(true);
270     anim.Play();
271
272     mContainer.RaiseToTop();
273     mGrabCorner.RaiseToTop();
274
275     Property::Value labelText = mLabel.GetProperty( TextLabel::Property::TEXT );
276     std::cout << "Displaying text: \"" << labelText.Get< std::string >() << "\"" << std::endl;
277   }
278
279   // If the styling buttons should colapse (hide) then the color buttons should also hide.
280   bool OnExpandingButtonCollapsing( Demo::ExpandingButtons button )
281   {
282     mCollapseColorsAndStyles = true;
283     HideColorButtons();
284     return true;
285   }
286
287   // Get the style type from the given button
288   StyleType GetStyleTypeFromButton( Toolkit::Button button )
289   {
290     StyleType style = StyleType::TEXT_COLOR;
291
292     if( button == mStyleButtons[ StyleType::OUTLINE ] )
293     {
294       style = StyleType::OUTLINE;
295     }
296     else if( button == mStyleButtons[ StyleType::SHADOW ] )
297     {
298       style = StyleType::SHADOW;
299     }
300     return style;
301   }
302
303   // Style selected, show color buttons
304   bool OnStyleButtonClicked( Toolkit::Button button )
305   {
306     StyleType selectedStyle = GetStyleTypeFromButton( button );
307     if ( mStyleActivatedForColor == selectedStyle )
308     {
309       HideColorButtons();
310     }
311     else
312     {
313       ResetColorButtons( mColorButtons, NUMBER_OF_COLORS );
314       ShowColorButtons( selectedStyle);
315     }
316     return true;
317   }
318
319   // Set style to selected color
320   bool OnColorSelected( Toolkit::Button button )
321   {
322     for( unsigned int index = 0; index < NUMBER_OF_COLORS; index++)
323     {
324       if ( mColorButtons[index] == button )
325       {
326         mSelectedColor = AVAILABLE_COLORS[ index ];
327       }
328     }
329
330     switch ( mStyleActivatedForColor )
331     {
332       case TEXT_COLOR :
333       {
334         Animation animation = Animation::New( 1.f );
335         animation.AnimateTo( Property( mLabel, TextLabel::Property::TEXT_COLOR ), mSelectedColor, AlphaFunction::LINEAR );
336         mCurrentStyleColor[ TEXT_COLOR ] = mSelectedColor;
337         animation.Play();
338         break;
339       }
340       case OUTLINE :
341       {
342         Property::Map outlineMap;
343         float outlineWidth = OUTLINE_WIDTH;
344
345         if( mStyleActiveState[ OUTLINE ] )
346         {
347           outlineWidth = ( Color::WHITE == mSelectedColor ) ? 0.0f : OUTLINE_WIDTH ;  // toggles outline on/off
348         }
349         mStyleActiveState[ OUTLINE ] = ( outlineWidth > 0.0f ) ? true : false;
350
351         outlineMap["color"] = mSelectedColor;
352         outlineMap["width"] = outlineWidth;
353         mCurrentStyleColor[ OUTLINE ] = mSelectedColor;
354         mLabel.SetProperty( TextLabel::Property::OUTLINE, outlineMap );
355         break;
356       }
357       case SHADOW :
358       {
359         Vector2 shadowOffset( SHADOW_OFFSET ); // Will be set to zeros if color already set
360         Property::Value value = mLabel.GetProperty( TextLabel::Property::SHADOW_COLOR  );
361         Vector4 currentShadowColor;
362         value.Get( currentShadowColor );
363
364         if ( mStyleActiveState[ SHADOW ] )
365         {
366           // toggle shadow off ( zero offset ) if color is already set
367           shadowOffset = (  Color::WHITE == mSelectedColor ) ? Vector2::ZERO : Vector2( SHADOW_OFFSET );
368         }
369
370         mStyleActiveState[ SHADOW ] = ( shadowOffset == Vector2::ZERO ) ? false : true;
371         mCurrentStyleColor[ SHADOW ] = mSelectedColor;
372
373         mLabel.SetProperty( TextLabel::Property::SHADOW_OFFSET, shadowOffset );
374         mLabel.SetProperty( TextLabel::Property::SHADOW_COLOR, mSelectedColor );
375         break;
376       }
377       default :
378         break;
379     }
380
381     return true;
382   }
383
384   // Set the inital color button that should be be selected.
385   // If the style already has a color set then that should be used
386   void SetInitialSelectedColorButton( StyleType styleButtonIndex )
387   {
388     Vector4 selectedColor = mCurrentStyleColor[ styleButtonIndex ];
389
390     for ( unsigned int i = 0; i < NUMBER_OF_COLORS; i++ )
391     {
392       if ( AVAILABLE_COLORS[i] == selectedColor )
393       {
394         if ( mColorButtons[i] )
395         {
396           mColorButtons[ i ].SetProperty( Toolkit::DevelButton::Property::SELECTED, true );
397         }
398         break;
399       }
400     }
401   }
402
403   // Create a bar of color buttons that the user can select.
404   void ShowColorButtons( StyleType styleButtonIndex )
405   {
406     mCollapseColorsAndStyles = false; // Request to show colors so reset flag
407     mStyleActivatedForColor = styleButtonIndex;
408
409     for( unsigned int index = 0; index < NUMBER_OF_COLORS; index++)
410     {
411       if( !mColorButtonsAnimation )
412       {
413         mColorButtonsAnimation = Animation::New( 0.15f );
414         mColorButtonsAnimation.FinishedSignal().Connect( this, &TextLabelExample::OnColorButtonAnimationFinished );
415       }
416
417       // Create a color button
418       if ( ! mColorButtons[index] )
419       {
420         mColorButtons[index] = RadioButton::New();
421         mColorButtons[index].SetSize( mButtonSize );
422         mColorButtons[index].ClickedSignal().Connect( this, &TextLabelExample::OnColorSelected );
423         mColorButtons[index].SetProperty( Button::Property::TOGGLABLE, true );
424         Property::Map propertyMap;
425         propertyMap.Insert(Visual::Property::TYPE,  Visual::COLOR);
426         propertyMap.Insert(ColorVisual::Property::MIX_COLOR, AVAILABLE_COLORS[ index ]);
427         mColorButtons[index].SetProperty( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, propertyMap );
428         mColorButtons[index].SetProperty( Toolkit::DevelButton::Property::UNSELECTED_VISUAL, propertyMap );
429         mColorButtons[index].SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER );
430         mColorButtons[index].SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
431
432
433         propertyMap.Insert(Visual::Property::TYPE,  Visual::COLOR);
434         propertyMap.Insert(ColorVisual::Property::MIX_COLOR, AVAILABLE_COLORS[ index ]);
435         mColorButtons[index].SetProperty( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, propertyMap );
436
437         mColorButtons[index].SetProperty( Toolkit::DevelButton::Property::SELECTED_VISUAL,
438                             Property::Map().Add( Visual::Property::TYPE, Visual::BORDER )
439                                            .Add( BorderVisual::Property::COLOR, Color::WHITE )
440                                            .Add( BorderVisual::Property::SIZE, 4.0f )
441                                            .Add( BorderVisual::Property::ANTI_ALIASING, true ) );
442
443         // Use a white button with 50% transparency as a clear color button
444         if ( Color::WHITE == AVAILABLE_COLORS[ index ] && styleButtonIndex != StyleType::TEXT_COLOR )
445         {
446           mColorButtons[index].SetOpacity(0.5f);
447
448           mColorButtons[index].SetProperty( Toolkit::Button::Property::LABEL,
449                                             Property::Map().Add( Toolkit::Visual::Property::TYPE, Toolkit::Visual::TEXT )
450                                                            .Add( Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT, HorizontalAlignment::CENTER )
451                                                            .Add( Toolkit::TextVisual::Property::TEXT, "off") );
452
453         }
454       }
455
456       SetInitialSelectedColorButton( mStyleActivatedForColor );
457
458       mColorButtons[index].Unparent();
459
460       mStyleButtons[styleButtonIndex].Add( mColorButtons[index] );
461       mColorButtons[index].Lower();
462
463       // Position button using nice animation
464       mColorButtons[index].SetY( -GAP_BETWEEN_BUTTONS );
465       float desiredPosition = -( mButtonSize.height + GAP_BETWEEN_BUTTONS ) * (index);
466       AlphaFunction focusedAlphaFunction = AlphaFunction( Vector2 ( 0.32f, 0.08f ), Vector2( 0.38f, 1.72f ) );
467       mColorButtonsAnimation.AnimateBy( Property( mColorButtons[index], Actor::Property::POSITION_Y ), desiredPosition, focusedAlphaFunction );
468     }
469
470     mColorButtonsHidden = false;
471     mColorButtonsAnimation.Play();
472   }
473
474   // Remove the color buttons when not being shown.
475   void ResetColorButtons( Button buttons[], unsigned int numberOfButtons )
476   {
477     for( unsigned int index = 0; index < numberOfButtons; index++)
478     {
479       UnparentAndReset( buttons[index] );
480     }
481   }
482
483   void OnColorButtonAnimationFinished( Animation& animation )
484   {
485     animation.Clear();
486     if ( mColorButtonsHidden )
487     {
488       ResetColorButtons( mColorButtons, NUMBER_OF_COLORS );
489       animation.Reset(); // Handle reset
490       if ( mCollapseColorsAndStyles )
491       {
492         mExpandingButtons.Collapse();
493       }
494     }
495   }
496
497   // Create the style buttons that will expand from the expanding button.
498   void CreateStyleButtons()
499   {
500     for ( unsigned int index = 0; index < NUMBER_OF_STYLES; index++ )
501     {
502       if ( ! mStyleButtons[index] )
503       {
504         mStyleButtons[index] = PushButton::New();
505         mStyleButtons[index].SetProperty( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, BUTTON_IMAGES[ index ] );
506         mStyleButtons[index].SetProperty( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, STYLE_SELECTED_IMAGE );
507         mStyleButtons[index].SetProperty( Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
508         mStyleButtons[index].SetSize( mButtonSize );
509         mStyleButtons[index].ClickedSignal().Connect( this, &TextLabelExample::OnStyleButtonClicked );
510       }
511     }
512   }
513
514   // Animate away the color bar.
515   void HideColorButtons()
516   {
517     if ( ! mColorButtonsHidden )
518     {
519       for( unsigned int index = 0; index < NUMBER_OF_COLORS; index++)
520       {
521         mColorButtonsAnimation.AnimateTo( Property( mColorButtons[index], Actor::Property::POSITION_Y ), 0.0f );
522       }
523       mColorButtonsHidden = true;
524       mColorButtonsAnimation.Play();
525     }
526     mStyleActivatedForColor = NUMBER_OF_STYLES;
527   }
528
529   //  Request the expanding button to collapse.
530   void HideStyleAndColorButtons()
531   {
532     mCollapseColorsAndStyles = true;
533     if ( mColorButtonsHidden )
534     {
535       mExpandingButtons.Collapse();
536     }
537     else
538     {
539       HideColorButtons();
540     }
541   }
542
543   // Resize the text-label with pan gesture
544   void OnPan( Actor actor, const PanGesture& gesture )
545   {
546     // Reset mLayoutSize when the pan starts
547     if( gesture.state == Gesture::Started )
548     {
549       if( mLayoutSize.x < 2.0f )
550       {
551         mLayoutSize.x = 2.0f;
552       }
553
554       if( mLayoutSize.y < 2.0f )
555       {
556         mLayoutSize.y = 2.0f;
557       }
558
559       // Only show the border during the panning
560       mBorder.SetVisible(true);
561
562       HideStyleAndColorButtons();
563     }
564
565     mLayoutSize.x += gesture.displacement.x * 2.0f;
566     mLayoutSize.y += gesture.displacement.y * 2.0f;
567
568     if( mLayoutSize.x >= 2.0f ||
569         mLayoutSize.y >= 2.0f )
570     {
571       mLayoutSize.x = std::min ( mLayoutSize.x, mStageSize.width );
572       mLayoutSize.y = std::min ( mLayoutSize.y, mStageSize.height*.9f );
573
574       // Avoid pixel mis-alignment issue
575       Vector2 clampedSize = Vector2( std::max( ConvertToEven( static_cast<int>( mLayoutSize.x )), 2 ),
576                                      std::max( ConvertToEven( static_cast<int>( mLayoutSize.y )), 2 ) );
577
578       mContainer.SetSize( clampedSize );
579     }
580
581     if( gesture.state == Gesture::Cancelled || gesture.state == Gesture::Finished )
582     {
583       // Resize the text label to match the container size when panning is finished
584       mLabel.SetSize(mLayoutSize);
585       mBorder.SetVisible(false);
586     }
587   }
588
589   /**
590    * Main key event handler
591    */
592   void OnKeyEvent(const KeyEvent& event)
593   {
594     if(event.state == KeyEvent::Down)
595     {
596       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
597       {
598         mApplication.Quit();
599       }
600       else if( event.IsCtrlModifier() )
601       {
602         switch( event.keyCode )
603         {
604           // Select rendering back-end
605           case KEY_ZERO: // fall through
606           case KEY_ONE:
607           {
608             mLabel.SetProperty( TextLabel::Property::RENDERING_BACKEND, event.keyCode - 10 );
609             break;
610           }
611           case KEY_A: // Animate text colour
612           {
613             Animation animation = Animation::New( 2.f );
614             animation.AnimateTo( Property( mLabel, TextLabel::Property::TEXT_COLOR ), Color::RED, AlphaFunction::SIN );
615             animation.SetLoopCount( 3 );
616             animation.Play();
617             break;
618           }
619           case KEY_F: // Fill vertically
620           {
621             if( ResizePolicy::DIMENSION_DEPENDENCY == mLabel.GetResizePolicy(Dimension::HEIGHT) )
622             {
623               mLabel.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
624             }
625             else
626             {
627               mLabel.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
628             }
629             break;
630           }
631           case KEY_H: // Horizontal alignment
632           {
633             if( ++mAlignment >= H_ALIGNMENT_STRING_COUNT )
634             {
635               mAlignment = 0u;
636             }
637
638             mLabel.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, H_ALIGNMENT_STRING_TABLE[ mAlignment ] );
639             break;
640           }
641           case KEY_V: // Vertical alignment
642           {
643             if( ++mAlignment >= V_ALIGNMENT_STRING_COUNT )
644             {
645               mAlignment = 0u;
646             }
647
648             mLabel.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, V_ALIGNMENT_STRING_TABLE[ mAlignment ] );
649             break;
650           }
651           case KEY_M: // Multi-line
652           {
653             bool multiLine = mLabel.GetProperty<bool>( TextLabel::Property::MULTI_LINE );
654             mLabel.SetProperty( TextLabel::Property::MULTI_LINE, !multiLine );
655             break;
656           }
657           case KEY_L: // Language
658           {
659             const Language& language = LANGUAGES[ mLanguageId ];
660
661             mLabel.SetProperty( TextLabel::Property::TEXT, language.text );
662
663             if( ++mLanguageId >= NUMBER_OF_LANGUAGES )
664             {
665               mLanguageId = 0u;
666             }
667             break;
668           }
669           case KEY_S: // Shadow color
670           {
671             if( Color::BLACK == mLabel.GetProperty<Vector4>( TextLabel::Property::SHADOW_COLOR ) )
672             {
673               mLabel.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::RED );
674             }
675             else
676             {
677               mLabel.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::BLACK );
678             }
679             break;
680           }
681           case KEY_U: // Markup
682           {
683             mLabel.SetProperty( TextLabel::Property::ENABLE_MARKUP, true );
684             mLabel.SetProperty( TextLabel::Property::TEXT, "<font family='DejaVuSerif' size='18'>H<color value='blue'>ello</color> <font weight='bold'>world</font> demo</font>" );
685             break;
686           }
687           case KEY_PLUS: // Increase shadow offset
688           {
689             mLabel.SetProperty( TextLabel::Property::SHADOW_OFFSET, mLabel.GetProperty<Vector2>( TextLabel::Property::SHADOW_OFFSET ) + Vector2( 1.0f, 1.0f ) );
690             break;
691           }
692           case KEY_MINUS: // Decrease shadow offset
693           {
694             mLabel.SetProperty( TextLabel::Property::SHADOW_OFFSET, mLabel.GetProperty<Vector2>( TextLabel::Property::SHADOW_OFFSET ) - Vector2( 1.0f, 1.0f ) );
695             break;
696           }
697
698         }
699       }
700     }
701   }
702
703 private:
704
705   Application& mApplication;
706
707   TextLabel mLabel;
708
709   Demo::ExpandingButtons mExpandingButtons;
710   PushButton mStyleButtons[ NUMBER_OF_STYLES ];
711   bool mStyleActiveState[ NUMBER_OF_STYLES ];
712
713   Vector4 mCurrentStyleColor[NUMBER_OF_STYLES ];
714
715   Vector4 mSelectedColor;
716
717   Button mColorButtons[ NUMBER_OF_COLORS ];
718
719   StyleType mStyleActivatedForColor; // The style that the color bar is connected to
720
721   Control mContainer;
722   Control mGrabCorner;
723   Control mBorder;
724
725   PanGestureDetector mPanGestureDetector;
726
727   Vector2 mLayoutSize;
728
729   Animation mColorButtonsAnimation;
730
731   Size mStageSize;
732   Size mButtonSize;
733
734   unsigned int mLanguageId;
735   unsigned int mAlignment;
736   Property::Index mHueAngleIndex;
737   Property::Index mOverrideMixColorIndex;
738
739   bool mColorButtonsHidden;
740   bool mCollapseColorsAndStyles;
741 };
742
743 int DALI_EXPORT_API main( int argc, char **argv )
744 {
745   Application application = Application::New( &argc, &argv, DEMO_THEME_PATH );
746   TextLabelExample test( application );
747   application.MainLoop();
748   return 0;
749 }