Text clean.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-label-impl.cpp
1 /*
2  * Copyright (c) 2015 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.h>
23 #include <dali/devel-api/object/type-registry-helper.h>
24 #include <dali/devel-api/scripting/scripting.h>
25 #include <dali/integration-api/debug.h>
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/public-api/text/rendering-backend.h>
29 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
30 #include <dali-toolkit/internal/text/rendering/text-backend.h>
31 #include <dali-toolkit/internal/text/text-view.h>
32 #include <dali-toolkit/internal/styling/style-manager-impl.h>
33
34 using Dali::Toolkit::Text::LayoutEngine;
35 using Dali::Toolkit::Text::Backend;
36
37 namespace Dali
38 {
39
40 namespace Toolkit
41 {
42
43 namespace Internal
44 {
45
46 namespace
47 {
48   const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
49 }
50
51 namespace
52 {
53
54 const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
55 {
56   { "BEGIN",  Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN  },
57   { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER },
58   { "END",    Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_END    },
59 };
60 const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] );
61
62 const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] =
63 {
64   { "TOP",    Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP    },
65   { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER },
66   { "BOTTOM", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_BOTTOM },
67 };
68 const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( VERTICAL_ALIGNMENT_STRING_TABLE ) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] );
69
70 // Type registration
71 BaseHandle Create()
72 {
73   return Toolkit::TextLabel::New();
74 }
75
76 // Setup properties, signals and actions using the type-registry.
77 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextLabel, Toolkit::Control, Create );
78
79 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "rendering-backend",    INTEGER, RENDERING_BACKEND    )
80 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "text",                 STRING,  TEXT                 )
81 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "font-family",          STRING,  FONT_FAMILY          )
82 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "font-style",           STRING,  FONT_STYLE           )
83 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "point-size",           FLOAT,   POINT_SIZE           )
84 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "multi-line",           BOOLEAN, MULTI_LINE           )
85 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "horizontal-alignment", STRING,  HORIZONTAL_ALIGNMENT )
86 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "vertical-alignment",   STRING,  VERTICAL_ALIGNMENT   )
87 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "text-color",           VECTOR4, TEXT_COLOR           )
88 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "shadow-offset",        VECTOR2, SHADOW_OFFSET        )
89 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "shadow-color",         VECTOR4, SHADOW_COLOR         )
90 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "underline-enabled",    BOOLEAN, UNDERLINE_ENABLED    )
91 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "underline-color",      VECTOR4, UNDERLINE_COLOR      )
92 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "underline-height",     FLOAT,   UNDERLINE_HEIGHT     )
93
94 DALI_TYPE_REGISTRATION_END()
95
96 } // namespace
97
98 Toolkit::TextLabel TextLabel::New()
99 {
100   // Create the implementation, temporarily owned by this handle on stack
101   IntrusivePtr< TextLabel > impl = new TextLabel();
102
103   // Pass ownership to CustomActor handle
104   Toolkit::TextLabel handle( *impl );
105
106   // Second-phase init of the implementation
107   // This can only be done after the CustomActor connection has been made...
108   impl->Initialize();
109
110   return handle;
111 }
112
113 void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
114 {
115   Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( Dali::BaseHandle( object ) );
116
117   if( label )
118   {
119     TextLabel& impl( GetImpl( label ) );
120     switch( index )
121     {
122       case Toolkit::TextLabel::Property::RENDERING_BACKEND:
123       {
124         const int backend = value.Get< int >();
125
126         if( impl.mRenderingBackend != backend )
127         {
128           impl.mRenderingBackend = backend;
129           impl.mRenderer.Reset();
130           impl.RequestTextRelayout();
131         }
132         break;
133       }
134       case Toolkit::TextLabel::Property::TEXT:
135       {
136         if( impl.mController )
137         {
138           impl.mController->SetText( value.Get< std::string >() );
139         }
140         break;
141       }
142       case Toolkit::TextLabel::Property::FONT_FAMILY:
143       {
144         if( impl.mController )
145         {
146           const std::string fontFamily = value.Get< std::string >();
147
148           if( impl.mController->GetDefaultFontFamily() != fontFamily )
149           {
150             impl.mController->SetDefaultFontFamily( fontFamily );
151           }
152         }
153         break;
154       }
155       case Toolkit::TextLabel::Property::FONT_STYLE:
156       {
157         if( impl.mController )
158         {
159           const std::string fontStyle = value.Get< std::string >();
160
161           if( impl.mController->GetDefaultFontStyle() != fontStyle )
162           {
163             impl.mController->SetDefaultFontStyle( fontStyle );
164           }
165         }
166         break;
167       }
168       case Toolkit::TextLabel::Property::POINT_SIZE:
169       {
170         if( impl.mController )
171         {
172           const float pointSize = value.Get< float >();
173
174           if( !Equals( impl.mController->GetDefaultPointSize(), pointSize ) )
175           {
176             impl.mController->SetDefaultPointSize( pointSize );
177           }
178         }
179         break;
180       }
181       case Toolkit::TextLabel::Property::MULTI_LINE:
182       {
183         if( impl.mController )
184         {
185           impl.mController->SetMultiLineEnabled( value.Get< bool >() );
186         }
187         break;
188       }
189       case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT:
190       {
191         if( impl.mController )
192         {
193           LayoutEngine::HorizontalAlignment alignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN );
194           if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(),
195                                                                                              HORIZONTAL_ALIGNMENT_STRING_TABLE,
196                                                                                              HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
197                                                                                              alignment ) )
198           {
199             impl.mController->SetHorizontalAlignment( alignment );
200           }
201         }
202         break;
203       }
204       case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT:
205       {
206         if( impl.mController )
207         {
208           LayoutEngine::VerticalAlignment alignment( LayoutEngine::VERTICAL_ALIGN_BOTTOM );
209           if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(),
210                                                                                            VERTICAL_ALIGNMENT_STRING_TABLE,
211                                                                                            VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
212                                                                                            alignment ) )
213           {
214             impl.mController->SetVerticalAlignment( alignment );
215           }
216         }
217         break;
218       }
219
220       case Toolkit::TextLabel::Property::TEXT_COLOR:
221       {
222         if( impl.mController )
223         {
224           const Vector4 textColor = value.Get< Vector4 >();
225           if( impl.mController->GetTextColor() != textColor )
226           {
227             impl.mController->SetTextColor( textColor );
228             impl.mRenderer.Reset();
229           }
230         }
231         break;
232       }
233
234       case Toolkit::TextLabel::Property::SHADOW_OFFSET:
235       {
236         if( impl.mController )
237         {
238           const Vector2 shadowOffset = value.Get< Vector2 >();
239           if ( impl.mController->GetShadowOffset() != shadowOffset )
240           {
241             impl.mController->SetShadowOffset( shadowOffset );
242             impl.mRenderer.Reset();
243           }
244         }
245         break;
246       }
247       case Toolkit::TextLabel::Property::SHADOW_COLOR:
248       {
249         if( impl.mController )
250         {
251           const Vector4 shadowColor = value.Get< Vector4 >();
252           if ( impl.mController->GetShadowColor() != shadowColor )
253           {
254             impl.mController->SetShadowColor( shadowColor );
255             impl.mRenderer.Reset();
256           }
257         }
258         break;
259       }
260       case Toolkit::TextLabel::Property::UNDERLINE_COLOR:
261       {
262         if( impl.mController )
263         {
264           const Vector4 color = value.Get< Vector4 >();
265           if ( impl.mController->GetUnderlineColor() != color )
266           {
267             impl.mController->SetUnderlineColor( color );
268             impl.mRenderer.Reset();
269           }
270         }
271         break;
272       }
273       case Toolkit::TextLabel::Property::UNDERLINE_ENABLED:
274       {
275         if( impl.mController )
276         {
277           const bool enabled = value.Get< bool >();
278           if ( impl.mController->IsUnderlineEnabled() != enabled )
279           {
280             impl.mController->SetUnderlineEnabled( enabled );
281             impl.mRenderer.Reset();
282           }
283         }
284         break;
285       }
286
287       case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT:
288       {
289         if( impl.mController )
290         {
291           float height = value.Get< float >();
292           if ( impl.mController->GetUnderlineHeight() != height )
293           {
294             impl.mController->SetUnderlineHeight( height );
295             impl.mRenderer.Reset();
296           }
297         }
298         break;
299       }
300     }
301   }
302 }
303
304 Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index index )
305 {
306   Property::Value value;
307
308   Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( Dali::BaseHandle( object ) );
309
310   if( label )
311   {
312     TextLabel& impl( GetImpl( label ) );
313     switch( index )
314     {
315       case Toolkit::TextLabel::Property::RENDERING_BACKEND:
316       {
317         value = impl.mRenderingBackend;
318         break;
319       }
320       case Toolkit::TextLabel::Property::TEXT:
321       {
322         if( impl.mController )
323         {
324           std::string text;
325           impl.mController->GetText( text );
326           value = text;
327         }
328         break;
329       }
330       case Toolkit::TextLabel::Property::FONT_FAMILY:
331       {
332         if( impl.mController )
333         {
334           value = impl.mController->GetDefaultFontFamily();
335         }
336         break;
337       }
338       case Toolkit::TextLabel::Property::FONT_STYLE:
339       {
340         if( impl.mController )
341         {
342           value = impl.mController->GetDefaultFontStyle();
343         }
344         break;
345       }
346       case Toolkit::TextLabel::Property::POINT_SIZE:
347       {
348         if( impl.mController )
349         {
350           value = impl.mController->GetDefaultPointSize();
351         }
352         break;
353       }
354       case Toolkit::TextLabel::Property::MULTI_LINE:
355       {
356         if( impl.mController )
357         {
358           value = impl.mController->IsMultiLineEnabled();
359         }
360         break;
361       }
362       case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT:
363       {
364         if( impl.mController )
365         {
366           const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetHorizontalAlignment(),
367                                                                                                                 HORIZONTAL_ALIGNMENT_STRING_TABLE,
368                                                                                                                 HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
369           if( name )
370           {
371             value = std::string( name );
372           }
373         }
374         break;
375       }
376       case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT:
377       {
378         if( impl.mController )
379         {
380           const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetVerticalAlignment(),
381                                                                                                               VERTICAL_ALIGNMENT_STRING_TABLE,
382                                                                                                               VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
383           if( name )
384           {
385             value = std::string( name );
386           }
387         }
388         break;
389       }
390       case Toolkit::TextLabel::Property::TEXT_COLOR:
391       {
392         if ( impl.mController )
393         {
394           value = impl.mController->GetTextColor();
395         }
396         break;
397       }
398       case Toolkit::TextLabel::Property::SHADOW_OFFSET:
399       {
400         if ( impl.mController )
401         {
402           value = impl.mController->GetShadowOffset();
403         }
404         break;
405       }
406       case Toolkit::TextLabel::Property::SHADOW_COLOR:
407       {
408         if ( impl.mController )
409         {
410           value = impl.mController->GetShadowColor();
411         }
412         break;
413       }
414       case Toolkit::TextLabel::Property::UNDERLINE_COLOR:
415       {
416         if ( impl.mController )
417         {
418           value = impl.mController->GetUnderlineColor();
419         }
420         break;
421       }
422       case Toolkit::TextLabel::Property::UNDERLINE_ENABLED:
423       {
424         if ( impl.mController )
425         {
426           value = impl.mController->IsUnderlineEnabled();
427         }
428         break;
429       }
430       case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT:
431       {
432         if ( impl.mController )
433         {
434           value = impl.mController->GetUnderlineHeight();
435         }
436         break;
437       }
438     }
439   }
440
441   return value;
442 }
443
444 void TextLabel::OnInitialize()
445 {
446   Actor self = Self();
447
448   mController = Text::Controller::New( *this );
449
450   // Use height-for-width negotiation by default
451   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
452   self.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
453
454   // Enable the text ellipsis.
455   LayoutEngine& engine = mController->GetLayoutEngine();
456   engine.SetTextEllipsisEnabled( true );
457   self.OnStageSignal().Connect( this, &TextLabel::OnStageConnect );
458 }
459
460 void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
461 {
462   GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
463 }
464
465 Vector3 TextLabel::GetNaturalSize()
466 {
467   return mController->GetNaturalSize();
468 }
469
470 float TextLabel::GetHeightForWidth( float width )
471 {
472   return mController->GetHeightForWidth( width );
473 }
474
475 void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container )
476 {
477   if( mController->Relayout( size ) ||
478       !mRenderer )
479   {
480     if( !mRenderer )
481     {
482       mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
483     }
484     RenderText();
485   }
486 }
487
488 void TextLabel::RequestTextRelayout()
489 {
490   RelayoutRequest();
491 }
492
493 void TextLabel::RenderText()
494 {
495   Actor self = Self();
496   Actor renderableActor;
497   if( mRenderer )
498   {
499     renderableActor = mRenderer->Render( mController->GetView(), self.GetHierarchyDepth() );
500   }
501
502   if( renderableActor != mRenderableActor )
503   {
504     UnparentAndReset( mRenderableActor );
505
506     if( renderableActor )
507     {
508       const Vector2& alignmentOffset = mController->GetAlignmentOffset();
509       renderableActor.SetPosition( alignmentOffset.x, alignmentOffset.y );
510
511       self.Add( renderableActor );
512     }
513     mRenderableActor = renderableActor;
514   }
515 }
516
517 void TextLabel::OnStageConnect( Dali::Actor actor )
518 {
519   if ( mHasBeenStaged )
520   {
521     RenderText();
522   }
523   else
524   {
525     mHasBeenStaged = true;
526   }
527 }
528
529 void TextLabel::AddDecoration( Actor& actor, bool needsClipping )
530 {
531   // TextLabel does not show decorations
532 }
533
534 void TextLabel::OnStageConnection( int depth )
535 {
536   // Call the Control::OnStageConnection() to set the depth of the background.
537   Control::OnStageConnection( depth );
538
539   // The depth of the text renderer is set in the RenderText() called from OnRelayout().
540 }
541
542 void TextLabel::TextChanged()
543 {
544   // TextLabel does not provide a signal for this
545 }
546
547 void TextLabel::MaxLengthReached()
548 {
549   // Pure Virtual from TextController Interface, only needed when inputting text
550 }
551
552 TextLabel::TextLabel()
553 : Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
554   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
555   mHasBeenStaged( false )
556 {
557 }
558
559 TextLabel::~TextLabel()
560 {
561 }
562
563 } // namespace Internal
564
565 } // namespace Toolkit
566
567 } // namespace Dali