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