Merge "Fix ImageView OnRelayout and add a commnet in MARGIN property" into devel...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-label-impl.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 // CLASS HEADER
19 #include <dali-toolkit/internal/controls/text-controls/text-label-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/object/type-registry-helper.h>
23 #include <dali/devel-api/object/property-helper-devel.h>
24 #include <dali/devel-api/adaptor-framework/image-loading.h>
25 #include <dali/integration-api/debug.h>
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/public-api/text/rendering-backend.h>
29 #include <dali-toolkit/public-api/text/text-enumerations.h>
30 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
31 #include <dali-toolkit/internal/text/property-string-parser.h>
32 #include <dali-toolkit/internal/text/rendering/text-backend.h>
33 #include <dali-toolkit/internal/text/text-effects-style.h>
34 #include <dali-toolkit/internal/text/text-font-style.h>
35 #include <dali-toolkit/internal/text/text-view.h>
36 #include <dali-toolkit/internal/text/text-definitions.h>
37 #include <dali-toolkit/internal/styling/style-manager-impl.h>
38
39 #include <dali-toolkit/public-api/align-enumerations.h>
40 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
41 #include <dali-toolkit/devel-api/controls/control-devel.h>
42 #include <dali-toolkit/devel-api/visual-factory/visual-base.h>
43 #include <dali-toolkit/public-api/visuals/text-visual-properties.h>
44 #include <dali-toolkit/public-api/visuals/visual-properties.h>
45 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
46
47 using namespace Dali::Toolkit::Text;
48
49 namespace Dali
50 {
51
52 namespace Toolkit
53 {
54
55 namespace Internal
56 {
57
58 namespace
59 {
60   const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
61 }
62
63 namespace
64 {
65
66 #if defined ( DEBUG_ENABLED )
67   Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
68 #endif
69
70 const Scripting::StringEnum AUTO_SCROLL_STOP_MODE_TABLE[] =
71 {
72   { "IMMEDIATE", Toolkit::TextLabel::AutoScrollStopMode::IMMEDIATE },
73   { "FINISH_LOOP",  Toolkit::TextLabel::AutoScrollStopMode::FINISH_LOOP  },
74 };
75 const unsigned int AUTO_SCROLL_STOP_MODE_TABLE_COUNT = sizeof( AUTO_SCROLL_STOP_MODE_TABLE ) / sizeof( AUTO_SCROLL_STOP_MODE_TABLE[0] );
76
77 // Type registration
78 BaseHandle Create()
79 {
80   return Toolkit::TextLabel::New();
81 }
82
83 // Setup properties, signals and actions using the type-registry.
84 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextLabel, Toolkit::Control, Create );
85
86 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "renderingBackend",          INTEGER, RENDERING_BACKEND          )
87 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "text",                      STRING,  TEXT                       )
88 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "fontFamily",                STRING,  FONT_FAMILY                )
89 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "fontStyle",                 MAP,     FONT_STYLE                 )
90 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "pointSize",                 FLOAT,   POINT_SIZE                 )
91 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "multiLine",                 BOOLEAN, MULTI_LINE                 )
92 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "horizontalAlignment",       STRING,  HORIZONTAL_ALIGNMENT       )
93 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "verticalAlignment",         STRING,  VERTICAL_ALIGNMENT         )
94 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "unusedPropertyTextColor",   VECTOR4, UNUSED_PROPERTY_TEXT_COLOR )
95 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "shadowOffset",              VECTOR2, SHADOW_OFFSET              )
96 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "shadowColor",               VECTOR4, SHADOW_COLOR               )
97 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "underlineEnabled",          BOOLEAN, UNDERLINE_ENABLED          )
98 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "underlineColor",            VECTOR4, UNDERLINE_COLOR            )
99 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "underlineHeight",           FLOAT,   UNDERLINE_HEIGHT           )
100 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "enableMarkup",              BOOLEAN, ENABLE_MARKUP              )
101 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "enableAutoScroll",          BOOLEAN, ENABLE_AUTO_SCROLL         )
102 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "autoScrollSpeed",           INTEGER, AUTO_SCROLL_SPEED          )
103 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "autoScrollLoopCount",       INTEGER, AUTO_SCROLL_LOOP_COUNT     )
104 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "autoScrollGap",             FLOAT,   AUTO_SCROLL_GAP            )
105 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "lineSpacing",               FLOAT,   LINE_SPACING               )
106 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "underline",                 MAP,     UNDERLINE                  )
107 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "shadow",                    MAP,     SHADOW                     )
108 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "emboss",                    MAP,     EMBOSS                     )
109 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "outline",                   MAP,     OUTLINE                    )
110 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "pixelSize",                 FLOAT,   PIXEL_SIZE                 )
111 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "ellipsis",                  BOOLEAN, ELLIPSIS                   )
112 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "autoScrollLoopDelay",       FLOAT,   AUTO_SCROLL_LOOP_DELAY     )
113 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "autoScrollStopMode",        STRING,  AUTO_SCROLL_STOP_MODE      )
114 DALI_PROPERTY_REGISTRATION_READ_ONLY( Toolkit, TextLabel, "lineCount",                 INTEGER, LINE_COUNT                 )
115 DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "lineWrapMode",              INTEGER, LINE_WRAP_MODE             )
116 DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT( Toolkit, TextLabel, "textColor",      Color::BLACK,     TEXT_COLOR     )
117 DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit,    TextLabel, "textColorRed",   TEXT_COLOR_RED,   TEXT_COLOR, 0  )
118 DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit,    TextLabel, "textColorGreen", TEXT_COLOR_GREEN, TEXT_COLOR, 1  )
119 DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit,    TextLabel, "textColorBlue",  TEXT_COLOR_BLUE,  TEXT_COLOR, 2  )
120 DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit,    TextLabel, "textColorAlpha", TEXT_COLOR_ALPHA, TEXT_COLOR, 3  )
121 DALI_TYPE_REGISTRATION_END()
122
123 } // namespace
124
125 Toolkit::TextLabel TextLabel::New()
126 {
127   // Create the implementation, temporarily owned by this handle on stack
128   IntrusivePtr< TextLabel > impl = new TextLabel();
129
130   // Pass ownership to CustomActor handle
131   Toolkit::TextLabel handle( *impl );
132
133   // Second-phase init of the implementation
134   // This can only be done after the CustomActor connection has been made...
135   impl->Initialize();
136
137   return handle;
138 }
139
140 void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
141 {
142   Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( Dali::BaseHandle( object ) );
143
144   if( label )
145   {
146     TextLabel& impl( GetImpl( label ) );
147     switch( index )
148     {
149       case Toolkit::TextLabel::Property::RENDERING_BACKEND:
150       {
151         DALI_LOG_WARNING("[%s] Using deprecated Property TextLabel::Property::RENDERING_BACKEND which is no longer supported and will be ignored\n", __FUNCTION__);
152
153         int backend = value.Get< int >();
154
155 #ifndef ENABLE_VECTOR_BASED_TEXT_RENDERING
156         if( Text::RENDERING_VECTOR_BASED == backend )
157         {
158           backend = TextAbstraction::BITMAP_GLYPH; // Fallback to bitmap-based rendering
159         }
160 #endif
161         if( impl.mRenderingBackend != backend )
162         {
163           impl.mRenderingBackend = backend;
164           impl.mTextUpdateNeeded = true;
165
166           if( impl.mController )
167           {
168             // When using the vector-based rendering, the size of the GLyphs are different
169             TextAbstraction::GlyphType glyphType = (Text::RENDERING_VECTOR_BASED == impl.mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH;
170             impl.mController->SetGlyphType( glyphType );
171           }
172         }
173         break;
174       }
175       case Toolkit::TextLabel::Property::TEXT:
176       {
177         if( impl.mController )
178         {
179           impl.mController->SetText( value.Get< std::string >() );
180         }
181         break;
182       }
183       case Toolkit::TextLabel::Property::FONT_FAMILY:
184       {
185         if( impl.mController )
186         {
187           const std::string& fontFamily = value.Get< std::string >();
188
189           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextLabel::SetProperty Property::FONT_FAMILY newFont(%s)\n", fontFamily.c_str() );
190           impl.mController->SetDefaultFontFamily( fontFamily );
191         }
192         break;
193       }
194       case Toolkit::TextLabel::Property::FONT_STYLE:
195       {
196         SetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT );
197         break;
198       }
199       case Toolkit::TextLabel::Property::POINT_SIZE:
200       {
201         if( impl.mController )
202         {
203           const float pointSize = value.Get< float >();
204
205           if( !Equals( impl.mController->GetDefaultFontSize( Text::Controller::POINT_SIZE ), pointSize ) )
206           {
207             impl.mController->SetDefaultFontSize( pointSize, Text::Controller::POINT_SIZE );
208           }
209         }
210         break;
211       }
212       case Toolkit::TextLabel::Property::MULTI_LINE:
213       {
214         if( impl.mController )
215         {
216           impl.mController->SetMultiLineEnabled( value.Get< bool >() );
217         }
218         break;
219       }
220       case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT:
221       {
222         if( impl.mController )
223         {
224           Text::HorizontalAlignment::Type alignment( static_cast< Text::HorizontalAlignment::Type >( -1 ) ); // Set to invalid value to ensure a valid mode does get set
225           if( Text::GetHorizontalAlignmentEnumeration( value, alignment ) )
226           {
227             impl.mController->SetHorizontalAlignment( alignment );
228           }
229         }
230         break;
231       }
232       case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT:
233       {
234         if( impl.mController )
235         {
236           Toolkit::Text::VerticalAlignment::Type alignment( static_cast< Text::VerticalAlignment::Type >( -1 ) ); // Set to invalid value to ensure a valid mode does get set
237           if( Text::GetVerticalAlignmentEnumeration( value, alignment ) )
238           {
239             impl.mController->SetVerticalAlignment( alignment );
240           }
241         }
242         break;
243       }
244
245       case Toolkit::TextLabel::Property::UNUSED_PROPERTY_TEXT_COLOR:
246       {
247         label.SetProperty( Toolkit::TextLabel::Property::TEXT_COLOR, value );
248         impl.mTextUpdateNeeded = true;
249         break;
250       }
251
252       case Toolkit::TextLabel::Property::SHADOW_OFFSET:
253       {
254         if( impl.mController )
255         {
256           const Vector2& shadowOffset = value.Get< Vector2 >();
257           if ( impl.mController->GetShadowOffset() != shadowOffset )
258           {
259             impl.mController->SetShadowOffset( shadowOffset );
260             impl.mTextUpdateNeeded = true;
261           }
262         }
263         break;
264       }
265       case Toolkit::TextLabel::Property::SHADOW_COLOR:
266       {
267         if( impl.mController )
268         {
269           const Vector4& shadowColor = value.Get< Vector4 >();
270           if ( impl.mController->GetShadowColor() != shadowColor )
271           {
272             impl.mController->SetShadowColor( shadowColor );
273             impl.mTextUpdateNeeded = true;
274           }
275         }
276         break;
277       }
278       case Toolkit::TextLabel::Property::UNDERLINE_COLOR:
279       {
280         if( impl.mController )
281         {
282           const Vector4& color = value.Get< Vector4 >();
283           if ( impl.mController->GetUnderlineColor() != color )
284           {
285             impl.mController->SetUnderlineColor( color );
286             impl.mTextUpdateNeeded = true;
287           }
288         }
289         break;
290       }
291       case Toolkit::TextLabel::Property::UNDERLINE_ENABLED:
292       {
293         if( impl.mController )
294         {
295           const bool enabled = value.Get< bool >();
296           if ( impl.mController->IsUnderlineEnabled() != enabled )
297           {
298             impl.mController->SetUnderlineEnabled( enabled );
299             impl.mTextUpdateNeeded = true;
300           }
301         }
302         break;
303       }
304
305       case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT:
306       {
307         if( impl.mController )
308         {
309           float height = value.Get< float >();
310           if( fabsf( impl.mController->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 )
311           {
312             impl.mController->SetUnderlineHeight( height );
313             impl.mTextUpdateNeeded = true;
314           }
315         }
316         break;
317       }
318       case Toolkit::TextLabel::Property::ENABLE_MARKUP:
319       {
320         if( impl.mController )
321         {
322           const bool enableMarkup = value.Get<bool>();
323           impl.mController->SetMarkupProcessorEnabled( enableMarkup );
324         }
325         break;
326       }
327       case Toolkit::TextLabel::Property::ENABLE_AUTO_SCROLL:
328       {
329         if( impl.mController )
330         {
331           const bool enableAutoScroll = value.Get<bool>();
332           // If request to auto scroll is the same as current state then do nothing.
333           if ( enableAutoScroll != impl.mController->IsAutoScrollEnabled() )
334           {
335              // If request is disable (false) and auto scrolling is enabled then need to stop it
336              if ( enableAutoScroll == false )
337              {
338                if( impl.mTextScroller )
339                {
340                  impl.mTextScroller->StopScrolling();
341                }
342              }
343              // If request is enable (true) then start autoscroll as not already running
344              else
345              {
346                impl.mController->SetTextElideEnabled( false );
347                impl.mController->SetAutoScrollEnabled( enableAutoScroll );
348              }
349           }
350         }
351         break;
352       }
353       case Toolkit::TextLabel::Property::AUTO_SCROLL_STOP_MODE:
354       {
355         if( !impl.mTextScroller )
356         {
357           impl.mTextScroller = Text::TextScroller::New( impl );
358         }
359         Toolkit::TextLabel::AutoScrollStopMode::Type stopMode = impl.mTextScroller->GetStopMode();
360         if( Scripting::GetEnumerationProperty< Toolkit::TextLabel::AutoScrollStopMode::Type >( value,
361                                                                                                     AUTO_SCROLL_STOP_MODE_TABLE,
362                                                                                                     AUTO_SCROLL_STOP_MODE_TABLE_COUNT,
363                                                                                                     stopMode ) )
364         {
365             impl.mTextScroller->SetStopMode( stopMode );
366         }
367         break;
368       }
369       case Toolkit::TextLabel::Property::AUTO_SCROLL_SPEED:
370       {
371         if( !impl.mTextScroller )
372         {
373           impl.mTextScroller = Text::TextScroller::New( impl );
374         }
375         impl.mTextScroller->SetSpeed( value.Get<int>() );
376         break;
377       }
378       case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_COUNT:
379       {
380         if( !impl.mTextScroller )
381         {
382           impl.mTextScroller = Text::TextScroller::New( impl );
383         }
384         impl.mTextScroller->SetLoopCount( value.Get<int>() );
385         break;
386       }
387       case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_DELAY:
388       {
389          if( !impl.mTextScroller )
390         {
391           impl.mTextScroller = Text::TextScroller::New( impl );
392         }
393         impl.mTextScroller->SetLoopDelay( value.Get<float>() );
394         break;
395       }
396       case Toolkit::TextLabel::Property::AUTO_SCROLL_GAP:
397       {
398         if( !impl.mTextScroller )
399         {
400           impl.mTextScroller = Text::TextScroller::New( impl );
401         }
402         impl.mTextScroller->SetGap( value.Get<float>() );
403         break;
404       }
405       case Toolkit::TextLabel::Property::LINE_SPACING:
406       {
407         if( impl.mController )
408         {
409           const float lineSpacing = value.Get<float>();
410           impl.mController->SetDefaultLineSpacing( lineSpacing );
411           impl.mTextUpdateNeeded = true;
412         }
413         break;
414       }
415       case Toolkit::TextLabel::Property::UNDERLINE:
416       {
417         const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
418         if( update )
419         {
420           impl.mTextUpdateNeeded = true;
421         }
422         break;
423       }
424       case Toolkit::TextLabel::Property::SHADOW:
425       {
426         const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
427         if( update )
428         {
429           impl.mTextUpdateNeeded = true;
430         }
431         break;
432       }
433       case Toolkit::TextLabel::Property::EMBOSS:
434       {
435         const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
436         if( update )
437         {
438           impl.mTextUpdateNeeded = true;
439         }
440         break;
441       }
442       case Toolkit::TextLabel::Property::OUTLINE:
443       {
444         const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
445         if( update )
446         {
447           impl.mTextUpdateNeeded = true;
448         }
449         break;
450       }
451       case Toolkit::TextLabel::Property::PIXEL_SIZE:
452       {
453         if( impl.mController )
454         {
455           const float pixelSize = value.Get< float >();
456           DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel %p PIXEL_SIZE %f\n", impl.mController.Get(), pixelSize );
457
458           if( !Equals( impl.mController->GetDefaultFontSize( Text::Controller::PIXEL_SIZE ), pixelSize ) )
459           {
460             impl.mController->SetDefaultFontSize( pixelSize, Text::Controller::PIXEL_SIZE );
461           }
462         }
463         break;
464       }
465       case Toolkit::TextLabel::Property::ELLIPSIS:
466       {
467         if( impl.mController )
468         {
469           const bool ellipsis = value.Get<bool>();
470           DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel %p ELLIPSIS %d\n", impl.mController.Get(), ellipsis );
471
472           impl.mController->SetTextElideEnabled( ellipsis );
473         }
474         break;
475       }
476       case Toolkit::TextLabel::Property::LINE_WRAP_MODE:
477       {
478         if( impl.mController )
479         {
480           Text::LineWrap::Mode lineWrapMode( static_cast< Text::LineWrap::Mode >( -1 ) ); // Set to invalid value to ensure a valid mode does get set
481           if( GetLineWrapModeEnumeration( value, lineWrapMode ) )
482           {
483             DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel %p LineWrap::MODE %d\n", impl.mController.Get(), lineWrapMode );
484             impl.mController->SetLineWrapMode( lineWrapMode );
485           }
486         }
487         break;
488       }
489     }
490   }
491 }
492
493 Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index index )
494 {
495   Property::Value value;
496
497   Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( Dali::BaseHandle( object ) );
498
499   if( label )
500   {
501     TextLabel& impl( GetImpl( label ) );
502     switch( index )
503     {
504       case Toolkit::TextLabel::Property::RENDERING_BACKEND:
505       {
506         DALI_LOG_WARNING("[%s] Using deprecated Property TextLabel::Property::RENDERING_BACKEND which is no longer supported and will be ignored\n", __FUNCTION__);
507
508         value = impl.mRenderingBackend;
509         break;
510       }
511       case Toolkit::TextLabel::Property::TEXT:
512       {
513         if( impl.mController )
514         {
515           std::string text;
516           impl.mController->GetText( text );
517           value = text;
518         }
519         break;
520       }
521       case Toolkit::TextLabel::Property::FONT_FAMILY:
522       {
523         if( impl.mController )
524         {
525           value = impl.mController->GetDefaultFontFamily();
526         }
527         break;
528       }
529       case Toolkit::TextLabel::Property::FONT_STYLE:
530       {
531         GetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT );
532         break;
533       }
534       case Toolkit::TextLabel::Property::POINT_SIZE:
535       {
536         if( impl.mController )
537         {
538           value = impl.mController->GetDefaultFontSize( Text::Controller::POINT_SIZE );
539         }
540         break;
541       }
542       case Toolkit::TextLabel::Property::MULTI_LINE:
543       {
544         if( impl.mController )
545         {
546           value = impl.mController->IsMultiLineEnabled();
547         }
548         break;
549       }
550       case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT:
551       {
552         if( impl.mController )
553         {
554           const char* name = Text::GetHorizontalAlignmentString( impl.mController->GetHorizontalAlignment() );
555
556            if ( name )
557            {
558              value = std::string( name );
559            }
560         }
561         break;
562       }
563       case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT:
564       {
565         if( impl.mController )
566         {
567           const char* name = Text::GetVerticalAlignmentString( impl.mController->GetVerticalAlignment() );
568           if( name )
569           {
570             value = std::string( name );
571           }
572         }
573         break;
574       }
575       case Toolkit::TextLabel::Property::UNUSED_PROPERTY_TEXT_COLOR:
576       {
577         value = label.GetProperty( Toolkit::TextLabel::Property::TEXT_COLOR );
578         break;
579       }
580       case Toolkit::TextLabel::Property::SHADOW_OFFSET:
581       {
582         if ( impl.mController )
583         {
584           value = impl.mController->GetShadowOffset();
585         }
586         break;
587       }
588       case Toolkit::TextLabel::Property::SHADOW_COLOR:
589       {
590         if ( impl.mController )
591         {
592           value = impl.mController->GetShadowColor();
593         }
594         break;
595       }
596       case Toolkit::TextLabel::Property::UNDERLINE_COLOR:
597       {
598         if ( impl.mController )
599         {
600           value = impl.mController->GetUnderlineColor();
601         }
602         break;
603       }
604       case Toolkit::TextLabel::Property::UNDERLINE_ENABLED:
605       {
606         if ( impl.mController )
607         {
608           value = impl.mController->IsUnderlineEnabled();
609         }
610         break;
611       }
612       case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT:
613       {
614         if ( impl.mController )
615         {
616           value = impl.mController->GetUnderlineHeight();
617         }
618         break;
619       }
620       case Toolkit::TextLabel::Property::ENABLE_MARKUP:
621       {
622         if( impl.mController )
623         {
624           value = impl.mController->IsMarkupProcessorEnabled();
625         }
626         break;
627       }
628       case Toolkit::TextLabel::Property::ENABLE_AUTO_SCROLL:
629       {
630         if( impl.mController )
631         {
632           value = impl.mController->IsAutoScrollEnabled();
633         }
634         break;
635       }
636       case Toolkit::TextLabel::Property::AUTO_SCROLL_STOP_MODE:
637       {
638         if( impl.mTextScroller )
639         {
640           const char* mode = Scripting::GetEnumerationName< Toolkit::TextLabel::AutoScrollStopMode::Type >( impl.mTextScroller->GetStopMode(),
641                                                                                                                  AUTO_SCROLL_STOP_MODE_TABLE,
642                                                                                                                  AUTO_SCROLL_STOP_MODE_TABLE_COUNT );
643           if( mode )
644           {
645             value = std::string( mode );
646           }
647         }
648         break;
649       }
650       case Toolkit::TextLabel::Property::AUTO_SCROLL_SPEED:
651       {
652         TextLabel& impl( GetImpl( label ) );
653         if ( impl.mTextScroller )
654         {
655           value = impl.mTextScroller->GetSpeed();
656         }
657         break;
658       }
659       case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_COUNT:
660       {
661         if( impl.mController )
662         {
663           TextLabel& impl( GetImpl( label ) );
664           if ( impl.mTextScroller )
665           {
666             value = impl.mTextScroller->GetLoopCount();
667           }
668         }
669         break;
670       }
671       case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_DELAY:
672       {
673         if( impl.mController )
674         {
675           TextLabel& impl( GetImpl( label ) );
676           if ( impl.mTextScroller )
677           {
678             value = impl.mTextScroller->GetLoopDelay();
679           }
680         }
681         break;
682       }
683       case Toolkit::TextLabel::Property::AUTO_SCROLL_GAP:
684       {
685         TextLabel& impl( GetImpl( label ) );
686         if ( impl.mTextScroller )
687         {
688           value = impl.mTextScroller->GetGap();
689         }
690         break;
691       }
692       case Toolkit::TextLabel::Property::LINE_SPACING:
693       {
694         if( impl.mController )
695         {
696           value = impl.mController->GetDefaultLineSpacing();
697         }
698         break;
699       }
700       case Toolkit::TextLabel::Property::UNDERLINE:
701       {
702         GetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
703         break;
704       }
705       case Toolkit::TextLabel::Property::SHADOW:
706       {
707         GetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
708         break;
709       }
710       case Toolkit::TextLabel::Property::EMBOSS:
711       {
712         GetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
713         break;
714       }
715       case Toolkit::TextLabel::Property::OUTLINE:
716       {
717         GetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
718         break;
719       }
720       case Toolkit::TextLabel::Property::PIXEL_SIZE:
721       {
722         if( impl.mController )
723         {
724           value = impl.mController->GetDefaultFontSize( Text::Controller::PIXEL_SIZE );
725         }
726         break;
727       }
728       case Toolkit::TextLabel::Property::ELLIPSIS:
729       {
730         if( impl.mController )
731         {
732           value = impl.mController->IsTextElideEnabled();
733         }
734         break;
735       }
736       case Toolkit::TextLabel::Property::LINE_WRAP_MODE:
737       {
738         if( impl.mController )
739         {
740           value = impl.mController->GetLineWrapMode();
741         }
742         break;
743       }
744       case Toolkit::TextLabel::Property::LINE_COUNT:
745       {
746         if( impl.mController )
747         {
748           float width = label.GetProperty( Actor::Property::SIZE_WIDTH ).Get<float>();
749           value = impl.mController->GetLineCount( width );
750         }
751         break;
752       }
753     }
754   }
755
756   return value;
757 }
758
759 void TextLabel::OnInitialize()
760 {
761   Actor self = Self();
762
763   Property::Map propertyMap;
764   propertyMap.Add( Toolkit::Visual::Property::TYPE, Toolkit::Visual::TEXT );
765
766   mVisual =  Toolkit::VisualFactory::Get().CreateVisual( propertyMap );
767   DevelControl::RegisterVisual( *this, Toolkit::TextLabel::Property::TEXT, mVisual  );
768
769   TextVisual::SetAnimatableTextColorProperty( mVisual, Toolkit::TextLabel::Property::TEXT_COLOR );
770
771   mController = TextVisual::GetController(mVisual);
772   if( mController )
773   {
774     mController->SetControlInterface(this);
775   }
776
777   // Use height-for-width negotiation by default
778   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
779   self.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
780
781   // Enable the text ellipsis.
782   mController->SetTextElideEnabled( true );   // If false then text larger than control will overflow
783
784   Layout::Engine& engine = mController->GetLayoutEngine();
785   engine.SetCursorWidth( 0u ); // Do not layout space for the cursor.
786 }
787
788 void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
789 {
790   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextLabel::OnStyleChange\n");
791
792   switch ( change )
793   {
794     case StyleChange::DEFAULT_FONT_CHANGE:
795     {
796       // Property system did not set the font so should update it.
797       const std::string& newFont = GetImpl( styleManager ).GetDefaultFontFamily();
798       DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::OnStyleChange StyleChange::DEFAULT_FONT_CHANGE newFont(%s)\n", newFont.c_str() );
799       mController->UpdateAfterFontChange( newFont );
800       RelayoutRequest();
801       break;
802     }
803     case StyleChange::DEFAULT_FONT_SIZE_CHANGE:
804     {
805       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
806       RelayoutRequest();
807       break;
808     }
809     case StyleChange::THEME_CHANGE:
810     {
811       // Nothing to do, let control base class handle this
812       break;
813     }
814   }
815
816   // Up call to Control
817   Control::OnStyleChange( styleManager, change );
818 }
819
820 Vector3 TextLabel::GetNaturalSize()
821 {
822   return mController->GetNaturalSize();
823 }
824
825 float TextLabel::GetHeightForWidth( float width )
826 {
827   Extents padding;
828   padding = Self().GetProperty<Extents>( Toolkit::Control::Property::PADDING );
829
830   return mController->GetHeightForWidth( width ) + padding.top + padding.bottom;
831 }
832
833 void TextLabel::OnPropertySet( Property::Index index, Property::Value propertyValue )
834 {
835   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextLabel::OnPropertySet index[%d]\n", index );
836
837   switch ( index )
838   {
839     case Toolkit::TextLabel::Property::TEXT_COLOR:
840     {
841       const Vector4& textColor = propertyValue.Get< Vector4 >();
842       if( mController->GetDefaultColor() != textColor )
843       {
844          mController->SetDefaultColor( textColor );
845          mTextUpdateNeeded = true;
846       }
847       break;
848     }
849     default:
850     {
851       Control::OnPropertySet( index, propertyValue ); // up call to control for non-handled properties
852       break;
853     }
854   }
855 }
856
857 void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container )
858 {
859   DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::OnRelayout\n" );
860
861   Extents padding;
862   padding = Self().GetProperty<Extents>( Toolkit::Control::Property::PADDING );
863
864   Vector2 contentSize( size.x - ( padding.start + padding.end ), size.y - ( padding.top + padding.bottom ) );
865
866   const Text::Controller::UpdateTextType updateTextType = mController->Relayout( contentSize );
867
868   if( ( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) )
869      || mTextUpdateNeeded )
870   {
871     DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::OnRelayout IsAutoScrollEnabled[%s] [%p]\n", ( mController->IsAutoScrollEnabled())?"true":"false", this );
872
873     // Update the visual
874     TextVisual::EnableRendererUpdate( mVisual );
875
876     Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>( Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>() );
877     if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection )
878     {
879       std::swap(padding.start, padding.end);
880     }
881
882     Property::Map visualTransform;
883     visualTransform.Add( Toolkit::Visual::Transform::Property::SIZE, contentSize )
884                    .Add( Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) )
885                    .Add( Toolkit::Visual::Transform::Property::OFFSET, Vector2(padding.start, padding.top) )
886                    .Add( Toolkit::Visual::Transform::Property::OFFSET_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) )
887                    .Add( Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN )
888                    .Add( Toolkit::Visual::Transform::Property::ANCHOR_POINT, Toolkit::Align::TOP_BEGIN );
889     mVisual.SetTransformAndSize( visualTransform, size );
890
891     if ( mController->IsAutoScrollEnabled() )
892     {
893       SetUpAutoScrolling();
894     }
895
896     mTextUpdateNeeded = false;
897   }
898 }
899
900 void TextLabel::RequestTextRelayout()
901 {
902   RelayoutRequest();
903 }
904
905 void TextLabel::SetUpAutoScrolling()
906 {
907   const Size& controlSize = mController->GetView().GetControlSize();
908   const Size textNaturalSize = GetNaturalSize().GetVectorXY(); // As relayout of text may not be done at this point natural size is used to get size. Single line scrolling only.
909   const Text::CharacterDirection direction = mController->GetAutoScrollDirection();
910
911   DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling textNaturalSize[%f,%f] controlSize[%f,%f]\n",
912                  textNaturalSize.x,textNaturalSize.y , controlSize.x,controlSize.y );
913
914   if ( !mTextScroller )
915   {
916     DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling Creating default TextScoller\n" );
917
918     // If speed, loopCount or gap not set via property system then will need to create a TextScroller with defaults
919     mTextScroller = Text::TextScroller::New( *this );
920   }
921
922   // Calculate the actual gap before scrolling wraps.
923   int textPadding = std::max( controlSize.x - textNaturalSize.x, 0.0f );
924   float wrapGap = std::max( mTextScroller->GetGap(), textPadding );
925   Vector2 textureSize = textNaturalSize + Vector2(wrapGap, 0.0f); // Add the gap as a part of the texture
926
927   // Create a texture of the text for scrolling
928   Size verifiedSize = textureSize;
929   const int maxTextureSize = Dali::GetMaxTextureSize();
930
931   //if the texture size width exceed maxTextureSize, modify the visual model size and enabled the ellipsis
932   if( verifiedSize.width > maxTextureSize )
933   {
934     verifiedSize.width = maxTextureSize;
935     if( textNaturalSize.width > maxTextureSize )
936     {
937       mController->SetTextElideEnabled( true );
938     }
939     GetHeightForWidth( maxTextureSize );
940     wrapGap = std::max( maxTextureSize - textNaturalSize.width, 0.0f );
941   }
942
943   Text::TypesetterPtr typesetter = Text::Typesetter::New( mController->GetTextModel() );
944
945   PixelData data = typesetter->Render( verifiedSize, Text::Typesetter::RENDER_TEXT_AND_STYLES, true, Pixel::RGBA8888 ); // ignore the horizontal alignment
946   Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D,
947                                   data.GetPixelFormat(),
948                                   data.GetWidth(),
949                                   data.GetHeight() );
950   texture.Upload( data );
951
952   TextureSet textureSet = TextureSet::New();
953   textureSet.SetTexture( 0u, texture );
954
955   // Filter mode needs to be set to linear to produce better quality while scaling.
956   Sampler sampler = Sampler::New();
957   sampler.SetFilterMode( FilterMode::LINEAR, FilterMode::LINEAR );
958   sampler.SetWrapMode( Dali::WrapMode::DEFAULT, Dali::WrapMode::REPEAT, Dali::WrapMode::DEFAULT ); // Wrap the texture in the x direction
959   textureSet.SetSampler( 0u, sampler );
960
961   // Set parameters for scrolling
962   Renderer renderer = static_cast<Internal::Visual::Base&>( GetImplementation( mVisual ) ).GetRenderer();
963   mTextScroller->SetParameters( Self(), renderer, textureSet, controlSize, verifiedSize, wrapGap, direction, mController->GetHorizontalAlignment(), mController->GetVerticalAlignment() );
964 }
965
966 void TextLabel::ScrollingFinished()
967 {
968   // Pure Virtual from TextScroller Interface
969   DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::ScrollingFinished\n");
970   mController->SetAutoScrollEnabled( false );
971   mController->SetTextElideEnabled( true );
972   RequestTextRelayout();
973 }
974
975 TextLabel::TextLabel()
976 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
977   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
978   mTextUpdateNeeded( false )
979 {
980 }
981
982 TextLabel::~TextLabel()
983 {
984 }
985
986 } // namespace Internal
987
988 } // namespace Toolkit
989
990 } // namespace Dali