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