Uses depth within tree to set the depth index of text controls and their renderers.
[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/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         const 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         }
139         break;
140       }
141       case Toolkit::TextLabel::Property::FONT_FAMILY:
142       {
143         if( impl.mController )
144         {
145           const std::string fontFamily = value.Get< std::string >();
146
147           if( impl.mController->GetDefaultFontFamily() != fontFamily )
148           {
149             impl.mController->SetDefaultFontFamily( fontFamily );
150           }
151         }
152         break;
153       }
154       case Toolkit::TextLabel::Property::FONT_STYLE:
155       {
156         if( impl.mController )
157         {
158           const std::string fontStyle = value.Get< std::string >();
159
160           if( impl.mController->GetDefaultFontStyle() != fontStyle )
161           {
162             impl.mController->SetDefaultFontStyle( fontStyle );
163           }
164         }
165         break;
166       }
167       case Toolkit::TextLabel::Property::POINT_SIZE:
168       {
169         if( impl.mController )
170         {
171           const float pointSize = value.Get< float >();
172
173           if( !Equals( impl.mController->GetDefaultPointSize(), pointSize ) )
174           {
175             impl.mController->SetDefaultPointSize( pointSize );
176           }
177         }
178         break;
179       }
180       case Toolkit::TextLabel::Property::MULTI_LINE:
181       {
182         if( impl.mController )
183         {
184           impl.mController->SetMultiLineEnabled( value.Get< bool >() );
185         }
186         break;
187       }
188       case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT:
189       {
190         if( impl.mController )
191         {
192           const LayoutEngine::HorizontalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(),
193                                                                                                                                              HORIZONTAL_ALIGNMENT_STRING_TABLE,
194                                                                                                                                              HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
195
196           impl.mController->SetHorizontalAlignment( alignment );
197         }
198         break;
199       }
200       case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT:
201       {
202         if( impl.mController )
203         {
204           const LayoutEngine::VerticalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(),
205                                                                                                                                          VERTICAL_ALIGNMENT_STRING_TABLE,
206                                                                                                                                          VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
207
208           impl.mController->SetVerticalAlignment( alignment );
209         }
210         break;
211       }
212
213       case Toolkit::TextLabel::Property::TEXT_COLOR:
214       {
215         if( impl.mController )
216         {
217           const Vector4 textColor = value.Get< Vector4 >();
218           if( impl.mController->GetTextColor() != textColor )
219           {
220             impl.mController->SetTextColor( textColor );
221             impl.mRenderer.Reset();
222           }
223         }
224         break;
225       }
226
227       case Toolkit::TextLabel::Property::SHADOW_OFFSET:
228       {
229         if( impl.mController )
230         {
231           const Vector2 shadowOffset = value.Get< Vector2 >();
232           if ( impl.mController->GetShadowOffset() != shadowOffset )
233           {
234             impl.mController->SetShadowOffset( shadowOffset );
235             impl.mRenderer.Reset();
236           }
237         }
238         break;
239       }
240       case Toolkit::TextLabel::Property::SHADOW_COLOR:
241       {
242         if( impl.mController )
243         {
244           const Vector4 shadowColor = value.Get< Vector4 >();
245           if ( impl.mController->GetShadowColor() != shadowColor )
246           {
247             impl.mController->SetShadowColor( shadowColor );
248             impl.mRenderer.Reset();
249           }
250         }
251         break;
252       }
253       case Toolkit::TextLabel::Property::UNDERLINE_COLOR:
254       {
255         if( impl.mController )
256         {
257           const Vector4 color = value.Get< Vector4 >();
258           if ( impl.mController->GetUnderlineColor() != color )
259           {
260             impl.mController->SetUnderlineColor( color );
261             impl.mRenderer.Reset();
262           }
263         }
264         break;
265       }
266       case Toolkit::TextLabel::Property::UNDERLINE_ENABLED:
267       {
268         if( impl.mController )
269         {
270           const bool enabled = value.Get< bool >();
271           if ( impl.mController->IsUnderlineEnabled() != enabled )
272           {
273             impl.mController->SetUnderlineEnabled( enabled );
274             impl.mRenderer.Reset();
275           }
276         }
277         break;
278       }
279
280       case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT:
281       {
282         if( impl.mController )
283         {
284           float height = value.Get< float >();
285           if ( impl.mController->GetUnderlineHeight() != height )
286           {
287             impl.mController->SetUnderlineHeight( height );
288             impl.mRenderer.Reset();
289           }
290         }
291         break;
292       }
293     }
294   }
295 }
296
297 Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index index )
298 {
299   Property::Value value;
300
301   Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( Dali::BaseHandle( object ) );
302
303   if( label )
304   {
305     TextLabel& impl( GetImpl( label ) );
306     switch( index )
307     {
308       case Toolkit::TextLabel::Property::RENDERING_BACKEND:
309       {
310         value = impl.mRenderingBackend;
311         break;
312       }
313       case Toolkit::TextLabel::Property::TEXT:
314       {
315         if( impl.mController )
316         {
317           std::string text;
318           impl.mController->GetText( text );
319           value = text;
320         }
321         break;
322       }
323       case Toolkit::TextLabel::Property::FONT_FAMILY:
324       {
325         if( impl.mController )
326         {
327           value = impl.mController->GetDefaultFontFamily();
328         }
329         break;
330       }
331       case Toolkit::TextLabel::Property::FONT_STYLE:
332       {
333         if( impl.mController )
334         {
335           value = impl.mController->GetDefaultFontStyle();
336         }
337         break;
338       }
339       case Toolkit::TextLabel::Property::POINT_SIZE:
340       {
341         if( impl.mController )
342         {
343           value = impl.mController->GetDefaultPointSize();
344         }
345         break;
346       }
347       case Toolkit::TextLabel::Property::MULTI_LINE:
348       {
349         if( impl.mController )
350         {
351           value = impl.mController->IsMultiLineEnabled();
352         }
353         break;
354       }
355       case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT:
356       {
357         if( impl.mController )
358         {
359           value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetHorizontalAlignment(),
360                                                                                                                   HORIZONTAL_ALIGNMENT_STRING_TABLE,
361                                                                                                                   HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ) );
362         }
363         break;
364       }
365       case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT:
366       {
367         if( impl.mController )
368         {
369           value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetVerticalAlignment(),
370                                                                                                                 VERTICAL_ALIGNMENT_STRING_TABLE,
371                                                                                                                 VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ) );
372         }
373         break;
374       }
375       case Toolkit::TextLabel::Property::TEXT_COLOR:
376       {
377         if ( impl.mController )
378         {
379           value = impl.mController->GetTextColor();
380         }
381         break;
382       }
383       case Toolkit::TextLabel::Property::SHADOW_OFFSET:
384       {
385         if ( impl.mController )
386         {
387           value = impl.mController->GetShadowOffset();
388         }
389         break;
390       }
391       case Toolkit::TextLabel::Property::SHADOW_COLOR:
392       {
393         if ( impl.mController )
394         {
395           value = impl.mController->GetShadowColor();
396         }
397         break;
398       }
399       case Toolkit::TextLabel::Property::UNDERLINE_COLOR:
400       {
401         if ( impl.mController )
402         {
403           value = impl.mController->GetUnderlineColor();
404         }
405         break;
406       }
407       case Toolkit::TextLabel::Property::UNDERLINE_ENABLED:
408       {
409         if ( impl.mController )
410         {
411           value = impl.mController->IsUnderlineEnabled();
412         }
413         break;
414       }
415       case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT:
416       {
417         if ( impl.mController )
418         {
419           value = impl.mController->GetUnderlineHeight();
420         }
421         break;
422       }
423     }
424   }
425
426   return value;
427 }
428
429 void TextLabel::OnInitialize()
430 {
431   Actor self = Self();
432
433   mController = Text::Controller::New( *this );
434
435   // Use height-for-width negotiation by default
436   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
437   self.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
438
439   // Enable the text ellipsis.
440   LayoutEngine& engine = mController->GetLayoutEngine();
441   engine.SetTextEllipsisEnabled( true );
442 }
443
444 void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
445 {
446   GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
447 }
448
449 Vector3 TextLabel::GetNaturalSize()
450 {
451   return mController->GetNaturalSize();
452 }
453
454 float TextLabel::GetHeightForWidth( float width )
455 {
456   return mController->GetHeightForWidth( width );
457 }
458
459 void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container )
460 {
461   if( mController->Relayout( size ) ||
462       !mRenderer )
463   {
464     if( !mRenderer )
465     {
466       mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
467     }
468
469     Actor renderableActor;
470     if( mRenderer )
471     {
472       renderableActor = mRenderer->Render( mController->GetView(), mDepth );
473     }
474
475     if( renderableActor != mRenderableActor )
476     {
477       UnparentAndReset( mRenderableActor );
478
479       if( renderableActor )
480       {
481         const Vector2& alignmentOffset = mController->GetAlignmentOffset();
482         renderableActor.SetPosition( alignmentOffset.x, alignmentOffset.y );
483
484         Self().Add( renderableActor );
485       }
486
487       mRenderableActor = renderableActor;
488     }
489   }
490 }
491
492 void TextLabel::RequestTextRelayout()
493 {
494   RelayoutRequest();
495 }
496
497 void TextLabel::OnStageConnection( unsigned int depth )
498 {
499   mDepth = depth;
500 }
501
502 void TextLabel::TextChanged()
503 {
504   // TextLabel does not provide a signal for this
505 }
506
507 void TextLabel::MaxLengthReached()
508 {
509   // Pure Virtual from TextController Interface, only needed when inputting text
510 }
511
512 TextLabel::TextLabel()
513 : Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
514   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
515   mDepth( 0 )
516 {
517 }
518
519 TextLabel::~TextLabel()
520 {
521 }
522
523 } // namespace Internal
524
525 } // namespace Toolkit
526
527 } // namespace Dali