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