0312f6b08be0d6e7b25ca9f19da00963f8722602
[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   // If there is text changed, callback is called.
1313   if(mTextChanged)
1314   {
1315     EmitTextChangedSignal();
1316   }
1317
1318   const Text::Controller::UpdateTextType updateTextType = mController->Relayout(contentSize, layoutDirection);
1319
1320   if((Text::Controller::NONE_UPDATED != updateTextType) ||
1321      !mRenderer)
1322   {
1323     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::OnRelayout %p Displaying new contents\n", mController.Get());
1324
1325     if(mDecorator &&
1326        (Text::Controller::NONE_UPDATED != (Text::Controller::DECORATOR_UPDATED & updateTextType)))
1327     {
1328       mDecorator->Relayout(size);
1329     }
1330
1331     if(!mRenderer)
1332     {
1333       mRenderer = Backend::Get().NewRenderer(mRenderingBackend);
1334     }
1335
1336     RenderText(updateTextType);
1337   }
1338
1339   // The text-editor emits signals when the input style changes. These changes of style are
1340   // detected during the relayout process (size negotiation), i.e after the cursor has been moved. Signals
1341   // can't be emitted during the size negotiation as the callbacks may update the UI.
1342   // The text-editor adds an idle callback to the adaptor to emit the signals after the size negotiation.
1343   if(!mController->IsInputStyleChangedSignalsQueueEmpty())
1344   {
1345     if(Adaptor::IsAvailable())
1346     {
1347       Adaptor& adaptor = Adaptor::Get();
1348
1349       if(NULL == mIdleCallback)
1350       {
1351         // @note: The callback manager takes the ownership of the callback object.
1352         mIdleCallback = MakeCallback(this, &TextEditor::OnIdleSignal);
1353         adaptor.AddIdle(mIdleCallback, false);
1354       }
1355     }
1356   }
1357 }
1358
1359 void TextEditor::RenderText(Text::Controller::UpdateTextType updateTextType)
1360 {
1361   Actor renderableActor;
1362
1363   if(Text::Controller::NONE_UPDATED != (Text::Controller::MODEL_UPDATED & updateTextType))
1364   {
1365     if(mRenderer)
1366     {
1367       Dali::Toolkit::TextEditor handle = Dali::Toolkit::TextEditor(GetOwner());
1368
1369       renderableActor = mRenderer->Render(mController->GetView(),
1370                                           handle,
1371                                           Property::INVALID_INDEX, // Animatable property not supported
1372                                           mAlignmentOffset,
1373                                           DepthIndex::CONTENT);
1374     }
1375
1376     if(renderableActor != mRenderableActor)
1377     {
1378       UnparentAndReset(mBackgroundActor);
1379       UnparentAndReset(mRenderableActor);
1380       mRenderableActor = renderableActor;
1381
1382       if(mRenderableActor)
1383       {
1384         mBackgroundActor = mController->CreateBackgroundActor();
1385       }
1386     }
1387   }
1388
1389   if(mRenderableActor)
1390   {
1391     const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition();
1392
1393     float renderableActorPositionX, renderableActorPositionY;
1394
1395     if(mStencil)
1396     {
1397       renderableActorPositionX = scrollOffset.x + mAlignmentOffset;
1398       renderableActorPositionY = scrollOffset.y;
1399     }
1400     else
1401     {
1402       Extents padding;
1403       padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
1404
1405       // Support Right-To-Left of padding
1406       Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
1407       if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
1408       {
1409         std::swap(padding.start, padding.end);
1410       }
1411
1412       renderableActorPositionX = scrollOffset.x + mAlignmentOffset + padding.start;
1413       renderableActorPositionY = scrollOffset.y + padding.top;
1414     }
1415
1416     mRenderableActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY));
1417     // Make sure the actors are parented correctly with/without clipping
1418     Actor self = mStencil ? mStencil : Self();
1419
1420     Actor highlightActor;
1421
1422     for(std::vector<Actor>::iterator it    = mClippingDecorationActors.begin(),
1423                                      endIt = mClippingDecorationActors.end();
1424         it != endIt;
1425         ++it)
1426     {
1427       self.Add(*it);
1428       it->LowerToBottom();
1429
1430       if(it->GetProperty<std::string>(Dali::Actor::Property::NAME) == "HighlightActor")
1431       {
1432         highlightActor = *it;
1433       }
1434     }
1435     mClippingDecorationActors.clear();
1436
1437     self.Add(mRenderableActor);
1438
1439     if(mBackgroundActor)
1440     {
1441       if(mDecorator && mDecorator->IsHighlightVisible())
1442       {
1443         self.Add(mBackgroundActor);
1444         mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY)); // In text field's coords.
1445         mBackgroundActor.LowerBelow(highlightActor);
1446       }
1447       else
1448       {
1449         mRenderableActor.Add(mBackgroundActor);
1450         mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f)); // In renderable actor's coords.
1451         mBackgroundActor.LowerToBottom();
1452       }
1453     }
1454
1455     ApplyScrollPosition();
1456   }
1457   UpdateScrollBar();
1458 }
1459
1460 void TextEditor::OnKeyInputFocusGained()
1461 {
1462   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::OnKeyInputFocusGained %p\n", mController.Get());
1463   if(mInputMethodContext && IsEditable())
1464   {
1465     mInputMethodContext.StatusChangedSignal().Connect(this, &TextEditor::KeyboardStatusChanged);
1466
1467     mInputMethodContext.EventReceivedSignal().Connect(this, &TextEditor::OnInputMethodContextEvent);
1468
1469     // Notify that the text editing start.
1470     mInputMethodContext.Activate();
1471
1472     // When window gain lost focus, the InputMethodContext is deactivated. Thus when window gain focus again, the InputMethodContext must be activated.
1473     mInputMethodContext.SetRestoreAfterFocusLost(true);
1474   }
1475   ClipboardEventNotifier notifier(ClipboardEventNotifier::Get());
1476
1477   if(notifier)
1478   {
1479     notifier.ContentSelectedSignal().Connect(this, &TextEditor::OnClipboardTextSelected);
1480   }
1481
1482   mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
1483
1484   EmitKeyInputFocusSignal(true); // Calls back into the Control hence done last.
1485 }
1486
1487 void TextEditor::OnKeyInputFocusLost()
1488 {
1489   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor:OnKeyInputFocusLost %p\n", mController.Get());
1490   if(mInputMethodContext)
1491   {
1492     mInputMethodContext.StatusChangedSignal().Disconnect(this, &TextEditor::KeyboardStatusChanged);
1493
1494     // The text editing is finished. Therefore the InputMethodContext don't have restore activation.
1495     mInputMethodContext.SetRestoreAfterFocusLost(false);
1496
1497     // Notify that the text editing finish.
1498     mInputMethodContext.Deactivate();
1499
1500     mInputMethodContext.EventReceivedSignal().Disconnect(this, &TextEditor::OnInputMethodContextEvent);
1501   }
1502   ClipboardEventNotifier notifier(ClipboardEventNotifier::Get());
1503
1504   if(notifier)
1505   {
1506     notifier.ContentSelectedSignal().Disconnect(this, &TextEditor::OnClipboardTextSelected);
1507   }
1508
1509   mController->KeyboardFocusLostEvent();
1510
1511   EmitKeyInputFocusSignal(false); // Calls back into the Control hence done last.
1512 }
1513
1514 void TextEditor::OnTap(const TapGesture& gesture)
1515 {
1516   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::OnTap %p\n", mController.Get());
1517   if(mInputMethodContext && IsEditable())
1518   {
1519     mInputMethodContext.Activate();
1520   }
1521   // Deliver the tap before the focus event to controller; this allows us to detect when focus is gained due to tap-gestures
1522   Extents padding;
1523   padding                   = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
1524   const Vector2& localPoint = gesture.GetLocalPoint();
1525   mController->TapEvent(gesture.GetNumberOfTaps(), localPoint.x - padding.start, localPoint.y - padding.top);
1526
1527   SetKeyInputFocus();
1528 }
1529
1530 void TextEditor::OnPan(const PanGesture& gesture)
1531 {
1532   mController->PanEvent(gesture.GetState(), gesture.GetDisplacement());
1533 }
1534
1535 void TextEditor::OnLongPress(const LongPressGesture& gesture)
1536 {
1537   if(mInputMethodContext && IsEditable())
1538   {
1539     mInputMethodContext.Activate();
1540   }
1541   Extents padding;
1542   padding                   = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
1543   const Vector2& localPoint = gesture.GetLocalPoint();
1544   mController->LongPressEvent(gesture.GetState(), localPoint.x - padding.start, localPoint.y - padding.top);
1545
1546   SetKeyInputFocus();
1547 }
1548
1549 bool TextEditor::OnKeyEvent(const KeyEvent& event)
1550 {
1551   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::OnKeyEvent %p keyCode %d\n", mController.Get(), event.GetKeyCode());
1552
1553   if(Dali::DALI_KEY_ESCAPE == event.GetKeyCode() && mController->ShouldClearFocusOnEscape())
1554   {
1555     // Make sure ClearKeyInputFocus when only key is up
1556     if(event.GetState() == KeyEvent::UP)
1557     {
1558       ClearKeyInputFocus();
1559     }
1560
1561     return true;
1562   }
1563
1564   return mController->KeyEvent(event);
1565 }
1566
1567 void TextEditor::RequestTextRelayout()
1568 {
1569   RelayoutRequest();
1570 }
1571
1572 void TextEditor::TextChanged(bool immediate)
1573 {
1574   if(immediate) // Emits TextChangedSignal immediately
1575   {
1576     EmitTextChangedSignal();
1577   }
1578   else
1579   {
1580     mTextChanged = true;
1581   }
1582 }
1583
1584 void TextEditor::EmitTextChangedSignal()
1585 {
1586   Dali::Toolkit::TextEditor handle(GetOwner());
1587   mTextChangedSignal.Emit(handle);
1588   mTextChanged = false;
1589 }
1590
1591 void TextEditor::MaxLengthReached()
1592 {
1593   Dali::Toolkit::TextEditor handle(GetOwner());
1594   mMaxLengthReachedSignal.Emit(handle);
1595 }
1596
1597 void TextEditor::InputStyleChanged(Text::InputStyle::Mask inputStyleMask)
1598 {
1599   Dali::Toolkit::TextEditor handle(GetOwner());
1600
1601   Toolkit::TextEditor::InputStyle::Mask editorInputStyleMask = Toolkit::TextEditor::InputStyle::NONE;
1602
1603   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_COLOR))
1604   {
1605     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::COLOR);
1606   }
1607   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_FAMILY))
1608   {
1609     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_FAMILY);
1610   }
1611   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_POINT_SIZE))
1612   {
1613     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::POINT_SIZE);
1614   }
1615   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_WEIGHT))
1616   {
1617     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE);
1618   }
1619   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_WIDTH))
1620   {
1621     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE);
1622   }
1623   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_SLANT))
1624   {
1625     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE);
1626   }
1627   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_LINE_SPACING))
1628   {
1629     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::LINE_SPACING);
1630   }
1631   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_UNDERLINE))
1632   {
1633     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::UNDERLINE);
1634   }
1635   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_SHADOW))
1636   {
1637     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::SHADOW);
1638   }
1639   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_EMBOSS))
1640   {
1641     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::EMBOSS);
1642   }
1643   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_OUTLINE))
1644   {
1645     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>(editorInputStyleMask | Toolkit::TextEditor::InputStyle::OUTLINE);
1646   }
1647
1648   mInputStyleChangedSignal.Emit(handle, editorInputStyleMask);
1649 }
1650
1651 void TextEditor::AddDecoration(Actor& actor, bool needsClipping)
1652 {
1653   if(actor)
1654   {
1655     if(needsClipping)
1656     {
1657       mClippingDecorationActors.push_back(actor);
1658     }
1659     else
1660     {
1661       actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
1662       actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1663       Self().Add(actor);
1664       mActiveLayer = actor;
1665     }
1666   }
1667 }
1668
1669 void TextEditor::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
1670 {
1671   if(mController && mController->IsShowingRealText())
1672   {
1673     mController->SetTextSelectionRange(start, end);
1674     SetKeyInputFocus();
1675   }
1676 }
1677
1678 Uint32Pair TextEditor::GetTextSelectionRange() const
1679 {
1680   Uint32Pair range(0, 0);
1681   if(mController && mController->IsShowingRealText())
1682   {
1683     range = mController->GetTextSelectionRange();
1684   }
1685   return range;
1686 }
1687
1688 void TextEditor::GetControlBackgroundColor(Vector4& color) const
1689 {
1690   Property::Value propValue = Self().GetProperty(Toolkit::Control::Property::BACKGROUND);
1691   Property::Map*  resultMap = propValue.GetMap();
1692
1693   Property::Value* colorValue = nullptr;
1694   if(resultMap && (colorValue = resultMap->Find(ColorVisual::Property::MIX_COLOR)))
1695   {
1696     colorValue->Get(color);
1697   }
1698 }
1699
1700 void TextEditor::UpdateScrollBar()
1701 {
1702   using namespace Dali;
1703
1704   float scrollPosition;
1705   float controlSize;
1706   float layoutSize;
1707   bool  latestScrolled;
1708
1709   if(!mScrollBarEnabled)
1710   {
1711     return;
1712   }
1713   latestScrolled = mController->GetTextScrollInfo(scrollPosition, controlSize, layoutSize);
1714   if(!latestScrolled || controlSize > layoutSize)
1715   {
1716     return;
1717   }
1718
1719   CustomActor self = Self();
1720   if(!mScrollBar)
1721   {
1722     mScrollBar = Toolkit::ScrollBar::New(Toolkit::ScrollBar::VERTICAL);
1723     mScrollBar.SetIndicatorHeightPolicy(Toolkit::ScrollBar::VARIABLE);
1724     mScrollBar.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_RIGHT);
1725     mScrollBar.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_RIGHT);
1726     mScrollBar.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT);
1727     mScrollBar.SetResizePolicy(ResizePolicy::FIT_TO_CHILDREN, Dimension::WIDTH);
1728
1729     // Register the scroll position property
1730     Property::Index propertyScrollPosition = self.RegisterProperty(SCROLL_BAR_POSITION, scrollPosition);
1731     // Register the minimum scroll position property
1732     Property::Index propertyMinScrollPosition = self.RegisterProperty(SCROLL_BAR_POSITION_MIN, 0.0f);
1733     // Register the maximum scroll position property
1734     Property::Index propertyMaxScrollPosition = self.RegisterProperty(SCROLL_BAR_POSITION_MAX, (layoutSize - controlSize));
1735     // Register the scroll content size property
1736     Property::Index propertyScrollContentSize = self.RegisterProperty(SCROLL_BAR_CONTENT_SIZE, layoutSize);
1737
1738     mScrollBar.SetScrollPropertySource(self, propertyScrollPosition, propertyMinScrollPosition, propertyMaxScrollPosition, propertyScrollContentSize);
1739
1740     // Set style name of ScrollBar for styling
1741     mScrollBar.SetStyleName("TextEditorScrollBar");
1742     Toolkit::Control scrollIndicator = Toolkit::Control::DownCast(mScrollBar.GetScrollIndicator());
1743     if(scrollIndicator)
1744     {
1745       // Set style name of ScrollBarIndicator for styling
1746       scrollIndicator.SetStyleName("TextEditorScrollBarIndicator");
1747     }
1748
1749     self.Add(mScrollBar);
1750   }
1751   else
1752   {
1753     Property::Index propertyScrollPosition    = self.GetPropertyIndex(SCROLL_BAR_POSITION);
1754     Property::Index propertyMaxScrollPosition = self.GetPropertyIndex(SCROLL_BAR_POSITION_MAX);
1755     Property::Index propertyScrollContentSize = self.GetPropertyIndex(SCROLL_BAR_CONTENT_SIZE);
1756
1757     self.SetProperty(propertyScrollPosition, scrollPosition);
1758     self.SetProperty(propertyMaxScrollPosition, (layoutSize - controlSize));
1759     self.SetProperty(propertyScrollContentSize, layoutSize);
1760   }
1761
1762   // If scrolling is not started, start scrolling and emit ScrollStateChangedSignal
1763   if(!mScrollStarted)
1764   {
1765     mScrollStarted = true;
1766     Dali::Toolkit::TextEditor handle(GetOwner());
1767     mScrollStateChangedSignal.Emit(handle, Toolkit::TextEditor::Scroll::STARTED);
1768   }
1769
1770   Actor indicator = mScrollBar.GetScrollIndicator();
1771   if(mAnimation)
1772   {
1773     mAnimation.Stop(); // Cancel any animation
1774   }
1775   else
1776   {
1777     mAnimation = Animation::New(mAnimationPeriod.durationSeconds);
1778   }
1779   indicator.SetProperty(Actor::Property::OPACITY, 1.0f);
1780   mAnimation.AnimateTo(Property(indicator, Actor::Property::COLOR_ALPHA), 0.0f, AlphaFunction::EASE_IN, mAnimationPeriod);
1781   mAnimation.Play();
1782   mAnimation.FinishedSignal().Connect(this, &TextEditor::OnScrollIndicatorAnimationFinished);
1783 }
1784
1785 void TextEditor::OnScrollIndicatorAnimationFinished(Animation& animation)
1786 {
1787   // If animation is successfully ended, then emit ScrollStateChangedSignal
1788   if(animation.GetCurrentProgress() == 0.0f)
1789   {
1790     mScrollStarted = false;
1791     Dali::Toolkit::TextEditor handle(GetOwner());
1792     mScrollStateChangedSignal.Emit(handle, Toolkit::TextEditor::Scroll::FINISHED);
1793   }
1794 }
1795
1796 void TextEditor::OnSceneConnect(Dali::Actor actor)
1797 {
1798   if(mHasBeenStaged)
1799   {
1800     RenderText(static_cast<Text::Controller::UpdateTextType>(Text::Controller::MODEL_UPDATED | Text::Controller::DECORATOR_UPDATED));
1801   }
1802   else
1803   {
1804     mHasBeenStaged = true;
1805   }
1806 }
1807
1808 InputMethodContext::CallbackData TextEditor::OnInputMethodContextEvent(Dali::InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
1809 {
1810   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::OnInputMethodContextEvent %p eventName %d\n", mController.Get(), inputMethodContextEvent.eventName);
1811   return mController->OnInputMethodContextEvent(inputMethodContext, inputMethodContextEvent);
1812 }
1813
1814 void TextEditor::GetHandleImagePropertyValue(Property::Value& value, Text::HandleType handleType, Text::HandleImageType handleImageType)
1815 {
1816   if(mDecorator)
1817   {
1818     Property::Map map;
1819     map[IMAGE_MAP_FILENAME_STRING] = mDecorator->GetHandleImage(handleType, handleImageType);
1820     value                          = map;
1821   }
1822 }
1823
1824 void TextEditor::OnClipboardTextSelected(ClipboardEventNotifier& clipboard)
1825 {
1826   mController->PasteClipboardItemEvent();
1827 }
1828
1829 void TextEditor::KeyboardStatusChanged(bool keyboardShown)
1830 {
1831   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor::KeyboardStatusChanged %p keyboardShown %d\n", mController.Get(), keyboardShown);
1832
1833   // Just hide the grab handle when keyboard is hidden.
1834   if(!keyboardShown)
1835   {
1836     mController->KeyboardFocusLostEvent();
1837   }
1838   else
1839   {
1840     mController->KeyboardFocusGainEvent(); // Initially called by OnKeyInputFocusGained
1841   }
1842 }
1843
1844 void TextEditor::OnSceneConnection(int depth)
1845 {
1846   // Sets the depth to the visuals inside the text's decorator.
1847   mDecorator->SetTextDepth(depth);
1848
1849   // The depth of the text renderer is set in the RenderText() called from OnRelayout().
1850
1851   // Call the Control::OnSceneConnection() to set the depth of the background.
1852   Control::OnSceneConnection(depth);
1853 }
1854
1855 bool TextEditor::OnTouched(Actor actor, const TouchEvent& touch)
1856 {
1857   return false;
1858 }
1859
1860 void TextEditor::OnIdleSignal()
1861 {
1862   // Emits the change of input style signals.
1863   mController->ProcessInputStyleChangedSignals();
1864
1865   // Set the pointer to null as the callback manager deletes the callback after execute it.
1866   mIdleCallback = NULL;
1867 }
1868
1869 void TextEditor::ApplyScrollPosition()
1870 {
1871   const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition();
1872   float          scrollAmount = 0.0f;
1873
1874   if(mScrollAnimationEnabled)
1875   {
1876     scrollAmount = mController->GetScrollAmountByUserInput();
1877   }
1878   if(mTextVerticalScroller)
1879   {
1880     mTextVerticalScroller->CheckStartAnimation(mRenderableActor, scrollOffset.x + mAlignmentOffset, scrollOffset.y - scrollAmount, scrollAmount);
1881   }
1882   else if(Equals(scrollAmount, 0.0f, Math::MACHINE_EPSILON_1))
1883   {
1884     mRenderableActor.SetProperty(Actor::Property::POSITION, Vector2(scrollOffset.x + mAlignmentOffset, scrollOffset.y - scrollAmount));
1885   }
1886   else
1887   {
1888     mTextVerticalScroller = Text::TextVerticalScroller::New();
1889     if(!Equals(mScrollAnimationDuration, 0.0f, Math::MACHINE_EPSILON_1))
1890     {
1891       mTextVerticalScroller->SetDuration(mScrollAnimationDuration);
1892     }
1893     mTextVerticalScroller->CheckStartAnimation(mRenderableActor, scrollOffset.x + mAlignmentOffset, scrollOffset.y - scrollAmount, scrollAmount);
1894   }
1895 }
1896
1897 bool TextEditor::IsEditable() const
1898 {
1899   return mController->IsEditable();
1900 }
1901
1902 void TextEditor::SetEditable(bool editable)
1903 {
1904   mController->SetEditable(editable);
1905   if(mInputMethodContext && !editable)
1906   {
1907     mInputMethodContext.Deactivate();
1908   }
1909 }
1910
1911 TextEditor::TextEditor()
1912 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
1913   mAnimationPeriod(0.0f, 0.0f),
1914   mIdleCallback(NULL),
1915   mAlignmentOffset(0.f),
1916   mScrollAnimationDuration(0.f),
1917   mLineSpacing(0.f),
1918   mRenderingBackend(DEFAULT_RENDERING_BACKEND),
1919   mHasBeenStaged(false),
1920   mScrollAnimationEnabled(false),
1921   mScrollBarEnabled(false),
1922   mScrollStarted(false),
1923   mTextChanged(false)
1924 {
1925 }
1926
1927 TextEditor::~TextEditor()
1928 {
1929   UnparentAndReset(mStencil);
1930
1931   if((NULL != mIdleCallback) && Adaptor::IsAvailable())
1932   {
1933     // Removes the callback from the callback manager in case the text-editor is destroyed before the callback is executed.
1934     Adaptor::Get().RemoveIdle(mIdleCallback);
1935   }
1936 }
1937
1938 } // namespace Internal
1939
1940 } // namespace Toolkit
1941
1942 } // namespace Dali