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