More Text related logging & clean-up
[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 <string>
23 #include <iostream>
24 #include <cstring>
25 #include <dali/public-api/adaptor-framework/key.h>
26 #include <dali/public-api/common/stage.h>
27 #include <dali/public-api/images/resource-image.h>
28 #include <dali/public-api/object/type-registry.h>
29 #include <dali/public-api/object/type-registry-helper.h>
30 #include <dali/public-api/scripting/scripting.h>
31 #include <dali/public-api/adaptor-framework/virtual-keyboard.h>
32 #include <dali/integration-api/debug.h>
33
34 // INTERNAL INCLUDES
35 #include <dali-toolkit/public-api/text/rendering-backend.h>
36 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
37 #include <dali-toolkit/internal/text/rendering/text-backend.h>
38 #include <dali-toolkit/internal/styling/style-manager-impl.h>
39
40 using namespace Dali::Toolkit::Text;
41
42 namespace Dali
43 {
44
45 namespace Toolkit
46 {
47
48 namespace Internal
49 {
50
51 namespace // unnamed namespace
52 {
53
54 #if defined(DEBUG_ENABLED)
55   Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS");
56 #endif
57
58   const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
59
60 } // unnamed namespace
61
62 namespace
63 {
64
65 const Scripting::StringEnum< Toolkit::Text::LayoutEngine::HorizontalAlignment > HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
66 {
67   { "BEGIN",  Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN  },
68   { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER },
69   { "END",    Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_END    },
70 };
71 const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] );
72
73 const Scripting::StringEnum< Toolkit::Text::LayoutEngine::VerticalAlignment > VERTICAL_ALIGNMENT_STRING_TABLE[] =
74 {
75   { "TOP",    Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP    },
76   { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER },
77   { "BOTTOM", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_BOTTOM },
78 };
79 const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( VERTICAL_ALIGNMENT_STRING_TABLE ) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] );
80
81 // Type registration
82 BaseHandle Create()
83 {
84   return Toolkit::TextField::New();
85 }
86
87 // Setup properties, signals and actions using the type-registry.
88 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextField, Toolkit::Control, Create );
89
90 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "rendering-backend",                    INTEGER,   RENDERING_BACKEND                    )
91 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "text",                                 STRING,    TEXT                                 )
92 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "placeholder-text",                     STRING,    PLACEHOLDER_TEXT                     )
93 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "placeholder-text-focused",             STRING,    PLACEHOLDER_TEXT_FOCUSED             )
94 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "font-family",                          STRING,    FONT_FAMILY                          )
95 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "font-style",                           STRING,    FONT_STYLE                           )
96 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "point-size",                           FLOAT,     POINT_SIZE                           )
97 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "max-length",                           INTEGER,   MAX_LENGTH                           )
98 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "exceed-policy",                        INTEGER,   EXCEED_POLICY                        )
99 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "horizontal-alignment",                 STRING,    HORIZONTAL_ALIGNMENT                 )
100 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "vertical-alignment",                   STRING,    VERTICAL_ALIGNMENT                   )
101 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "text-color",                           VECTOR4,   TEXT_COLOR                           )
102 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "placeholder-text-color",               VECTOR4,   PLACEHOLDER_TEXT_COLOR               )
103 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "shadow-offset",                        VECTOR2,   SHADOW_OFFSET                        )
104 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "shadow-color",                         VECTOR4,   SHADOW_COLOR                         )
105 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "primary-cursor-color",                 VECTOR4,   PRIMARY_CURSOR_COLOR                 )
106 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "secondary-cursor-color",               VECTOR4,   SECONDARY_CURSOR_COLOR               )
107 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "enable-cursor-blink",                  BOOLEAN,   ENABLE_CURSOR_BLINK                  )
108 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "cursor-blink-interval",                FLOAT,     CURSOR_BLINK_INTERVAL                )
109 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "cursor-blink-duration",                FLOAT,     CURSOR_BLINK_DURATION                )
110 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "grab-handle-image",                    STRING,    GRAB_HANDLE_IMAGE                    )
111 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "grab-handle-pressed-image",            VECTOR4,   GRAB_HANDLE_PRESSED_IMAGE            )
112 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "scroll-threshold",                     FLOAT,     SCROLL_THRESHOLD                     )
113 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "scroll-speed",                         FLOAT,     SCROLL_SPEED                         )
114 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selection-handle-image-left",          STRING,    SELECTION_HANDLE_IMAGE_LEFT          )
115 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selection-handle-image-right",         STRING,    SELECTION_HANDLE_IMAGE_RIGHT         )
116 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selection-handle-pressed-image-left",  STRING,    SELECTION_HANDLE_PRESSED_IMAGE_LEFT  )
117 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selection-handle-pressed-image-right", STRING,    SELECTION_HANDLE_PRESSED_IMAGE_RIGHT )
118 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selection-highlight-color",            STRING,    SELECTION_HIGHLIGHT_COLOR            )
119 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "decoration-bounding-box",              RECTANGLE, DECORATION_BOUNDING_BOX              )
120
121 DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "max-length-reached", SIGNAL_MAX_LENGTH_REACHED )
122
123 DALI_TYPE_REGISTRATION_END()
124
125 } // namespace
126
127 Toolkit::TextField TextField::New()
128 {
129   // Create the implementation, temporarily owned by this handle on stack
130   IntrusivePtr< TextField > impl = new TextField();
131
132   // Pass ownership to CustomActor handle
133   Toolkit::TextField handle( *impl );
134
135   // Second-phase init of the implementation
136   // This can only be done after the CustomActor connection has been made...
137   impl->Initialize();
138
139   return handle;
140 }
141
142 void TextField::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
143 {
144   Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) );
145
146   if( textField )
147   {
148     TextField& impl( GetImpl( textField ) );
149
150     switch( index )
151     {
152       case Toolkit::TextField::Property::RENDERING_BACKEND:
153       {
154         int backend = value.Get< int >();
155         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p RENDERING_BACKEND %d\n", impl.mController.Get(), backend );
156
157         if( impl.mRenderingBackend != backend )
158         {
159           impl.mRenderingBackend = backend;
160           impl.mRenderer.Reset();
161         }
162         break;
163       }
164       case Toolkit::TextField::Property::TEXT:
165       {
166         if( impl.mController )
167         {
168           std::string text = value.Get< std::string >();
169           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p TEXT %s\n", impl.mController.Get(), text.c_str() );
170
171           impl.mController->SetText( text );
172         }
173         break;
174       }
175       case Toolkit::TextField::Property::PLACEHOLDER_TEXT:
176       {
177         if( impl.mController )
178         {
179           std::string text = value.Get< std::string >();
180           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT %s\n", impl.mController.Get(), text.c_str() );
181
182           impl.mController->SetPlaceholderText( PLACEHOLDER_TYPE_INACTIVE, text );
183         }
184         break;
185       }
186       case Toolkit::TextField::Property::PLACEHOLDER_TEXT_FOCUSED:
187       {
188         if( impl.mController )
189         {
190           std::string text = value.Get< std::string >();
191           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT_FOCUSED %s\n", impl.mController.Get(), text.c_str() );
192
193           impl.mController->SetPlaceholderText( PLACEHOLDER_TYPE_ACTIVE, text );
194         }
195         break;
196       }
197       case Toolkit::TextField::Property::FONT_FAMILY:
198       {
199         if( impl.mController )
200         {
201           std::string fontFamily = value.Get< std::string >();
202           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str() );
203
204           if( impl.mController->GetDefaultFontFamily() != fontFamily )
205           {
206             impl.mController->SetDefaultFontFamily( fontFamily );
207             impl.RequestTextRelayout();
208           }
209         }
210         break;
211       }
212       case Toolkit::TextField::Property::FONT_STYLE:
213       {
214         if( impl.mController )
215         {
216           std::string fontStyle = value.Get< std::string >();
217           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p FONT_STYLE %s\n", impl.mController.Get(), fontStyle.c_str() );
218
219           if( impl.mController->GetDefaultFontStyle() != fontStyle )
220           {
221             impl.mController->SetDefaultFontStyle( fontStyle );
222             impl.RequestTextRelayout();
223           }
224         }
225         break;
226       }
227       case Toolkit::TextField::Property::POINT_SIZE:
228       {
229         if( impl.mController )
230         {
231           float pointSize = value.Get< float >();
232           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p FONT_STYLE %f\n", impl.mController.Get(), pointSize );
233
234           if( !Equals( impl.mController->GetDefaultPointSize(), pointSize ) )
235           {
236             impl.mController->SetDefaultPointSize( pointSize );
237             impl.RequestTextRelayout();
238           }
239         }
240         break;
241       }
242       case Toolkit::TextField::Property::EXCEED_POLICY:
243       {
244         // TODO
245         break;
246       }
247       case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT:
248       {
249         if( impl.mController )
250         {
251           std::string alignStr = value.Get< std::string >();
252           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p HORIZONTAL_ALIGNMENT %f\n", impl.mController.Get(), alignStr.c_str() );
253
254           LayoutEngine& engine = impl.mController->GetLayoutEngine();
255           LayoutEngine::HorizontalAlignment alignment = Scripting::GetEnumeration< LayoutEngine::HorizontalAlignment >( alignStr.c_str(),
256                                                                                                                         HORIZONTAL_ALIGNMENT_STRING_TABLE,
257                                                                                                                         HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
258
259           if( engine.GetHorizontalAlignment() != alignment )
260           {
261             engine.SetHorizontalAlignment( alignment );
262             impl.RequestTextRelayout();
263           }
264         }
265         break;
266       }
267       case Toolkit::TextField::Property::VERTICAL_ALIGNMENT:
268       {
269         if( impl.mController )
270         {
271           std::string alignStr = value.Get< std::string >();
272           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p VERTICAL_ALIGNMENT %f\n", impl.mController.Get(), alignStr.c_str() );
273
274           LayoutEngine& engine = impl.mController->GetLayoutEngine();
275           LayoutEngine::VerticalAlignment alignment = Scripting::GetEnumeration< LayoutEngine::VerticalAlignment >( alignStr.c_str(),
276                                                                                                                     VERTICAL_ALIGNMENT_STRING_TABLE,
277                                                                                                                     VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
278
279           if( engine.GetVerticalAlignment() != alignment )
280           {
281             engine.SetVerticalAlignment( alignment );
282             impl.RequestTextRelayout();
283           }
284         }
285         break;
286       }
287       case Toolkit::TextField::Property::TEXT_COLOR:
288       {
289         if ( impl.mController )
290         {
291           Vector4 textColor = value.Get< Vector4 >();
292           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a );
293
294           if ( impl.mController->GetTextColor() != textColor )
295           {
296             impl.mController->SetTextColor( textColor );
297             impl.RequestTextRelayout();
298           }
299         }
300         break;
301       }
302       case Toolkit::TextField::Property::PLACEHOLDER_TEXT_COLOR:
303       {
304         if ( impl.mController )
305         {
306           Vector4 textColor = value.Get< Vector4 >();
307           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a );
308
309           if ( impl.mController->GetPlaceholderTextColor() != textColor )
310           {
311             impl.mController->SetPlaceholderTextColor( textColor );
312             impl.RequestTextRelayout();
313           }
314         }
315         break;
316       }
317       case Toolkit::TextField::Property::SHADOW_OFFSET:
318       {
319         if( impl.mController )
320         {
321           Vector2 shadowOffset = value.Get< Vector2 >();
322           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SHADOW_OFFSET %f,%f\n", impl.mController.Get(), shadowOffset.x, shadowOffset.y );
323
324           if ( impl.mController->GetShadowOffset() != shadowOffset )
325           {
326             impl.mController->SetShadowOffset( shadowOffset );
327             impl.RequestTextRelayout();
328           }
329         }
330         break;
331       }
332       case Toolkit::TextField::Property::SHADOW_COLOR:
333       {
334         if( impl.mController )
335         {
336           Vector4 shadowColor = value.Get< Vector4 >();
337           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SHADOW_COLOR %f,%f,%f,%f\n", impl.mController.Get(), shadowColor.r, shadowColor.g, shadowColor.b, shadowColor.a );
338
339           if ( impl.mController->GetShadowColor() != shadowColor )
340           {
341             impl.mController->SetShadowColor( shadowColor );
342             impl.RequestTextRelayout();
343           }
344         }
345         break;
346       }
347       case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR:
348       {
349         if( impl.mDecorator )
350         {
351           Vector4 color = value.Get< Vector4 >();
352           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p PRIMARY_CURSOR_COLOR %f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
353
354           impl.mDecorator->SetColor( PRIMARY_CURSOR, color );
355         }
356         break;
357       }
358       case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR:
359       {
360         if( impl.mDecorator )
361         {
362           Vector4 color = value.Get< Vector4 >();
363           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SECONDARY_CURSOR_COLOR %f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
364
365           impl.mDecorator->SetColor( SECONDARY_CURSOR, color );
366         }
367         break;
368       }
369       case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK:
370       {
371         if( impl.mController )
372         {
373           bool enable = value.Get< bool >();
374           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p ENABLE_CURSOR_BLINK %d\n", impl.mController.Get(), enable );
375
376           impl.mController->SetEnableCursorBlink( enable );
377         }
378         break;
379       }
380       case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL:
381       {
382         if( impl.mDecorator )
383         {
384           float interval = value.Get< float >();
385           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p CURSOR_BLINK_INTERVAL %f\n", impl.mController.Get(), interval );
386
387           impl.mDecorator->SetCursorBlinkInterval( interval );
388         }
389         break;
390       }
391       case Toolkit::TextField::Property::CURSOR_BLINK_DURATION:
392       {
393         if( impl.mDecorator )
394         {
395           float duration = value.Get< float >();
396           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p CURSOR_BLINK_INTERVAL %f\n", impl.mController.Get(), duration );
397
398           impl.mDecorator->SetCursorBlinkDuration( duration );
399         }
400         break;
401       }
402       case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE:
403       {
404         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
405         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p GRAB_HANDLE_IMAGE %s\n", impl.mController.Get(), image.GetUrl().c_str() );
406
407         if( impl.mDecorator )
408         {
409           impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED, image );
410         }
411         break;
412       }
413       case Toolkit::TextField::Property::GRAB_HANDLE_PRESSED_IMAGE:
414       {
415         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
416         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p GRAB_HANDLE_PRESSED_IMAGE %s\n", impl.mController.Get(), image.GetUrl().c_str() );
417
418         if( impl.mDecorator )
419         {
420           impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED, image );
421         }
422         break;
423       }
424       case Toolkit::TextField::Property::SCROLL_THRESHOLD:
425       {
426         float threshold = value.Get< float >();
427         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SCROLL_THRESHOLD %f\n", impl.mController.Get(), threshold );
428
429         if( impl.mDecorator )
430         {
431           impl.mDecorator->SetScrollThreshold( threshold );
432         }
433         break;
434       }
435       case Toolkit::TextField::Property::SCROLL_SPEED:
436       {
437         float speed = value.Get< float >();
438         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SCROLL_SPEED %f\n", impl.mController.Get(), speed );
439
440         if( impl.mDecorator )
441         {
442           impl.mDecorator->SetScrollSpeed( speed );
443         }
444         break;
445       }
446       case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_LEFT:
447       {
448         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
449         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SELECTION_HANDLE_IMAGE_LEFT %f\n", impl.mController.Get(), image.GetUrl().c_str() );
450
451         if( impl.mDecorator )
452         {
453           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image );
454         }
455         break;
456       }
457       case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT:
458       {
459         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
460         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SELECTION_HANDLE_IMAGE_RIGHT %f\n", impl.mController.Get(), image.GetUrl().c_str() );
461
462         if( impl.mDecorator )
463         {
464           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image );
465         }
466         break;
467       }
468       case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
469       {
470         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
471         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SELECTION_HANDLE_PRESSED_IMAGE_LEFT %f\n", impl.mController.Get(), image.GetUrl().c_str() );
472
473         if( impl.mDecorator )
474         {
475           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image );
476         }
477         break;
478       }
479       case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
480       {
481         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
482         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SELECTION_HANDLE_PRESSED_IMAGE_RIGHT %f\n", impl.mController.Get(), image.GetUrl().c_str() );
483
484         if( impl.mDecorator )
485         {
486           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image );
487         }
488         break;
489       }
490       case Toolkit::TextField::Property::SELECTION_HIGHLIGHT_COLOR:
491       {
492         Vector4 color = value.Get< Vector4 >();
493         DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SELECTION_HIGHLIGHT_COLOR %f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
494
495         if( impl.mDecorator )
496         {
497           impl.mDecorator->SetHighlightColor( color );
498         }
499         break;
500       }
501       case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX:
502       {
503         if( impl.mDecorator )
504         {
505           Rect<int> box = value.Get< Rect<int> >();
506           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p DECORATION_BOUNDING_BOX %d,%d %dx%d\n", impl.mController.Get(), box.x, box.y, box.width, box.height );
507
508           impl.mDecorator->SetBoundingBox( box );
509         }
510         break;
511       }
512       case Toolkit::TextField::Property::MAX_LENGTH:
513       {
514         if( impl.mController )
515         {
516           int max = value.Get< int >();
517           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p MAX_LENGTH %d\n", impl.mController.Get(), max );
518
519           impl.mController->SetMaximumNumberOfCharacters( max );
520         }
521         break;
522       }
523     } // switch
524   } // textfield
525 }
526
527 Property::Value TextField::GetProperty( BaseObject* object, Property::Index index )
528 {
529   Property::Value value;
530
531   Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) );
532
533   if( textField )
534   {
535     TextField& impl( GetImpl( textField ) );
536
537     switch( index )
538     {
539       case Toolkit::TextField::Property::RENDERING_BACKEND:
540       {
541         value = impl.mRenderingBackend;
542         break;
543       }
544       case Toolkit::TextField::Property::TEXT:
545       {
546         if( impl.mController )
547         {
548           std::string text;
549           impl.mController->GetText( text );
550           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p returning text: %s\n", impl.mController.Get(), text.c_str() );
551           value = text;
552         }
553         break;
554       }
555       case Toolkit::TextField::Property::PLACEHOLDER_TEXT:
556       {
557         if( impl.mController )
558         {
559           std::string text;
560           impl.mController->GetPlaceholderText( PLACEHOLDER_TYPE_INACTIVE, text );
561           value = text;
562         }
563         break;
564       }
565       case Toolkit::TextField::Property::PLACEHOLDER_TEXT_FOCUSED:
566       {
567         if( impl.mController )
568         {
569           std::string text;
570           impl.mController->GetPlaceholderText( PLACEHOLDER_TYPE_ACTIVE, text );
571           value = text;
572         }
573         break;
574       }
575       case Toolkit::TextField::Property::EXCEED_POLICY:
576       {
577         value = impl.mExceedPolicy;
578         break;
579       }
580       case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT:
581       {
582         if( impl.mController )
583         {
584           value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetLayoutEngine().GetHorizontalAlignment(),
585                                                                                                                   HORIZONTAL_ALIGNMENT_STRING_TABLE,
586                                                                                                                   HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ) );
587         }
588         break;
589       }
590       case Toolkit::TextField::Property::VERTICAL_ALIGNMENT:
591       {
592         if( impl.mController )
593         {
594           value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetLayoutEngine().GetVerticalAlignment(),
595                                                                                                                   VERTICAL_ALIGNMENT_STRING_TABLE,
596                                                                                                                   VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ) );
597         }
598         break;
599       }
600       case Toolkit::TextField::Property::TEXT_COLOR:
601       {
602         if ( impl.mController )
603         {
604           value = impl.mController->GetTextColor();
605         }
606         break;
607       }
608       case Toolkit::TextField::Property::PLACEHOLDER_TEXT_COLOR:
609       {
610         if ( impl.mController )
611         {
612           value = impl.mController->GetPlaceholderTextColor();
613         }
614         break;
615       }
616       case Toolkit::TextField::Property::SHADOW_OFFSET:
617       {
618         if ( impl.mController )
619         {
620           value = impl.mController->GetShadowOffset();
621         }
622         break;
623       }
624       case Toolkit::TextField::Property::SHADOW_COLOR:
625       {
626         if ( impl.mController )
627         {
628           value = impl.mController->GetShadowColor();
629         }
630         break;
631       }
632       case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR:
633       {
634         if( impl.mDecorator )
635         {
636           value = impl.mDecorator->GetColor( PRIMARY_CURSOR );
637         }
638         break;
639       }
640       case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR:
641       {
642         if( impl.mDecorator )
643         {
644           value = impl.mDecorator->GetColor( SECONDARY_CURSOR );
645         }
646         break;
647       }
648       case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK:
649       {
650         value = impl.mController->GetEnableCursorBlink();
651         break;
652       }
653       case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL:
654       {
655         if( impl.mDecorator )
656         {
657           value = impl.mDecorator->GetCursorBlinkInterval();
658         }
659         break;
660       }
661       case Toolkit::TextField::Property::CURSOR_BLINK_DURATION:
662       {
663         if( impl.mDecorator )
664         {
665           value = impl.mDecorator->GetCursorBlinkDuration();
666         }
667         break;
668       }
669       case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE:
670       {
671         if( impl.mDecorator )
672         {
673           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED ) );
674           if( image )
675           {
676             value = image.GetUrl();
677           }
678         }
679         break;
680       }
681       case Toolkit::TextField::Property::GRAB_HANDLE_PRESSED_IMAGE:
682       {
683         if( impl.mDecorator )
684         {
685           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED ) );
686           if( image )
687           {
688             value = image.GetUrl();
689           }
690         }
691         break;
692       }
693       case Toolkit::TextField::Property::SCROLL_THRESHOLD:
694       {
695         if( impl.mDecorator )
696         {
697           value = impl.mDecorator->GetScrollThreshold();
698         }
699         break;
700       }
701       case Toolkit::TextField::Property::SCROLL_SPEED:
702       {
703         if( impl.mDecorator )
704         {
705           value = impl.mDecorator->GetScrollSpeed();
706         }
707         break;
708       }
709       case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_LEFT:
710       {
711         if( impl.mDecorator )
712         {
713           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED ) );
714           if( image )
715           {
716             value = image.GetUrl();
717           }
718         }
719         break;
720       }
721       case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT:
722       {
723         if( impl.mDecorator )
724         {
725           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED ) );
726           if( image )
727           {
728             value = image.GetUrl();
729           }
730         }
731         break;
732       }
733       case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
734       {
735         if( impl.mDecorator )
736         {
737           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED ) );
738           if( image )
739           {
740             value = image.GetUrl();
741           }
742         }
743         break;
744       }
745       case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
746       {
747         if( impl.mDecorator )
748         {
749           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED ) );
750           if( image )
751           {
752             value = image.GetUrl();
753           }
754         }
755         break;
756       }
757       case Toolkit::TextField::Property::SELECTION_HIGHLIGHT_COLOR:
758       {
759         if( impl.mDecorator )
760         {
761           value = impl.mDecorator->GetHighlightColor();
762         }
763         break;
764       }
765       case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX:
766       {
767         if( impl.mDecorator )
768         {
769           value = impl.mDecorator->GetBoundingBox();
770         }
771         break;
772       }
773       case Toolkit::TextField::Property::MAX_LENGTH:
774       {
775         if( impl.mController )
776         {
777           value = impl.mController->GetMaximumNumberOfCharacters();
778         }
779         break;
780       }
781     } //switch
782   }
783
784   return value;
785 }
786
787 bool TextField::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
788 {
789   Dali::BaseHandle handle( object );
790
791   bool connected( true );
792   Toolkit::TextField field = Toolkit::TextField::DownCast( handle );
793
794   if( 0 == strcmp( signalName.c_str(), SIGNAL_MAX_LENGTH_REACHED ) )
795   {
796     field.MaxLengthReachedSignal().Connect( tracker, functor );
797   }
798   else
799   {
800     // signalName does not match any signal
801     connected = false;
802   }
803
804   return connected;
805 }
806
807 Toolkit::TextField::MaxLengthReachedSignalType& TextField::MaxLengthReachedSignal()
808 {
809   return mMaxLengthReachedSignal;
810 }
811
812 void TextField::OnInitialize()
813 {
814   Actor self = Self();
815
816   mController = Text::Controller::New( *this );
817
818   mDecorator = Text::Decorator::New( *this, *mController );
819
820   mController->GetLayoutEngine().SetLayout( LayoutEngine::SINGLE_LINE_BOX );
821
822   mController->EnableTextInput( mDecorator );
823
824   // Forward input events to controller
825   EnableGestureDetection(Gesture::Tap);
826   GetTapGestureDetector().SetMaximumTapsRequired( 2 );
827   EnableGestureDetection(Gesture::Pan);
828
829   // Set BoundingBox to stage size if not already set.
830   if ( mDecorator->GetBoundingBox().IsEmpty() )
831   {
832     Vector2 stageSize = Dali::Stage::GetCurrent().GetSize();
833     mDecorator->SetBoundingBox( Rect<int>( 0.0f, 0.0f, stageSize.width, stageSize.height ) );
834   }
835
836   // Fill-parent area by default
837   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
838   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
839 }
840
841 void TextField::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change )
842 {
843   GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
844 }
845
846 Vector3 TextField::GetNaturalSize()
847 {
848   return mController->GetNaturalSize();
849 }
850
851 float TextField::GetHeightForWidth( float width )
852 {
853   return mController->GetHeightForWidth( width );
854 }
855
856 void TextField::OnRelayout( const Vector2& size, RelayoutContainer& container )
857 {
858   if( mController->Relayout( size ) ||
859       !mRenderer )
860   {
861     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnRelayout %p Displaying new contents\n", mController.Get() );
862
863     if( mDecorator )
864     {
865       mDecorator->Relayout( size );
866     }
867
868     if( !mRenderer )
869     {
870       mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
871     }
872
873     RenderableActor renderableActor;
874     if( mRenderer )
875     {
876       renderableActor = mRenderer->Render( mController->GetView() );
877     }
878
879     EnableClipping( (Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == mExceedPolicy), size );
880
881     if( renderableActor != mRenderableActor )
882     {
883       UnparentAndReset( mRenderableActor );
884       mRenderableActor = renderableActor;
885     }
886
887     if( mRenderableActor )
888     {
889       const Vector2 offset = mController->GetScrollPosition() + mController->GetAlignmentOffset();
890
891       mRenderableActor.SetPosition( offset.x, offset.y );
892
893       // Make sure the actor is parented correctly with/without clipping
894       if( mClipper )
895       {
896         mClipper->GetRootActor().Add( mRenderableActor );
897       }
898       else
899       {
900         Self().Add( mRenderableActor );
901       }
902     }
903   }
904 }
905
906 void TextField::OnKeyInputFocusGained()
907 {
908   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnKeyInputFocusGained %p\n", mController.Get() );
909
910   VirtualKeyboard::StatusChangedSignal().Connect( this, &TextField::KeyboardStatusChanged );
911
912   ImfManager imfManager = ImfManager::Get();
913
914   if ( imfManager )
915   {
916     imfManager.EventReceivedSignal().Connect( this, &TextField::OnImfEvent );
917
918     // Notify that the text editing start.
919     imfManager.Activate();
920
921     // When window gain lost focus, the imf manager is deactivated. Thus when window gain focus again, the imf manager must be activated.
922     imfManager.SetRestoreAfterFocusLost( true );
923   }
924
925   mController->KeyboardFocusGainEvent();
926
927   EmitKeyInputFocusSignal( true ); // Calls back into the Control hence done last.
928 }
929
930 void TextField::OnKeyInputFocusLost()
931 {
932   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField:OnKeyInputFocusLost %p\n", mController.Get() );
933
934   VirtualKeyboard::StatusChangedSignal().Disconnect( this, &TextField::KeyboardStatusChanged );
935
936   ImfManager imfManager = ImfManager::Get();
937   if ( imfManager )
938   {
939     // The text editing is finished. Therefore the imf manager don't have restore activation.
940     imfManager.SetRestoreAfterFocusLost( false );
941
942     // Notify that the text editing finish.
943     imfManager.Deactivate();
944
945     imfManager.EventReceivedSignal().Disconnect( this, &TextField::OnImfEvent );
946   }
947
948   mController->KeyboardFocusLostEvent();
949
950   EmitKeyInputFocusSignal( false ); // Calls back into the Control hence done last.
951 }
952
953 void TextField::OnTap( const TapGesture& gesture )
954 {
955   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnTap %p\n", mController.Get() );
956
957   // Show the keyboard if it was hidden.
958   if (!VirtualKeyboard::IsVisible())
959   {
960     VirtualKeyboard::Show();
961   }
962
963   // Deliver the tap before the focus event to controller; this allows us to detect when focus is gained due to tap-gestures
964   mController->TapEvent( gesture.numberOfTaps, gesture.localPoint.x, gesture.localPoint.y );
965
966   SetKeyInputFocus();
967 }
968
969 void TextField::OnPan( const PanGesture& gesture )
970 {
971   mController->PanEvent( gesture.state, gesture.displacement );
972 }
973
974 bool TextField::OnKeyEvent( const KeyEvent& event )
975 {
976   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnKeyEvent %p keyCode %d\n", mController.Get(), event.keyCode );
977
978   if( Dali::DALI_KEY_ESCAPE == event.keyCode ||
979       "Return" == event.keyPressedName ) // Make a Dali key code for this
980   {
981     ClearKeyInputFocus();
982     return true;
983   }
984
985   return mController->KeyEvent( event );
986 }
987
988 ImfManager::ImfCallbackData TextField::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
989 {
990   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnImfEvent %p eventName %d\n", mController.Get(), imfEvent.eventName );
991
992   bool update( false );
993
994   std::string text;
995   unsigned int cursorPosition( 0 );
996
997   switch ( imfEvent.eventName )
998   {
999     case ImfManager::COMMIT:
1000     {
1001       mController->InsertText( imfEvent.predictiveString, Text::Controller::COMMIT );
1002       break;
1003     }
1004     case ImfManager::PREEDIT:
1005     {
1006       mController->InsertText( imfEvent.predictiveString, Text::Controller::PRE_EDIT );
1007       update = true;
1008       break;
1009     }
1010     case ImfManager::DELETESURROUNDING:
1011     {
1012       mController->RemoveText( imfEvent.cursorOffset, imfEvent.numberOfChars );
1013       break;
1014     }
1015     case ImfManager::GETSURROUNDING:
1016     {
1017       mController->GetText( text );
1018       cursorPosition = mController->GetLogicalCursorPosition();
1019
1020       imfManager.SetSurroundingText( text );
1021       imfManager.SetCursorPosition( cursorPosition );
1022       break;
1023     }
1024     case ImfManager::VOID:
1025     {
1026       // do nothing
1027       break;
1028     }
1029   } // end switch
1030
1031   if( ImfManager::GETSURROUNDING != imfEvent.eventName )
1032   {
1033     mController->GetText( text );
1034     cursorPosition = mController->GetLogicalCursorPosition();
1035   }
1036
1037   ImfManager::ImfCallbackData callbackData( update, cursorPosition, text, false );
1038
1039   return callbackData;
1040 }
1041
1042 void TextField::RequestTextRelayout()
1043 {
1044   RelayoutRequest();
1045 }
1046
1047 void TextField::MaxLengthReached()
1048 {
1049   Dali::Toolkit::TextField handle( GetOwner() );
1050   mMaxLengthReachedSignal.Emit( handle );
1051 }
1052
1053 void TextField::EnableClipping( bool clipping, const Vector2& size )
1054 {
1055   if( clipping )
1056   {
1057     // Not worth to created clip actor if width or height is equal to zero.
1058     if( size.width > Math::MACHINE_EPSILON_1000 && size.height > Math::MACHINE_EPSILON_1000 )
1059     {
1060       if( !mClipper )
1061       {
1062         Actor self = Self();
1063
1064         mClipper = Clipper::New( size );
1065         self.Add( mClipper->GetRootActor() );
1066         self.Add( mClipper->GetImageActor() );
1067       }
1068       else if ( mClipper )
1069       {
1070         mClipper->Refresh( size );
1071       }
1072     }
1073   }
1074   else
1075   {
1076     // Note - this will automatically remove the root & image actors
1077     mClipper.Reset();
1078   }
1079 }
1080
1081 void TextField::KeyboardStatusChanged(bool keyboardShown)
1082 {
1083   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::KeyboardStatusChanged %p keyboardShown %d\n", mController.Get(), keyboardShown );
1084
1085   // Just hide the grab handle when keyboard is hidden.
1086   if (!keyboardShown )
1087   {
1088     mController->KeyboardFocusLostEvent();
1089   }
1090 }
1091
1092 TextField::TextField()
1093 : Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
1094   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
1095   mExceedPolicy( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP )
1096 {
1097 }
1098
1099 TextField::~TextField()
1100 {
1101   mClipper.Reset();
1102 }
1103
1104 } // namespace Internal
1105
1106 } // namespace Toolkit
1107
1108 } // namespace Dali