Added interface for queuing input events in TextController
[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/integration-api/debug.h>
25
26 // INTERNAL INCLUDES
27 #include <dali-toolkit/public-api/text/layouts/layout-engine.h>
28 #include <dali-toolkit/public-api/text/rendering/basic/text-basic-renderer.h> // TODO - Get from RendererFactory
29
30 using namespace Dali::Toolkit::Text;
31
32 namespace
33 {
34
35 } // namespace
36
37 namespace Dali
38 {
39
40 namespace Toolkit
41 {
42
43 const Property::Index TextField::PROPERTY_PLACEHOLDER_TEXT(       Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX );
44 const Property::Index TextField::PROPERTY_TEXT(                   Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 1 );
45 const Property::Index TextField::PROPERTY_CURSOR_IMAGE(           Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 2 );
46 const Property::Index TextField::PROPERTY_PRIMARY_CURSOR_COLOR(   Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 3 );
47 const Property::Index TextField::PROPERTY_SECONDARY_CURSOR_COLOR( Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 4 );
48 const Property::Index TextField::PROPERTY_ENABLE_CURSOR_BLINK(    Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 5 );
49 const Property::Index TextField::PROPERTY_CURSOR_BLINK_INTERVAL(  Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 6 );
50 const Property::Index TextField::PROPERTY_CURSOR_BLINK_DURATION(  Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 7 );
51 const Property::Index TextField::PROPERTY_GRAB_HANDLE_IMAGE(      Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 8 );
52
53 namespace Internal
54 {
55
56 namespace
57 {
58
59 // Type registration
60 BaseHandle Create()
61 {
62   return Toolkit::TextField::New();
63 }
64
65 TypeRegistration mType( typeid(Toolkit::TextField), typeid(Toolkit::Control), Create );
66
67 PropertyRegistration property1( mType, "placeholder-text",       Toolkit::TextField::PROPERTY_PLACEHOLDER_TEXT,       Property::STRING,  &TextField::SetProperty, &TextField::GetProperty );
68 PropertyRegistration property2( mType, "text",                   Toolkit::TextField::PROPERTY_TEXT,                   Property::STRING,  &TextField::SetProperty, &TextField::GetProperty );
69 PropertyRegistration property3( mType, "cursor-image",           Toolkit::TextField::PROPERTY_CURSOR_IMAGE,           Property::STRING,  &TextField::SetProperty, &TextField::GetProperty );
70 PropertyRegistration property4( mType, "primary-cursor-color",   Toolkit::TextField::PROPERTY_PRIMARY_CURSOR_COLOR,   Property::VECTOR4, &TextField::SetProperty, &TextField::GetProperty );
71 PropertyRegistration property5( mType, "secondary-cursor-color", Toolkit::TextField::PROPERTY_SECONDARY_CURSOR_COLOR, Property::VECTOR4, &TextField::SetProperty, &TextField::GetProperty );
72 PropertyRegistration property6( mType, "enable-cursor-blink",    Toolkit::TextField::PROPERTY_ENABLE_CURSOR_BLINK,    Property::BOOLEAN, &TextField::SetProperty, &TextField::GetProperty );
73 PropertyRegistration property7( mType, "cursor-blink-interval",  Toolkit::TextField::PROPERTY_CURSOR_BLINK_INTERVAL,  Property::FLOAT,   &TextField::SetProperty, &TextField::GetProperty );
74 PropertyRegistration property8( mType, "cursor-blink-duration",  Toolkit::TextField::PROPERTY_CURSOR_BLINK_DURATION,  Property::FLOAT,   &TextField::SetProperty, &TextField::GetProperty );
75 PropertyRegistration property9( mType, "grab-handle-image",      Toolkit::TextField::PROPERTY_GRAB_HANDLE_IMAGE,      Property::STRING,  &TextField::SetProperty, &TextField::GetProperty );
76
77 } // namespace
78
79 Toolkit::TextField TextField::New()
80 {
81   // Create the implementation, temporarily owned by this handle on stack
82   IntrusivePtr< TextField > impl = new TextField();
83
84   // Pass ownership to CustomActor handle
85   Toolkit::TextField handle( *impl );
86
87   // Second-phase init of the implementation
88   // This can only be done after the CustomActor connection has been made...
89   impl->Initialize();
90
91   return handle;
92 }
93
94 void TextField::SetRenderer( Text::RendererPtr renderer )
95 {
96   mRenderer = renderer;
97 }
98
99 void TextField::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
100 {
101   Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) );
102
103   if( textField )
104   {
105     TextField& impl( GetImpl( textField ) );
106
107     switch( index )
108     {
109       case Toolkit::TextField::PROPERTY_PLACEHOLDER_TEXT:
110       {
111         if( impl.mController )
112         {
113           //impl.mController->SetPlaceholderText( value.Get< std::string >() ); TODO
114         }
115         break;
116       }
117       case Toolkit::TextField::PROPERTY_TEXT:
118       {
119         if( impl.mController )
120         {
121           impl.mController->SetText( value.Get< std::string >() );
122         }
123         break;
124       }
125       case Toolkit::TextField::PROPERTY_CURSOR_IMAGE:
126       {
127         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
128
129         if( impl.mDecorator )
130         {
131           impl.mDecorator->SetCursorImage( image );
132         }
133         break;
134       }
135       case Toolkit::TextField::PROPERTY_PRIMARY_CURSOR_COLOR:
136       {
137         if( impl.mDecorator )
138         {
139           impl.mDecorator->SetColor( PRIMARY_CURSOR, value.Get< Vector4 >() );
140         }
141         break;
142       }
143       case Toolkit::TextField::PROPERTY_SECONDARY_CURSOR_COLOR:
144       {
145         if( impl.mDecorator )
146         {
147           impl.mDecorator->SetColor( SECONDARY_CURSOR, value.Get< Vector4 >() );
148         }
149         break;
150       }
151       case Toolkit::TextField::PROPERTY_ENABLE_CURSOR_BLINK:
152       {
153         if( impl.mController )
154         {
155           //impl.mController->SetEnableCursorBlink( value.Get< bool >() ); TODO
156         }
157         break;
158       }
159       case Toolkit::TextField::PROPERTY_CURSOR_BLINK_INTERVAL:
160       {
161         if( impl.mDecorator )
162         {
163           impl.mDecorator->SetCursorBlinkInterval( value.Get< float >() );
164         }
165         break;
166       }
167       case Toolkit::TextField::PROPERTY_CURSOR_BLINK_DURATION:
168       {
169         if( impl.mDecorator )
170         {
171           impl.mDecorator->SetCursorBlinkDuration( value.Get< float >() );
172         }
173         break;
174       }
175       case Toolkit::TextField::PROPERTY_GRAB_HANDLE_IMAGE:
176       {
177         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
178
179         if( impl.mDecorator )
180         {
181           impl.mDecorator->SetGrabHandleImage( image );
182         }
183         break;
184       }
185     }
186   }
187 }
188
189 Property::Value TextField::GetProperty( BaseObject* object, Property::Index index )
190 {
191   Property::Value value;
192
193   Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) );
194
195   if( textField )
196   {
197     TextField& impl( GetImpl( textField ) );
198
199     switch( index )
200     {
201       case Toolkit::TextField::PROPERTY_PLACEHOLDER_TEXT:
202       {
203         DALI_LOG_WARNING( "UTF-8 text representation was discarded\n" );
204         break;
205       }
206       case Toolkit::TextField::PROPERTY_TEXT:
207       {
208         DALI_LOG_WARNING( "UTF-8 text representation was discarded\n" );
209         break;
210       }
211       case Toolkit::TextField::PROPERTY_CURSOR_IMAGE:
212       {
213         if( impl.mDecorator )
214         {
215           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetCursorImage() );
216           if( image )
217           {
218             value = image.GetUrl();
219           }
220         }
221         break;
222       }
223       case Toolkit::TextField::PROPERTY_PRIMARY_CURSOR_COLOR:
224       {
225         if( impl.mDecorator )
226         {
227           value = impl.mDecorator->GetColor( PRIMARY_CURSOR );
228         }
229         break;
230       }
231       case Toolkit::TextField::PROPERTY_SECONDARY_CURSOR_COLOR:
232       {
233         if( impl.mDecorator )
234         {
235           value = impl.mDecorator->GetColor( SECONDARY_CURSOR );
236         }
237         break;
238       }
239       case Toolkit::TextField::PROPERTY_ENABLE_CURSOR_BLINK:
240       {
241         //value = impl.mController->GetEnableCursorBlink(); TODO
242         break;
243       }
244       case Toolkit::TextField::PROPERTY_CURSOR_BLINK_INTERVAL:
245       {
246         if( impl.mDecorator )
247         {
248           value = impl.mDecorator->GetCursorBlinkInterval();
249         }
250         break;
251       }
252       case Toolkit::TextField::PROPERTY_CURSOR_BLINK_DURATION:
253       {
254         if( impl.mDecorator )
255         {
256           value = impl.mDecorator->GetCursorBlinkDuration();
257         }
258         break;
259       }
260       case Toolkit::TextField::PROPERTY_GRAB_HANDLE_IMAGE:
261       {
262         if( impl.mDecorator )
263         {
264           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetCursorImage() );
265           if( image )
266           {
267             value = image.GetUrl();
268           }
269         }
270         break;
271       }
272     }
273   }
274
275   return value;
276 }
277
278 void TextField::OnInitialize()
279 {
280   mController = Text::Controller::New( *this );
281
282   mDecorator = Text::Decorator::New( *this, *mController );
283
284   mController->GetLayoutEngine().SetLayout( LayoutEngine::SINGLE_LINE_BOX );
285
286   mController->EnableTextInput( mDecorator );
287
288   // Forward input events to controller
289   EnableGestureDetection( Gesture::Tap );
290 }
291
292 void TextField::OnRelayout( const Vector2& size, ActorSizeContainer& container )
293 {
294   if( mController->Relayout( size ) )
295   {
296     if( !mRenderer )
297     {
298       // TODO - Get from RendererFactory
299       mRenderer = Dali::Toolkit::Text::BasicRenderer::New();
300     }
301
302     if( mRenderer )
303     {
304       Actor renderableActor = mRenderer->Render( mController->GetView() );
305
306       if( renderableActor )
307       {
308         Self().Add( renderableActor );
309       }
310     }
311   }
312 }
313
314 void TextField::OnTap( const TapGesture& tap )
315 {
316   mController->TapEvent( tap.localPoint.x, tap.localPoint.y );
317 }
318
319 void TextField::RequestTextRelayout()
320 {
321   RelayoutRequest();
322 }
323
324 TextField::TextField()
325 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_NONE ) )
326 {
327 }
328
329 TextField::~TextField()
330 {
331 }
332
333 } // namespace Internal
334
335 } // namespace Toolkit
336
337 } // namespace Dali