Merge remote-tracking branch 'origin/tizen' into new_text
[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( TextLabel, "rendering-backend",    INTEGER, RENDERING_BACKEND    )
79 DALI_PROPERTY_REGISTRATION( TextLabel, "text",                 STRING,  TEXT                 )
80 DALI_PROPERTY_REGISTRATION( TextLabel, "font-family",          STRING,  FONT_FAMILY          )
81 DALI_PROPERTY_REGISTRATION( TextLabel, "font-style",           STRING,  FONT_STYLE           )
82 DALI_PROPERTY_REGISTRATION( TextLabel, "point-size",           FLOAT,   POINT_SIZE           )
83 DALI_PROPERTY_REGISTRATION( TextLabel, "multi-line",           BOOLEAN, MULTI_LINE           )
84 DALI_PROPERTY_REGISTRATION( TextLabel, "horizontal-alignment", STRING,  HORIZONTAL_ALIGNMENT )
85 DALI_PROPERTY_REGISTRATION( TextLabel, "vertical-alignment",   STRING,  VERTICAL_ALIGNMENT   )
86 DALI_PROPERTY_REGISTRATION( TextLabel, "shadow-offset",     VECTOR2, SHADOW_OFFSET     )
87 DALI_PROPERTY_REGISTRATION( TextLabel, "shadow-color",      VECTOR4, SHADOW_COLOR      )
88
89 DALI_TYPE_REGISTRATION_END()
90
91 } // namespace
92
93 Toolkit::TextLabel TextLabel::New()
94 {
95   // Create the implementation, temporarily owned by this handle on stack
96   IntrusivePtr< TextLabel > impl = new TextLabel();
97
98   // Pass ownership to CustomActor handle
99   Toolkit::TextLabel handle( *impl );
100
101   // Second-phase init of the implementation
102   // This can only be done after the CustomActor connection has been made...
103   impl->Initialize();
104
105   return handle;
106 }
107
108 void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
109 {
110   Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( Dali::BaseHandle( object ) );
111
112   if( label )
113   {
114     TextLabel& impl( GetImpl( label ) );
115     switch( index )
116     {
117       case Toolkit::TextLabel::Property::RENDERING_BACKEND:
118       {
119         int backend = value.Get< int >();
120
121         if( impl.mRenderingBackend != backend )
122         {
123           impl.mRenderingBackend = backend;
124           impl.mRenderer.Reset();
125           impl.RequestTextRelayout();
126         }
127         break;
128       }
129       case Toolkit::TextLabel::Property::TEXT:
130       {
131         if( impl.mController )
132         {
133           impl.mController->SetText( value.Get< std::string >() );
134           impl.RequestTextRelayout();
135         }
136         break;
137       }
138       case Toolkit::TextLabel::Property::FONT_FAMILY:
139       {
140         if( impl.mController )
141         {
142           std::string fontFamily = value.Get< std::string >();
143
144           if( impl.mController->GetDefaultFontFamily() != fontFamily )
145           {
146             impl.mController->SetDefaultFontFamily( fontFamily );
147             impl.RequestTextRelayout();
148           }
149         }
150         break;
151       }
152       case Toolkit::TextLabel::Property::FONT_STYLE:
153       {
154         if( impl.mController )
155         {
156           std::string fontStyle = value.Get< std::string >();
157
158           if( impl.mController->GetDefaultFontStyle() != fontStyle )
159           {
160             impl.mController->SetDefaultFontStyle( fontStyle );
161             impl.RequestTextRelayout();
162           }
163         }
164         break;
165       }
166       case Toolkit::TextLabel::Property::POINT_SIZE:
167       {
168         if( impl.mController )
169         {
170           float pointSize = value.Get< float >();
171
172           if( impl.mController->GetDefaultPointSize() != pointSize /*TODO - epsilon*/ )
173           {
174             impl.mController->SetDefaultPointSize( pointSize );
175             impl.RequestTextRelayout();
176           }
177         }
178         break;
179       }
180       case Toolkit::TextLabel::Property::MULTI_LINE:
181       {
182         if( impl.mController )
183         {
184           LayoutEngine& engine = impl.mController->GetLayoutEngine();
185           LayoutEngine::Layout layout = value.Get< bool >() ? LayoutEngine::MULTI_LINE_BOX : LayoutEngine::SINGLE_LINE_BOX;
186
187           if( engine.GetLayout() != layout )
188           {
189             engine.SetLayout( layout );
190             impl.RequestTextRelayout();
191           }
192         }
193         break;
194       }
195       case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT:
196       {
197         LayoutEngine& engine = impl.mController->GetLayoutEngine();
198         const LayoutEngine::HorizontalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(),
199                                                                                                                                            HORIZONTAL_ALIGNMENT_STRING_TABLE,
200                                                                                                                                            HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
201
202         if( engine.GetHorizontalAlignment() != alignment )
203         {
204           engine.SetHorizontalAlignment( alignment );
205           impl.RequestTextRelayout();
206         }
207         break;
208       }
209       case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT:
210       {
211         LayoutEngine& engine = impl.mController->GetLayoutEngine();
212         const LayoutEngine::VerticalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(),
213                                                                                                                                        VERTICAL_ALIGNMENT_STRING_TABLE,
214                                                                                                                                        VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
215
216         if( engine.GetVerticalAlignment() != alignment )
217         {
218           engine.SetVerticalAlignment( alignment );
219           impl.RequestTextRelayout();
220         }
221         break;
222       }
223      case Toolkit::TextLabel::Property::SHADOW_OFFSET:
224       {
225         if( impl.mController )
226         {
227           Vector2 shadowOffset = value.Get< Vector2 >();
228           if ( impl.mController->GetShadowOffset() != shadowOffset )
229           {
230             impl.mController->SetShadowOffset( shadowOffset );
231             impl.RequestTextRelayout();
232           }
233         }
234         break;
235       }
236       case Toolkit::TextLabel::Property::SHADOW_COLOR:
237       {
238         if( impl.mController )
239         {
240           Vector4 shadowColor = value.Get< Vector4 >();
241           if ( impl.mController->GetShadowColor() != shadowColor )
242           {
243             impl.mController->SetShadowColor( shadowColor );
244             impl.RequestTextRelayout();
245           }
246         }
247         break;
248       }
249     }
250   }
251 }
252
253 Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index index )
254 {
255   Property::Value value;
256
257   Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( Dali::BaseHandle( object ) );
258
259   if( label )
260   {
261     TextLabel& impl( GetImpl( label ) );
262     switch( index )
263     {
264       case Toolkit::TextLabel::Property::RENDERING_BACKEND:
265       {
266         value = impl.mRenderingBackend;
267         break;
268       }
269       case Toolkit::TextLabel::Property::TEXT:
270       {
271         if( impl.mController )
272         {
273           std::string text;
274           impl.mController->GetText( text );
275           value = text;
276         }
277         break;
278       }
279       case Toolkit::TextLabel::Property::MULTI_LINE:
280       {
281         if( impl.mController )
282         {
283           value = static_cast<bool>( LayoutEngine::MULTI_LINE_BOX == impl.mController->GetLayoutEngine().GetLayout() );
284         }
285         break;
286       }
287       case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT:
288       {
289         if( impl.mController )
290         {
291           value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetLayoutEngine().GetHorizontalAlignment(),
292                                                                                                                   HORIZONTAL_ALIGNMENT_STRING_TABLE,
293                                                                                                                   HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ) );
294         }
295         break;
296       }
297       case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT:
298       {
299         if( impl.mController )
300         {
301           value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetLayoutEngine().GetVerticalAlignment(),
302                                                                                                                 VERTICAL_ALIGNMENT_STRING_TABLE,
303                                                                                                                 VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ) );
304         }
305         break;
306       }
307      case Toolkit::TextLabel::Property::SHADOW_OFFSET:
308       {
309         if ( impl.mController )
310         {
311           value = impl.mController->GetShadowOffset();
312         }
313         break;
314       }
315       case Toolkit::TextLabel::Property::SHADOW_COLOR:
316       {
317         if ( impl.mController )
318         {
319           value = impl.mController->GetShadowColor();
320         }
321         break;
322       }
323     }
324   }
325
326   return value;
327 }
328
329 void TextLabel::OnInitialize()
330 {
331   Actor self = Self();
332
333   mController = Text::Controller::New( *this );
334
335   // Use height-for-width negotiation by default
336   self.SetResizePolicy( FILL_TO_PARENT, WIDTH );
337   self.SetDimensionDependency( HEIGHT, WIDTH );
338 }
339
340 void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change )
341 {
342   GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
343 }
344
345 Vector3 TextLabel::GetNaturalSize()
346 {
347   return mController->GetNaturalSize();
348 }
349
350 float TextLabel::GetHeightForWidth( float width )
351 {
352   return mController->GetHeightForWidth( width );
353 }
354
355 void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container )
356 {
357   if( mController->Relayout( size ) ||
358       !mRenderer )
359   {
360     if( !mRenderer )
361     {
362       mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
363     }
364
365     RenderableActor renderableActor;
366     if( mRenderer )
367     {
368       renderableActor = mRenderer->Render( mController->GetView() );
369     }
370
371     if( renderableActor != mRenderableActor )
372     {
373       UnparentAndReset( mRenderableActor );
374
375       if( renderableActor )
376       {
377         const Vector2& alignmentOffset = mController->GetAlignmentOffset();
378         renderableActor.SetPosition( alignmentOffset.x, alignmentOffset.y );
379
380         Self().Add( renderableActor );
381       }
382
383       mRenderableActor = renderableActor;
384     }
385   }
386 }
387
388 void TextLabel::RequestTextRelayout()
389 {
390   RelayoutRequest();
391 }
392
393 TextLabel::TextLabel()
394 : Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
395   mRenderingBackend( DEFAULT_RENDERING_BACKEND )
396 {
397 }
398
399 TextLabel::~TextLabel()
400 {
401 }
402
403 } // namespace Internal
404
405 } // namespace Toolkit
406
407 } // namespace Dali