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