Restored control-depth-index-ranges.h to released version but using devel values...
[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/devel-api/object/type-registry-helper.h>
23 #include <dali/integration-api/debug.h>
24
25 // INTERNAL INCLUDES
26 #include <dali-toolkit/public-api/text/rendering-backend.h>
27 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
28 #include <dali-toolkit/internal/controls/text-controls/text-font-style.h>
29 #include <dali-toolkit/internal/text/rendering/text-backend.h>
30 #include <dali-toolkit/internal/text/text-view.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 #if defined(DEBUG_ENABLED)
54   Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS");
55 #endif
56
57 const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
58 {
59   { "BEGIN",  Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN  },
60   { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER },
61   { "END",    Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_END    },
62 };
63 const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] );
64
65 const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] =
66 {
67   { "TOP",    Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP    },
68   { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER },
69   { "BOTTOM", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_BOTTOM },
70 };
71 const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( VERTICAL_ALIGNMENT_STRING_TABLE ) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] );
72
73 // Type registration
74 BaseHandle Create()
75 {
76   return Toolkit::TextLabel::New();
77 }
78
79 // Setup properties, signals and actions using the type-registry.
80 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextLabel, Toolkit::Control, Create );
81
82 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "renderingBackend",     INTEGER, RENDERING_BACKEND    )
83 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "text",                 STRING,  TEXT                 )
84 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "fontFamily",           STRING,  FONT_FAMILY          )
85 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "fontStyle",            STRING,  FONT_STYLE           )
86 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "pointSize",            FLOAT,   POINT_SIZE           )
87 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "multiLine",            BOOLEAN, MULTI_LINE           )
88 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "horizontalAlignment",  STRING,  HORIZONTAL_ALIGNMENT )
89 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "verticalAlignment",    STRING,  VERTICAL_ALIGNMENT   )
90 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "textColor",            VECTOR4, TEXT_COLOR           )
91 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "shadowOffset",         VECTOR2, SHADOW_OFFSET        )
92 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "shadowColor",          VECTOR4, SHADOW_COLOR         )
93 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "underlineEnabled",     BOOLEAN, UNDERLINE_ENABLED    )
94 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "underlineColor",       VECTOR4, UNDERLINE_COLOR      )
95 DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "underlineHeight",      FLOAT,   UNDERLINE_HEIGHT     )
96
97 DALI_TYPE_REGISTRATION_END()
98
99 } // namespace
100
101 Toolkit::TextLabel TextLabel::New()
102 {
103   // Create the implementation, temporarily owned by this handle on stack
104   IntrusivePtr< TextLabel > impl = new TextLabel();
105
106   // Pass ownership to CustomActor handle
107   Toolkit::TextLabel handle( *impl );
108
109   // Second-phase init of the implementation
110   // This can only be done after the CustomActor connection has been made...
111   impl->Initialize();
112
113   return handle;
114 }
115
116 void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
117 {
118   Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( Dali::BaseHandle( object ) );
119
120   if( label )
121   {
122     TextLabel& impl( GetImpl( label ) );
123     switch( index )
124     {
125       case Toolkit::TextLabel::Property::RENDERING_BACKEND:
126       {
127         const int backend = value.Get< int >();
128
129         if( impl.mRenderingBackend != backend )
130         {
131           impl.mRenderingBackend = backend;
132           impl.mRenderer.Reset();
133           impl.RequestTextRelayout();
134         }
135         break;
136       }
137       case Toolkit::TextLabel::Property::TEXT:
138       {
139         if( impl.mController )
140         {
141           impl.mController->SetText( value.Get< std::string >() );
142         }
143         break;
144       }
145       case Toolkit::TextLabel::Property::FONT_FAMILY:
146       {
147         if( impl.mController )
148         {
149           const std::string fontFamily = value.Get< std::string >();
150
151           DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetProperty Property::FONT_FAMILY newFont(%s)\n", fontFamily.c_str() );
152           impl.mController->SetDefaultFontFamily( fontFamily );
153         }
154         break;
155       }
156       case Toolkit::TextLabel::Property::FONT_STYLE:
157       {
158         SetFontStyleProperty( impl.mController, value );
159         break;
160       }
161       case Toolkit::TextLabel::Property::POINT_SIZE:
162       {
163         if( impl.mController )
164         {
165           const float pointSize = value.Get< float >();
166
167           if( !Equals( impl.mController->GetDefaultPointSize(), pointSize ) )
168           {
169             impl.mController->SetDefaultPointSize( pointSize );
170           }
171         }
172         break;
173       }
174       case Toolkit::TextLabel::Property::MULTI_LINE:
175       {
176         if( impl.mController )
177         {
178           impl.mController->SetMultiLineEnabled( value.Get< bool >() );
179         }
180         break;
181       }
182       case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT:
183       {
184         if( impl.mController )
185         {
186           LayoutEngine::HorizontalAlignment alignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN );
187           if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(),
188                                                                                              HORIZONTAL_ALIGNMENT_STRING_TABLE,
189                                                                                              HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
190                                                                                              alignment ) )
191           {
192             impl.mController->SetHorizontalAlignment( alignment );
193           }
194         }
195         break;
196       }
197       case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT:
198       {
199         if( impl.mController )
200         {
201           LayoutEngine::VerticalAlignment alignment( LayoutEngine::VERTICAL_ALIGN_BOTTOM );
202           if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(),
203                                                                                            VERTICAL_ALIGNMENT_STRING_TABLE,
204                                                                                            VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
205                                                                                            alignment ) )
206           {
207             impl.mController->SetVerticalAlignment( alignment );
208           }
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( fabsf( impl.mController->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 )
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         GetFontStyleProperty( impl.mController, value );
334         break;
335       }
336       case Toolkit::TextLabel::Property::POINT_SIZE:
337       {
338         if( impl.mController )
339         {
340           value = impl.mController->GetDefaultPointSize();
341         }
342         break;
343       }
344       case Toolkit::TextLabel::Property::MULTI_LINE:
345       {
346         if( impl.mController )
347         {
348           value = impl.mController->IsMultiLineEnabled();
349         }
350         break;
351       }
352       case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT:
353       {
354         if( impl.mController )
355         {
356           const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetHorizontalAlignment(),
357                                                                                                                 HORIZONTAL_ALIGNMENT_STRING_TABLE,
358                                                                                                                 HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
359           if( name )
360           {
361             value = std::string( name );
362           }
363         }
364         break;
365       }
366       case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT:
367       {
368         if( impl.mController )
369         {
370           const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetVerticalAlignment(),
371                                                                                                               VERTICAL_ALIGNMENT_STRING_TABLE,
372                                                                                                               VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
373           if( name )
374           {
375             value = std::string( name );
376           }
377         }
378         break;
379       }
380       case Toolkit::TextLabel::Property::TEXT_COLOR:
381       {
382         if ( impl.mController )
383         {
384           value = impl.mController->GetTextColor();
385         }
386         break;
387       }
388       case Toolkit::TextLabel::Property::SHADOW_OFFSET:
389       {
390         if ( impl.mController )
391         {
392           value = impl.mController->GetShadowOffset();
393         }
394         break;
395       }
396       case Toolkit::TextLabel::Property::SHADOW_COLOR:
397       {
398         if ( impl.mController )
399         {
400           value = impl.mController->GetShadowColor();
401         }
402         break;
403       }
404       case Toolkit::TextLabel::Property::UNDERLINE_COLOR:
405       {
406         if ( impl.mController )
407         {
408           value = impl.mController->GetUnderlineColor();
409         }
410         break;
411       }
412       case Toolkit::TextLabel::Property::UNDERLINE_ENABLED:
413       {
414         if ( impl.mController )
415         {
416           value = impl.mController->IsUnderlineEnabled();
417         }
418         break;
419       }
420       case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT:
421       {
422         if ( impl.mController )
423         {
424           value = impl.mController->GetUnderlineHeight();
425         }
426         break;
427       }
428     }
429   }
430
431   return value;
432 }
433
434 void TextLabel::OnInitialize()
435 {
436   Actor self = Self();
437
438   mController = Text::Controller::New( *this );
439
440   // Use height-for-width negotiation by default
441   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
442   self.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
443
444   // Enable the text ellipsis.
445   LayoutEngine& engine = mController->GetLayoutEngine();
446
447   engine.SetTextEllipsisEnabled( true );
448   engine.SetCursorWidth( 0u ); // Do not layout space for the cursor.
449
450   self.OnStageSignal().Connect( this, &TextLabel::OnStageConnect );
451 }
452
453 void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
454 {
455
456   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextLabel::OnStyleChange\n");
457
458   switch ( change )
459   {
460     case StyleChange::DEFAULT_FONT_CHANGE:
461     {
462       // Property system did not set the font so should update it.
463       std::string newFont = styleManager.GetDefaultFontFamily();
464       DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::OnStyleChange StyleChange::DEFAULT_FONT_CHANGE newFont(%s)\n", newFont.c_str() );
465       mController->UpdateAfterFontChange( newFont );
466       break;
467     }
468
469     case StyleChange::DEFAULT_FONT_SIZE_CHANGE:
470     {
471       DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::OnStyleChange StyleChange::DEFAULT_FONT_SIZE_CHANGE (%f)\n", mController->GetDefaultPointSize() );
472
473       if ( (mController->GetDefaultPointSize() <= 0.0f) ) // If DefaultPointSize not set by Property system it will be 0.0f
474       {
475         // Property system did not set the PointSize so should update it.
476         // todo instruct text-controller to update model
477       }
478       break;
479     }
480     case StyleChange::THEME_CHANGE:
481     {
482       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
483       break;
484     }
485   }
486 }
487
488 Vector3 TextLabel::GetNaturalSize()
489 {
490   return mController->GetNaturalSize();
491 }
492
493 float TextLabel::GetHeightForWidth( float width )
494 {
495   return mController->GetHeightForWidth( width );
496 }
497
498 void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container )
499 {
500   if( mController->Relayout( size ) ||
501       !mRenderer )
502   {
503     if( !mRenderer )
504     {
505       mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
506     }
507     RenderText();
508   }
509 }
510
511 void TextLabel::RequestTextRelayout()
512 {
513   RelayoutRequest();
514 }
515
516 void TextLabel::RenderText()
517 {
518   Actor self = Self();
519   Actor renderableActor;
520   if( mRenderer )
521   {
522     renderableActor = mRenderer->Render( mController->GetView(), DepthIndex::TEXT );
523   }
524
525   if( renderableActor != mRenderableActor )
526   {
527     UnparentAndReset( mRenderableActor );
528
529     if( renderableActor )
530     {
531       const Vector2& alignmentOffset = mController->GetAlignmentOffset();
532       renderableActor.SetPosition( alignmentOffset.x, alignmentOffset.y );
533
534       self.Add( renderableActor );
535     }
536     mRenderableActor = renderableActor;
537   }
538 }
539
540 void TextLabel::OnStageConnect( Dali::Actor actor )
541 {
542   if ( mHasBeenStaged )
543   {
544     RenderText();
545   }
546   else
547   {
548     mHasBeenStaged = true;
549   }
550 }
551
552 void TextLabel::AddDecoration( Actor& actor, bool needsClipping )
553 {
554   // TextLabel does not show decorations
555 }
556
557 void TextLabel::OnStageConnection( int depth )
558 {
559   // Call the Control::OnStageConnection() to set the depth of the background.
560   Control::OnStageConnection( depth );
561
562   // The depth of the text renderer is set in the RenderText() called from OnRelayout().
563 }
564
565 void TextLabel::TextChanged()
566 {
567   // TextLabel does not provide a signal for this
568 }
569
570 void TextLabel::MaxLengthReached()
571 {
572   // Pure Virtual from TextController Interface, only needed when inputting text
573 }
574
575 TextLabel::TextLabel()
576 : Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
577   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
578   mHasBeenStaged( false )
579 {
580 }
581
582 TextLabel::~TextLabel()
583 {
584 }
585
586 } // namespace Internal
587
588 } // namespace Toolkit
589
590 } // namespace Dali