Merge "Encapsulated visual URL in new VisualUrl class." into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-field-impl.cpp
1 /*
2  * Copyright (c) 2017 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 <cstring>
23 #include <dali/public-api/adaptor-framework/key.h>
24 #include <dali/public-api/common/stage.h>
25 #include <dali/public-api/images/resource-image.h>
26 #include <dali/public-api/object/type-registry-helper.h>
27 #include <dali/integration-api/adaptors/adaptor.h>
28 #include <dali/integration-api/debug.h>
29
30 // INTERNAL INCLUDES
31 #include <dali-toolkit/public-api/text/rendering-backend.h>
32 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
33 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
34 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
35 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
36 #include <dali-toolkit/internal/text/rendering/text-backend.h>
37 #include <dali-toolkit/internal/text/text-effects-style.h>
38 #include <dali-toolkit/internal/text/text-font-style.h>
39 #include <dali-toolkit/internal/text/text-view.h>
40 #include <dali-toolkit/internal/styling/style-manager-impl.h>
41
42 using namespace Dali::Toolkit::Text;
43
44 namespace Dali
45 {
46
47 namespace Toolkit
48 {
49
50 namespace Internal
51 {
52
53 namespace // unnamed namespace
54 {
55
56 #if defined(DEBUG_ENABLED)
57   Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS");
58 #endif
59
60   const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
61 } // unnamed namespace
62
63 namespace
64 {
65
66 const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
67 {
68   { "BEGIN",  Toolkit::Text::Layout::HORIZONTAL_ALIGN_BEGIN  },
69   { "CENTER", Toolkit::Text::Layout::HORIZONTAL_ALIGN_CENTER },
70   { "END",    Toolkit::Text::Layout::HORIZONTAL_ALIGN_END    },
71 };
72 const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] );
73
74 const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] =
75 {
76   { "TOP",    Toolkit::Text::Layout::VERTICAL_ALIGN_TOP    },
77   { "CENTER", Toolkit::Text::Layout::VERTICAL_ALIGN_CENTER },
78   { "BOTTOM", Toolkit::Text::Layout::VERTICAL_ALIGN_BOTTOM },
79 };
80 const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( VERTICAL_ALIGNMENT_STRING_TABLE ) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] );
81
82 // Type registration
83 BaseHandle Create()
84 {
85   return Toolkit::TextField::New();
86 }
87
88 // Setup properties, signals and actions using the type-registry.
89 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextField, Toolkit::Control, Create );
90
91 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "renderingBackend",                     INTEGER,   RENDERING_BACKEND                    )
92 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "text",                                 STRING,    TEXT                                 )
93 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "placeholderText",                      STRING,    PLACEHOLDER_TEXT                     )
94 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "placeholderTextFocused",               STRING,    PLACEHOLDER_TEXT_FOCUSED             )
95 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "fontFamily",                           STRING,    FONT_FAMILY                          )
96 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "fontStyle",                            MAP,       FONT_STYLE                           )
97 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "pointSize",                            FLOAT,     POINT_SIZE                           )
98 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "maxLength",                            INTEGER,   MAX_LENGTH                           )
99 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "exceedPolicy",                         INTEGER,   EXCEED_POLICY                        )
100 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "horizontalAlignment",                  STRING,    HORIZONTAL_ALIGNMENT                 )
101 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "verticalAlignment",                    STRING,    VERTICAL_ALIGNMENT                   )
102 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "textColor",                            VECTOR4,   TEXT_COLOR                           )
103 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "placeholderTextColor",                 VECTOR4,   PLACEHOLDER_TEXT_COLOR               )
104 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "shadowOffset",                         VECTOR2,   SHADOW_OFFSET                        )
105 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "shadowColor",                          VECTOR4,   SHADOW_COLOR                         )
106 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "primaryCursorColor",                   VECTOR4,   PRIMARY_CURSOR_COLOR                 )
107 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "secondaryCursorColor",                 VECTOR4,   SECONDARY_CURSOR_COLOR               )
108 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "enableCursorBlink",                    BOOLEAN,   ENABLE_CURSOR_BLINK                  )
109 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "cursorBlinkInterval",                  FLOAT,     CURSOR_BLINK_INTERVAL                )
110 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "cursorBlinkDuration",                  FLOAT,     CURSOR_BLINK_DURATION                )
111 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "cursorWidth",                          INTEGER,   CURSOR_WIDTH                         )
112 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "grabHandleImage",                      STRING,    GRAB_HANDLE_IMAGE                    )
113 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "grabHandlePressedImage",               STRING,    GRAB_HANDLE_PRESSED_IMAGE            )
114 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "scrollThreshold",                      FLOAT,     SCROLL_THRESHOLD                     )
115 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "scrollSpeed",                          FLOAT,     SCROLL_SPEED                         )
116 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selectionHandleImageLeft",             MAP,       SELECTION_HANDLE_IMAGE_LEFT          )
117 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selectionHandleImageRight",            MAP,       SELECTION_HANDLE_IMAGE_RIGHT         )
118 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selectionHandlePressedImageLeft",      MAP,       SELECTION_HANDLE_PRESSED_IMAGE_LEFT  )
119 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selectionHandlePressedImageRight",     MAP,       SELECTION_HANDLE_PRESSED_IMAGE_RIGHT )
120 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selectionHandleMarkerImageLeft",       MAP,       SELECTION_HANDLE_MARKER_IMAGE_LEFT   )
121 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selectionHandleMarkerImageRight",      MAP,       SELECTION_HANDLE_MARKER_IMAGE_RIGHT  )
122 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selectionHighlightColor",              VECTOR4,   SELECTION_HIGHLIGHT_COLOR            )
123 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "decorationBoundingBox",                RECTANGLE, DECORATION_BOUNDING_BOX              )
124 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputMethodSettings",                  MAP,       INPUT_METHOD_SETTINGS                )
125 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputColor",                           VECTOR4,   INPUT_COLOR                          )
126 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "enableMarkup",                         BOOLEAN,   ENABLE_MARKUP                        )
127 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputFontFamily",                      STRING,    INPUT_FONT_FAMILY                    )
128 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputFontStyle",                       MAP,       INPUT_FONT_STYLE                     )
129 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputPointSize",                       FLOAT,     INPUT_POINT_SIZE                     )
130 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "underline",                            MAP,       UNDERLINE                            )
131 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputUnderline",                       MAP,       INPUT_UNDERLINE                      )
132 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "shadow",                               MAP,       SHADOW                               )
133 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputShadow",                          MAP,       INPUT_SHADOW                         )
134 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "emboss",                               MAP,       EMBOSS                               )
135 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputEmboss",                          MAP,       INPUT_EMBOSS                         )
136 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "outline",                              MAP,       OUTLINE                              )
137 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputOutline",                         MAP,       INPUT_OUTLINE                        )
138
139 DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "textChanged",        SIGNAL_TEXT_CHANGED )
140 DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "maxLengthReached",   SIGNAL_MAX_LENGTH_REACHED )
141 DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "inputStyleChanged",  SIGNAL_INPUT_STYLE_CHANGED )
142
143 DALI_TYPE_REGISTRATION_END()
144
145 } // namespace
146
147 Toolkit::TextField TextField::New()
148 {
149   // Create the implementation, temporarily owned by this handle on stack
150   IntrusivePtr< TextField > impl = new TextField();
151
152   // Pass ownership to CustomActor handle
153   Toolkit::TextField handle( *impl );
154
155   // Second-phase init of the implementation
156   // This can only be done after the CustomActor connection has been made...
157   impl->Initialize();
158
159   return handle;
160 }
161
162 void TextField::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
163 {
164   Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) );
165
166   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField SetProperty\n");
167
168
169   if( textField )
170   {
171     TextField& impl( GetImpl( textField ) );
172
173     switch( index )
174     {
175       case Toolkit::TextField::Property::RENDERING_BACKEND:
176       {
177         int backend = value.Get< int >();
178         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p RENDERING_BACKEND %d\n", impl.mController.Get(), backend );
179
180 #ifndef ENABLE_VECTOR_BASED_TEXT_RENDERING
181         if( Text::RENDERING_VECTOR_BASED == backend )
182         {
183           backend = TextAbstraction::BITMAP_GLYPH; // Fallback to bitmap-based rendering
184         }
185 #endif
186         if( impl.mRenderingBackend != backend )
187         {
188           impl.mRenderingBackend = backend;
189           impl.mRenderer.Reset();
190
191           if( impl.mController )
192           {
193             // When using the vector-based rendering, the size of the GLyphs are different
194             TextAbstraction::GlyphType glyphType = (Text::RENDERING_VECTOR_BASED == impl.mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH;
195             impl.mController->SetGlyphType( glyphType );
196           }
197         }
198         break;
199       }
200       case Toolkit::TextField::Property::TEXT:
201       {
202         if( impl.mController )
203         {
204           const std::string& text = value.Get< std::string >();
205           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p TEXT %s\n", impl.mController.Get(), text.c_str() );
206
207           impl.mController->SetText( text );
208         }
209         break;
210       }
211       case Toolkit::TextField::Property::PLACEHOLDER_TEXT:
212       {
213         if( impl.mController )
214         {
215           const std::string& text = value.Get< std::string >();
216           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT %s\n", impl.mController.Get(), text.c_str() );
217
218           impl.mController->SetPlaceholderText( Controller::PLACEHOLDER_TYPE_INACTIVE, text );
219         }
220         break;
221       }
222       case Toolkit::TextField::Property::PLACEHOLDER_TEXT_FOCUSED:
223       {
224         if( impl.mController )
225         {
226           const std::string& text = value.Get< std::string >();
227           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT_FOCUSED %s\n", impl.mController.Get(), text.c_str() );
228
229           impl.mController->SetPlaceholderText( Controller::PLACEHOLDER_TYPE_ACTIVE, text );
230         }
231         break;
232       }
233       case Toolkit::TextField::Property::FONT_FAMILY:
234       {
235         if( impl.mController )
236         {
237           const std::string& fontFamily = value.Get< std::string >();
238           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str() );
239           impl.mController->SetDefaultFontFamily( fontFamily );
240         }
241         break;
242       }
243       case Toolkit::TextField::Property::FONT_STYLE:
244       {
245         SetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT );
246         break;
247       }
248       case Toolkit::TextField::Property::POINT_SIZE:
249       {
250         if( impl.mController )
251         {
252           const float pointSize = value.Get< float >();
253           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p POINT_SIZE %f\n", impl.mController.Get(), pointSize );
254
255           if( !Equals( impl.mController->GetDefaultPointSize(), pointSize ) )
256           {
257             impl.mController->SetDefaultPointSize( pointSize );
258           }
259         }
260         break;
261       }
262       case Toolkit::TextField::Property::MAX_LENGTH:
263       {
264         if( impl.mController )
265         {
266           const int max = value.Get< int >();
267           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p MAX_LENGTH %d\n", impl.mController.Get(), max );
268
269           impl.mController->SetMaximumNumberOfCharacters( max );
270         }
271         break;
272       }
273       case Toolkit::TextField::Property::EXCEED_POLICY:
274       {
275         impl.mExceedPolicy = value.Get<int>();
276
277         if( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == impl.mExceedPolicy )
278         {
279           impl.EnableClipping();
280         }
281         else
282         {
283           UnparentAndReset( impl.mStencil );
284         }
285         impl.RequestTextRelayout();
286         break;
287       }
288       case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT:
289       {
290         if( impl.mController )
291         {
292           const std::string& alignStr = value.Get< std::string >();
293           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p HORIZONTAL_ALIGNMENT %s\n", impl.mController.Get(), alignStr.c_str() );
294
295           Layout::HorizontalAlignment alignment( Layout::HORIZONTAL_ALIGN_BEGIN );
296           if( Scripting::GetEnumeration< Layout::HorizontalAlignment >( alignStr.c_str(),
297                                                                         HORIZONTAL_ALIGNMENT_STRING_TABLE,
298                                                                         HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
299                                                                         alignment ) )
300           {
301             impl.mController->SetHorizontalAlignment( alignment );
302           }
303         }
304         break;
305       }
306       case Toolkit::TextField::Property::VERTICAL_ALIGNMENT:
307       {
308         if( impl.mController )
309         {
310           const std::string& alignStr = value.Get< std::string >();
311           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p VERTICAL_ALIGNMENT %s\n", impl.mController.Get(), alignStr.c_str() );
312
313           Layout::VerticalAlignment alignment( Layout::VERTICAL_ALIGN_BOTTOM );
314           if( Scripting::GetEnumeration< Layout::VerticalAlignment >( alignStr.c_str(),
315                                                                       VERTICAL_ALIGNMENT_STRING_TABLE,
316                                                                       VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
317                                                                       alignment ) )
318           {
319             impl.mController->SetVerticalAlignment( alignment );
320           }
321         }
322         break;
323       }
324       case Toolkit::TextField::Property::TEXT_COLOR:
325       {
326         if( impl.mController )
327         {
328           const Vector4& textColor = value.Get< Vector4 >();
329           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 );
330
331           if( impl.mController->GetDefaultColor() != textColor )
332           {
333             impl.mController->SetDefaultColor( textColor );
334             impl.mController->SetInputColor( textColor );
335             impl.mRenderer.Reset();
336           }
337         }
338         break;
339       }
340       case Toolkit::TextField::Property::PLACEHOLDER_TEXT_COLOR:
341       {
342         if( impl.mController )
343         {
344           const Vector4& textColor = value.Get< Vector4 >();
345           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 );
346
347           if( impl.mController->GetPlaceholderTextColor() != textColor )
348           {
349             impl.mController->SetPlaceholderTextColor( textColor );
350             impl.mRenderer.Reset();
351           }
352         }
353         break;
354       }
355       case Toolkit::TextField::Property::SHADOW_OFFSET:
356       {
357         if( impl.mController )
358         {
359           const Vector2& shadowOffset = value.Get< Vector2 >();
360           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SHADOW_OFFSET %f,%f\n", impl.mController.Get(), shadowOffset.x, shadowOffset.y );
361
362           if ( impl.mController->GetShadowOffset() != shadowOffset )
363           {
364             impl.mController->SetShadowOffset( shadowOffset );
365             impl.mRenderer.Reset();
366           }
367         }
368         break;
369       }
370       case Toolkit::TextField::Property::SHADOW_COLOR:
371       {
372         if( impl.mController )
373         {
374           const Vector4& shadowColor = value.Get< Vector4 >();
375           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 );
376
377           if ( impl.mController->GetShadowColor() != shadowColor )
378           {
379             impl.mController->SetShadowColor( shadowColor );
380             impl.mRenderer.Reset();
381           }
382         }
383         break;
384       }
385       case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR:
386       {
387         if( impl.mDecorator )
388         {
389           const Vector4& color = value.Get< Vector4 >();
390           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p PRIMARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
391
392           impl.mDecorator->SetCursorColor( PRIMARY_CURSOR, color );
393           impl.RequestTextRelayout();
394         }
395         break;
396       }
397       case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR:
398       {
399         if( impl.mDecorator )
400         {
401           const Vector4& color = value.Get< Vector4 >();
402           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SECONDARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
403
404           impl.mDecorator->SetCursorColor( SECONDARY_CURSOR, color );
405           impl.RequestTextRelayout();
406         }
407         break;
408       }
409       case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK:
410       {
411         if( impl.mController )
412         {
413           const bool enable = value.Get< bool >();
414           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p ENABLE_CURSOR_BLINK %d\n", impl.mController.Get(), enable );
415
416           impl.mController->SetEnableCursorBlink( enable );
417           impl.RequestTextRelayout();
418         }
419         break;
420       }
421       case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL:
422       {
423         if( impl.mDecorator )
424         {
425           const float interval = value.Get< float >();
426           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p CURSOR_BLINK_INTERVAL %f\n", impl.mController.Get(), interval );
427
428           impl.mDecorator->SetCursorBlinkInterval( interval );
429         }
430         break;
431       }
432       case Toolkit::TextField::Property::CURSOR_BLINK_DURATION:
433       {
434         if( impl.mDecorator )
435         {
436           const float duration = value.Get< float >();
437           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p CURSOR_BLINK_DURATION %f\n", impl.mController.Get(), duration );
438
439           impl.mDecorator->SetCursorBlinkDuration( duration );
440         }
441         break;
442       }
443       case Toolkit::TextField::Property::CURSOR_WIDTH:
444       {
445         if( impl.mDecorator )
446         {
447           const int width = value.Get< int >();
448           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p CURSOR_WIDTH %d\n", impl.mController.Get(), width );
449
450           impl.mDecorator->SetCursorWidth( width );
451           impl.mController->GetLayoutEngine().SetCursorWidth( width );
452         }
453         break;
454       }
455       case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE:
456       {
457         const ResourceImage image = ResourceImage::New( value.Get< std::string >() );
458         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p GRAB_HANDLE_IMAGE %s\n", impl.mController.Get(), image.GetUrl().c_str() );
459
460         if( impl.mDecorator )
461         {
462           impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED, image );
463           impl.RequestTextRelayout();
464         }
465         break;
466       }
467       case Toolkit::TextField::Property::GRAB_HANDLE_PRESSED_IMAGE:
468       {
469         const ResourceImage image = ResourceImage::New( value.Get< std::string >() );
470         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p GRAB_HANDLE_PRESSED_IMAGE %s\n", impl.mController.Get(), image.GetUrl().c_str() );
471
472         if( impl.mDecorator )
473         {
474           impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED, image );
475           impl.RequestTextRelayout();
476         }
477         break;
478       }
479       case Toolkit::TextField::Property::SCROLL_THRESHOLD:
480       {
481         const float threshold = value.Get< float >();
482         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SCROLL_THRESHOLD %f\n", impl.mController.Get(), threshold );
483
484         if( impl.mDecorator )
485         {
486           impl.mDecorator->SetScrollThreshold( threshold );
487         }
488         break;
489       }
490       case Toolkit::TextField::Property::SCROLL_SPEED:
491       {
492         const float speed = value.Get< float >();
493         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SCROLL_SPEED %f\n", impl.mController.Get(), speed );
494
495         if( impl.mDecorator )
496         {
497           impl.mDecorator->SetScrollSpeed( speed );
498         }
499         break;
500       }
501       case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_LEFT:
502       {
503         const Image image = Scripting::NewImage( value );
504
505         if( impl.mDecorator && image )
506         {
507           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image );
508           impl.RequestTextRelayout();
509         }
510         break;
511       }
512       case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT:
513       {
514         const Image image = Scripting::NewImage( value );
515
516         if( impl.mDecorator && image )
517         {
518           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image );
519           impl.RequestTextRelayout();
520         }
521         break;
522       }
523       case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
524       {
525         const Image image = Scripting::NewImage( value );
526
527         if( impl.mDecorator && image )
528         {
529           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image );
530           impl.RequestTextRelayout();
531         }
532         break;
533       }
534       case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
535       {
536         const Image image = Scripting::NewImage( value );
537
538         if( impl.mDecorator && image )
539         {
540           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image );
541           impl.RequestTextRelayout();
542         }
543         break;
544       }
545       case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT:
546       {
547         const Image image = Scripting::NewImage( value );
548
549         if( impl.mDecorator && image )
550         {
551           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, image );
552           impl.RequestTextRelayout();
553         }
554         break;
555       }
556       case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT:
557       {
558         const Image image = Scripting::NewImage( value );
559
560         if( impl.mDecorator && image )
561         {
562           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, image );
563           impl.RequestTextRelayout();
564         }
565         break;
566       }
567       case Toolkit::TextField::Property::SELECTION_HIGHLIGHT_COLOR:
568       {
569         const Vector4 color = value.Get< Vector4 >();
570         DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SELECTION_HIGHLIGHT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
571
572         if( impl.mDecorator )
573         {
574           impl.mDecorator->SetHighlightColor( color );
575           impl.RequestTextRelayout();
576         }
577         break;
578       }
579       case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX:
580       {
581         if( impl.mDecorator )
582         {
583           const Rect<int> box = value.Get< Rect<int> >();
584           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 );
585
586           impl.mDecorator->SetBoundingBox( box );
587           impl.RequestTextRelayout();
588         }
589         break;
590       }
591       case Toolkit::TextField::Property::INPUT_METHOD_SETTINGS:
592       {
593         const Property::Map* map = value.GetMap();
594         if (map)
595         {
596           impl.mInputMethodOptions.ApplyProperty( *map );
597         }
598         impl.mController->SetInputModePassword( impl.mInputMethodOptions.IsPassword() );
599
600         Toolkit::Control control = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
601         if (control == textField)
602         {
603           impl.mImfManager.ApplyOptions( impl.mInputMethodOptions );
604         }
605         break;
606       }
607       case Toolkit::TextField::Property::INPUT_COLOR:
608       {
609         if( impl.mController )
610         {
611           const Vector4 inputColor = value.Get< Vector4 >();
612           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p INPUT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), inputColor.r, inputColor.g, inputColor.b, inputColor.a );
613
614           impl.mController->SetInputColor( inputColor );
615         }
616         break;
617       }
618       case Toolkit::TextField::Property::ENABLE_MARKUP:
619       {
620         if( impl.mController )
621         {
622           const bool enableMarkup = value.Get<bool>();
623           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p ENABLE_MARKUP %d\n", impl.mController.Get(), enableMarkup );
624
625           impl.mController->SetMarkupProcessorEnabled( enableMarkup );
626         }
627         break;
628       }
629       case Toolkit::TextField::Property::INPUT_FONT_FAMILY:
630       {
631         if( impl.mController )
632         {
633           const std::string& fontFamily = value.Get< std::string >();
634           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p INPUT_FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str() );
635           impl.mController->SetInputFontFamily( fontFamily );
636         }
637         break;
638       }
639       case Toolkit::TextField::Property::INPUT_FONT_STYLE:
640       {
641         SetFontStyleProperty( impl.mController, value, Text::FontStyle::INPUT );
642         break;
643       }
644       case Toolkit::TextField::Property::INPUT_POINT_SIZE:
645       {
646         if( impl.mController )
647         {
648           const float pointSize = value.Get< float >();
649           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p INPUT_POINT_SIZE %f\n", impl.mController.Get(), pointSize );
650           impl.mController->SetInputFontPointSize( pointSize );
651         }
652         break;
653       }
654       case Toolkit::TextField::Property::UNDERLINE:
655       {
656         const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
657         if( update )
658         {
659           impl.mRenderer.Reset();
660         }
661         break;
662       }
663       case Toolkit::TextField::Property::INPUT_UNDERLINE:
664       {
665         const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
666         if( update )
667         {
668           impl.mRenderer.Reset();
669         }
670         break;
671       }
672       case Toolkit::TextField::Property::SHADOW:
673       {
674         const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
675         if( update )
676         {
677           impl.mRenderer.Reset();
678         }
679         break;
680       }
681       case Toolkit::TextField::Property::INPUT_SHADOW:
682       {
683         const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::INPUT );
684         if( update )
685         {
686           impl.mRenderer.Reset();
687         }
688         break;
689       }
690       case Toolkit::TextField::Property::EMBOSS:
691       {
692         const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
693         if( update )
694         {
695           impl.mRenderer.Reset();
696         }
697         break;
698       }
699       case Toolkit::TextField::Property::INPUT_EMBOSS:
700       {
701         const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::INPUT );
702         if( update )
703         {
704           impl.mRenderer.Reset();
705         }
706         break;
707       }
708       case Toolkit::TextField::Property::OUTLINE:
709       {
710         const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
711         if( update )
712         {
713           impl.mRenderer.Reset();
714         }
715         break;
716       }
717       case Toolkit::TextField::Property::INPUT_OUTLINE:
718       {
719         const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
720         if( update )
721         {
722           impl.mRenderer.Reset();
723         }
724         break;
725       }
726     } // switch
727   } // textfield
728 }
729
730 Property::Value TextField::GetProperty( BaseObject* object, Property::Index index )
731 {
732   Property::Value value;
733
734   Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) );
735
736   if( textField )
737   {
738     TextField& impl( GetImpl( textField ) );
739
740     switch( index )
741     {
742       case Toolkit::TextField::Property::RENDERING_BACKEND:
743       {
744         value = impl.mRenderingBackend;
745         break;
746       }
747       case Toolkit::TextField::Property::TEXT:
748       {
749         if( impl.mController )
750         {
751           std::string text;
752           impl.mController->GetText( text );
753           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p returning text: %s\n", impl.mController.Get(), text.c_str() );
754           value = text;
755         }
756         break;
757       }
758       case Toolkit::TextField::Property::PLACEHOLDER_TEXT:
759       {
760         if( impl.mController )
761         {
762           std::string text;
763           impl.mController->GetPlaceholderText( Controller::PLACEHOLDER_TYPE_INACTIVE, text );
764           value = text;
765         }
766         break;
767       }
768       case Toolkit::TextField::Property::PLACEHOLDER_TEXT_FOCUSED:
769       {
770         if( impl.mController )
771         {
772           std::string text;
773           impl.mController->GetPlaceholderText( Controller::PLACEHOLDER_TYPE_ACTIVE, text );
774           value = text;
775         }
776         break;
777       }
778       case Toolkit::TextField::Property::FONT_FAMILY:
779       {
780         if( impl.mController )
781         {
782           value = impl.mController->GetDefaultFontFamily();
783         }
784         break;
785       }
786       case Toolkit::TextField::Property::FONT_STYLE:
787       {
788         GetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT );
789         break;
790       }
791       case Toolkit::TextField::Property::POINT_SIZE:
792       {
793         if( impl.mController )
794         {
795           value = impl.mController->GetDefaultPointSize();
796         }
797         break;
798       }
799       case Toolkit::TextField::Property::MAX_LENGTH:
800       {
801         if( impl.mController )
802         {
803           value = impl.mController->GetMaximumNumberOfCharacters();
804         }
805         break;
806       }
807       case Toolkit::TextField::Property::EXCEED_POLICY:
808       {
809         value = impl.mExceedPolicy;
810         break;
811       }
812       case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT:
813       {
814         if( impl.mController )
815         {
816           const char* name = Scripting::GetEnumerationName< Toolkit::Text::Layout::HorizontalAlignment >( impl.mController->GetHorizontalAlignment(),
817                                                                                                           HORIZONTAL_ALIGNMENT_STRING_TABLE,
818                                                                                                           HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
819           if( name )
820           {
821             value = std::string( name );
822           }
823         }
824         break;
825       }
826       case Toolkit::TextField::Property::VERTICAL_ALIGNMENT:
827       {
828         if( impl.mController )
829         {
830           const char* name = Scripting::GetEnumerationName< Toolkit::Text::Layout::VerticalAlignment >( impl.mController->GetVerticalAlignment(),
831                                                                                                         VERTICAL_ALIGNMENT_STRING_TABLE,
832                                                                                                         VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
833           if( name )
834           {
835             value = std::string( name );
836           }
837         }
838         break;
839       }
840       case Toolkit::TextField::Property::TEXT_COLOR:
841       {
842         if ( impl.mController )
843         {
844           value = impl.mController->GetDefaultColor();
845         }
846         break;
847       }
848       case Toolkit::TextField::Property::PLACEHOLDER_TEXT_COLOR:
849       {
850         if ( impl.mController )
851         {
852           value = impl.mController->GetPlaceholderTextColor();
853         }
854         break;
855       }
856       case Toolkit::TextField::Property::SHADOW_OFFSET:
857       {
858         if ( impl.mController )
859         {
860           value = impl.mController->GetShadowOffset();
861         }
862         break;
863       }
864       case Toolkit::TextField::Property::SHADOW_COLOR:
865       {
866         if ( impl.mController )
867         {
868           value = impl.mController->GetShadowColor();
869         }
870         break;
871       }
872       case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR:
873       {
874         if( impl.mDecorator )
875         {
876           value = impl.mDecorator->GetColor( PRIMARY_CURSOR );
877         }
878         break;
879       }
880       case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR:
881       {
882         if( impl.mDecorator )
883         {
884           value = impl.mDecorator->GetColor( SECONDARY_CURSOR );
885         }
886         break;
887       }
888       case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK:
889       {
890         value = impl.mController->GetEnableCursorBlink();
891         break;
892       }
893       case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL:
894       {
895         if( impl.mDecorator )
896         {
897           value = impl.mDecorator->GetCursorBlinkInterval();
898         }
899         break;
900       }
901       case Toolkit::TextField::Property::CURSOR_BLINK_DURATION:
902       {
903         if( impl.mDecorator )
904         {
905           value = impl.mDecorator->GetCursorBlinkDuration();
906         }
907         break;
908       }
909       case Toolkit::TextField::Property::CURSOR_WIDTH:
910       {
911         if( impl.mDecorator )
912         {
913           value = impl.mDecorator->GetCursorWidth();
914         }
915         break;
916       }
917       case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE:
918       {
919         if( impl.mDecorator )
920         {
921           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED ) );
922           if( image )
923           {
924             value = image.GetUrl();
925           }
926         }
927         break;
928       }
929       case Toolkit::TextField::Property::GRAB_HANDLE_PRESSED_IMAGE:
930       {
931         if( impl.mDecorator )
932         {
933           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED ) );
934           if( image )
935           {
936             value = image.GetUrl();
937           }
938         }
939         break;
940       }
941       case Toolkit::TextField::Property::SCROLL_THRESHOLD:
942       {
943         if( impl.mDecorator )
944         {
945           value = impl.mDecorator->GetScrollThreshold();
946         }
947         break;
948       }
949       case Toolkit::TextField::Property::SCROLL_SPEED:
950       {
951         if( impl.mDecorator )
952         {
953           value = impl.mDecorator->GetScrollSpeed();
954         }
955         break;
956       }
957       case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_LEFT:
958       {
959         impl.GetHandleImagePropertyValue( value, LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED );
960         break;
961       }
962       case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT:
963       {
964         impl.GetHandleImagePropertyValue( value, RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED ) ;
965         break;
966       }
967       case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
968       {
969         impl.GetHandleImagePropertyValue( value, LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED );
970         break;
971       }
972       case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
973       {
974         impl.GetHandleImagePropertyValue( value, RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED );
975         break;
976       }
977       case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT:
978       {
979         impl.GetHandleImagePropertyValue( value, LEFT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED );
980         break;
981       }
982       case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT:
983       {
984         impl.GetHandleImagePropertyValue( value, RIGHT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED );
985         break;
986       }
987       case Toolkit::TextField::Property::SELECTION_HIGHLIGHT_COLOR:
988       {
989         if( impl.mDecorator )
990         {
991           value = impl.mDecorator->GetHighlightColor();
992         }
993         break;
994       }
995       case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX:
996       {
997         if( impl.mDecorator )
998         {
999           Rect<int> boundingBox;
1000           impl.mDecorator->GetBoundingBox( boundingBox );
1001           value = boundingBox;
1002         }
1003         break;
1004       }
1005       case Toolkit::TextField::Property::INPUT_METHOD_SETTINGS:
1006       {
1007         Property::Map map;
1008         impl.mInputMethodOptions.RetrieveProperty( map );
1009         value = map;
1010         break;
1011       }
1012       case Toolkit::TextField::Property::INPUT_COLOR:
1013       {
1014         if( impl.mController )
1015         {
1016           value = impl.mController->GetInputColor();
1017         }
1018         break;
1019       }
1020       case Toolkit::TextField::Property::ENABLE_MARKUP:
1021       {
1022         if( impl.mController )
1023         {
1024           value = impl.mController->IsMarkupProcessorEnabled();
1025         }
1026         break;
1027       }
1028       case Toolkit::TextField::Property::INPUT_FONT_FAMILY:
1029       {
1030         if( impl.mController )
1031         {
1032           value = impl.mController->GetInputFontFamily();
1033         }
1034         break;
1035       }
1036       case Toolkit::TextField::Property::INPUT_FONT_STYLE:
1037       {
1038         GetFontStyleProperty( impl.mController, value, Text::FontStyle::INPUT );
1039         break;
1040       }
1041       case Toolkit::TextField::Property::INPUT_POINT_SIZE:
1042       {
1043         if( impl.mController )
1044         {
1045           value = impl.mController->GetInputFontPointSize();
1046         }
1047         break;
1048       }
1049       case Toolkit::TextField::Property::UNDERLINE:
1050       {
1051         GetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
1052         break;
1053       }
1054       case Toolkit::TextField::Property::INPUT_UNDERLINE:
1055       {
1056         GetUnderlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
1057         break;
1058       }
1059       case Toolkit::TextField::Property::SHADOW:
1060       {
1061         GetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
1062         break;
1063       }
1064       case Toolkit::TextField::Property::INPUT_SHADOW:
1065       {
1066         GetShadowProperties( impl.mController, value, Text::EffectStyle::INPUT );
1067         break;
1068       }
1069       case Toolkit::TextField::Property::EMBOSS:
1070       {
1071         GetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
1072         break;
1073       }
1074       case Toolkit::TextField::Property::INPUT_EMBOSS:
1075       {
1076         GetEmbossProperties( impl.mController, value, Text::EffectStyle::INPUT );
1077         break;
1078       }
1079       case Toolkit::TextField::Property::OUTLINE:
1080       {
1081         GetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
1082         break;
1083       }
1084       case Toolkit::TextField::Property::INPUT_OUTLINE:
1085       {
1086         GetOutlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
1087         break;
1088       }
1089     } //switch
1090   }
1091
1092   return value;
1093 }
1094
1095 bool TextField::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1096 {
1097   Dali::BaseHandle handle( object );
1098
1099   bool connected( true );
1100   Toolkit::TextField field = Toolkit::TextField::DownCast( handle );
1101
1102   if( 0 == strcmp( signalName.c_str(), SIGNAL_TEXT_CHANGED ) )
1103   {
1104     field.TextChangedSignal().Connect( tracker, functor );
1105   }
1106   else if( 0 == strcmp( signalName.c_str(), SIGNAL_MAX_LENGTH_REACHED ) )
1107   {
1108     field.MaxLengthReachedSignal().Connect( tracker, functor );
1109   }
1110   else if( 0 == strcmp( signalName.c_str(), SIGNAL_INPUT_STYLE_CHANGED ) )
1111   {
1112     field.InputStyleChangedSignal().Connect( tracker, functor );
1113   }
1114   else
1115   {
1116     // signalName does not match any signal
1117     connected = false;
1118   }
1119
1120   return connected;
1121 }
1122
1123 Toolkit::TextField::TextChangedSignalType& TextField::TextChangedSignal()
1124 {
1125   return mTextChangedSignal;
1126 }
1127
1128 Toolkit::TextField::MaxLengthReachedSignalType& TextField::MaxLengthReachedSignal()
1129 {
1130   return mMaxLengthReachedSignal;
1131 }
1132
1133 Toolkit::TextField::InputStyleChangedSignalType& TextField::InputStyleChangedSignal()
1134 {
1135   return mInputStyleChangedSignal;
1136 }
1137
1138 void TextField::OnInitialize()
1139 {
1140   Actor self = Self();
1141
1142   mController = Text::Controller::New( this, this );
1143
1144   // When using the vector-based rendering, the size of the GLyphs are different
1145   TextAbstraction::GlyphType glyphType = (Text::RENDERING_VECTOR_BASED == mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH;
1146   mController->SetGlyphType( glyphType );
1147
1148   mDecorator = Text::Decorator::New( *mController,
1149                                      *mController );
1150
1151   mController->GetLayoutEngine().SetLayout( Layout::Engine::SINGLE_LINE_BOX );
1152
1153   // Enables the text input.
1154   mController->EnableTextInput( mDecorator );
1155
1156   // Enables the horizontal scrolling after the text input has been enabled.
1157   mController->SetHorizontalScrollEnabled( true );
1158
1159   // Disables the vertical scrolling.
1160   mController->SetVerticalScrollEnabled( false );
1161
1162   // Disable the smooth handle panning.
1163   mController->SetSmoothHandlePanEnabled( false );
1164
1165   mController->SetNoTextDoubleTapAction( Controller::NoTextTap::HIGHLIGHT );
1166   mController->SetNoTextLongPressAction( Controller::NoTextTap::HIGHLIGHT );
1167
1168   // Forward input events to controller
1169   EnableGestureDetection( static_cast<Gesture::Type>( Gesture::Tap | Gesture::Pan | Gesture::LongPress ) );
1170   GetTapGestureDetector().SetMaximumTapsRequired( 2 );
1171
1172   mImfManager = ImfManager::Get();
1173
1174   self.TouchSignal().Connect( this, &TextField::OnTouched );
1175
1176   // Set BoundingBox to stage size if not already set.
1177   Rect<int> boundingBox;
1178   mDecorator->GetBoundingBox( boundingBox );
1179
1180   if( boundingBox.IsEmpty() )
1181   {
1182     Vector2 stageSize = Dali::Stage::GetCurrent().GetSize();
1183     mDecorator->SetBoundingBox( Rect<int>( 0.0f, 0.0f, stageSize.width, stageSize.height ) );
1184   }
1185
1186   // Flip vertically the 'left' selection handle
1187   mDecorator->FlipHandleVertically( LEFT_SELECTION_HANDLE, true );
1188
1189   // Fill-parent area by default
1190   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
1191   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
1192   self.OnStageSignal().Connect( this, &TextField::OnStageConnect );
1193
1194   if( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == mExceedPolicy )
1195   {
1196     EnableClipping();
1197   }
1198 }
1199
1200 void TextField::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
1201 {
1202   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnStyleChange\n");
1203
1204   switch ( change )
1205   {
1206     case StyleChange::DEFAULT_FONT_CHANGE:
1207     {
1208       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnStyleChange DEFAULT_FONT_CHANGE\n");
1209       const std::string& newFont = GetImpl( styleManager ).GetDefaultFontFamily();
1210       // Property system did not set the font so should update it.
1211       mController->UpdateAfterFontChange( newFont );
1212       break;
1213     }
1214
1215     case StyleChange::DEFAULT_FONT_SIZE_CHANGE:
1216     {
1217       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
1218       break;
1219     }
1220     case StyleChange::THEME_CHANGE:
1221     {
1222       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
1223       break;
1224     }
1225   }
1226 }
1227
1228 Vector3 TextField::GetNaturalSize()
1229 {
1230   return mController->GetNaturalSize();
1231 }
1232
1233 float TextField::GetHeightForWidth( float width )
1234 {
1235   return mController->GetHeightForWidth( width );
1236 }
1237
1238 void TextField::OnRelayout( const Vector2& size, RelayoutContainer& container )
1239 {
1240   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField OnRelayout\n");
1241
1242   const Text::Controller::UpdateTextType updateTextType = mController->Relayout( size );
1243
1244   if( ( Text::Controller::NONE_UPDATED != updateTextType ) ||
1245       !mRenderer )
1246   {
1247     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnRelayout %p Displaying new contents\n", mController.Get() );
1248
1249     if( mDecorator &&
1250         ( Text::Controller::NONE_UPDATED != ( Text::Controller::DECORATOR_UPDATED & updateTextType ) ) )
1251     {
1252       mDecorator->Relayout( size );
1253     }
1254
1255     if( !mRenderer )
1256     {
1257       mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
1258     }
1259
1260     RenderText( updateTextType );
1261   }
1262
1263   // The text-field emits signals when the input style changes. These changes of style are
1264   // detected during the relayout process (size negotiation), i.e after the cursor has been moved. Signals
1265   // can't be emitted during the size negotiation as the callbacks may update the UI.
1266   // The text-field adds an idle callback to the adaptor to emit the signals after the size negotiation.
1267   if( !mController->IsInputStyleChangedSignalsQueueEmpty() )
1268   {
1269     if( Adaptor::IsAvailable() )
1270     {
1271       Adaptor& adaptor = Adaptor::Get();
1272
1273       if( NULL == mIdleCallback )
1274       {
1275         // @note: The callback manager takes the ownership of the callback object.
1276         mIdleCallback = MakeCallback( this, &TextField::OnIdleSignal );
1277         adaptor.AddIdle( mIdleCallback );
1278       }
1279     }
1280   }
1281 }
1282
1283 void TextField::RenderText( Text::Controller::UpdateTextType updateTextType )
1284 {
1285   Actor renderableActor;
1286
1287   if( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) )
1288   {
1289     if( mRenderer )
1290     {
1291       renderableActor = mRenderer->Render( mController->GetView(),
1292                                            mAlignmentOffset,
1293                                            DepthIndex::CONTENT );
1294     }
1295
1296     if( renderableActor != mRenderableActor )
1297     {
1298       UnparentAndReset( mRenderableActor );
1299       mRenderableActor = renderableActor;
1300     }
1301   }
1302
1303   if( mRenderableActor )
1304   {
1305     const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition();
1306
1307     mRenderableActor.SetPosition( scrollOffset.x + mAlignmentOffset, scrollOffset.y );
1308
1309     // Make sure the actors are parented correctly with/without clipping
1310     Actor self = mStencil ? mStencil : Self();
1311
1312     for( std::vector<Actor>::const_iterator it = mClippingDecorationActors.begin(),
1313            endIt = mClippingDecorationActors.end();
1314          it != endIt;
1315          ++it )
1316     {
1317       self.Add( *it );
1318     }
1319     mClippingDecorationActors.clear();
1320
1321     self.Add( mRenderableActor );
1322   }
1323 }
1324
1325 void TextField::OnKeyInputFocusGained()
1326 {
1327   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnKeyInputFocusGained %p\n", mController.Get() );
1328
1329   mImfManager.ApplyOptions( mInputMethodOptions );
1330
1331   mImfManager.StatusChangedSignal().Connect( this, &TextField::KeyboardStatusChanged );
1332
1333   mImfManager.EventReceivedSignal().Connect( this, &TextField::OnImfEvent );
1334
1335   // Notify that the text editing start.
1336   mImfManager.Activate();
1337
1338   // When window gain lost focus, the imf manager is deactivated. Thus when window gain focus again, the imf manager must be activated.
1339   mImfManager.SetRestoreAfterFocusLost( true );
1340
1341    ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
1342
1343    if ( notifier )
1344    {
1345       notifier.ContentSelectedSignal().Connect( this, &TextField::OnClipboardTextSelected );
1346    }
1347
1348   mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
1349
1350   EmitKeyInputFocusSignal( true ); // Calls back into the Control hence done last.
1351 }
1352
1353 void TextField::OnKeyInputFocusLost()
1354 {
1355   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField:OnKeyInputFocusLost %p\n", mController.Get() );
1356
1357   mImfManager.StatusChangedSignal().Disconnect( this, &TextField::KeyboardStatusChanged );
1358   // The text editing is finished. Therefore the imf manager don't have restore activation.
1359   mImfManager.SetRestoreAfterFocusLost( false );
1360
1361   // Notify that the text editing finish.
1362   mImfManager.Deactivate();
1363
1364   mImfManager.EventReceivedSignal().Disconnect( this, &TextField::OnImfEvent );
1365
1366   ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
1367
1368   if ( notifier )
1369   {
1370     notifier.ContentSelectedSignal().Disconnect( this, &TextField::OnClipboardTextSelected );
1371   }
1372
1373   mController->KeyboardFocusLostEvent();
1374
1375   EmitKeyInputFocusSignal( false ); // Calls back into the Control hence done last.
1376 }
1377
1378 void TextField::OnTap( const TapGesture& gesture )
1379 {
1380   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnTap %p\n", mController.Get() );
1381
1382   mImfManager.Activate();
1383
1384   // Deliver the tap before the focus event to controller; this allows us to detect when focus is gained due to tap-gestures
1385   mController->TapEvent( gesture.numberOfTaps, gesture.localPoint.x, gesture.localPoint.y );
1386
1387   SetKeyInputFocus();
1388 }
1389
1390 void TextField::OnPan( const PanGesture& gesture )
1391 {
1392   mController->PanEvent( gesture.state, gesture.displacement );
1393 }
1394
1395 void TextField::OnLongPress( const LongPressGesture& gesture )
1396 {
1397   mImfManager.Activate();
1398
1399   mController->LongPressEvent( gesture.state, gesture.localPoint.x, gesture.localPoint.y );
1400
1401   SetKeyInputFocus();
1402 }
1403
1404 bool TextField::OnKeyEvent( const KeyEvent& event )
1405 {
1406   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnKeyEvent %p keyCode %d\n", mController.Get(), event.keyCode );
1407
1408   if( Dali::DALI_KEY_ESCAPE == event.keyCode || "Return" == event.keyPressedName ) // Make a Dali key code for this
1409   {
1410     // Make sure ClearKeyInputFocus when only key is up
1411     if( event.state == KeyEvent::Up )
1412     {
1413       ClearKeyInputFocus();
1414     }
1415
1416     return true;
1417   }
1418
1419   return mController->KeyEvent( event );
1420 }
1421
1422 void TextField::RequestTextRelayout()
1423 {
1424   RelayoutRequest();
1425 }
1426
1427 void TextField::TextChanged()
1428 {
1429   Dali::Toolkit::TextField handle( GetOwner() );
1430   mTextChangedSignal.Emit( handle );
1431 }
1432
1433 void TextField::MaxLengthReached()
1434 {
1435   Dali::Toolkit::TextField handle( GetOwner() );
1436   mMaxLengthReachedSignal.Emit( handle );
1437 }
1438
1439 void TextField::InputStyleChanged( Text::InputStyle::Mask inputStyleMask )
1440 {
1441   Dali::Toolkit::TextField handle( GetOwner() );
1442
1443   Toolkit::TextField::InputStyle::Mask fieldInputStyleMask = Toolkit::TextField::InputStyle::NONE;
1444
1445   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_COLOR ) )
1446   {
1447     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>( fieldInputStyleMask | Toolkit::TextField::InputStyle::COLOR );
1448   }
1449   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_FAMILY ) )
1450   {
1451     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>( fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_FAMILY );
1452   }
1453   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_POINT_SIZE ) )
1454   {
1455     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>( fieldInputStyleMask | Toolkit::TextField::InputStyle::POINT_SIZE );
1456   }
1457   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_WEIGHT ) )
1458   {
1459     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>( fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE );
1460   }
1461   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_WIDTH ) )
1462   {
1463     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>( fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE );
1464   }
1465   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_SLANT ) )
1466   {
1467     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>( fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE );
1468   }
1469   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_UNDERLINE ) )
1470   {
1471     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>( fieldInputStyleMask | Toolkit::TextField::InputStyle::UNDERLINE );
1472   }
1473   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_SHADOW ) )
1474   {
1475     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>( fieldInputStyleMask | Toolkit::TextField::InputStyle::SHADOW );
1476   }
1477   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_EMBOSS ) )
1478   {
1479     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>( fieldInputStyleMask | Toolkit::TextField::InputStyle::EMBOSS );
1480   }
1481   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_OUTLINE ) )
1482   {
1483     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>( fieldInputStyleMask | Toolkit::TextField::InputStyle::OUTLINE );
1484   }
1485
1486   mInputStyleChangedSignal.Emit( handle, fieldInputStyleMask );
1487 }
1488
1489 void TextField::AddDecoration( Actor& actor, bool needsClipping )
1490 {
1491   if( actor )
1492   {
1493     if( needsClipping )
1494     {
1495       mClippingDecorationActors.push_back( actor );
1496     }
1497     else
1498     {
1499       Self().Add( actor );
1500     }
1501   }
1502 }
1503
1504 void TextField::OnStageConnect( Dali::Actor actor )
1505 {
1506   if ( mHasBeenStaged )
1507   {
1508     RenderText( static_cast<Text::Controller::UpdateTextType>( Text::Controller::MODEL_UPDATED | Text::Controller::DECORATOR_UPDATED ) );
1509   }
1510   else
1511   {
1512     mHasBeenStaged = true;
1513   }
1514 }
1515
1516 ImfManager::ImfCallbackData TextField::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
1517 {
1518   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnImfEvent %p eventName %d\n", mController.Get(), imfEvent.eventName );
1519   return mController->OnImfEvent( imfManager, imfEvent );
1520 }
1521
1522 void TextField::GetHandleImagePropertyValue(  Property::Value& value, Text::HandleType handleType, Text::HandleImageType handleImageType )
1523 {
1524   if( mDecorator )
1525   {
1526     ResourceImage image = ResourceImage::DownCast( mDecorator->GetHandleImage( handleType, handleImageType ) );
1527
1528     if ( image )
1529     {
1530       Property::Map map;
1531       Scripting::CreatePropertyMap( image, map );
1532       value = map;
1533     }
1534   }
1535 }
1536
1537 void TextField::EnableClipping()
1538 {
1539   if( !mStencil )
1540   {
1541     // Creates an extra control to be used as stencil buffer.
1542     mStencil = Control::New();
1543     mStencil.SetAnchorPoint( AnchorPoint::CENTER );
1544     mStencil.SetParentOrigin( ParentOrigin::CENTER );
1545
1546     // Creates a background visual. Even if the color is transparent it updates the stencil.
1547     mStencil.SetProperty( Toolkit::Control::Property::BACKGROUND,
1548                           Property::Map().Add( Toolkit::Visual::Property::TYPE, DevelVisual::COLOR ).
1549                           Add( ColorVisual::Property::MIX_COLOR, Color::TRANSPARENT ) );
1550
1551     // Enable the clipping property.
1552     mStencil.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN );
1553     mStencil.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
1554
1555     Self().Add( mStencil );
1556   }
1557 }
1558
1559 void TextField::OnClipboardTextSelected( ClipboardEventNotifier& clipboard )
1560 {
1561   mController->PasteClipboardItemEvent();
1562 }
1563
1564 void TextField::KeyboardStatusChanged(bool keyboardShown)
1565 {
1566   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::KeyboardStatusChanged %p keyboardShown %d\n", mController.Get(), keyboardShown );
1567
1568   // Just hide the grab handle when keyboard is hidden.
1569   if (!keyboardShown )
1570   {
1571     mController->KeyboardFocusLostEvent();
1572   }
1573   else
1574   {
1575     mController->KeyboardFocusGainEvent(); // Initially called by OnKeyInputFocusGained
1576   }
1577 }
1578
1579 void TextField::OnStageConnection( int depth )
1580 {
1581   // Sets the depth to the visuals inside the text's decorator.
1582   mDecorator->SetTextDepth( depth );
1583
1584   // The depth of the text renderer is set in the RenderText() called from OnRelayout().
1585
1586   // Call the Control::OnStageConnection() to set the depth of the background.
1587   Control::OnStageConnection( depth );
1588 }
1589
1590 bool TextField::OnTouched( Actor actor, const TouchData& touch )
1591 {
1592   return true;
1593 }
1594
1595 void TextField::OnIdleSignal()
1596 {
1597   // Emits the change of input style signals.
1598   mController->ProcessInputStyleChangedSignals();
1599
1600   // Set the pointer to null as the callback manager deletes the callback after execute it.
1601   mIdleCallback = NULL;
1602 }
1603
1604 TextField::TextField()
1605 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
1606   mIdleCallback( NULL ),
1607   mAlignmentOffset( 0.f ),
1608   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
1609   mExceedPolicy( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP ),
1610   mHasBeenStaged( false )
1611 {
1612 }
1613
1614 TextField::~TextField()
1615 {
1616   UnparentAndReset( mStencil );
1617
1618   if( ( NULL != mIdleCallback ) && Adaptor::IsAvailable() )
1619   {
1620     Adaptor::Get().RemoveIdle( mIdleCallback );
1621   }
1622 }
1623
1624 } // namespace Internal
1625
1626 } // namespace Toolkit
1627
1628 } // namespace Dali