7b4e8a2f5d21321fa110289c0630cd53487869e6
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-editor-impl.cpp
1 /*
2  * Copyright (c) 2020 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-editor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring>
23 #include <limits>
24 #include <dali/public-api/adaptor-framework/key.h>
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/devel-api/adaptor-framework/window-devel.h>
27 #include <dali/devel-api/common/stage.h>
28 #include <dali/devel-api/actors/actor-devel.h>
29 #include <dali/devel-api/object/property-helper-devel.h>
30 #include <dali/public-api/object/type-registry-helper.h>
31 #include <dali/integration-api/debug.h>
32 #include <dali/integration-api/adaptor-framework/adaptor.h>
33
34 // INTERNAL INCLUDES
35 #include <dali-toolkit/public-api/text/text-enumerations.h>
36 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
37 #include <dali-toolkit/devel-api/text/rendering-backend.h>
38 #include <dali-toolkit/devel-api/controls/control-devel.h>
39 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
40 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
41 #include <dali-toolkit/public-api/visuals/visual-properties.h>
42 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
43 #include <dali-toolkit/internal/text/rendering/text-backend.h>
44 #include <dali-toolkit/internal/text/text-effects-style.h>
45 #include <dali-toolkit/internal/text/text-font-style.h>
46 #include <dali-toolkit/internal/text/text-view.h>
47 #include <dali-toolkit/internal/styling/style-manager-impl.h>
48 #include <dali-toolkit/devel-api/controls/control-devel.h>
49
50 using namespace Dali::Toolkit::Text;
51
52 namespace Dali
53 {
54
55 namespace Toolkit
56 {
57
58 namespace Internal
59 {
60
61 namespace // unnamed namespace
62 {
63
64 #if defined(DEBUG_ENABLED)
65 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS");
66 #endif
67
68 const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::DevelText::DEFAULT_RENDERING_BACKEND;
69 const float DEFAULT_SCROLL_SPEED = 1200.f; ///< The default scroll speed for the text editor in pixels/second.
70 } // unnamed namespace
71
72 namespace
73 {
74 const char* const SCROLL_BAR_POSITION("sourcePosition");
75 const char* const SCROLL_BAR_POSITION_MIN("sourcePositionMin");
76 const char* const SCROLL_BAR_POSITION_MAX("sourcePositionMax");
77 const char* const SCROLL_BAR_CONTENT_SIZE("sourceContentSize");
78
79 // Type registration
80 BaseHandle Create()
81 {
82   return Toolkit::TextEditor::New();
83 }
84
85 // Setup properties, signals and actions using the type-registry.
86 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextEditor, Toolkit::Control, Create );
87
88 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "text",                                 STRING,    TEXT                                 )
89 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "textColor",                            VECTOR4,   TEXT_COLOR                           )
90 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "fontFamily",                           STRING,    FONT_FAMILY                          )
91 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "fontStyle",                            MAP,       FONT_STYLE                           )
92 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "pointSize",                            FLOAT,     POINT_SIZE                           )
93 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "horizontalAlignment",                  STRING,    HORIZONTAL_ALIGNMENT                 )
94 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "scrollThreshold",                      FLOAT,     SCROLL_THRESHOLD                     )
95 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "scrollSpeed",                          FLOAT,     SCROLL_SPEED                         )
96 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "primaryCursorColor",                   VECTOR4,   PRIMARY_CURSOR_COLOR                 )
97 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "secondaryCursorColor",                 VECTOR4,   SECONDARY_CURSOR_COLOR               )
98 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableCursorBlink",                    BOOLEAN,   ENABLE_CURSOR_BLINK                  )
99 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "cursorBlinkInterval",                  FLOAT,     CURSOR_BLINK_INTERVAL                )
100 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "cursorBlinkDuration",                  FLOAT,     CURSOR_BLINK_DURATION                )
101 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "cursorWidth",                          INTEGER,   CURSOR_WIDTH                         )
102 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "grabHandleImage",                      STRING,    GRAB_HANDLE_IMAGE                    )
103 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "grabHandlePressedImage",               STRING,    GRAB_HANDLE_PRESSED_IMAGE            )
104 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandleImageLeft",             MAP,       SELECTION_HANDLE_IMAGE_LEFT          )
105 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandleImageRight",            MAP,       SELECTION_HANDLE_IMAGE_RIGHT         )
106 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandlePressedImageLeft",      MAP,       SELECTION_HANDLE_PRESSED_IMAGE_LEFT  )
107 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandlePressedImageRight",     MAP,       SELECTION_HANDLE_PRESSED_IMAGE_RIGHT )
108 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandleMarkerImageLeft",       MAP,       SELECTION_HANDLE_MARKER_IMAGE_LEFT   )
109 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandleMarkerImageRight",      MAP,       SELECTION_HANDLE_MARKER_IMAGE_RIGHT  )
110 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHighlightColor",              VECTOR4,   SELECTION_HIGHLIGHT_COLOR            )
111 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "decorationBoundingBox",                RECTANGLE, DECORATION_BOUNDING_BOX              )
112 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableMarkup",                         BOOLEAN,   ENABLE_MARKUP                        )
113 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputColor",                           VECTOR4,   INPUT_COLOR                          )
114 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputFontFamily",                      STRING,    INPUT_FONT_FAMILY                    )
115 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputFontStyle",                       MAP,       INPUT_FONT_STYLE                     )
116 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputPointSize",                       FLOAT,     INPUT_POINT_SIZE                     )
117 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "lineSpacing",                          FLOAT,     LINE_SPACING                         )
118 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputLineSpacing",                     FLOAT,     INPUT_LINE_SPACING                   )
119 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "underline",                            MAP,       UNDERLINE                            )
120 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputUnderline",                       MAP,       INPUT_UNDERLINE                      )
121 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "shadow",                               MAP,       SHADOW                               )
122 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputShadow",                          MAP,       INPUT_SHADOW                         )
123 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "emboss",                               MAP,       EMBOSS                               )
124 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputEmboss",                          MAP,       INPUT_EMBOSS                         )
125 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "outline",                              MAP,       OUTLINE                              )
126 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputOutline",                         MAP,       INPUT_OUTLINE                        )
127 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "smoothScroll",                         BOOLEAN,   SMOOTH_SCROLL                        )
128 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "smoothScrollDuration",                 FLOAT,     SMOOTH_SCROLL_DURATION               )
129 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableScrollBar",                      BOOLEAN,   ENABLE_SCROLL_BAR                    )
130 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "scrollBarShowDuration",                FLOAT,     SCROLL_BAR_SHOW_DURATION             )
131 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "scrollBarFadeDuration",                FLOAT,     SCROLL_BAR_FADE_DURATION             )
132 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "pixelSize",                            FLOAT,     PIXEL_SIZE                           )
133 DALI_PROPERTY_REGISTRATION_READ_ONLY( Toolkit, TextEditor, "lineCount",                  INTEGER,   LINE_COUNT                           )
134 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableSelection",                      BOOLEAN,   ENABLE_SELECTION                     )
135 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "placeholder",                          MAP,       PLACEHOLDER                          )
136 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "lineWrapMode",                         INTEGER,   LINE_WRAP_MODE                       )
137 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "placeholderText",                STRING,    PLACEHOLDER_TEXT                     )
138 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "placeholderTextColor",           VECTOR4,   PLACEHOLDER_TEXT_COLOR               )
139 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableShiftSelection",           BOOLEAN,   ENABLE_SHIFT_SELECTION               )
140 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableGrabHandle",               BOOLEAN,   ENABLE_GRAB_HANDLE                   )
141 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "matchSystemLanguageDirection",   BOOLEAN,   MATCH_SYSTEM_LANGUAGE_DIRECTION      )
142 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "renderingBackend",               INTEGER,   RENDERING_BACKEND                    )
143 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "maxLength",                      INTEGER,   MAX_LENGTH                           )
144 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectedTextStart",              INTEGER,   SELECTED_TEXT_START                  )
145 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectedTextEnd",                INTEGER,   SELECTED_TEXT_END                    )
146 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableEditing",                  BOOLEAN,   ENABLE_EDITING                       )
147 DALI_DEVEL_PROPERTY_REGISTRATION_READ_ONLY( Toolkit, TextEditor, "selectedText",         STRING,    SELECTED_TEXT                        )
148
149 DALI_SIGNAL_REGISTRATION( Toolkit, TextEditor, "textChanged",        SIGNAL_TEXT_CHANGED )
150 DALI_SIGNAL_REGISTRATION( Toolkit, TextEditor, "inputStyleChanged",  SIGNAL_INPUT_STYLE_CHANGED )
151 DALI_SIGNAL_REGISTRATION( Toolkit, TextEditor, "maxLengthReached",   SIGNAL_MAX_LENGTH_REACHED )
152
153 DALI_TYPE_REGISTRATION_END()
154
155 const char * const IMAGE_MAP_FILENAME_STRING = "filename";
156
157 /// Retrieves a filename from a value that is a Property::Map
158 std::string GetImageFileNameFromPropertyValue( const Property::Value& value )
159 {
160   std::string filename;
161   const Property::Map* map = value.GetMap();
162   if( map )
163   {
164     const Property::Value* filenameValue = map->Find( IMAGE_MAP_FILENAME_STRING );
165     if( filenameValue )
166     {
167       filenameValue->Get( filename );
168     }
169   }
170   return filename;
171 }
172
173 } // namespace
174
175 Toolkit::TextEditor TextEditor::New()
176 {
177   // Create the implementation, temporarily owned by this handle on stack
178   IntrusivePtr< TextEditor > impl = new TextEditor();
179
180   // Pass ownership to CustomActor handle
181   Toolkit::TextEditor handle( *impl );
182
183   // Second-phase init of the implementation
184   // This can only be done after the CustomActor connection has been made...
185   impl->Initialize();
186
187   return handle;
188 }
189
190 void TextEditor::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
191 {
192   Toolkit::TextEditor textEditor = Toolkit::TextEditor::DownCast( Dali::BaseHandle( object ) );
193
194   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor SetProperty\n");
195
196
197   if( textEditor )
198   {
199     TextEditor& impl( GetImpl( textEditor ) );
200     DALI_ASSERT_DEBUG( impl.mController && "No text contoller" );
201     DALI_ASSERT_DEBUG( impl.mDecorator && "No text decorator" );
202
203     switch( index )
204     {
205       case Toolkit::DevelTextEditor::Property::RENDERING_BACKEND:
206       {
207         int backend = value.Get< int >();
208         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p RENDERING_BACKEND %d\n", impl.mController.Get(), backend );
209
210         if( impl.mRenderingBackend != backend )
211         {
212           impl.mRenderingBackend = backend;
213           impl.mRenderer.Reset();
214           impl.RequestTextRelayout();
215         }
216         break;
217       }
218       case Toolkit::TextEditor::Property::TEXT:
219       {
220         const std::string& text = value.Get< std::string >();
221         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p TEXT %s\n", impl.mController.Get(), text.c_str() );
222
223         impl.mController->SetText( text );
224         break;
225       }
226       case Toolkit::TextEditor::Property::TEXT_COLOR:
227       {
228         const Vector4& textColor = value.Get< Vector4 >();
229         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a );
230
231         if( impl.mController->GetDefaultColor() != textColor )
232         {
233           impl.mController->SetDefaultColor( textColor );
234           impl.mController->SetInputColor( textColor );
235           impl.mRenderer.Reset();
236         }
237         break;
238       }
239       case Toolkit::TextEditor::Property::FONT_FAMILY:
240       {
241         const std::string& fontFamily = value.Get< std::string >();
242         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str() );
243         impl.mController->SetDefaultFontFamily( fontFamily );
244         break;
245       }
246       case Toolkit::TextEditor::Property::FONT_STYLE:
247       {
248         SetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT );
249         break;
250       }
251       case Toolkit::TextEditor::Property::POINT_SIZE:
252       {
253         const float pointSize = value.Get< float >();
254         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p POINT_SIZE %f\n", impl.mController.Get(), pointSize );
255
256         if( !Equals( impl.mController->GetDefaultFontSize( Text::Controller::POINT_SIZE ), pointSize ) )
257         {
258           impl.mController->SetDefaultFontSize( pointSize, Text::Controller::POINT_SIZE );
259         }
260         break;
261       }
262       case Toolkit::TextEditor::Property::HORIZONTAL_ALIGNMENT:
263       {
264         Text::HorizontalAlignment::Type alignment( static_cast< Text::HorizontalAlignment::Type >( -1 ) ); // Set to invalid value to ensure a valid mode does get set
265         if( Text::GetHorizontalAlignmentEnumeration( value, alignment ) )
266         {
267           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p HORIZONTAL_ALIGNMENT %d\n", impl.mController.Get(), alignment );
268           impl.mController->SetHorizontalAlignment( alignment );
269         }
270         break;
271       }
272       case Toolkit::TextEditor::Property::SCROLL_THRESHOLD:
273       {
274         const float threshold = value.Get< float >();
275         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p SCROLL_THRESHOLD %f\n", impl.mController.Get(), threshold );
276
277         impl.mDecorator->SetScrollThreshold( threshold );
278         break;
279       }
280       case Toolkit::TextEditor::Property::SCROLL_SPEED:
281       {
282         const float speed = value.Get< float >();
283         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p SCROLL_SPEED %f\n", impl.mController.Get(), speed );
284
285         impl.mDecorator->SetScrollSpeed( speed );
286         break;
287       }
288       case Toolkit::TextEditor::Property::PRIMARY_CURSOR_COLOR:
289       {
290         const Vector4& color = value.Get< Vector4 >();
291         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p PRIMARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
292
293         impl.mDecorator->SetCursorColor( PRIMARY_CURSOR, color );
294         impl.RequestTextRelayout();
295         break;
296       }
297       case Toolkit::TextEditor::Property::SECONDARY_CURSOR_COLOR:
298       {
299         const Vector4& color = value.Get< Vector4 >();
300         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p SECONDARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
301
302         impl.mDecorator->SetCursorColor( SECONDARY_CURSOR, color );
303         impl.RequestTextRelayout();
304         break;
305       }
306       case Toolkit::TextEditor::Property::ENABLE_CURSOR_BLINK:
307       {
308         const bool enable = value.Get< bool >();
309         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p ENABLE_CURSOR_BLINK %d\n", impl.mController.Get(), enable );
310
311         impl.mController->SetEnableCursorBlink( enable );
312         impl.RequestTextRelayout();
313         break;
314       }
315       case Toolkit::TextEditor::Property::CURSOR_BLINK_INTERVAL:
316       {
317         const float interval = value.Get< float >();
318         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p CURSOR_BLINK_INTERVAL %f\n", impl.mController.Get(), interval );
319
320         impl.mDecorator->SetCursorBlinkInterval( interval );
321         break;
322       }
323       case Toolkit::TextEditor::Property::CURSOR_BLINK_DURATION:
324       {
325         const float duration = value.Get< float >();
326         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p CURSOR_BLINK_DURATION %f\n", impl.mController.Get(), duration );
327
328         impl.mDecorator->SetCursorBlinkDuration( duration );
329         break;
330       }
331       case Toolkit::TextEditor::Property::CURSOR_WIDTH:
332       {
333         const int width = value.Get< int >();
334         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p CURSOR_WIDTH %d\n", impl.mController.Get(), width );
335
336         impl.mDecorator->SetCursorWidth( width );
337         impl.mController->GetLayoutEngine().SetCursorWidth( width );
338         break;
339       }
340       case Toolkit::TextEditor::Property::GRAB_HANDLE_IMAGE:
341       {
342         const std::string imageFileName = value.Get< std::string >();
343         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p GRAB_HANDLE_IMAGE %s\n", impl.mController.Get(), imageFileName.c_str() );
344
345         if( imageFileName.size() )
346         {
347           impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED, imageFileName );
348           impl.RequestTextRelayout();
349         }
350         break;
351       }
352       case Toolkit::TextEditor::Property::GRAB_HANDLE_PRESSED_IMAGE:
353       {
354         const std::string imageFileName = value.Get< std::string >();
355         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p GRAB_HANDLE_PRESSED_IMAGE %s\n", impl.mController.Get(), imageFileName.c_str() );
356
357         if( imageFileName.size() )
358         {
359           impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED, imageFileName );
360           impl.RequestTextRelayout();
361         }
362         break;
363       }
364       case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_LEFT:
365       {
366         const std::string filename = GetImageFileNameFromPropertyValue( value );
367
368         if( filename.size() )
369         {
370           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, filename );
371           impl.RequestTextRelayout();
372         }
373         break;
374       }
375       case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_RIGHT:
376       {
377         const std::string filename = GetImageFileNameFromPropertyValue( value );
378
379         if( filename.size() )
380         {
381           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, filename );
382           impl.RequestTextRelayout();
383         }
384         break;
385       }
386       case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
387       {
388         const std::string filename = GetImageFileNameFromPropertyValue( value );
389
390         if( filename.size() )
391         {
392           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, filename );
393           impl.RequestTextRelayout();
394         }
395         break;
396       }
397       case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
398       {
399         const std::string filename = GetImageFileNameFromPropertyValue( value );
400
401         if( filename.size() )
402         {
403           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, filename );
404           impl.RequestTextRelayout();
405         }
406         break;
407       }
408       case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT:
409       {
410         const std::string filename = GetImageFileNameFromPropertyValue( value );
411
412         if( filename.size() )
413         {
414           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, filename );
415           impl.RequestTextRelayout();
416         }
417         break;
418       }
419       case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT:
420       {
421         const std::string filename = GetImageFileNameFromPropertyValue( value );
422
423         if( filename.size() )
424         {
425           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, filename );
426           impl.RequestTextRelayout();
427         }
428         break;
429       }
430       case Toolkit::TextEditor::Property::SELECTION_HIGHLIGHT_COLOR:
431       {
432         const Vector4 color = value.Get< Vector4 >();
433         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p SELECTION_HIGHLIGHT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
434
435         impl.mDecorator->SetHighlightColor( color );
436         impl.RequestTextRelayout();
437         break;
438       }
439       case Toolkit::TextEditor::Property::DECORATION_BOUNDING_BOX:
440       {
441         const Rect<int>& box = value.Get< Rect<int> >();
442         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p DECORATION_BOUNDING_BOX %d,%d %dx%d\n", impl.mController.Get(), box.x, box.y, box.width, box.height );
443
444         impl.mDecorator->SetBoundingBox( box );
445         impl.RequestTextRelayout();
446         break;
447       }
448       case Toolkit::TextEditor::Property::ENABLE_MARKUP:
449       {
450         const bool enableMarkup = value.Get<bool>();
451         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p ENABLE_MARKUP %d\n", impl.mController.Get(), enableMarkup );
452
453         impl.mController->SetMarkupProcessorEnabled( enableMarkup );
454         break;
455       }
456       case Toolkit::TextEditor::Property::INPUT_COLOR:
457       {
458         const Vector4& inputColor = value.Get< Vector4 >();
459         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p INPUT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), inputColor.r, inputColor.g, inputColor.b, inputColor.a );
460
461         impl.mController->SetInputColor( inputColor );
462         break;
463       }
464       case Toolkit::TextEditor::Property::INPUT_FONT_FAMILY:
465       {
466         const std::string& fontFamily = value.Get< std::string >();
467         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p INPUT_FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str() );
468         impl.mController->SetInputFontFamily( fontFamily );
469         break;
470       }
471       case Toolkit::TextEditor::Property::INPUT_FONT_STYLE:
472       {
473         SetFontStyleProperty( impl.mController, value, Text::FontStyle::INPUT );
474         break;
475       }
476       case Toolkit::TextEditor::Property::INPUT_POINT_SIZE:
477       {
478         const float pointSize = value.Get< float >();
479         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p INPUT_POINT_SIZE %f\n", impl.mController.Get(), pointSize );
480         impl.mController->SetInputFontPointSize( pointSize );
481         break;
482       }
483       case Toolkit::TextEditor::Property::LINE_SPACING:
484       {
485         // The line spacing isn't supported by the TextEditor. Since it's supported
486         // by the TextLabel for now it must be ignored. The property is being shadowed
487         // locally so its value isn't affected.
488         const float lineSpacing = value.Get<float>();
489         impl.mLineSpacing = lineSpacing;
490         // set it to 0.0 due to missing implementation
491         impl.mController->SetDefaultLineSpacing( 0.0f );
492         impl.mRenderer.Reset();
493         break;
494       }
495       case Toolkit::TextEditor::Property::INPUT_LINE_SPACING:
496       {
497         const float lineSpacing = value.Get<float>();
498         impl.mController->SetInputLineSpacing( lineSpacing );
499         impl.mRenderer.Reset();
500         break;
501       }
502       case Toolkit::TextEditor::Property::UNDERLINE:
503       {
504         const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
505         if( update )
506         {
507           impl.mRenderer.Reset();
508         }
509         break;
510       }
511       case Toolkit::TextEditor::Property::INPUT_UNDERLINE:
512       {
513         const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
514         if( update )
515         {
516           impl.mRenderer.Reset();
517         }
518         break;
519       }
520       case Toolkit::TextEditor::Property::SHADOW:
521       {
522         const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
523         if( update )
524         {
525           impl.mRenderer.Reset();
526         }
527         break;
528       }
529       case Toolkit::TextEditor::Property::INPUT_SHADOW:
530       {
531         const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::INPUT );
532         if( update )
533         {
534           impl.mRenderer.Reset();
535         }
536         break;
537       }
538       case Toolkit::TextEditor::Property::EMBOSS:
539       {
540         const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
541         if( update )
542         {
543           impl.mRenderer.Reset();
544         }
545         break;
546       }
547       case Toolkit::TextEditor::Property::INPUT_EMBOSS:
548       {
549         const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::INPUT );
550         if( update )
551         {
552           impl.mRenderer.Reset();
553         }
554         break;
555       }
556       case Toolkit::TextEditor::Property::OUTLINE:
557       {
558         const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
559         if( update )
560         {
561           impl.mRenderer.Reset();
562         }
563         break;
564       }
565       case Toolkit::TextEditor::Property::INPUT_OUTLINE:
566       {
567         const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
568         if( update )
569         {
570           impl.mRenderer.Reset();
571         }
572         break;
573       }
574       case Toolkit::TextEditor::Property::SMOOTH_SCROLL:
575       {
576         const bool enable = value.Get< bool >();
577         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor SMOOTH_SCROLL %d\n", enable );
578
579         impl.mScrollAnimationEnabled = enable;
580         break;
581       }
582       case Toolkit::TextEditor::Property::SMOOTH_SCROLL_DURATION:
583       {
584         const float duration = value.Get< float >();
585         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor SMOOTH_SCROLL_DURATION %f\n", duration );
586
587         impl.mScrollAnimationDuration = duration;
588         if ( impl.mTextVerticalScroller )
589         {
590           impl.mTextVerticalScroller->SetDuration( duration );
591         }
592         break;
593       }
594       case Toolkit::TextEditor::Property::ENABLE_SCROLL_BAR:
595       {
596         const bool enable = value.Get< bool >();
597         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor SHOW_SCROLL_BAR %d\n", enable );
598
599         impl.mScrollBarEnabled = enable;
600         break;
601       }
602       case Toolkit::TextEditor::Property::SCROLL_BAR_SHOW_DURATION:
603       {
604         const float duration = value.Get< float >();
605         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor SCROLL_BAR_SHOW_DURATION %f\n", duration );
606
607         impl.mAnimationPeriod.delaySeconds = duration;
608         break;
609       }
610       case Toolkit::TextEditor::Property::SCROLL_BAR_FADE_DURATION:
611       {
612         const float duration = value.Get< float >();
613         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor SCROLL_BAR_FADE_DURATION %f\n", duration );
614
615         impl.mAnimationPeriod.durationSeconds = duration;
616         break;
617       }
618       case Toolkit::TextEditor::Property::PIXEL_SIZE:
619       {
620         const float pixelSize = value.Get< float >();
621         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p PIXEL_SIZE %f\n", impl.mController.Get(), pixelSize );
622
623         if( !Equals( impl.mController->GetDefaultFontSize( Text::Controller::PIXEL_SIZE ), pixelSize ) )
624         {
625           impl.mController->SetDefaultFontSize( pixelSize, Text::Controller::PIXEL_SIZE );
626         }
627         break;
628       }
629       case Toolkit::DevelTextEditor::Property::PLACEHOLDER_TEXT:
630       {
631         const std::string& text = value.Get< std::string >();
632         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor::OnPropertySet %p PLACEHOLDER_TEXT %s\n", impl.mController.Get(), text.c_str() );
633
634         impl.mController->SetPlaceholderText( Controller::PLACEHOLDER_TYPE_INACTIVE, text );
635         break;
636       }
637       case Toolkit::DevelTextEditor::Property::PLACEHOLDER_TEXT_COLOR:
638       {
639         const Vector4& textColor = value.Get< Vector4 >();
640         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p PLACEHOLDER_TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a );
641
642         if( impl.mController->GetPlaceholderTextColor() != textColor )
643         {
644           impl.mController->SetPlaceholderTextColor( textColor );
645           impl.mRenderer.Reset();
646         }
647         break;
648       }
649       case Toolkit::TextEditor::Property::ENABLE_SELECTION:
650       {
651         const bool enableSelection = value.Get< bool >();
652         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p ENABLE_SELECTION %d\n", impl.mController.Get(), enableSelection );
653         impl.mController->SetSelectionEnabled( enableSelection );
654         break;
655       }
656       case Toolkit::TextEditor::Property::PLACEHOLDER:
657       {
658         const Property::Map* map = value.GetMap();
659         if( map )
660         {
661           impl.mController->SetPlaceholderProperty( *map );
662         }
663         break;
664       }
665       case Toolkit::TextEditor::Property::LINE_WRAP_MODE:
666       {
667         Text::LineWrap::Mode lineWrapMode( static_cast< Text::LineWrap::Mode >( -1 ) ); // Set to invalid value to ensure a valid mode does get set
668         if( GetLineWrapModeEnumeration( value, lineWrapMode ) )
669         {
670           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p LineWrap::MODE %d\n", impl.mController.Get(), lineWrapMode );
671           impl.mController->SetLineWrapMode( lineWrapMode );
672         }
673         break;
674       }
675       case Toolkit::DevelTextEditor::Property::ENABLE_SHIFT_SELECTION:
676       {
677         const bool shiftSelection = value.Get<bool>();
678         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p ENABLE_SHIFT_SELECTION %d\n", impl.mController.Get(), shiftSelection );
679
680         impl.mController->SetShiftSelectionEnabled( shiftSelection );
681         break;
682       }
683       case Toolkit::DevelTextEditor::Property::ENABLE_GRAB_HANDLE:
684       {
685         const bool grabHandleEnabled = value.Get<bool>();
686         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p ENABLE_GRAB_HANDLE %d\n", impl.mController.Get(), grabHandleEnabled );
687
688         impl.mController->SetGrabHandleEnabled( grabHandleEnabled );
689         break;
690       }
691       case Toolkit::DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
692       {
693         impl.mController->SetMatchSystemLanguageDirection(value.Get< bool >());
694         break;
695       }
696       case Toolkit::DevelTextEditor::Property::MAX_LENGTH:
697       {
698         const int max = value.Get< int >();
699         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p MAX_LENGTH %d\n", impl.mController.Get(), max );
700
701         impl.mController->SetMaximumNumberOfCharacters( max );
702         break;
703       }
704       case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_START:
705       {
706         uint32_t start = static_cast<uint32_t>(value.Get< int >());
707         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p SELECTED_TEXT_START %d\n", impl.mController.Get(), start );
708         impl.SetTextSelectionRange( &start, nullptr );
709         break;
710       }
711       case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_END:
712       {
713         uint32_t end = static_cast<uint32_t>(value.Get< int >());
714         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p SELECTED_TEXT_END %d\n", impl.mController.Get(), end );
715         impl.SetTextSelectionRange( nullptr, &end );
716         break;
717       }
718       case Toolkit::DevelTextEditor::Property::ENABLE_EDITING:
719       {
720         const bool editable = value.Get< bool >();
721         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p ENABLE_EDITING %d\n", impl.mController.Get(), editable );
722         impl.SetEditable( editable );
723         break;
724       }
725     } // switch
726   } // texteditor
727 }
728
729 Property::Value TextEditor::GetProperty( BaseObject* object, Property::Index index )
730 {
731   Property::Value value;
732
733   Toolkit::TextEditor textEditor = Toolkit::TextEditor::DownCast( Dali::BaseHandle( object ) );
734
735   if( textEditor )
736   {
737     TextEditor& impl( GetImpl( textEditor ) );
738     DALI_ASSERT_DEBUG( impl.mController && "No text contoller" );
739     DALI_ASSERT_DEBUG( impl.mDecorator && "No text decorator" );
740
741     switch( index )
742     {
743       case Toolkit::DevelTextEditor::Property::RENDERING_BACKEND:
744       {
745         value = impl.mRenderingBackend;
746         break;
747       }
748       case Toolkit::TextEditor::Property::TEXT:
749       {
750         std::string text;
751         impl.mController->GetText( text );
752         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p returning text: %s\n", impl.mController.Get(), text.c_str() );
753         value = text;
754         break;
755       }
756       case Toolkit::TextEditor::Property::TEXT_COLOR:
757       {
758         value = impl.mController->GetDefaultColor();
759         break;
760       }
761       case Toolkit::TextEditor::Property::FONT_FAMILY:
762       {
763         value = impl.mController->GetDefaultFontFamily();
764         break;
765       }
766       case Toolkit::TextEditor::Property::FONT_STYLE:
767       {
768         GetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT );
769         break;
770       }
771       case Toolkit::TextEditor::Property::POINT_SIZE:
772       {
773         value = impl.mController->GetDefaultFontSize( Text::Controller::POINT_SIZE );
774         break;
775       }
776       case Toolkit::TextEditor::Property::HORIZONTAL_ALIGNMENT:
777       {
778         const char* name = GetHorizontalAlignmentString( impl.mController->GetHorizontalAlignment() );
779         if( name )
780         {
781           value = std::string( name );
782         }
783         break;
784       }
785       case Toolkit::TextEditor::Property::SCROLL_THRESHOLD:
786       {
787         value = impl.mDecorator->GetScrollThreshold();
788         break;
789       }
790       case Toolkit::TextEditor::Property::SCROLL_SPEED:
791       {
792         value = impl.mDecorator->GetScrollSpeed();
793         break;
794       }
795       case Toolkit::TextEditor::Property::PRIMARY_CURSOR_COLOR:
796       {
797         value = impl.mDecorator->GetColor( PRIMARY_CURSOR );
798         break;
799       }
800       case Toolkit::TextEditor::Property::SECONDARY_CURSOR_COLOR:
801       {
802         value = impl.mDecorator->GetColor( SECONDARY_CURSOR );
803         break;
804       }
805       case Toolkit::TextEditor::Property::ENABLE_CURSOR_BLINK:
806       {
807         value = impl.mController->GetEnableCursorBlink();
808         break;
809       }
810       case Toolkit::TextEditor::Property::CURSOR_BLINK_INTERVAL:
811       {
812         value = impl.mDecorator->GetCursorBlinkInterval();
813         break;
814       }
815       case Toolkit::TextEditor::Property::CURSOR_BLINK_DURATION:
816       {
817         value = impl.mDecorator->GetCursorBlinkDuration();
818         break;
819       }
820       case Toolkit::TextEditor::Property::CURSOR_WIDTH:
821       {
822         value = impl.mDecorator->GetCursorWidth();
823         break;
824       }
825       case Toolkit::TextEditor::Property::GRAB_HANDLE_IMAGE:
826       {
827         value = impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED );
828         break;
829       }
830       case Toolkit::TextEditor::Property::GRAB_HANDLE_PRESSED_IMAGE:
831       {
832         value = impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED );
833         break;
834       }
835       case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_LEFT:
836       {
837         impl.GetHandleImagePropertyValue( value, LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED );
838         break;
839       }
840       case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_RIGHT:
841       {
842         impl.GetHandleImagePropertyValue( value, RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED ) ;
843         break;
844       }
845       case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
846       {
847         impl.GetHandleImagePropertyValue( value, LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED );
848         break;
849       }
850       case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
851       {
852         impl.GetHandleImagePropertyValue( value, RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED );
853         break;
854       }
855       case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT:
856       {
857         impl.GetHandleImagePropertyValue( value, LEFT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED );
858         break;
859       }
860       case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT:
861       {
862         impl.GetHandleImagePropertyValue( value, RIGHT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED );
863         break;
864       }
865       case Toolkit::TextEditor::Property::SELECTION_HIGHLIGHT_COLOR:
866       {
867         value = impl.mDecorator->GetHighlightColor();
868         break;
869       }
870       case Toolkit::TextEditor::Property::DECORATION_BOUNDING_BOX:
871       {
872         Rect<int> boundingBox;
873         impl.mDecorator->GetBoundingBox( boundingBox );
874         value = boundingBox;
875         break;
876       }
877       case Toolkit::TextEditor::Property::ENABLE_MARKUP:
878       {
879         value = impl.mController->IsMarkupProcessorEnabled();
880         break;
881       }
882       case Toolkit::TextEditor::Property::INPUT_COLOR:
883       {
884         value = impl.mController->GetInputColor();
885         break;
886       }
887       case Toolkit::TextEditor::Property::INPUT_FONT_FAMILY:
888       {
889         value = impl.mController->GetInputFontFamily();
890         break;
891       }
892       case Toolkit::TextEditor::Property::INPUT_FONT_STYLE:
893       {
894         GetFontStyleProperty( impl.mController, value, Text::FontStyle::INPUT );
895         break;
896       }
897       case Toolkit::TextEditor::Property::INPUT_POINT_SIZE:
898       {
899         value = impl.mController->GetInputFontPointSize();
900         break;
901       }
902       case Toolkit::TextEditor::Property::LINE_SPACING:
903       {
904         // LINE_SPACING isn't implemented for the TextEditor. Returning
905         // only shadowed value, not the real one.
906         value = impl.mLineSpacing;
907         break;
908       }
909       case Toolkit::TextEditor::Property::INPUT_LINE_SPACING:
910       {
911         value = impl.mController->GetInputLineSpacing();
912         break;
913       }
914       case Toolkit::TextEditor::Property::UNDERLINE:
915       {
916         GetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
917         break;
918       }
919       case Toolkit::TextEditor::Property::INPUT_UNDERLINE:
920       {
921         GetUnderlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
922         break;
923       }
924       case Toolkit::TextEditor::Property::SHADOW:
925       {
926         GetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
927         break;
928       }
929       case Toolkit::TextEditor::Property::INPUT_SHADOW:
930       {
931         GetShadowProperties( impl.mController, value, Text::EffectStyle::INPUT );
932         break;
933       }
934       case Toolkit::TextEditor::Property::EMBOSS:
935       {
936         GetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
937         break;
938       }
939       case Toolkit::TextEditor::Property::INPUT_EMBOSS:
940       {
941         GetEmbossProperties( impl.mController, value, Text::EffectStyle::INPUT );
942         break;
943       }
944       case Toolkit::TextEditor::Property::OUTLINE:
945       {
946         GetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
947         break;
948       }
949       case Toolkit::TextEditor::Property::INPUT_OUTLINE:
950       {
951         GetOutlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
952         break;
953       }
954       case Toolkit::TextEditor::Property::SMOOTH_SCROLL:
955       {
956         value = impl.mScrollAnimationEnabled;
957         break;
958       }
959       case Toolkit::TextEditor::Property::SMOOTH_SCROLL_DURATION:
960       {
961         value = impl.mScrollAnimationDuration;
962         break;
963       }
964       case Toolkit::TextEditor::Property::ENABLE_SCROLL_BAR:
965       {
966         value = impl.mScrollBarEnabled;
967         break;
968       }
969       case Toolkit::TextEditor::Property::SCROLL_BAR_SHOW_DURATION:
970       {
971         value = impl.mAnimationPeriod.delaySeconds;
972         break;
973       }
974       case Toolkit::TextEditor::Property::SCROLL_BAR_FADE_DURATION:
975       {
976         value = impl.mAnimationPeriod.durationSeconds;
977         break;
978       }
979       case Toolkit::TextEditor::Property::PIXEL_SIZE:
980       {
981         value = impl.mController->GetDefaultFontSize( Text::Controller::PIXEL_SIZE );
982         break;
983       }
984       case Toolkit::TextEditor::Property::LINE_COUNT:
985       {
986         float width = textEditor.GetProperty( Actor::Property::SIZE_WIDTH ).Get<float>();
987         value = impl.mController->GetLineCount( width );
988         break;
989       }
990       case Toolkit::DevelTextEditor::Property::PLACEHOLDER_TEXT:
991       {
992         std::string text;
993         impl.mController->GetPlaceholderText( Controller::PLACEHOLDER_TYPE_INACTIVE, text );
994         value = text;
995         break;
996       }
997       case Toolkit::DevelTextEditor::Property::PLACEHOLDER_TEXT_COLOR:
998       {
999         value = impl.mController->GetPlaceholderTextColor();
1000         break;
1001       }
1002       case Toolkit::TextEditor::Property::ENABLE_SELECTION:
1003       {
1004         value = impl.mController->IsSelectionEnabled();
1005         break;
1006       }
1007       case Toolkit::TextEditor::Property::PLACEHOLDER:
1008       {
1009         Property::Map map;
1010         impl.mController->GetPlaceholderProperty( map );
1011         value = map;
1012         break;
1013       }
1014       case Toolkit::TextEditor::Property::LINE_WRAP_MODE:
1015       {
1016         value = impl.mController->GetLineWrapMode();
1017         break;
1018       }
1019       case Toolkit::DevelTextEditor::Property::ENABLE_SHIFT_SELECTION:
1020       {
1021         value = impl.mController->IsShiftSelectionEnabled();
1022         break;
1023       }
1024       case Toolkit::DevelTextEditor::Property::ENABLE_GRAB_HANDLE:
1025       {
1026         value = impl.mController->IsGrabHandleEnabled();
1027         break;
1028       }
1029       case Toolkit::DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
1030       {
1031         value = impl.mController->IsMatchSystemLanguageDirection();
1032         break;
1033       }
1034       case Toolkit::DevelTextEditor::Property::MAX_LENGTH:
1035       {
1036         value = impl.mController->GetMaximumNumberOfCharacters();
1037         break;
1038       }
1039       case Toolkit::DevelTextEditor::Property::SELECTED_TEXT:
1040       {
1041         value = impl.mController->GetSelectedText( );
1042         break;
1043       }
1044       case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_START:
1045       {
1046         Uint32Pair range = impl.GetTextSelectionRange();
1047         value = static_cast<int>(range.first);
1048         break;
1049       }
1050       case Toolkit::DevelTextEditor::Property::SELECTED_TEXT_END:
1051       {
1052         Uint32Pair range = impl.GetTextSelectionRange();
1053         value = static_cast<int>(range.second);
1054         break;
1055       }
1056       case Toolkit::DevelTextEditor::Property::ENABLE_EDITING:
1057       {
1058         value = impl.IsEditable();
1059         break;
1060       }
1061     } //switch
1062   }
1063
1064   return value;
1065 }
1066
1067 void TextEditor::SelectWholeText()
1068 {
1069   if( mController && mController->IsShowingRealText() )
1070   {
1071     mController->SelectWholeText();
1072     SetKeyInputFocus();
1073   }
1074 }
1075
1076 void TextEditor::SelectNone()
1077 {
1078   if( mController && mController->IsShowingRealText() )
1079   {
1080     mController->SelectNone();
1081   }
1082 }
1083
1084 string TextEditor::GetSelectedText() const
1085 {
1086   string selectedText = "";
1087   if( mController && mController->IsShowingRealText() )
1088   {
1089     selectedText = mController->GetSelectedText( );
1090   }
1091   return selectedText;
1092 }
1093
1094 InputMethodContext TextEditor::GetInputMethodContext()
1095 {
1096   return mInputMethodContext;
1097 }
1098
1099 DevelTextEditor::MaxLengthReachedSignalType& TextEditor::MaxLengthReachedSignal()
1100 {
1101   return mMaxLengthReachedSignal;
1102 }
1103
1104 Text::ControllerPtr TextEditor::getController()
1105 {
1106   return mController;
1107 }
1108
1109 bool TextEditor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1110 {
1111   Dali::BaseHandle handle( object );
1112
1113   bool connected( true );
1114   Toolkit::TextEditor editor = Toolkit::TextEditor::DownCast( handle );
1115
1116   if( 0 == strcmp( signalName.c_str(), SIGNAL_TEXT_CHANGED ) )
1117   {
1118     editor.TextChangedSignal().Connect( tracker, functor );
1119   }
1120   else if( 0 == strcmp( signalName.c_str(), SIGNAL_INPUT_STYLE_CHANGED ) )
1121   {
1122     editor.InputStyleChangedSignal().Connect( tracker, functor );
1123   }
1124   else if( 0 == strcmp( signalName.c_str(), SIGNAL_MAX_LENGTH_REACHED ) )
1125   {
1126     if( editor )
1127     {
1128       Internal::TextEditor& editorImpl( GetImpl( editor ) );
1129       editorImpl.MaxLengthReachedSignal().Connect( tracker, functor );
1130     }
1131   }
1132   else
1133   {
1134     // signalName does not match any signal
1135     connected = false;
1136   }
1137
1138   return connected;
1139 }
1140
1141 Toolkit::TextEditor::TextChangedSignalType& TextEditor::TextChangedSignal()
1142 {
1143   return mTextChangedSignal;
1144 }
1145
1146 Toolkit::TextEditor::InputStyleChangedSignalType& TextEditor::InputStyleChangedSignal()
1147 {
1148   return mInputStyleChangedSignal;
1149 }
1150
1151 Toolkit::TextEditor::ScrollStateChangedSignalType& TextEditor::ScrollStateChangedSignal()
1152 {
1153   return mScrollStateChangedSignal;
1154 }
1155
1156 void TextEditor::OnInitialize()
1157 {
1158   Actor self = Self();
1159
1160   mController = Text::Controller::New( this, this, this);
1161
1162   mDecorator = Text::Decorator::New( *mController,
1163                                      *mController );
1164
1165   mInputMethodContext = InputMethodContext::New( self );
1166
1167   mController->GetLayoutEngine().SetLayout( Layout::Engine::MULTI_LINE_BOX );
1168
1169   // Enables the text input.
1170   mController->EnableTextInput( mDecorator, mInputMethodContext );
1171
1172   // Enables the vertical scrolling after the text input has been enabled.
1173   mController->SetVerticalScrollEnabled( true );
1174
1175   // Disables the horizontal scrolling.
1176   mController->SetHorizontalScrollEnabled( false );
1177
1178   // Sets the maximum number of characters.
1179   mController->SetMaximumNumberOfCharacters( std::numeric_limits<Length>::max() );
1180
1181   // Enable the smooth handle panning.
1182   mController->SetSmoothHandlePanEnabled( true );
1183
1184   mController->SetNoTextDoubleTapAction( Controller::NoTextTap::HIGHLIGHT );
1185   mController->SetNoTextLongPressAction( Controller::NoTextTap::HIGHLIGHT );
1186
1187   // Sets layoutDirection value
1188   Dali::Stage stage = Dali::Stage::GetCurrent();
1189   Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>( stage.GetRootLayer().GetProperty( Dali::Actor::Property::LAYOUT_DIRECTION ).Get<int>() );
1190   mController->SetLayoutDirection( layoutDirection );
1191
1192   // Forward input events to controller
1193   EnableGestureDetection( static_cast<GestureType::Value>( GestureType::TAP | GestureType::PAN | GestureType::LONG_PRESS ) );
1194   GetTapGestureDetector().SetMaximumTapsRequired( 2 );
1195
1196   self.TouchedSignal().Connect( this, &TextEditor::OnTouched );
1197
1198   // Set BoundingBox to stage size if not already set.
1199   Rect<int> boundingBox;
1200   mDecorator->GetBoundingBox( boundingBox );
1201
1202   if( boundingBox.IsEmpty() )
1203   {
1204     Vector2 stageSize = Dali::Stage::GetCurrent().GetSize();
1205     mDecorator->SetBoundingBox( Rect<int>( 0.0f, 0.0f, stageSize.width, stageSize.height ) );
1206   }
1207
1208   // Whether to flip the selection handles as soon as they cross.
1209   mDecorator->FlipSelectionHandlesOnCrossEnabled( true );
1210
1211   // Set the default scroll speed.
1212   mDecorator->SetScrollSpeed( DEFAULT_SCROLL_SPEED );
1213
1214   // Fill-parent area by default
1215   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
1216   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
1217   self.OnSceneSignal().Connect( this, &TextEditor::OnSceneConnect );
1218
1219   //Enable highightability
1220   self.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true );
1221
1222   DevelControl::SetInputMethodContext( *this, mInputMethodContext );
1223
1224   // Creates an extra control to be used as stencil buffer.
1225   mStencil = Control::New();
1226   mStencil.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
1227   mStencil.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
1228
1229   // Creates a background visual. Even if the color is transparent it updates the stencil.
1230   mStencil.SetProperty( Toolkit::Control::Property::BACKGROUND,
1231                         Property::Map().Add( Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR ).
1232                         Add( ColorVisual::Property::MIX_COLOR, Color::TRANSPARENT ) );
1233
1234   // Enable the clipping property.
1235   mStencil.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_TO_BOUNDING_BOX );
1236   mStencil.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
1237
1238   self.Add( mStencil );
1239
1240   DevelControl::SetAccessibilityConstructor( self, []( Dali::Actor actor ) {
1241     return std::unique_ptr< Dali::Accessibility::Accessible >(
1242       new AccessibleImpl( actor, Dali::Accessibility::Role::ENTRY ) );
1243   } );
1244 }
1245
1246 void TextEditor::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
1247 {
1248   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnStyleChange\n");
1249
1250   switch ( change )
1251   {
1252     case StyleChange::DEFAULT_FONT_CHANGE:
1253     {
1254       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnStyleChange DEFAULT_FONT_CHANGE\n");
1255       const std::string& newFont = GetImpl( styleManager ).GetDefaultFontFamily();
1256       // Property system did not set the font so should update it.
1257       mController->UpdateAfterFontChange( newFont );
1258       RelayoutRequest();
1259       break;
1260     }
1261
1262     case StyleChange::DEFAULT_FONT_SIZE_CHANGE:
1263     {
1264       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
1265       RelayoutRequest();
1266       break;
1267     }
1268     case StyleChange::THEME_CHANGE:
1269     {
1270       // Nothing to do, let control base class handle this
1271       break;
1272     }
1273   }
1274
1275   // Up call to Control
1276   Control::OnStyleChange( styleManager, change );
1277 }
1278
1279 Vector3 TextEditor::GetNaturalSize()
1280 {
1281   Extents padding;
1282   padding = Self().GetProperty<Extents>( Toolkit::Control::Property::PADDING );
1283
1284   Vector3 naturalSize = mController->GetNaturalSize();
1285   naturalSize.width += ( padding.start + padding.end );
1286   naturalSize.height += ( padding.top + padding.bottom );
1287
1288   return naturalSize;
1289 }
1290
1291 float TextEditor::GetHeightForWidth( float width )
1292 {
1293   Extents padding;
1294   padding = Self().GetProperty<Extents>( Toolkit::Control::Property::PADDING );
1295   return mController->GetHeightForWidth( width ) + padding.top + padding.bottom;
1296 }
1297
1298 void TextEditor::OnRelayout( const Vector2& size, RelayoutContainer& container )
1299 {
1300   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor OnRelayout\n");
1301
1302   Actor self = Self();
1303
1304   Extents padding;
1305   padding = self.GetProperty<Extents>( Toolkit::Control::Property::PADDING );
1306
1307   Vector2 contentSize( size.x - ( padding.start + padding.end ), size.y - ( padding.top + padding.bottom ) );
1308
1309   // Support Right-To-Left of padding
1310   Dali::LayoutDirection::Type layoutDirection;
1311   if( mController->IsMatchSystemLanguageDirection() )
1312   {
1313     layoutDirection = static_cast<Dali::LayoutDirection::Type>( DevelWindow::Get( self ).GetRootLayer().GetProperty( Dali::Actor::Property::LAYOUT_DIRECTION ).Get<int>() );
1314   }
1315   else
1316   {
1317     layoutDirection = static_cast<Dali::LayoutDirection::Type>( self.GetProperty( Dali::Actor::Property::LAYOUT_DIRECTION ).Get<int>() );
1318   }
1319   if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection )
1320   {
1321     std::swap( padding.start, padding.end );
1322   }
1323
1324   if( mStencil )
1325   {
1326     mStencil.SetProperty( Actor::Property::POSITION, Vector2( padding.start, padding.top ));
1327   }
1328   if( mActiveLayer )
1329   {
1330     mActiveLayer.SetProperty( Actor::Property::POSITION, Vector2( padding.start, padding.top ));
1331   }
1332
1333   const Text::Controller::UpdateTextType updateTextType = mController->Relayout( contentSize, layoutDirection );
1334
1335   if( ( Text::Controller::NONE_UPDATED != updateTextType ) ||
1336       !mRenderer )
1337   {
1338     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnRelayout %p Displaying new contents\n", mController.Get() );
1339
1340     if( mDecorator &&
1341         ( Text::Controller::NONE_UPDATED != ( Text::Controller::DECORATOR_UPDATED & updateTextType ) ) )
1342     {
1343       mDecorator->Relayout( size );
1344     }
1345
1346     if( !mRenderer )
1347     {
1348       mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
1349     }
1350
1351     RenderText( updateTextType );
1352
1353   }
1354
1355   // The text-editor emits signals when the input style changes. These changes of style are
1356   // detected during the relayout process (size negotiation), i.e after the cursor has been moved. Signals
1357   // can't be emitted during the size negotiation as the callbacks may update the UI.
1358   // The text-editor adds an idle callback to the adaptor to emit the signals after the size negotiation.
1359   if( !mController->IsInputStyleChangedSignalsQueueEmpty() )
1360   {
1361     if( Adaptor::IsAvailable() )
1362     {
1363       Adaptor& adaptor = Adaptor::Get();
1364
1365       if( NULL == mIdleCallback )
1366       {
1367         // @note: The callback manager takes the ownership of the callback object.
1368         mIdleCallback = MakeCallback( this, &TextEditor::OnIdleSignal );
1369         adaptor.AddIdle( mIdleCallback, false );
1370       }
1371     }
1372   }
1373 }
1374
1375 void TextEditor::RenderText( Text::Controller::UpdateTextType updateTextType )
1376 {
1377   Actor renderableActor;
1378
1379   if( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) )
1380   {
1381     if( mRenderer )
1382     {
1383       Dali::Toolkit::TextEditor handle = Dali::Toolkit::TextEditor( GetOwner() );
1384
1385       renderableActor = mRenderer->Render( mController->GetView(),
1386                                            handle,
1387                                            Property::INVALID_INDEX, // Animatable property not supported
1388                                            mAlignmentOffset,
1389                                            DepthIndex::CONTENT );
1390     }
1391
1392     if( renderableActor != mRenderableActor )
1393     {
1394       UnparentAndReset( mRenderableActor );
1395       mRenderableActor = renderableActor;
1396     }
1397   }
1398
1399   if( mRenderableActor )
1400   {
1401     // Make sure the actors are parented correctly with/without clipping
1402     Actor self = mStencil ? mStencil : Self();
1403
1404     for( std::vector<Actor>::iterator it = mClippingDecorationActors.begin(),
1405            endIt = mClippingDecorationActors.end();
1406          it != endIt;
1407          ++it )
1408     {
1409       self.Add( *it );
1410       it->LowerToBottom();
1411     }
1412     mClippingDecorationActors.clear();
1413
1414     self.Add( mRenderableActor );
1415
1416     ApplyScrollPosition();
1417   }
1418   UpdateScrollBar();
1419 }
1420
1421 void TextEditor::OnKeyInputFocusGained()
1422 {
1423   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnKeyInputFocusGained %p\n", mController.Get() );
1424   if ( mInputMethodContext  && IsEditable() )
1425   {
1426     mInputMethodContext.StatusChangedSignal().Connect( this, &TextEditor::KeyboardStatusChanged );
1427
1428     mInputMethodContext.EventReceivedSignal().Connect( this, &TextEditor::OnInputMethodContextEvent );
1429
1430     // Notify that the text editing start.
1431     mInputMethodContext.Activate();
1432
1433     // When window gain lost focus, the InputMethodContext is deactivated. Thus when window gain focus again, the InputMethodContext must be activated.
1434     mInputMethodContext.SetRestoreAfterFocusLost( true );
1435   }
1436   ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
1437
1438   if ( notifier )
1439   {
1440     notifier.ContentSelectedSignal().Connect( this, &TextEditor::OnClipboardTextSelected );
1441   }
1442
1443   mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
1444
1445   EmitKeyInputFocusSignal( true ); // Calls back into the Control hence done last.
1446 }
1447
1448 void TextEditor::OnKeyInputFocusLost()
1449 {
1450   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor:OnKeyInputFocusLost %p\n", mController.Get() );
1451   if ( mInputMethodContext )
1452   {
1453     mInputMethodContext.StatusChangedSignal().Disconnect( this, &TextEditor::KeyboardStatusChanged );
1454
1455     // The text editing is finished. Therefore the InputMethodContext don't have restore activation.
1456     mInputMethodContext.SetRestoreAfterFocusLost( false );
1457
1458     // Notify that the text editing finish.
1459     mInputMethodContext.Deactivate();
1460
1461     mInputMethodContext.EventReceivedSignal().Disconnect( this, &TextEditor::OnInputMethodContextEvent );
1462   }
1463   ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
1464
1465   if ( notifier )
1466   {
1467     notifier.ContentSelectedSignal().Disconnect( this, &TextEditor::OnClipboardTextSelected );
1468   }
1469
1470   mController->KeyboardFocusLostEvent();
1471
1472   EmitKeyInputFocusSignal( false ); // Calls back into the Control hence done last.
1473 }
1474
1475 bool TextEditor::OnAccessibilityActivated()
1476 {
1477   SetKeyInputFocus();
1478   return true;
1479 }
1480
1481 void TextEditor::OnTap( const TapGesture& gesture )
1482 {
1483   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnTap %p\n", mController.Get() );
1484   if ( mInputMethodContext && IsEditable() )
1485   {
1486     mInputMethodContext.Activate();
1487   }
1488   // Deliver the tap before the focus event to controller; this allows us to detect when focus is gained due to tap-gestures
1489   Extents padding;
1490   padding = Self().GetProperty<Extents>( Toolkit::Control::Property::PADDING );
1491   const Vector2& localPoint = gesture.GetLocalPoint();
1492   mController->TapEvent( gesture.GetNumberOfTaps(), localPoint.x - padding.start, localPoint.y - padding.top );
1493
1494   SetKeyInputFocus();
1495 }
1496
1497 void TextEditor::OnPan( const PanGesture& gesture )
1498 {
1499   mController->PanEvent( gesture.GetState(), gesture.GetDisplacement() );
1500 }
1501
1502 void TextEditor::OnLongPress( const LongPressGesture& gesture )
1503 {
1504   if ( mInputMethodContext && IsEditable() )
1505   {
1506     mInputMethodContext.Activate();
1507   }
1508   Extents padding;
1509   padding = Self().GetProperty<Extents>( Toolkit::Control::Property::PADDING );
1510   const Vector2& localPoint = gesture.GetLocalPoint();
1511   mController->LongPressEvent( gesture.GetState(), localPoint.x - padding.start, localPoint.y - padding.top );
1512
1513   SetKeyInputFocus();
1514 }
1515
1516 bool TextEditor::OnKeyEvent( const KeyEvent& event )
1517 {
1518   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnKeyEvent %p keyCode %d\n", mController.Get(), event.GetKeyCode() );
1519
1520   if( Dali::DALI_KEY_ESCAPE == event.GetKeyCode() && mController->ShouldClearFocusOnEscape() )
1521   {
1522     // Make sure ClearKeyInputFocus when only key is up
1523     if( event.GetState() == KeyEvent::UP )
1524     {
1525       ClearKeyInputFocus();
1526     }
1527
1528     return true;
1529   }
1530
1531   return mController->KeyEvent( event );
1532 }
1533
1534 void TextEditor::RequestTextRelayout()
1535 {
1536   RelayoutRequest();
1537 }
1538
1539 void TextEditor::TextInserted( unsigned int position, unsigned int length, const std::string &content )
1540 {
1541   if( Accessibility::IsUp() )
1542   {
1543     Control::Impl::GetAccessibilityObject( Self() )->EmitTextInserted( position, length, content );
1544   }
1545 }
1546
1547 void TextEditor::TextDeleted( unsigned int position, unsigned int length, const std::string &content )
1548 {
1549   if( Accessibility::IsUp() )
1550   {
1551         Control::Impl::GetAccessibilityObject( Self() )->EmitTextDeleted( position, length, content );
1552   }
1553 }
1554
1555 void TextEditor::CaretMoved( unsigned int position )
1556 {
1557   if( Accessibility::IsUp() )
1558   {
1559     Control::Impl::GetAccessibilityObject( Self() )->EmitTextCaretMoved( position );
1560   }
1561 }
1562
1563 void TextEditor::TextChanged()
1564 {
1565   Dali::Toolkit::TextEditor handle( GetOwner() );
1566   mTextChangedSignal.Emit( handle );
1567 }
1568
1569 void TextEditor::MaxLengthReached()
1570 {
1571   Dali::Toolkit::TextEditor handle( GetOwner() );
1572   mMaxLengthReachedSignal.Emit( handle );
1573 }
1574
1575 void TextEditor::InputStyleChanged( Text::InputStyle::Mask inputStyleMask )
1576 {
1577   Dali::Toolkit::TextEditor handle( GetOwner() );
1578
1579   Toolkit::TextEditor::InputStyle::Mask editorInputStyleMask = Toolkit::TextEditor::InputStyle::NONE;
1580
1581   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_COLOR ) )
1582   {
1583     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::COLOR );
1584   }
1585   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_FAMILY ) )
1586   {
1587     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_FAMILY );
1588   }
1589   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_POINT_SIZE ) )
1590   {
1591     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::POINT_SIZE );
1592   }
1593   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_WEIGHT ) )
1594   {
1595     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE );
1596   }
1597   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_WIDTH ) )
1598   {
1599     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE );
1600   }
1601   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_SLANT ) )
1602   {
1603     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE );
1604   }
1605   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_LINE_SPACING ) )
1606   {
1607     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::LINE_SPACING );
1608   }
1609   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_UNDERLINE ) )
1610   {
1611     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::UNDERLINE );
1612   }
1613   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_SHADOW ) )
1614   {
1615     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::SHADOW );
1616   }
1617   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_EMBOSS ) )
1618   {
1619     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::EMBOSS );
1620   }
1621   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_OUTLINE ) )
1622   {
1623     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::OUTLINE );
1624   }
1625
1626   mInputStyleChangedSignal.Emit( handle, editorInputStyleMask );
1627 }
1628
1629 void TextEditor::AddDecoration( Actor& actor, bool needsClipping )
1630 {
1631   if( actor )
1632   {
1633     if( needsClipping )
1634     {
1635       mClippingDecorationActors.push_back( actor );
1636     }
1637     else
1638     {
1639       actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
1640       actor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
1641       Self().Add( actor );
1642       mActiveLayer = actor;
1643     }
1644   }
1645 }
1646
1647 void TextEditor::SetTextSelectionRange(const uint32_t *start, const uint32_t *end)
1648 {
1649   if( mController && mController->IsShowingRealText() )
1650   {
1651     mController->SetTextSelectionRange( start, end );
1652     SetKeyInputFocus();
1653   }
1654 }
1655
1656 Uint32Pair TextEditor::GetTextSelectionRange() const
1657 {
1658   Uint32Pair range(0, 0);
1659   if( mController && mController->IsShowingRealText() )
1660   {
1661     range = mController->GetTextSelectionRange();
1662   }
1663   return range;
1664 }
1665
1666 void TextEditor::UpdateScrollBar()
1667 {
1668   using namespace Dali;
1669
1670   float scrollPosition;
1671   float controlSize;
1672   float layoutSize;
1673   bool latestScrolled;
1674
1675   if ( !mScrollBarEnabled )
1676   {
1677     return;
1678   }
1679   latestScrolled = mController->GetTextScrollInfo( scrollPosition, controlSize, layoutSize );
1680   if ( !latestScrolled || controlSize > layoutSize)
1681   {
1682     return;
1683   }
1684
1685   CustomActor self = Self();
1686   if( !mScrollBar )
1687   {
1688     mScrollBar = Toolkit::ScrollBar::New( Toolkit::ScrollBar::VERTICAL );
1689     mScrollBar.SetIndicatorHeightPolicy( Toolkit::ScrollBar::VARIABLE );
1690     mScrollBar.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_RIGHT );
1691     mScrollBar.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_RIGHT );
1692     mScrollBar.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
1693     mScrollBar.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::WIDTH );
1694
1695     // Register the scroll position property
1696     Property::Index propertyScrollPosition = self.RegisterProperty( SCROLL_BAR_POSITION, scrollPosition );
1697     // Register the minimum scroll position property
1698     Property::Index propertyMinScrollPosition = self.RegisterProperty( SCROLL_BAR_POSITION_MIN, 0.0f );
1699     // Register the maximum scroll position property
1700     Property::Index propertyMaxScrollPosition = self.RegisterProperty( SCROLL_BAR_POSITION_MAX, (layoutSize - controlSize) );
1701     // Register the scroll content size property
1702     Property::Index propertyScrollContentSize = self.RegisterProperty( SCROLL_BAR_CONTENT_SIZE, layoutSize );
1703
1704     mScrollBar.SetScrollPropertySource(self, propertyScrollPosition, propertyMinScrollPosition, propertyMaxScrollPosition, propertyScrollContentSize);
1705
1706     // Set style name of ScrollBar for styling
1707     mScrollBar.SetStyleName("TextEditorScrollBar");
1708     Toolkit::Control scrollIndicator = Toolkit::Control::DownCast( mScrollBar.GetScrollIndicator() );
1709     if( scrollIndicator )
1710     {
1711       // Set style name of ScrollBarIndicator for styling
1712       scrollIndicator.SetStyleName("TextEditorScrollBarIndicator");
1713     }
1714
1715     self.Add( mScrollBar );
1716   }
1717   else
1718   {
1719     Property::Index propertyScrollPosition = self.GetPropertyIndex( SCROLL_BAR_POSITION );
1720     Property::Index propertyMaxScrollPosition = self.GetPropertyIndex( SCROLL_BAR_POSITION_MAX );
1721     Property::Index propertyScrollContentSize = self.GetPropertyIndex( SCROLL_BAR_CONTENT_SIZE );
1722
1723     self.SetProperty( propertyScrollPosition, scrollPosition );
1724     self.SetProperty( propertyMaxScrollPosition, (layoutSize - controlSize) );
1725     self.SetProperty( propertyScrollContentSize, layoutSize );
1726   }
1727
1728   // If scrolling is not started, start scrolling and emit ScrollStateChangedSignal
1729   if( !mScrollStarted )
1730   {
1731     mScrollStarted = true;
1732     Dali::Toolkit::TextEditor handle( GetOwner() );
1733     mScrollStateChangedSignal.Emit( handle, Toolkit::TextEditor::Scroll::STARTED );
1734   }
1735
1736   Actor indicator = mScrollBar.GetScrollIndicator();
1737   if( mAnimation )
1738   {
1739     mAnimation.Stop(); // Cancel any animation
1740   }
1741   else
1742   {
1743     mAnimation = Animation::New( mAnimationPeriod.durationSeconds );
1744   }
1745   indicator.SetProperty( Actor::Property::OPACITY,1.0f);
1746   mAnimation.AnimateTo( Property( indicator, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunction::EASE_IN, mAnimationPeriod );
1747   mAnimation.Play();
1748   mAnimation.FinishedSignal().Connect( this, &TextEditor::OnScrollIndicatorAnimationFinished );
1749 }
1750
1751 void TextEditor::OnScrollIndicatorAnimationFinished( Animation& animation )
1752 {
1753   // If animation is successfully ended, then emit ScrollStateChangedSignal
1754   if( animation.GetCurrentProgress() == 0.0f )
1755   {
1756     mScrollStarted = false;
1757     Dali::Toolkit::TextEditor handle( GetOwner() );
1758     mScrollStateChangedSignal.Emit( handle, Toolkit::TextEditor::Scroll::FINISHED );
1759   }
1760 }
1761
1762 void TextEditor::OnSceneConnect( Dali::Actor actor )
1763 {
1764   if ( mHasBeenStaged )
1765   {
1766     RenderText( static_cast<Text::Controller::UpdateTextType>( Text::Controller::MODEL_UPDATED | Text::Controller::DECORATOR_UPDATED ) );
1767   }
1768   else
1769   {
1770     mHasBeenStaged = true;
1771   }
1772 }
1773
1774 InputMethodContext::CallbackData TextEditor::OnInputMethodContextEvent( Dali::InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent )
1775 {
1776   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnInputMethodContextEvent %p eventName %d\n", mController.Get(), inputMethodContextEvent.eventName );
1777   return mController->OnInputMethodContextEvent( inputMethodContext, inputMethodContextEvent );
1778 }
1779
1780 void TextEditor::GetHandleImagePropertyValue(  Property::Value& value, Text::HandleType handleType, Text::HandleImageType handleImageType )
1781 {
1782   if( mDecorator )
1783   {
1784     Property::Map map;
1785     map[ IMAGE_MAP_FILENAME_STRING ] = mDecorator->GetHandleImage( handleType, handleImageType );
1786     value = map;
1787   }
1788 }
1789
1790 void TextEditor::OnClipboardTextSelected( ClipboardEventNotifier& clipboard )
1791 {
1792   mController->PasteClipboardItemEvent();
1793 }
1794
1795 void TextEditor::KeyboardStatusChanged(bool keyboardShown)
1796 {
1797   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::KeyboardStatusChanged %p keyboardShown %d\n", mController.Get(), keyboardShown );
1798
1799   // Just hide the grab handle when keyboard is hidden.
1800   if (!keyboardShown )
1801   {
1802     mController->KeyboardFocusLostEvent();
1803   }
1804   else
1805   {
1806     mController->KeyboardFocusGainEvent(); // Initially called by OnKeyInputFocusGained
1807   }
1808 }
1809
1810 void TextEditor::OnSceneConnection( int depth )
1811 {
1812   // Sets the depth to the visuals inside the text's decorator.
1813   mDecorator->SetTextDepth( depth );
1814
1815   // The depth of the text renderer is set in the RenderText() called from OnRelayout().
1816
1817   // Call the Control::OnSceneConnection() to set the depth of the background.
1818   Control::OnSceneConnection( depth );
1819 }
1820
1821 bool TextEditor::OnTouched( Actor actor, const TouchEvent& touch )
1822 {
1823   return false;
1824 }
1825
1826 void TextEditor::OnIdleSignal()
1827 {
1828   // Emits the change of input style signals.
1829   mController->ProcessInputStyleChangedSignals();
1830
1831   // Set the pointer to null as the callback manager deletes the callback after execute it.
1832   mIdleCallback = NULL;
1833 }
1834
1835 void TextEditor::ApplyScrollPosition()
1836 {
1837   const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition();
1838   float scrollAmount = 0.0f;
1839
1840   if ( mScrollAnimationEnabled )
1841   {
1842     scrollAmount = mController->GetScrollAmountByUserInput();
1843   }
1844   if ( mTextVerticalScroller )
1845   {
1846     mTextVerticalScroller->CheckStartAnimation( mRenderableActor, scrollOffset.x + mAlignmentOffset, scrollOffset.y - scrollAmount, scrollAmount );
1847   }
1848   else if ( Equals( scrollAmount, 0.0f, Math::MACHINE_EPSILON_1 ))
1849   {
1850     mRenderableActor.SetProperty( Actor::Property::POSITION, Vector2( scrollOffset.x + mAlignmentOffset, scrollOffset.y - scrollAmount ));
1851   }
1852   else
1853   {
1854     mTextVerticalScroller = Text::TextVerticalScroller::New();
1855     if ( !Equals( mScrollAnimationDuration, 0.0f, Math::MACHINE_EPSILON_1 ))
1856     {
1857       mTextVerticalScroller->SetDuration( mScrollAnimationDuration );
1858     }
1859     mTextVerticalScroller->CheckStartAnimation( mRenderableActor, scrollOffset.x + mAlignmentOffset, scrollOffset.y - scrollAmount, scrollAmount );
1860   }
1861 }
1862
1863 bool TextEditor::IsEditable() const
1864 {
1865   return mController->IsEditable();
1866 }
1867
1868 void TextEditor::SetEditable( bool editable )
1869 {
1870   mController->SetEditable(editable);
1871   if ( mInputMethodContext && !editable )
1872   {
1873     mInputMethodContext.Deactivate();
1874   }
1875 }
1876
1877 TextEditor::TextEditor()
1878 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
1879   mAnimationPeriod( 0.0f, 0.0f ),
1880   mIdleCallback( NULL ),
1881   mAlignmentOffset( 0.f ),
1882   mScrollAnimationDuration( 0.f ),
1883   mLineSpacing( 0.f ),
1884   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
1885   mHasBeenStaged( false ),
1886   mScrollAnimationEnabled( false ),
1887   mScrollBarEnabled( false ),
1888   mScrollStarted( false )
1889 {
1890 }
1891
1892 TextEditor::~TextEditor()
1893 {
1894   UnparentAndReset( mStencil );
1895
1896   if( ( NULL != mIdleCallback ) && Adaptor::IsAvailable() )
1897   {
1898     // Removes the callback from the callback manager in case the text-editor is destroyed before the callback is executed.
1899     Adaptor::Get().RemoveIdle( mIdleCallback );
1900   }
1901 }
1902
1903 std::string TextEditor::AccessibleImpl::GetName()
1904 {
1905   auto slf = Toolkit::TextEditor::DownCast( self );
1906   return slf.GetProperty( Toolkit::TextEditor::Property::TEXT )
1907       .Get< std::string >();
1908 }
1909
1910 std::string TextEditor::AccessibleImpl::GetText( size_t startOffset,
1911                                                  size_t endOffset )
1912 {
1913   if( endOffset <= startOffset )
1914     return {};
1915
1916   auto slf = Toolkit::TextEditor::DownCast( self );
1917   auto txt =
1918       slf.GetProperty( Toolkit::TextEditor::Property::TEXT ).Get< std::string >();
1919
1920   if( startOffset > txt.size() || endOffset > txt.size() )
1921     return {};
1922
1923   return txt.substr( startOffset, endOffset - startOffset );
1924 }
1925
1926 size_t TextEditor::AccessibleImpl::GetCharacterCount()
1927 {
1928   auto slf = Toolkit::TextEditor::DownCast( self );
1929   auto txt =
1930       slf.GetProperty( Toolkit::TextEditor::Property::TEXT ).Get< std::string >();
1931
1932   return txt.size();
1933 }
1934
1935 size_t TextEditor::AccessibleImpl::GetCaretOffset()
1936 {
1937   auto slf = Toolkit::TextEditor::DownCast( self );
1938   return Dali::Toolkit::GetImpl( slf ).getController()->GetCursorPosition();
1939 }
1940
1941 bool TextEditor::AccessibleImpl::SetCaretOffset(size_t offset)
1942 {
1943   auto slf = Toolkit::TextEditor::DownCast( self );
1944   auto txt = slf.GetProperty( Toolkit::TextEditor::Property::TEXT ).Get< std::string >();
1945   if (offset > txt.size())
1946     return false;
1947
1948   auto& slfImpl = Dali::Toolkit::GetImpl( slf );
1949   slfImpl.getController()->ResetCursorPosition( offset );
1950   slfImpl.RequestTextRelayout();
1951   return true;
1952 }
1953
1954 Dali::Accessibility::Range TextEditor::AccessibleImpl::GetTextAtOffset(
1955     size_t offset, Dali::Accessibility::TextBoundary boundary )
1956 {
1957   auto slf = Toolkit::TextEditor::DownCast( self );
1958   auto txt = slf.GetProperty( Toolkit::TextEditor::Property::TEXT ).Get< std::string >();
1959   auto txt_size = txt.size();
1960
1961   auto range = Dali::Accessibility::Range{};
1962
1963   switch(boundary)
1964   {
1965     case Dali::Accessibility::TextBoundary::CHARACTER:
1966       {
1967         if (offset < txt_size)
1968         {
1969           range.content = txt[offset];
1970           range.startOffset = offset;
1971           range.endOffset = offset + 1;
1972         }
1973       }
1974       break;
1975     case Dali::Accessibility::TextBoundary::WORD:
1976     case Dali::Accessibility::TextBoundary::LINE:
1977       {
1978         auto txt_c_string = txt.c_str();
1979         auto breaks = std::vector< char >( txt_size, 0 );
1980         if(boundary == Dali::Accessibility::TextBoundary::WORD)
1981           Accessibility::Accessible::FindWordSeparationsUtf8((const utf8_t *) txt_c_string, txt_size, "", breaks.data());
1982         else
1983           Accessibility::Accessible::FindLineSeparationsUtf8((const utf8_t *) txt_c_string, txt_size, "", breaks.data());
1984         auto index = 0u;
1985         auto counter = 0u;
1986         while( index < txt_size && counter <= offset )
1987         {
1988           auto start = index;
1989           if(breaks[index])
1990           {
1991             while(breaks[index])
1992               index++;
1993             counter++;
1994           }
1995           else
1996           {
1997             if (boundary == Dali::Accessibility::TextBoundary::WORD)
1998               index++;
1999             if (boundary == Dali::Accessibility::TextBoundary::LINE)
2000               counter++;
2001           }
2002           if ((counter - 1) == offset)
2003           {
2004             range.content = txt.substr(start, index - start + 1);
2005             range.startOffset = start;
2006             range.endOffset = index + 1;
2007           }
2008           if (boundary == Dali::Accessibility::TextBoundary::LINE)
2009               index++;
2010         }
2011       }
2012       break;
2013     case Dali::Accessibility::TextBoundary::SENTENCE:
2014       {
2015         /* not supported by efl */
2016       }
2017       break;
2018     case Dali::Accessibility::TextBoundary::PARAGRAPH:
2019       {
2020         /* Paragraph is not supported by libunibreak library */
2021       }
2022       break;
2023     default:
2024       break;
2025   }
2026
2027   return range;
2028 }
2029
2030 Dali::Accessibility::Range
2031 TextEditor::AccessibleImpl::GetSelection( size_t selectionNum )
2032 {
2033   // Since DALi supports only one selection indexes higher than 0 are ignored
2034   if( selectionNum > 0 )
2035     return {};
2036
2037   auto slf = Toolkit::TextEditor::DownCast( self );
2038   auto ctrl = Dali::Toolkit::GetImpl( slf ).getController();
2039   std::string ret;
2040   ctrl->RetrieveSelection( ret );
2041   auto r = ctrl->GetSelectionIndexes();
2042
2043   return { static_cast<size_t>(r.first), static_cast<size_t>(r.second), ret };
2044 }
2045
2046 bool TextEditor::AccessibleImpl::RemoveSelection( size_t selectionNum )
2047 {
2048   // Since DALi supports only one selection indexes higher than 0 are ignored
2049   if( selectionNum > 0 )
2050     return false;
2051
2052   auto slf = Toolkit::TextEditor::DownCast( self );
2053   Dali::Toolkit::GetImpl( slf ).getController()->SetSelection( 0, 0 );
2054   return true;
2055 }
2056
2057 bool TextEditor::AccessibleImpl::SetSelection( size_t selectionNum,
2058                                                size_t startOffset,
2059                                                size_t endOffset )
2060 {
2061   // Since DALi supports only one selection indexes higher than 0 are ignored
2062   if( selectionNum > 0 )
2063     return false;
2064
2065   auto slf = Toolkit::TextEditor::DownCast( self );
2066   Dali::Toolkit::GetImpl( slf ).getController()->SetSelection( startOffset,
2067                                                                endOffset );
2068   return true;
2069 }
2070
2071 bool TextEditor::AccessibleImpl::CopyText( size_t startPosition,
2072                                            size_t endPosition )
2073 {
2074   if( endPosition <= startPosition )
2075     return false;
2076
2077   auto slf = Toolkit::TextEditor::DownCast( self );
2078   auto txt = slf.GetProperty( Toolkit::TextEditor::Property::TEXT ).Get<std::string>();
2079   Dali::Toolkit::GetImpl( slf ).getController()->CopyStringToClipboard( txt.substr(startPosition, endPosition - startPosition) );
2080
2081   return true;
2082 }
2083
2084 bool TextEditor::AccessibleImpl::CutText( size_t startPosition,
2085                                           size_t endPosition )
2086 {
2087   if( endPosition <= startPosition )
2088     return false;
2089
2090   auto slf = Toolkit::TextEditor::DownCast( self );
2091   auto txt = slf.GetProperty( Toolkit::TextEditor::Property::TEXT ).Get<std::string>();
2092   Dali::Toolkit::GetImpl( slf ).getController()->CopyStringToClipboard( txt.substr(startPosition, endPosition - startPosition) );
2093
2094   slf.SetProperty( Toolkit::TextEditor::Property::TEXT,
2095                    txt.substr( 0, startPosition ) + txt.substr( endPosition - startPosition, txt.size()));
2096
2097   return true;
2098 }
2099
2100 Dali::Accessibility::States TextEditor::AccessibleImpl::CalculateStates()
2101 {
2102   using namespace Dali::Accessibility;
2103
2104   auto states = Control::Impl::AccessibleImpl::CalculateStates();
2105   states[State::EDITABLE] = true;
2106   states[State::FOCUSABLE] = true;
2107
2108   Toolkit::Control focusControl = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
2109   if (self == focusControl)
2110   {
2111     states[State::FOCUSED] = true;
2112   }
2113
2114   return states;
2115 }
2116
2117 } // namespace Internal
2118
2119 } // namespace Toolkit
2120
2121 } // namespace Dali