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