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