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