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