2c87bbc055fb1bb8ce3db20572f8e83e667b9bb1
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-field-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-field-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/images/resource-image.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/public-api/object/type-registry-helper.h>
25 #include <dali/public-api/common/stage.h>
26 #include <dali/integration-api/debug.h>
27
28 // INTERNAL INCLUDES
29 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
30 #include <dali-toolkit/internal/text/rendering/text-backend.h>
31
32 using namespace Dali::Toolkit::Text;
33
34 namespace
35 {
36
37 const unsigned int DEFAULT_RENDERING_BACKEND = 0;
38
39 } // namespace
40
41
42 namespace Dali
43 {
44
45 namespace Toolkit
46 {
47
48 namespace Internal
49 {
50
51 namespace
52 {
53
54 // Type registration
55 BaseHandle Create()
56 {
57   return Toolkit::TextField::New();
58 }
59
60 // Setup properties, signals and actions using the type-registry.
61 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextField, Toolkit::Control, Create );
62
63 DALI_PROPERTY_REGISTRATION( TextField, "rendering-backend",       INTEGER,   RENDERING_BACKEND       )
64 DALI_PROPERTY_REGISTRATION( TextField, "placeholder-text",        STRING,    PLACEHOLDER_TEXT        )
65 DALI_PROPERTY_REGISTRATION( TextField, "text",                    STRING,    TEXT                    )
66 DALI_PROPERTY_REGISTRATION( TextField, "font-family",             STRING,    FONT_FAMILY             )
67 DALI_PROPERTY_REGISTRATION( TextField, "font-style",              STRING,    FONT_STYLE              )
68 DALI_PROPERTY_REGISTRATION( TextField, "point-size",              FLOAT,     POINT_SIZE              )
69 DALI_PROPERTY_REGISTRATION( TextField, "cursor-image",            STRING,    CURSOR_IMAGE            )
70 DALI_PROPERTY_REGISTRATION( TextField, "primary-cursor-color",    VECTOR4,   PRIMARY_CURSOR_COLOR    )
71 DALI_PROPERTY_REGISTRATION( TextField, "secondary-cursor-color",  VECTOR4,   SECONDARY_CURSOR_COLOR  )
72 DALI_PROPERTY_REGISTRATION( TextField, "enable-cursor-blink",     BOOLEAN,   ENABLE_CURSOR_BLINK     )
73 DALI_PROPERTY_REGISTRATION( TextField, "cursor-blink-interval",   FLOAT,     CURSOR_BLINK_INTERVAL   )
74 DALI_PROPERTY_REGISTRATION( TextField, "cursor-blink-duration",   FLOAT,     CURSOR_BLINK_DURATION   )
75 DALI_PROPERTY_REGISTRATION( TextField, "grab-handle-image",       STRING,    GRAB_HANDLE_IMAGE       )
76 DALI_PROPERTY_REGISTRATION( TextField, "decoration bounding-box", RECTANGLE, DECORATION_BOUNDING_BOX )
77
78 DALI_TYPE_REGISTRATION_END()
79
80 } // namespace
81
82 Toolkit::TextField TextField::New()
83 {
84   // Create the implementation, temporarily owned by this handle on stack
85   IntrusivePtr< TextField > impl = new TextField();
86
87   // Pass ownership to CustomActor handle
88   Toolkit::TextField handle( *impl );
89
90   // Second-phase init of the implementation
91   // This can only be done after the CustomActor connection has been made...
92   impl->Initialize();
93
94   return handle;
95 }
96
97 void TextField::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
98 {
99   Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) );
100
101   if( textField )
102   {
103     TextField& impl( GetImpl( textField ) );
104
105     switch( index )
106     {
107       case Toolkit::TextField::Property::RENDERING_BACKEND:
108       {
109         unsigned int backend = value.Get< unsigned int >();
110
111         if( impl.mRenderingBackend != backend )
112         {
113           impl.mRenderingBackend = backend;
114           impl.mRenderer.Reset();
115         }
116         break;
117       }
118       case Toolkit::TextField::Property::PLACEHOLDER_TEXT:
119       {
120         if( impl.mController )
121         {
122           //impl.mController->SetPlaceholderText( value.Get< std::string >() ); TODO
123         }
124         break;
125       }
126       case Toolkit::TextField::Property::TEXT:
127       {
128         if( impl.mController )
129         {
130           impl.mController->SetText( value.Get< std::string >() );
131         }
132         break;
133       }
134       case Toolkit::TextField::Property::CURSOR_IMAGE:
135       {
136         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
137
138         if( impl.mDecorator )
139         {
140           impl.mDecorator->SetCursorImage( image );
141         }
142         break;
143       }
144       case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR:
145       {
146         if( impl.mDecorator )
147         {
148           impl.mDecorator->SetColor( PRIMARY_CURSOR, value.Get< Vector4 >() );
149         }
150         break;
151       }
152       case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR:
153       {
154         if( impl.mDecorator )
155         {
156           impl.mDecorator->SetColor( SECONDARY_CURSOR, value.Get< Vector4 >() );
157         }
158         break;
159       }
160       case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK:
161       {
162         if( impl.mController )
163         {
164           //impl.mController->SetEnableCursorBlink( value.Get< bool >() ); TODO
165         }
166         break;
167       }
168       case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL:
169       {
170         if( impl.mDecorator )
171         {
172           impl.mDecorator->SetCursorBlinkInterval( value.Get< float >() );
173         }
174         break;
175       }
176       case Toolkit::TextField::Property::CURSOR_BLINK_DURATION:
177       {
178         if( impl.mDecorator )
179         {
180           impl.mDecorator->SetCursorBlinkDuration( value.Get< float >() );
181         }
182         break;
183       }
184       case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE:
185       {
186         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
187
188         if( impl.mDecorator )
189         {
190           impl.mDecorator->SetGrabHandleImage( image );
191         }
192         break;
193       }
194       case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX:
195       {
196         if( impl.mDecorator )
197         {
198           impl.mDecorator->SetBoundingBox( value.Get< Rect<int> >() );
199         }
200         break;
201       }
202     }
203   }
204 }
205
206 Property::Value TextField::GetProperty( BaseObject* object, Property::Index index )
207 {
208   Property::Value value;
209
210   Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) );
211
212   if( textField )
213   {
214     TextField& impl( GetImpl( textField ) );
215
216     switch( index )
217     {
218       case Toolkit::TextField::Property::RENDERING_BACKEND:
219       {
220         value = impl.mRenderingBackend;
221         break;
222       }
223       case Toolkit::TextField::Property::PLACEHOLDER_TEXT:
224       {
225         DALI_LOG_WARNING( "UTF-8 text representation was discarded\n" );
226         break;
227       }
228       case Toolkit::TextField::Property::TEXT:
229       {
230         DALI_LOG_WARNING( "UTF-8 text representation was discarded\n" );
231         break;
232       }
233       case Toolkit::TextField::Property::CURSOR_IMAGE:
234       {
235         if( impl.mDecorator )
236         {
237           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetCursorImage() );
238           if( image )
239           {
240             value = image.GetUrl();
241           }
242         }
243         break;
244       }
245       case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR:
246       {
247         if( impl.mDecorator )
248         {
249           value = impl.mDecorator->GetColor( PRIMARY_CURSOR );
250         }
251         break;
252       }
253       case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR:
254       {
255         if( impl.mDecorator )
256         {
257           value = impl.mDecorator->GetColor( SECONDARY_CURSOR );
258         }
259         break;
260       }
261       case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK:
262       {
263         //value = impl.mController->GetEnableCursorBlink(); TODO
264         break;
265       }
266       case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL:
267       {
268         if( impl.mDecorator )
269         {
270           value = impl.mDecorator->GetCursorBlinkInterval();
271         }
272         break;
273       }
274       case Toolkit::TextField::Property::CURSOR_BLINK_DURATION:
275       {
276         if( impl.mDecorator )
277         {
278           value = impl.mDecorator->GetCursorBlinkDuration();
279         }
280         break;
281       }
282       case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE:
283       {
284         if( impl.mDecorator )
285         {
286           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetCursorImage() );
287           if( image )
288           {
289             value = image.GetUrl();
290           }
291         }
292         break;
293       }
294       case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX:
295       {
296         if( impl.mDecorator )
297         {
298           value = impl.mDecorator->GetBoundingBox();
299         }
300         break;
301       }
302     }
303   }
304
305   return value;
306 }
307
308 void TextField::OnInitialize()
309 {
310   mController = Text::Controller::New( *this );
311
312   mDecorator = Text::Decorator::New( *this, *mController );
313
314   mController->GetLayoutEngine().SetLayout( LayoutEngine::SINGLE_LINE_BOX );
315
316   mController->EnableTextInput( mDecorator );
317
318   // Forward input events to controller
319   mDoubleTapDetector = TapGestureDetector::New();
320   mDoubleTapDetector.SetMaximumTapsRequired( 2 );
321   mDoubleTapDetector.DetectedSignal().Connect( this, &TextField::OnTap );
322   mDoubleTapDetector.Attach(Self());
323
324   // Set BoundingBox to stage size if not already set.
325   if ( mDecorator->GetBoundingBox().IsEmpty() )
326   {
327     Vector2 stageSize = Dali::Stage::GetCurrent().GetSize();
328     mDecorator->SetBoundingBox( Rect<int>( 0.0f, 0.0f, stageSize.width, stageSize.height ) );
329   }
330 }
331
332 Vector3 TextField::GetNaturalSize()
333 {
334   return mController->GetNaturalSize();
335 }
336
337 float TextField::GetHeightForWidth( float width )
338 {
339   return mController->GetHeightForWidth( width );
340 }
341
342 void TextField::OnRelayout( const Vector2& size, ActorSizeContainer& container )
343 {
344   if( mController->Relayout( size ) )
345   {
346     if( mDecorator )
347     {
348       mDecorator->Relayout( size );
349     }
350
351     if( !mRenderer )
352     {
353       mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
354     }
355
356     if( mRenderer )
357     {
358       Actor renderableActor = mRenderer->Render( mController->GetView() );
359
360       if( renderableActor )
361       {
362         Self().Add( renderableActor );
363       }
364     }
365   }
366 }
367
368 void TextField::OnTap( Actor actor, const TapGesture& gesture )
369 {
370   mController->TapEvent( gesture.numberOfTaps, gesture.localPoint.x, gesture.localPoint.y );
371 }
372
373 void TextField::RequestTextRelayout()
374 {
375   RelayoutRequest();
376 }
377
378 TextField::TextField()
379 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_NONE ) ),
380   mRenderingBackend( DEFAULT_RENDERING_BACKEND )
381 {
382 }
383
384 TextField::~TextField()
385 {
386 }
387
388 } // namespace Internal
389
390 } // namespace Toolkit
391
392 } // namespace Dali