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