Call VirtualKeyboard ApplySettings
[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         Property::Map map = value.Get<Property::Map>();
528         VirtualKeyboard::ApplySettings( map );
529         break;
530       }
531     } // switch
532   } // textfield
533 }
534
535 Property::Value TextField::GetProperty( BaseObject* object, Property::Index index )
536 {
537   Property::Value value;
538
539   Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) );
540
541   if( textField )
542   {
543     TextField& impl( GetImpl( textField ) );
544
545     switch( index )
546     {
547       case Toolkit::TextField::Property::RENDERING_BACKEND:
548       {
549         value = impl.mRenderingBackend;
550         break;
551       }
552       case Toolkit::TextField::Property::TEXT:
553       {
554         if( impl.mController )
555         {
556           std::string text;
557           impl.mController->GetText( text );
558           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p returning text: %s\n", impl.mController.Get(), text.c_str() );
559           value = text;
560         }
561         break;
562       }
563       case Toolkit::TextField::Property::PLACEHOLDER_TEXT:
564       {
565         if( impl.mController )
566         {
567           std::string text;
568           impl.mController->GetPlaceholderText( PLACEHOLDER_TYPE_INACTIVE, text );
569           value = text;
570         }
571         break;
572       }
573       case Toolkit::TextField::Property::PLACEHOLDER_TEXT_FOCUSED:
574       {
575         if( impl.mController )
576         {
577           std::string text;
578           impl.mController->GetPlaceholderText( PLACEHOLDER_TYPE_ACTIVE, text );
579           value = text;
580         }
581         break;
582       }
583       case Toolkit::TextField::Property::EXCEED_POLICY:
584       {
585         value = impl.mExceedPolicy;
586         break;
587       }
588       case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT:
589       {
590         if( impl.mController )
591         {
592           value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetLayoutEngine().GetHorizontalAlignment(),
593                                                                                                                   HORIZONTAL_ALIGNMENT_STRING_TABLE,
594                                                                                                                   HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ) );
595         }
596         break;
597       }
598       case Toolkit::TextField::Property::VERTICAL_ALIGNMENT:
599       {
600         if( impl.mController )
601         {
602           value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetLayoutEngine().GetVerticalAlignment(),
603                                                                                                                   VERTICAL_ALIGNMENT_STRING_TABLE,
604                                                                                                                   VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ) );
605         }
606         break;
607       }
608       case Toolkit::TextField::Property::TEXT_COLOR:
609       {
610         if ( impl.mController )
611         {
612           value = impl.mController->GetTextColor();
613         }
614         break;
615       }
616       case Toolkit::TextField::Property::PLACEHOLDER_TEXT_COLOR:
617       {
618         if ( impl.mController )
619         {
620           value = impl.mController->GetPlaceholderTextColor();
621         }
622         break;
623       }
624       case Toolkit::TextField::Property::SHADOW_OFFSET:
625       {
626         if ( impl.mController )
627         {
628           value = impl.mController->GetShadowOffset();
629         }
630         break;
631       }
632       case Toolkit::TextField::Property::SHADOW_COLOR:
633       {
634         if ( impl.mController )
635         {
636           value = impl.mController->GetShadowColor();
637         }
638         break;
639       }
640       case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR:
641       {
642         if( impl.mDecorator )
643         {
644           value = impl.mDecorator->GetColor( PRIMARY_CURSOR );
645         }
646         break;
647       }
648       case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR:
649       {
650         if( impl.mDecorator )
651         {
652           value = impl.mDecorator->GetColor( SECONDARY_CURSOR );
653         }
654         break;
655       }
656       case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK:
657       {
658         value = impl.mController->GetEnableCursorBlink();
659         break;
660       }
661       case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL:
662       {
663         if( impl.mDecorator )
664         {
665           value = impl.mDecorator->GetCursorBlinkInterval();
666         }
667         break;
668       }
669       case Toolkit::TextField::Property::CURSOR_BLINK_DURATION:
670       {
671         if( impl.mDecorator )
672         {
673           value = impl.mDecorator->GetCursorBlinkDuration();
674         }
675         break;
676       }
677       case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE:
678       {
679         if( impl.mDecorator )
680         {
681           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED ) );
682           if( image )
683           {
684             value = image.GetUrl();
685           }
686         }
687         break;
688       }
689       case Toolkit::TextField::Property::GRAB_HANDLE_PRESSED_IMAGE:
690       {
691         if( impl.mDecorator )
692         {
693           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED ) );
694           if( image )
695           {
696             value = image.GetUrl();
697           }
698         }
699         break;
700       }
701       case Toolkit::TextField::Property::SCROLL_THRESHOLD:
702       {
703         if( impl.mDecorator )
704         {
705           value = impl.mDecorator->GetScrollThreshold();
706         }
707         break;
708       }
709       case Toolkit::TextField::Property::SCROLL_SPEED:
710       {
711         if( impl.mDecorator )
712         {
713           value = impl.mDecorator->GetScrollSpeed();
714         }
715         break;
716       }
717       case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_LEFT:
718       {
719         if( impl.mDecorator )
720         {
721           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED ) );
722           if( image )
723           {
724             value = image.GetUrl();
725           }
726         }
727         break;
728       }
729       case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT:
730       {
731         if( impl.mDecorator )
732         {
733           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED ) );
734           if( image )
735           {
736             value = image.GetUrl();
737           }
738         }
739         break;
740       }
741       case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
742       {
743         if( impl.mDecorator )
744         {
745           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED ) );
746           if( image )
747           {
748             value = image.GetUrl();
749           }
750         }
751         break;
752       }
753       case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
754       {
755         if( impl.mDecorator )
756         {
757           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED ) );
758           if( image )
759           {
760             value = image.GetUrl();
761           }
762         }
763         break;
764       }
765       case Toolkit::TextField::Property::SELECTION_HIGHLIGHT_COLOR:
766       {
767         if( impl.mDecorator )
768         {
769           value = impl.mDecorator->GetHighlightColor();
770         }
771         break;
772       }
773       case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX:
774       {
775         if( impl.mDecorator )
776         {
777           value = impl.mDecorator->GetBoundingBox();
778         }
779         break;
780       }
781       case Toolkit::TextField::Property::MAX_LENGTH:
782       {
783         if( impl.mController )
784         {
785           value = impl.mController->GetMaximumNumberOfCharacters();
786         }
787         break;
788       }
789       case Toolkit::TextField::Property::INPUT_METHOD_SETTINGS:
790       {
791         break;
792       }
793     } //switch
794   }
795
796   return value;
797 }
798
799 bool TextField::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
800 {
801   Dali::BaseHandle handle( object );
802
803   bool connected( true );
804   Toolkit::TextField field = Toolkit::TextField::DownCast( handle );
805
806   if( 0 == strcmp( signalName.c_str(), SIGNAL_MAX_LENGTH_REACHED ) )
807   {
808     field.MaxLengthReachedSignal().Connect( tracker, functor );
809   }
810   else
811   {
812     // signalName does not match any signal
813     connected = false;
814   }
815
816   return connected;
817 }
818
819 Toolkit::TextField::MaxLengthReachedSignalType& TextField::MaxLengthReachedSignal()
820 {
821   return mMaxLengthReachedSignal;
822 }
823
824 void TextField::OnInitialize()
825 {
826   Actor self = Self();
827
828   mController = Text::Controller::New( *this );
829
830   mDecorator = Text::Decorator::New( *this, *mController );
831
832   mController->GetLayoutEngine().SetLayout( LayoutEngine::SINGLE_LINE_BOX );
833
834   mController->EnableTextInput( mDecorator );
835
836   // Forward input events to controller
837   EnableGestureDetection(Gesture::Tap);
838   GetTapGestureDetector().SetMaximumTapsRequired( 2 );
839   EnableGestureDetection(Gesture::Pan);
840
841   // Set BoundingBox to stage size if not already set.
842   if ( mDecorator->GetBoundingBox().IsEmpty() )
843   {
844     Vector2 stageSize = Dali::Stage::GetCurrent().GetSize();
845     mDecorator->SetBoundingBox( Rect<int>( 0.0f, 0.0f, stageSize.width, stageSize.height ) );
846   }
847
848   // Fill-parent area by default
849   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
850   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
851 }
852
853 void TextField::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
854 {
855   GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
856 }
857
858 Vector3 TextField::GetNaturalSize()
859 {
860   return mController->GetNaturalSize();
861 }
862
863 float TextField::GetHeightForWidth( float width )
864 {
865   return mController->GetHeightForWidth( width );
866 }
867
868 void TextField::OnRelayout( const Vector2& size, RelayoutContainer& container )
869 {
870   if( mController->Relayout( size ) ||
871       !mRenderer )
872   {
873     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnRelayout %p Displaying new contents\n", mController.Get() );
874
875     if( mDecorator )
876     {
877       mDecorator->Relayout( size );
878     }
879
880     if( !mRenderer )
881     {
882       mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
883     }
884
885     RenderableActor renderableActor;
886     if( mRenderer )
887     {
888       renderableActor = mRenderer->Render( mController->GetView() );
889     }
890
891     EnableClipping( (Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == mExceedPolicy), size );
892
893     if( renderableActor != mRenderableActor )
894     {
895       UnparentAndReset( mRenderableActor );
896       mRenderableActor = renderableActor;
897     }
898
899     if( mRenderableActor )
900     {
901       const Vector2 offset = mController->GetScrollPosition() + mController->GetAlignmentOffset();
902
903       mRenderableActor.SetPosition( offset.x, offset.y );
904
905       // Make sure the actor is parented correctly with/without clipping
906       if( mClipper )
907       {
908         mClipper->GetRootActor().Add( mRenderableActor );
909       }
910       else
911       {
912         Self().Add( mRenderableActor );
913       }
914     }
915   }
916 }
917
918 void TextField::OnKeyInputFocusGained()
919 {
920   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnKeyInputFocusGained %p\n", mController.Get() );
921
922   VirtualKeyboard::StatusChangedSignal().Connect( this, &TextField::KeyboardStatusChanged );
923
924   ImfManager imfManager = ImfManager::Get();
925
926   if ( imfManager )
927   {
928     imfManager.EventReceivedSignal().Connect( this, &TextField::OnImfEvent );
929
930     // Notify that the text editing start.
931     imfManager.Activate();
932
933     // When window gain lost focus, the imf manager is deactivated. Thus when window gain focus again, the imf manager must be activated.
934     imfManager.SetRestoreAfterFocusLost( true );
935   }
936
937   mController->KeyboardFocusGainEvent();
938
939   EmitKeyInputFocusSignal( true ); // Calls back into the Control hence done last.
940 }
941
942 void TextField::OnKeyInputFocusLost()
943 {
944   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField:OnKeyInputFocusLost %p\n", mController.Get() );
945
946   VirtualKeyboard::StatusChangedSignal().Disconnect( this, &TextField::KeyboardStatusChanged );
947
948   ImfManager imfManager = ImfManager::Get();
949   if ( imfManager )
950   {
951     // The text editing is finished. Therefore the imf manager don't have restore activation.
952     imfManager.SetRestoreAfterFocusLost( false );
953
954     // Notify that the text editing finish.
955     imfManager.Deactivate();
956
957     imfManager.EventReceivedSignal().Disconnect( this, &TextField::OnImfEvent );
958   }
959
960   mController->KeyboardFocusLostEvent();
961
962   EmitKeyInputFocusSignal( false ); // Calls back into the Control hence done last.
963 }
964
965 void TextField::OnTap( const TapGesture& gesture )
966 {
967   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnTap %p\n", mController.Get() );
968
969   // Show the keyboard if it was hidden.
970   if (!VirtualKeyboard::IsVisible())
971   {
972     VirtualKeyboard::Show();
973   }
974
975   // Deliver the tap before the focus event to controller; this allows us to detect when focus is gained due to tap-gestures
976   mController->TapEvent( gesture.numberOfTaps, gesture.localPoint.x, gesture.localPoint.y );
977
978   SetKeyInputFocus();
979 }
980
981 void TextField::OnPan( const PanGesture& gesture )
982 {
983   mController->PanEvent( gesture.state, gesture.displacement );
984 }
985
986 bool TextField::OnKeyEvent( const KeyEvent& event )
987 {
988   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnKeyEvent %p keyCode %d\n", mController.Get(), event.keyCode );
989
990   if( Dali::DALI_KEY_ESCAPE == event.keyCode ||
991       "Return" == event.keyPressedName ) // Make a Dali key code for this
992   {
993     ClearKeyInputFocus();
994     return true;
995   }
996
997   return mController->KeyEvent( event );
998 }
999
1000 ImfManager::ImfCallbackData TextField::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
1001 {
1002   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnImfEvent %p eventName %d\n", mController.Get(), imfEvent.eventName );
1003
1004   bool update( false );
1005
1006   std::string text;
1007   unsigned int cursorPosition( 0 );
1008
1009   switch ( imfEvent.eventName )
1010   {
1011     case ImfManager::COMMIT:
1012     {
1013       mController->InsertText( imfEvent.predictiveString, Text::Controller::COMMIT );
1014       break;
1015     }
1016     case ImfManager::PREEDIT:
1017     {
1018       mController->InsertText( imfEvent.predictiveString, Text::Controller::PRE_EDIT );
1019       update = true;
1020       break;
1021     }
1022     case ImfManager::DELETESURROUNDING:
1023     {
1024       mController->RemoveText( imfEvent.cursorOffset, imfEvent.numberOfChars );
1025       break;
1026     }
1027     case ImfManager::GETSURROUNDING:
1028     {
1029       mController->GetText( text );
1030       cursorPosition = mController->GetLogicalCursorPosition();
1031
1032       imfManager.SetSurroundingText( text );
1033       imfManager.SetCursorPosition( cursorPosition );
1034       break;
1035     }
1036     case ImfManager::VOID:
1037     {
1038       // do nothing
1039       break;
1040     }
1041   } // end switch
1042
1043   if( ImfManager::GETSURROUNDING != imfEvent.eventName )
1044   {
1045     mController->GetText( text );
1046     cursorPosition = mController->GetLogicalCursorPosition();
1047   }
1048
1049   ImfManager::ImfCallbackData callbackData( update, cursorPosition, text, false );
1050
1051   return callbackData;
1052 }
1053
1054 void TextField::RequestTextRelayout()
1055 {
1056   RelayoutRequest();
1057 }
1058
1059 void TextField::MaxLengthReached()
1060 {
1061   Dali::Toolkit::TextField handle( GetOwner() );
1062   mMaxLengthReachedSignal.Emit( handle );
1063 }
1064
1065 void TextField::EnableClipping( bool clipping, const Vector2& size )
1066 {
1067   if( clipping )
1068   {
1069     // Not worth to created clip actor if width or height is equal to zero.
1070     if( size.width > Math::MACHINE_EPSILON_1000 && size.height > Math::MACHINE_EPSILON_1000 )
1071     {
1072       if( !mClipper )
1073       {
1074         Actor self = Self();
1075
1076         mClipper = Clipper::New( size );
1077         self.Add( mClipper->GetRootActor() );
1078         self.Add( mClipper->GetImageActor() );
1079       }
1080       else if ( mClipper )
1081       {
1082         mClipper->Refresh( size );
1083       }
1084     }
1085   }
1086   else
1087   {
1088     // Note - this will automatically remove the root & image actors
1089     mClipper.Reset();
1090   }
1091 }
1092
1093 void TextField::KeyboardStatusChanged(bool keyboardShown)
1094 {
1095   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::KeyboardStatusChanged %p keyboardShown %d\n", mController.Get(), keyboardShown );
1096
1097   // Just hide the grab handle when keyboard is hidden.
1098   if (!keyboardShown )
1099   {
1100     mController->KeyboardFocusLostEvent();
1101   }
1102 }
1103
1104 TextField::TextField()
1105 : Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
1106   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
1107   mExceedPolicy( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP )
1108 {
1109 }
1110
1111 TextField::~TextField()
1112 {
1113   mClipper.Reset();
1114 }
1115
1116 } // namespace Internal
1117
1118 } // namespace Toolkit
1119
1120 } // namespace Dali