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