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