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