Changed Type of PROPERTY_RENDERING_BACKEND to signed, to correct Property::Value...
[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/text-backend.h>
29
30 using namespace Dali::Toolkit::Text;
31
32 namespace
33 {
34
35 const unsigned int DEFAULT_RENDERING_BACKEND = 0;
36
37 } // namespace
38
39
40 namespace Dali
41 {
42
43 namespace Toolkit
44 {
45
46 const Property::Index TextField::PROPERTY_RENDERING_BACKEND(      Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX );
47 const Property::Index TextField::PROPERTY_PLACEHOLDER_TEXT(       Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 1 );
48 const Property::Index TextField::PROPERTY_TEXT(                   Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 2 );
49 const Property::Index TextField::PROPERTY_CURSOR_IMAGE(           Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 3 );
50 const Property::Index TextField::PROPERTY_PRIMARY_CURSOR_COLOR(   Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 4 );
51 const Property::Index TextField::PROPERTY_SECONDARY_CURSOR_COLOR( Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 5 );
52 const Property::Index TextField::PROPERTY_ENABLE_CURSOR_BLINK(    Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 6 );
53 const Property::Index TextField::PROPERTY_CURSOR_BLINK_INTERVAL(  Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 7 );
54 const Property::Index TextField::PROPERTY_CURSOR_BLINK_DURATION(  Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 8 );
55 const Property::Index TextField::PROPERTY_GRAB_HANDLE_IMAGE(      Internal::TextField::TEXTFIELD_PROPERTY_START_INDEX + 9 );
56
57 namespace Internal
58 {
59
60 namespace
61 {
62
63 // Type registration
64 BaseHandle Create()
65 {
66   return Toolkit::TextField::New();
67 }
68
69 TypeRegistration mType( typeid(Toolkit::TextField), typeid(Toolkit::Control), Create );
70
71 PropertyRegistration property01( mType, "rendering-backend",      Toolkit::TextField::PROPERTY_RENDERING_BACKEND,      Property::INTEGER,          &TextField::SetProperty, &TextField::GetProperty );
72 PropertyRegistration property02( mType, "placeholder-text",       Toolkit::TextField::PROPERTY_PLACEHOLDER_TEXT,       Property::STRING,           &TextField::SetProperty, &TextField::GetProperty );
73 PropertyRegistration property03( mType, "text",                   Toolkit::TextField::PROPERTY_TEXT,                   Property::STRING,           &TextField::SetProperty, &TextField::GetProperty );
74 PropertyRegistration property04( mType, "cursor-image",           Toolkit::TextField::PROPERTY_CURSOR_IMAGE,           Property::STRING,           &TextField::SetProperty, &TextField::GetProperty );
75 PropertyRegistration property05( mType, "primary-cursor-color",   Toolkit::TextField::PROPERTY_PRIMARY_CURSOR_COLOR,   Property::VECTOR4,          &TextField::SetProperty, &TextField::GetProperty );
76 PropertyRegistration property06( mType, "secondary-cursor-color", Toolkit::TextField::PROPERTY_SECONDARY_CURSOR_COLOR, Property::VECTOR4,          &TextField::SetProperty, &TextField::GetProperty );
77 PropertyRegistration property07( mType, "enable-cursor-blink",    Toolkit::TextField::PROPERTY_ENABLE_CURSOR_BLINK,    Property::BOOLEAN,          &TextField::SetProperty, &TextField::GetProperty );
78 PropertyRegistration property08( mType, "cursor-blink-interval",  Toolkit::TextField::PROPERTY_CURSOR_BLINK_INTERVAL,  Property::FLOAT,            &TextField::SetProperty, &TextField::GetProperty );
79 PropertyRegistration property09( mType, "cursor-blink-duration",  Toolkit::TextField::PROPERTY_CURSOR_BLINK_DURATION,  Property::FLOAT,            &TextField::SetProperty, &TextField::GetProperty );
80 PropertyRegistration property10( mType, "grab-handle-image",      Toolkit::TextField::PROPERTY_GRAB_HANDLE_IMAGE,      Property::STRING,           &TextField::SetProperty, &TextField::GetProperty );
81
82 } // namespace
83
84 Toolkit::TextField TextField::New()
85 {
86   // Create the implementation, temporarily owned by this handle on stack
87   IntrusivePtr< TextField > impl = new TextField();
88
89   // Pass ownership to CustomActor handle
90   Toolkit::TextField handle( *impl );
91
92   // Second-phase init of the implementation
93   // This can only be done after the CustomActor connection has been made...
94   impl->Initialize();
95
96   return handle;
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_RENDERING_BACKEND:
110       {
111         unsigned int backend = value.Get< unsigned int >();
112
113         if( impl.mRenderingBackend != backend )
114         {
115           impl.mRenderingBackend = backend;
116           impl.mRenderer.Reset();
117         }
118         break;
119       }
120       case Toolkit::TextField::PROPERTY_PLACEHOLDER_TEXT:
121       {
122         if( impl.mController )
123         {
124           //impl.mController->SetPlaceholderText( value.Get< std::string >() ); TODO
125         }
126         break;
127       }
128       case Toolkit::TextField::PROPERTY_TEXT:
129       {
130         if( impl.mController )
131         {
132           impl.mController->SetText( value.Get< std::string >() );
133         }
134         break;
135       }
136       case Toolkit::TextField::PROPERTY_CURSOR_IMAGE:
137       {
138         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
139
140         if( impl.mDecorator )
141         {
142           impl.mDecorator->SetCursorImage( image );
143         }
144         break;
145       }
146       case Toolkit::TextField::PROPERTY_PRIMARY_CURSOR_COLOR:
147       {
148         if( impl.mDecorator )
149         {
150           impl.mDecorator->SetColor( PRIMARY_CURSOR, value.Get< Vector4 >() );
151         }
152         break;
153       }
154       case Toolkit::TextField::PROPERTY_SECONDARY_CURSOR_COLOR:
155       {
156         if( impl.mDecorator )
157         {
158           impl.mDecorator->SetColor( SECONDARY_CURSOR, value.Get< Vector4 >() );
159         }
160         break;
161       }
162       case Toolkit::TextField::PROPERTY_ENABLE_CURSOR_BLINK:
163       {
164         if( impl.mController )
165         {
166           //impl.mController->SetEnableCursorBlink( value.Get< bool >() ); TODO
167         }
168         break;
169       }
170       case Toolkit::TextField::PROPERTY_CURSOR_BLINK_INTERVAL:
171       {
172         if( impl.mDecorator )
173         {
174           impl.mDecorator->SetCursorBlinkInterval( value.Get< float >() );
175         }
176         break;
177       }
178       case Toolkit::TextField::PROPERTY_CURSOR_BLINK_DURATION:
179       {
180         if( impl.mDecorator )
181         {
182           impl.mDecorator->SetCursorBlinkDuration( value.Get< float >() );
183         }
184         break;
185       }
186       case Toolkit::TextField::PROPERTY_GRAB_HANDLE_IMAGE:
187       {
188         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
189
190         if( impl.mDecorator )
191         {
192           impl.mDecorator->SetGrabHandleImage( image );
193         }
194         break;
195       }
196     }
197   }
198 }
199
200 Property::Value TextField::GetProperty( BaseObject* object, Property::Index index )
201 {
202   Property::Value value;
203
204   Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) );
205
206   if( textField )
207   {
208     TextField& impl( GetImpl( textField ) );
209
210     switch( index )
211     {
212       case Toolkit::TextField::PROPERTY_RENDERING_BACKEND:
213       {
214         value = impl.mRenderingBackend;
215         break;
216       }
217       case Toolkit::TextField::PROPERTY_PLACEHOLDER_TEXT:
218       {
219         DALI_LOG_WARNING( "UTF-8 text representation was discarded\n" );
220         break;
221       }
222       case Toolkit::TextField::PROPERTY_TEXT:
223       {
224         DALI_LOG_WARNING( "UTF-8 text representation was discarded\n" );
225         break;
226       }
227       case Toolkit::TextField::PROPERTY_CURSOR_IMAGE:
228       {
229         if( impl.mDecorator )
230         {
231           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetCursorImage() );
232           if( image )
233           {
234             value = image.GetUrl();
235           }
236         }
237         break;
238       }
239       case Toolkit::TextField::PROPERTY_PRIMARY_CURSOR_COLOR:
240       {
241         if( impl.mDecorator )
242         {
243           value = impl.mDecorator->GetColor( PRIMARY_CURSOR );
244         }
245         break;
246       }
247       case Toolkit::TextField::PROPERTY_SECONDARY_CURSOR_COLOR:
248       {
249         if( impl.mDecorator )
250         {
251           value = impl.mDecorator->GetColor( SECONDARY_CURSOR );
252         }
253         break;
254       }
255       case Toolkit::TextField::PROPERTY_ENABLE_CURSOR_BLINK:
256       {
257         //value = impl.mController->GetEnableCursorBlink(); TODO
258         break;
259       }
260       case Toolkit::TextField::PROPERTY_CURSOR_BLINK_INTERVAL:
261       {
262         if( impl.mDecorator )
263         {
264           value = impl.mDecorator->GetCursorBlinkInterval();
265         }
266         break;
267       }
268       case Toolkit::TextField::PROPERTY_CURSOR_BLINK_DURATION:
269       {
270         if( impl.mDecorator )
271         {
272           value = impl.mDecorator->GetCursorBlinkDuration();
273         }
274         break;
275       }
276       case Toolkit::TextField::PROPERTY_GRAB_HANDLE_IMAGE:
277       {
278         if( impl.mDecorator )
279         {
280           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetCursorImage() );
281           if( image )
282           {
283             value = image.GetUrl();
284           }
285         }
286         break;
287       }
288     }
289   }
290
291   return value;
292 }
293
294 void TextField::OnInitialize()
295 {
296   mController = Text::Controller::New( *this );
297
298   mDecorator = Text::Decorator::New( *this, *mController );
299
300   mController->GetLayoutEngine().SetLayout( LayoutEngine::SINGLE_LINE_BOX );
301
302   mController->EnableTextInput( mDecorator );
303
304   // Forward input events to controller
305   EnableGestureDetection( Gesture::Tap );
306
307   // TODO - Fix TapGestureDetector to support single and double tap
308   mDoubleTapDetector = TapGestureDetector::New();
309   mDoubleTapDetector.SetTapsRequired( 2 );
310   mDoubleTapDetector.DetectedSignal().Connect( this, &TextField::OnDoubleTap );
311   mDoubleTapDetector.Attach(Self());
312 }
313
314 void TextField::OnRelayout( const Vector2& size, ActorSizeContainer& container )
315 {
316   if( mController->Relayout( size ) )
317   {
318     if( mDecorator )
319     {
320       mDecorator->Relayout( size );
321     }
322
323     if( !mRenderer )
324     {
325       mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
326     }
327
328     if( mRenderer )
329     {
330       Actor renderableActor = mRenderer->Render( mController->GetView() );
331
332       if( renderableActor )
333       {
334         Self().Add( renderableActor );
335       }
336     }
337   }
338 }
339
340 void TextField::OnTap( const TapGesture& tap )
341 {
342   mController->TapEvent( tap.numberOfTaps, tap.localPoint.x, tap.localPoint.y );
343 }
344
345 void TextField::OnDoubleTap( Actor actor, const TapGesture& tap )
346 {
347   mController->TapEvent( tap.numberOfTaps, tap.localPoint.x, tap.localPoint.y );
348 }
349
350 void TextField::RequestTextRelayout()
351 {
352   RelayoutRequest();
353 }
354
355 TextField::TextField()
356 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_NONE ) ),
357   mRenderingBackend( DEFAULT_RENDERING_BACKEND )
358 {
359 }
360
361 TextField::~TextField()
362 {
363 }
364
365 } // namespace Internal
366
367 } // namespace Toolkit
368
369 } // namespace Dali