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