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