Merge "Fix text constraint issue" into devel/master
[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/common/stage.h>
25 #include <dali/devel-api/object/property-helper-devel.h>
26 #include <dali/integration-api/debug.h>
27 #include <dali/public-api/actors/layer.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-devel.h>
35 #include <dali-toolkit/devel-api/controls/text-controls/text-field-devel.h>
36 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
37 #include <dali-toolkit/devel-api/text/rendering-backend.h>
38 #include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
39 #include <dali-toolkit/internal/controls/text-controls/text-field-property-handler.h>
40 #include <dali-toolkit/internal/styling/style-manager-impl.h>
41 #include <dali-toolkit/internal/text/rendering/text-backend.h>
42 #include <dali-toolkit/internal/text/text-effects-style.h>
43 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
44 #include <dali-toolkit/internal/text/text-font-style.h>
45 #include <dali-toolkit/internal/text/text-view.h>
46 #include <dali-toolkit/public-api/text/text-enumerations.h>
47 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
48 #include <dali-toolkit/public-api/visuals/visual-properties.h>
49 #include <dali/integration-api/adaptor-framework/adaptor.h>
50
51 using namespace Dali::Toolkit::Text;
52
53 #if defined(DEBUG_ENABLED)
54 Debug::Filter* gTextFieldLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS");
55 #endif
56
57 namespace Dali
58 {
59 namespace Toolkit
60 {
61 namespace Internal
62 {
63 namespace // unnamed namespace
64 {
65 const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::DevelText::DEFAULT_RENDERING_BACKEND;
66 } // unnamed namespace
67
68 namespace
69 {
70 // Type registration
71 BaseHandle Create()
72 {
73   return Toolkit::TextField::New();
74 }
75
76 // clang-format off
77 // Setup properties, signals and actions using the type-registry.
78 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextField, Toolkit::Control, Create );
79
80 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "text",                             STRING,    TEXT                                )
81 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "placeholderText",                  STRING,    PLACEHOLDER_TEXT                    )
82 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "placeholderTextFocused",           STRING,    PLACEHOLDER_TEXT_FOCUSED            )
83 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "fontFamily",                       STRING,    FONT_FAMILY                         )
84 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "fontStyle",                        MAP,       FONT_STYLE                          )
85 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "pointSize",                        FLOAT,     POINT_SIZE                          )
86 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "maxLength",                        INTEGER,   MAX_LENGTH                          )
87 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "exceedPolicy",                     INTEGER,   EXCEED_POLICY                       )
88 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "horizontalAlignment",              STRING,    HORIZONTAL_ALIGNMENT                )
89 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "verticalAlignment",                STRING,    VERTICAL_ALIGNMENT                  )
90 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "textColor",                        VECTOR4,   TEXT_COLOR                          )
91 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "placeholderTextColor",             VECTOR4,   PLACEHOLDER_TEXT_COLOR              )
92 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "primaryCursorColor",               VECTOR4,   PRIMARY_CURSOR_COLOR                )
93 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "secondaryCursorColor",             VECTOR4,   SECONDARY_CURSOR_COLOR              )
94 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "enableCursorBlink",                BOOLEAN,   ENABLE_CURSOR_BLINK                 )
95 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "cursorBlinkInterval",              FLOAT,     CURSOR_BLINK_INTERVAL               )
96 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "cursorBlinkDuration",              FLOAT,     CURSOR_BLINK_DURATION               )
97 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "cursorWidth",                      INTEGER,   CURSOR_WIDTH                        )
98 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "grabHandleImage",                  STRING,    GRAB_HANDLE_IMAGE                   )
99 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "grabHandlePressedImage",           STRING,    GRAB_HANDLE_PRESSED_IMAGE           )
100 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "scrollThreshold",                  FLOAT,     SCROLL_THRESHOLD                    )
101 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "scrollSpeed",                      FLOAT,     SCROLL_SPEED                        )
102 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "selectionHandleImageLeft",         MAP,       SELECTION_HANDLE_IMAGE_LEFT         )
103 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "selectionHandleImageRight",        MAP,       SELECTION_HANDLE_IMAGE_RIGHT        )
104 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "selectionHandlePressedImageLeft",  MAP,       SELECTION_HANDLE_PRESSED_IMAGE_LEFT )
105 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "selectionHandlePressedImageRight", MAP,       SELECTION_HANDLE_PRESSED_IMAGE_RIGHT)
106 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "selectionHandleMarkerImageLeft",   MAP,       SELECTION_HANDLE_MARKER_IMAGE_LEFT  )
107 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "selectionHandleMarkerImageRight",  MAP,       SELECTION_HANDLE_MARKER_IMAGE_RIGHT )
108 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "selectionHighlightColor",          VECTOR4,   SELECTION_HIGHLIGHT_COLOR           )
109 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "decorationBoundingBox",            RECTANGLE, DECORATION_BOUNDING_BOX             )
110 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "inputMethodSettings",              MAP,       INPUT_METHOD_SETTINGS               )
111 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "inputColor",                       VECTOR4,   INPUT_COLOR                         )
112 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "enableMarkup",                     BOOLEAN,   ENABLE_MARKUP                       )
113 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "inputFontFamily",                  STRING,    INPUT_FONT_FAMILY                   )
114 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "inputFontStyle",                   MAP,       INPUT_FONT_STYLE                    )
115 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "inputPointSize",                   FLOAT,     INPUT_POINT_SIZE                    )
116 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "underline",                        MAP,       UNDERLINE                           )
117 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "inputUnderline",                   MAP,       INPUT_UNDERLINE                     )
118 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "shadow",                           MAP,       SHADOW                              )
119 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "inputShadow",                      MAP,       INPUT_SHADOW                        )
120 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "emboss",                           MAP,       EMBOSS                              )
121 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "inputEmboss",                      MAP,       INPUT_EMBOSS                        )
122 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "outline",                          MAP,       OUTLINE                             )
123 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "inputOutline",                     MAP,       INPUT_OUTLINE                       )
124 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "hiddenInputSettings",              MAP,       HIDDEN_INPUT_SETTINGS               )
125 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "pixelSize",                        FLOAT,     PIXEL_SIZE                          )
126 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "enableSelection",                  BOOLEAN,   ENABLE_SELECTION                    )
127 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "placeholder",                      MAP,       PLACEHOLDER                         )
128 DALI_PROPERTY_REGISTRATION(Toolkit,                 TextField, "ellipsis",                         BOOLEAN,   ELLIPSIS                            )
129 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "enableShiftSelection",             BOOLEAN,   ENABLE_SHIFT_SELECTION              )
130 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "enableGrabHandle",                 BOOLEAN,   ENABLE_GRAB_HANDLE                  )
131 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "matchSystemLanguageDirection",     BOOLEAN,   MATCH_SYSTEM_LANGUAGE_DIRECTION     )
132 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "enableGrabHandlePopup",            BOOLEAN,   ENABLE_GRAB_HANDLE_POPUP            )
133 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "textBackground",                   VECTOR4,   BACKGROUND                          )
134 DALI_DEVEL_PROPERTY_REGISTRATION_READ_ONLY(Toolkit, TextField, "selectedText",                     STRING,    SELECTED_TEXT                       )
135 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "renderingBackend",                 INTEGER,   RENDERING_BACKEND                   )
136 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "selectedTextStart",                INTEGER,   SELECTED_TEXT_START                 )
137 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "selectedTextEnd",                  INTEGER,   SELECTED_TEXT_END                   )
138 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "enableEditing",                    BOOLEAN,   ENABLE_EDITING                      )
139 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "fontSizeScale",                    FLOAT,     FONT_SIZE_SCALE                     )
140 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "primaryCursorPosition",            INTEGER,   PRIMARY_CURSOR_POSITION             )
141 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "grabHandleColor",                  VECTOR4,   GRAB_HANDLE_COLOR                   )
142 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "inputFilter",                      MAP,       INPUT_FILTER                        )
143 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "ellipsisPosition",                 INTEGER,   ELLIPSIS_POSITION                   )
144
145 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "textChanged",           SIGNAL_TEXT_CHANGED           )
146 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "maxLengthReached",      SIGNAL_MAX_LENGTH_REACHED     )
147 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "inputStyleChanged",     SIGNAL_INPUT_STYLE_CHANGED    )
148 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "anchorClicked",         SIGNAL_ANCHOR_CLICKED         )
149 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "inputFiltered",         SIGNAL_INPUT_FILTERED         )
150 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "cursorPositionChanged", SIGNAL_CURSOR_POSITION_CHANGED)
151 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "selectionChanged",      SIGNAL_SELECTION_CHANGED      )
152 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "selectionCleared",      SIGNAL_SELECTION_CLEARED      )
153
154 DALI_TYPE_REGISTRATION_END()
155 // clang-format on
156
157 Toolkit::TextField::InputStyle::Mask ConvertInputStyle(Text::InputStyle::Mask inputStyleMask)
158 {
159   Toolkit::TextField::InputStyle::Mask fieldInputStyleMask = Toolkit::TextField::InputStyle::NONE;
160
161   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_COLOR))
162   {
163     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::COLOR);
164   }
165   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_FAMILY))
166   {
167     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_FAMILY);
168   }
169   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_POINT_SIZE))
170   {
171     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::POINT_SIZE);
172   }
173   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_WEIGHT))
174   {
175     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE);
176   }
177   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_WIDTH))
178   {
179     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE);
180   }
181   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_SLANT))
182   {
183     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE);
184   }
185   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_UNDERLINE))
186   {
187     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::UNDERLINE);
188   }
189   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_SHADOW))
190   {
191     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::SHADOW);
192   }
193   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_EMBOSS))
194   {
195     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::EMBOSS);
196   }
197   if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_OUTLINE))
198   {
199     fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::OUTLINE);
200   }
201   return fieldInputStyleMask;
202 }
203
204 } // namespace
205
206 Toolkit::TextField TextField::New()
207 {
208   // Create the implementation, temporarily owned by this handle on stack
209   IntrusivePtr<TextField> impl = new TextField();
210
211   // Pass ownership to CustomActor handle
212   Toolkit::TextField handle(*impl);
213
214   // Second-phase init of the implementation
215   // This can only be done after the CustomActor connection has been made...
216   impl->Initialize();
217
218   return handle;
219 }
220
221 void TextField::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
222 {
223   Toolkit::TextField textField = Toolkit::TextField::DownCast(Dali::BaseHandle(object));
224
225   DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField SetProperty\n");
226
227   if(textField)
228   {
229     PropertyHandler::SetProperty(textField, index, value);
230   }
231 }
232
233 Property::Value TextField::GetProperty(BaseObject* object, Property::Index index)
234 {
235   Property::Value value;
236
237   Toolkit::TextField textField = Toolkit::TextField::DownCast(Dali::BaseHandle(object));
238
239   if(textField)
240   {
241     value = PropertyHandler::GetProperty(textField, index);
242   }
243
244   return value;
245 }
246
247 void TextField::SelectWholeText()
248 {
249   if(mController && mController->IsShowingRealText())
250   {
251     mController->SelectWholeText();
252     SetKeyInputFocus();
253   }
254 }
255
256 void TextField::SelectNone()
257 {
258   if(mController && mController->IsShowingRealText())
259   {
260     mController->SelectNone();
261   }
262 }
263
264 void TextField::SelectText(const uint32_t start, const uint32_t end)
265 {
266   if(mController && mController->IsShowingRealText())
267   {
268     mController->SelectText(start, end);
269     SetKeyInputFocus();
270   }
271 }
272
273 string TextField::GetSelectedText() const
274 {
275   string selectedText = "";
276   if(mController && mController->IsShowingRealText())
277   {
278     selectedText = mController->GetSelectedText();
279   }
280   return selectedText;
281 }
282
283 void TextField::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
284 {
285   if(mController && mController->IsShowingRealText())
286   {
287     mController->SetTextSelectionRange(start, end);
288     SetKeyInputFocus();
289   }
290 }
291
292 Uint32Pair TextField::GetTextSelectionRange() const
293 {
294   Uint32Pair range;
295   if(mController && mController->IsShowingRealText())
296   {
297     range = mController->GetTextSelectionRange();
298   }
299   return range;
300 }
301
302 string TextField::CopyText()
303 {
304   string copiedText = "";
305   if(mController && mController->IsShowingRealText())
306   {
307     copiedText = mController->CopyText();
308   }
309   return copiedText;
310 }
311
312 string TextField::CutText()
313 {
314   string cutText = "";
315   if(mController && mController->IsShowingRealText())
316   {
317     cutText = mController->CutText();
318   }
319   return cutText;
320 }
321
322 void TextField::PasteText()
323 {
324   if(mController)
325   {
326     SetKeyInputFocus(); //Giving focus to the field that was passed to the PasteText in case the passed field (current field) doesn't have focus.
327     mController->PasteText();
328   }
329 }
330
331 InputMethodContext TextField::GetInputMethodContext()
332 {
333   return mInputMethodContext;
334 }
335
336 bool TextField::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
337 {
338   Dali::BaseHandle handle(object);
339
340   bool               connected(true);
341   Toolkit::TextField field = Toolkit::TextField::DownCast(handle);
342
343   if(0 == strcmp(signalName.c_str(), SIGNAL_TEXT_CHANGED))
344   {
345     field.TextChangedSignal().Connect(tracker, functor);
346   }
347   else if(0 == strcmp(signalName.c_str(), SIGNAL_MAX_LENGTH_REACHED))
348   {
349     field.MaxLengthReachedSignal().Connect(tracker, functor);
350   }
351   else if(0 == strcmp(signalName.c_str(), SIGNAL_INPUT_STYLE_CHANGED))
352   {
353     field.InputStyleChangedSignal().Connect(tracker, functor);
354   }
355   else if(0 == strcmp(signalName.c_str(), SIGNAL_ANCHOR_CLICKED))
356   {
357     if(field)
358     {
359       Internal::TextField& fieldImpl(GetImpl(field));
360       fieldImpl.AnchorClickedSignal().Connect(tracker, functor);
361     }
362   }
363   else if(0 == strcmp(signalName.c_str(), SIGNAL_CURSOR_POSITION_CHANGED))
364   {
365     if(field)
366     {
367       Internal::TextField& fieldImpl(GetImpl(field));
368       fieldImpl.CursorPositionChangedSignal().Connect(tracker, functor);
369     }
370   }
371   else if(0 == strcmp(signalName.c_str(), SIGNAL_INPUT_FILTERED))
372   {
373     if(field)
374     {
375       Internal::TextField& fieldImpl(GetImpl(field));
376       fieldImpl.InputFilteredSignal().Connect(tracker, functor);
377     }
378   }
379   else if(0 == strcmp(signalName.c_str(), SIGNAL_SELECTION_CHANGED))
380   {
381     if(field)
382     {
383       Internal::TextField& fieldImpl(GetImpl(field));
384       fieldImpl.SelectionChangedSignal().Connect(tracker, functor);
385     }
386   }
387   else if(0 == strcmp(signalName.c_str(), SIGNAL_SELECTION_CLEARED))
388   {
389     if(field)
390     {
391       Internal::TextField& fieldImpl(GetImpl(field));
392       fieldImpl.SelectionClearedSignal().Connect(tracker, functor);
393     }
394   }
395   else
396   {
397     // signalName does not match any signal
398     connected = false;
399   }
400
401   return connected;
402 }
403
404 Toolkit::TextField::TextChangedSignalType& TextField::TextChangedSignal()
405 {
406   return mTextChangedSignal;
407 }
408
409 Toolkit::TextField::MaxLengthReachedSignalType& TextField::MaxLengthReachedSignal()
410 {
411   return mMaxLengthReachedSignal;
412 }
413
414 Toolkit::TextField::InputStyleChangedSignalType& TextField::InputStyleChangedSignal()
415 {
416   return mInputStyleChangedSignal;
417 }
418
419 DevelTextField::AnchorClickedSignalType& TextField::AnchorClickedSignal()
420 {
421   return mAnchorClickedSignal;
422 }
423
424 DevelTextField::CursorPositionChangedSignalType& TextField::CursorPositionChangedSignal()
425 {
426   return mCursorPositionChangedSignal;
427 }
428
429 DevelTextField::InputFilteredSignalType& TextField::InputFilteredSignal()
430 {
431   return mInputFilteredSignal;
432 }
433
434 DevelTextField::SelectionChangedSignalType& TextField::SelectionChangedSignal()
435 {
436   return mSelectionChangedSignal;
437 }
438
439 DevelTextField::SelectionClearedSignalType& TextField::SelectionClearedSignal()
440 {
441   return mSelectionClearedSignal;
442 }
443
444 void TextField::OnInitialize()
445 {
446   Actor self = Self();
447
448   mController = Text::Controller::New(this, this, this, this);
449
450   // When using the vector-based rendering, the size of the GLyphs are different
451   TextAbstraction::GlyphType glyphType = (DevelText::RENDERING_VECTOR_BASED == mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH;
452   mController->SetGlyphType(glyphType);
453
454   mDecorator = Text::Decorator::New(*mController,
455                                     *mController);
456
457   mInputMethodContext = InputMethodContext::New(self);
458
459   mController->GetLayoutEngine().SetLayout(Layout::Engine::SINGLE_LINE_BOX);
460
461   // Enables the text input.
462   mController->EnableTextInput(mDecorator, mInputMethodContext);
463
464   // Enables the horizontal scrolling after the text input has been enabled.
465   mController->SetHorizontalScrollEnabled(true);
466
467   // Disables the vertical scrolling.
468   mController->SetVerticalScrollEnabled(false);
469
470   // Disable the smooth handle panning.
471   mController->SetSmoothHandlePanEnabled(false);
472
473   mController->SetNoTextDoubleTapAction(Controller::NoTextTap::HIGHLIGHT);
474   mController->SetNoTextLongPressAction(Controller::NoTextTap::HIGHLIGHT);
475
476   // Sets layoutDirection value
477   Dali::Stage                 stage           = Dali::Stage::GetCurrent();
478   Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(stage.GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
479   mController->SetLayoutDirection(layoutDirection);
480
481   self.LayoutDirectionChangedSignal().Connect(this, &TextField::OnLayoutDirectionChanged);
482
483   // Forward input events to controller
484   EnableGestureDetection(static_cast<GestureType::Value>(GestureType::TAP | GestureType::PAN | GestureType::LONG_PRESS));
485   GetTapGestureDetector().SetMaximumTapsRequired(2);
486   GetTapGestureDetector().ReceiveAllTapEvents(true);
487
488   self.TouchedSignal().Connect(this, &TextField::OnTouched);
489
490   // Set BoundingBox to stage size if not already set.
491   Rect<int> boundingBox;
492   mDecorator->GetBoundingBox(boundingBox);
493
494   if(boundingBox.IsEmpty())
495   {
496     Vector2 stageSize = Dali::Stage::GetCurrent().GetSize();
497     mDecorator->SetBoundingBox(Rect<int>(0.0f, 0.0f, stageSize.width, stageSize.height));
498   }
499
500   // Flip vertically the 'left' selection handle
501   mDecorator->FlipHandleVertically(LEFT_SELECTION_HANDLE, true);
502
503   // Fill-parent area by default
504   self.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH);
505   self.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT);
506   self.OnSceneSignal().Connect(this, &TextField::OnSceneConnect);
507
508   //Enable highightability
509   self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
510
511   DevelControl::SetInputMethodContext(*this, mInputMethodContext);
512
513   if(Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == mExceedPolicy)
514   {
515     EnableClipping();
516   }
517
518   DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
519     return std::unique_ptr<Dali::Accessibility::Accessible>(
520       new AccessibleImpl(actor, Dali::Accessibility::Role::ENTRY));
521   });
522 }
523
524 void TextField::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change)
525 {
526   DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnStyleChange\n");
527
528   switch(change)
529   {
530     case StyleChange::DEFAULT_FONT_CHANGE:
531     {
532       DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnStyleChange DEFAULT_FONT_CHANGE\n");
533       const std::string& newFont = GetImpl(styleManager).GetDefaultFontFamily();
534       // Property system did not set the font so should update it.
535       mController->UpdateAfterFontChange(newFont);
536       RelayoutRequest();
537       break;
538     }
539
540     case StyleChange::DEFAULT_FONT_SIZE_CHANGE:
541     {
542       GetImpl(styleManager).ApplyThemeStyle(Toolkit::Control(GetOwner()));
543       RelayoutRequest();
544       break;
545     }
546     case StyleChange::THEME_CHANGE:
547     {
548       // Nothing to do, let control base class handle this
549       break;
550     }
551   }
552
553   // Up call to Control
554   Control::OnStyleChange(styleManager, change);
555 }
556
557 Vector3 TextField::GetNaturalSize()
558 {
559   Extents padding;
560   padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
561
562   Vector3 naturalSize = mController->GetNaturalSize();
563   naturalSize.width += (padding.start + padding.end);
564   naturalSize.height += (padding.top + padding.bottom);
565
566   return naturalSize;
567 }
568
569 float TextField::GetHeightForWidth(float width)
570 {
571   Extents padding;
572   padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
573   return mController->GetHeightForWidth(width) + padding.top + padding.bottom;
574 }
575
576 void TextField::ResizeActor(Actor& actor, const Vector2& size)
577 {
578   if(actor.GetProperty<Vector3>(Dali::Actor::Property::SIZE).GetVectorXY() != size)
579   {
580     actor.SetProperty(Actor::Property::SIZE, size);
581   }
582 }
583
584 void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container)
585 {
586   DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField OnRelayout\n");
587
588   Actor self = Self();
589
590   Extents padding;
591   padding = self.GetProperty<Extents>(Toolkit::Control::Property::PADDING);
592
593   Vector2 contentSize(size.x - (padding.start + padding.end), size.y - (padding.top + padding.bottom));
594
595   // Support Right-To-Left of padding
596   Dali::LayoutDirection::Type layoutDirection = mController->GetLayoutDirection(self);
597
598   if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
599   {
600     std::swap(padding.start, padding.end);
601   }
602
603   if(mStencil)
604   {
605     mStencil.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top));
606     ResizeActor(mStencil, contentSize);
607   }
608   if(mActiveLayer)
609   {
610     mActiveLayer.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top));
611     ResizeActor(mActiveLayer, contentSize);
612   }
613
614   // If there is text changed, callback is called.
615   if(mTextChanged)
616   {
617     EmitTextChangedSignal();
618   }
619
620   const Text::Controller::UpdateTextType updateTextType = mController->Relayout(contentSize, layoutDirection);
621
622   if((Text::Controller::NONE_UPDATED != updateTextType) ||
623      !mRenderer)
624   {
625     DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnRelayout %p Displaying new contents\n", mController.Get());
626
627     if(mDecorator &&
628        (Text::Controller::NONE_UPDATED != (Text::Controller::DECORATOR_UPDATED & updateTextType)))
629     {
630       mDecorator->Relayout(contentSize);
631     }
632
633     if(!mRenderer)
634     {
635       mRenderer = Backend::Get().NewRenderer(mRenderingBackend);
636     }
637
638     RenderText(updateTextType);
639   }
640
641   if(mCursorPositionChanged)
642   {
643     EmitCursorPositionChangedSignal();
644   }
645
646   if(mSelectionChanged)
647   {
648     EmitSelectionChangedSignal();
649   }
650
651   if(mSelectionCleared)
652   {
653     EmitSelectionClearedSignal();
654   }
655
656   // The text-field emits signals when the input style changes. These changes of style are
657   // detected during the relayout process (size negotiation), i.e after the cursor has been moved. Signals
658   // can't be emitted during the size negotiation as the callbacks may update the UI.
659   // The text-field adds an idle callback to the adaptor to emit the signals after the size negotiation.
660   if(!mController->IsInputStyleChangedSignalsQueueEmpty())
661   {
662     if(Adaptor::IsAvailable())
663     {
664       Adaptor& adaptor = Adaptor::Get();
665
666       if(NULL == mIdleCallback)
667       {
668         // @note: The callback manager takes the ownership of the callback object.
669         mIdleCallback = MakeCallback(this, &TextField::OnIdleSignal);
670         adaptor.AddIdle(mIdleCallback, false);
671       }
672     }
673   }
674 }
675
676 Text::ControllerPtr TextField::GetTextController()
677 {
678   return mController;
679 }
680
681 void TextField::RenderText(Text::Controller::UpdateTextType updateTextType)
682 {
683   CommonTextUtils::RenderText(Self(), mRenderer, mController, mDecorator, mAlignmentOffset, mRenderableActor, mBackgroundActor, mStencil, mClippingDecorationActors, updateTextType);
684 }
685
686 void TextField::OnKeyInputFocusGained()
687 {
688   DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnKeyInputFocusGained %p\n", mController.Get());
689   if(mInputMethodContext && IsEditable())
690   {
691     // All input panel properties, such as layout, return key type, and input hint, should be set before input panel activates (or shows).
692     mInputMethodContext.ApplyOptions(mInputMethodOptions);
693     mInputMethodContext.NotifyTextInputMultiLine(false);
694
695     mInputMethodContext.StatusChangedSignal().Connect(this, &TextField::KeyboardStatusChanged);
696
697     mInputMethodContext.EventReceivedSignal().Connect(this, &TextField::OnInputMethodContextEvent);
698
699     // Notify that the text editing start.
700     mInputMethodContext.Activate();
701
702     // When window gain lost focus, the inputMethodContext is deactivated. Thus when window gain focus again, the inputMethodContext must be activated.
703     mInputMethodContext.SetRestoreAfterFocusLost(true);
704   }
705   ClipboardEventNotifier notifier(ClipboardEventNotifier::Get());
706
707   if(notifier)
708   {
709     notifier.ContentSelectedSignal().Connect(this, &TextField::OnClipboardTextSelected);
710   }
711
712   mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
713
714   EmitKeyInputFocusSignal(true); // Calls back into the Control hence done last.
715 }
716
717 void TextField::OnKeyInputFocusLost()
718 {
719   DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField:OnKeyInputFocusLost %p\n", mController.Get());
720   if(mInputMethodContext)
721   {
722     mInputMethodContext.StatusChangedSignal().Disconnect(this, &TextField::KeyboardStatusChanged);
723     // The text editing is finished. Therefore the inputMethodContext don't have restore activation.
724     mInputMethodContext.SetRestoreAfterFocusLost(false);
725
726     // Notify that the text editing finish.
727     mInputMethodContext.Deactivate();
728
729     mInputMethodContext.EventReceivedSignal().Disconnect(this, &TextField::OnInputMethodContextEvent);
730   }
731   ClipboardEventNotifier notifier(ClipboardEventNotifier::Get());
732
733   if(notifier)
734   {
735     notifier.ContentSelectedSignal().Disconnect(this, &TextField::OnClipboardTextSelected);
736   }
737
738   mController->KeyboardFocusLostEvent();
739
740   EmitKeyInputFocusSignal(false); // Calls back into the Control hence done last.
741 }
742
743 bool TextField::OnAccessibilityActivated()
744 {
745   SetKeyInputFocus();
746   return true;
747 }
748
749 void TextField::OnTap(const TapGesture& gesture)
750 {
751   DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnTap %p\n", mController.Get());
752   if(mInputMethodContext && IsEditable())
753   {
754     mInputMethodContext.Activate();
755   }
756   // Deliver the tap before the focus event to controller; this allows us to detect when focus is gained due to tap-gestures
757   Extents padding;
758   padding                   = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
759   const Vector2& localPoint = gesture.GetLocalPoint();
760   mController->TapEvent(gesture.GetNumberOfTaps(), localPoint.x - padding.start, localPoint.y - padding.top);
761   mController->AnchorEvent(localPoint.x - padding.start, localPoint.y - padding.top);
762
763   SetKeyInputFocus();
764 }
765
766 void TextField::OnPan(const PanGesture& gesture)
767 {
768   mController->PanEvent(gesture.GetState(), gesture.GetDisplacement());
769 }
770
771 void TextField::OnLongPress(const LongPressGesture& gesture)
772 {
773   if(mInputMethodContext && IsEditable())
774   {
775     mInputMethodContext.Activate();
776   }
777   Extents padding;
778   padding                   = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
779   const Vector2& localPoint = gesture.GetLocalPoint();
780   mController->LongPressEvent(gesture.GetState(), localPoint.x - padding.start, localPoint.y - padding.top);
781
782   SetKeyInputFocus();
783 }
784
785 bool TextField::OnKeyEvent(const KeyEvent& event)
786 {
787   DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnKeyEvent %p keyCode %d\n", mController.Get(), event.GetKeyCode());
788
789   if(Dali::DALI_KEY_ESCAPE == event.GetKeyCode() && mController->ShouldClearFocusOnEscape())
790   {
791     // Make sure ClearKeyInputFocus when only key is up
792     if(event.GetState() == KeyEvent::UP)
793     {
794       ClearKeyInputFocus();
795     }
796
797     return true;
798   }
799   else if(Dali::DevelKey::DALI_KEY_RETURN == event.GetKeyCode())
800   {
801     // Do nothing when enter is comming.
802     return false;
803   }
804
805   return mController->KeyEvent(event);
806 }
807
808 void TextField::RequestTextRelayout()
809 {
810   RelayoutRequest();
811 }
812
813 bool TextField::IsEditable() const
814 {
815   return mController->IsEditable();
816 }
817
818 void TextField::SetEditable(bool editable)
819 {
820   mController->SetEditable(editable);
821   if(mInputMethodContext && !editable)
822   {
823     mInputMethodContext.Deactivate();
824   }
825 }
826
827 void TextField::TextInserted(unsigned int position, unsigned int length, const std::string& content)
828 {
829   if(Accessibility::IsUp())
830   {
831     Control::Impl::GetAccessibilityObject(Self())->EmitTextInserted(position, length, content);
832   }
833 }
834
835 void TextField::TextDeleted(unsigned int position, unsigned int length, const std::string& content)
836 {
837   if(Accessibility::IsUp())
838   {
839     Control::Impl::GetAccessibilityObject(Self())->EmitTextDeleted(position, length, content);
840   }
841 }
842
843 void TextField::CursorPositionChanged(unsigned int oldPosition, unsigned int newPosition)
844 {
845   if(Accessibility::IsUp())
846   {
847     Control::Impl::GetAccessibilityObject(Self())->EmitTextCursorMoved(newPosition);
848   }
849
850   if((oldPosition != newPosition) && !mCursorPositionChanged)
851   {
852     mCursorPositionChanged = true;
853     mOldPosition           = oldPosition;
854   }
855 }
856
857 void TextField::TextChanged(bool immediate)
858 {
859   if(immediate) // Emits TextChangedSignal immediately
860   {
861     EmitTextChangedSignal();
862   }
863   else
864   {
865     mTextChanged = true;
866   }
867 }
868
869 void TextField::EmitTextChangedSignal()
870 {
871   Dali::Toolkit::TextField handle(GetOwner());
872   mTextChangedSignal.Emit(handle);
873   mTextChanged = false;
874 }
875
876 void TextField::MaxLengthReached()
877 {
878   Dali::Toolkit::TextField handle(GetOwner());
879   mMaxLengthReachedSignal.Emit(handle);
880 }
881
882 void TextField::InputStyleChanged(Text::InputStyle::Mask inputStyleMask)
883 {
884   Dali::Toolkit::TextField handle(GetOwner());
885   mInputStyleChangedSignal.Emit(handle, ConvertInputStyle(inputStyleMask));
886 }
887
888 void TextField::AnchorClicked(const std::string& href)
889 {
890   Dali::Toolkit::TextField handle(GetOwner());
891   mAnchorClickedSignal.Emit(handle, href.c_str(), href.length());
892 }
893
894 void TextField::EmitCursorPositionChangedSignal()
895 {
896   Dali::Toolkit::TextField handle(GetOwner());
897   mCursorPositionChangedSignal.Emit(handle, mOldPosition);
898   mCursorPositionChanged = false;
899 }
900
901 void TextField::InputFiltered(Toolkit::InputFilter::Property::Type type)
902 {
903   Dali::Toolkit::TextField handle(GetOwner());
904   mInputFilteredSignal.Emit(handle, type);
905 }
906
907 void TextField::EmitSelectionChangedSignal()
908 {
909   Dali::Toolkit::TextField handle(GetOwner());
910   mSelectionChangedSignal.Emit(handle, mOldSelectionStart, mOldSelectionEnd);
911   mSelectionChanged = false;
912 }
913
914 void TextField::EmitSelectionClearedSignal()
915 {
916   Dali::Toolkit::TextField handle(GetOwner());
917   mSelectionClearedSignal.Emit(handle);
918   mSelectionCleared = false;
919 }
920
921 void TextField::SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t newStart, uint32_t newEnd)
922 {
923   if(((oldStart != newStart) || (oldEnd != newEnd)) && !mSelectionChanged)
924   {
925     if(newStart == newEnd)
926     {
927       mSelectionCleared = true;
928     }
929
930     mSelectionChanged  = true;
931     mOldSelectionStart = oldStart;
932     mOldSelectionEnd   = oldEnd;
933
934     if(mOldSelectionStart > mOldSelectionEnd)
935     {
936       //swap
937       uint32_t temp      = mOldSelectionStart;
938       mOldSelectionStart = mOldSelectionEnd;
939       mOldSelectionEnd   = temp;
940     }
941   }
942 }
943
944 void TextField::AddDecoration(Actor& actor, bool needsClipping)
945 {
946   if(actor)
947   {
948     if(needsClipping)
949     {
950       mClippingDecorationActors.push_back(actor);
951     }
952     else
953     {
954       actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
955       actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
956       Self().Add(actor);
957       mActiveLayer = actor;
958     }
959   }
960 }
961
962 void TextField::GetControlBackgroundColor(Vector4& color) const
963 {
964   Property::Value propValue = Self().GetProperty(Toolkit::Control::Property::BACKGROUND);
965   Property::Map*  resultMap = propValue.GetMap();
966
967   Property::Value* colorValue = nullptr;
968   if(resultMap && (colorValue = resultMap->Find(ColorVisual::Property::MIX_COLOR)))
969   {
970     colorValue->Get(color);
971   }
972 }
973
974 void TextField::OnSceneConnect(Dali::Actor actor)
975 {
976   if(mHasBeenStaged)
977   {
978     RenderText(static_cast<Text::Controller::UpdateTextType>(Text::Controller::MODEL_UPDATED | Text::Controller::DECORATOR_UPDATED));
979   }
980   else
981   {
982     mHasBeenStaged = true;
983   }
984 }
985
986 InputMethodContext::CallbackData TextField::OnInputMethodContextEvent(Dali::InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
987 {
988   DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnInputMethodContextEvent %p eventName %d\n", mController.Get(), inputMethodContextEvent.eventName);
989   return mController->OnInputMethodContextEvent(inputMethodContext, inputMethodContextEvent);
990 }
991
992 void TextField::GetHandleImagePropertyValue(Property::Value& value, Text::HandleType handleType, Text::HandleImageType handleImageType)
993 {
994   if(mDecorator)
995   {
996     Property::Map map;
997     map[PropertyHandler::IMAGE_MAP_FILENAME_STRING] = mDecorator->GetHandleImage(handleType, handleImageType);
998
999     value = map;
1000   }
1001 }
1002
1003 void TextField::EnableClipping()
1004 {
1005   if(!mStencil)
1006   {
1007     // Creates an extra control to be used as stencil buffer.
1008     mStencil = Control::New();
1009     mStencil.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1010     mStencil.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
1011
1012     // Creates a background visual. Even if the color is transparent it updates the stencil.
1013     mStencil.SetProperty(Toolkit::Control::Property::BACKGROUND,
1014                          Property::Map().Add(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR).Add(ColorVisual::Property::MIX_COLOR, Color::TRANSPARENT));
1015
1016     // Enable the clipping property.
1017     mStencil.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_TO_BOUNDING_BOX);
1018     mStencil.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
1019
1020     Self().Add(mStencil);
1021   }
1022 }
1023
1024 void TextField::OnClipboardTextSelected(ClipboardEventNotifier& clipboard)
1025 {
1026   mController->PasteClipboardItemEvent();
1027 }
1028
1029 void TextField::KeyboardStatusChanged(bool keyboardShown)
1030 {
1031   DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::KeyboardStatusChanged %p keyboardShown %d\n", mController.Get(), keyboardShown);
1032
1033   // Just hide the grab handle when keyboard is hidden.
1034   if(!keyboardShown)
1035   {
1036     mController->KeyboardFocusLostEvent();
1037   }
1038   else
1039   {
1040     mController->KeyboardFocusGainEvent(); // Initially called by OnKeyInputFocusGained
1041   }
1042 }
1043
1044 void TextField::OnSceneConnection(int depth)
1045 {
1046   // Sets the depth to the visuals inside the text's decorator.
1047   mDecorator->SetTextDepth(depth);
1048
1049   // The depth of the text renderer is set in the RenderText() called from OnRelayout().
1050
1051   // Call the Control::OnSceneConnection() to set the depth of the background.
1052   Control::OnSceneConnection(depth);
1053 }
1054
1055 bool TextField::OnTouched(Actor actor, const TouchEvent& touch)
1056 {
1057   return false;
1058 }
1059
1060 void TextField::OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type)
1061 {
1062   mController->ChangedLayoutDirection();
1063 }
1064
1065 void TextField::OnIdleSignal()
1066 {
1067   // Emits the change of input style signals.
1068   mController->ProcessInputStyleChangedSignals();
1069
1070   // Set the pointer to null as the callback manager deletes the callback after execute it.
1071   mIdleCallback = NULL;
1072 }
1073
1074 TextField::TextField()
1075 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
1076   mIdleCallback(NULL),
1077   mAlignmentOffset(0.f),
1078   mRenderingBackend(DEFAULT_RENDERING_BACKEND),
1079   mExceedPolicy(Dali::Toolkit::TextField::EXCEED_POLICY_CLIP),
1080   mHasBeenStaged(false),
1081   mTextChanged(false),
1082   mCursorPositionChanged(false),
1083   mSelectionChanged(false),
1084   mSelectionCleared(false),
1085   mOldPosition(0u),
1086   mOldSelectionStart(0u),
1087   mOldSelectionEnd(0u)
1088 {
1089 }
1090
1091 TextField::~TextField()
1092 {
1093   UnparentAndReset(mStencil);
1094
1095   if((NULL != mIdleCallback) && Adaptor::IsAvailable())
1096   {
1097     Adaptor::Get().RemoveIdle(mIdleCallback);
1098   }
1099 }
1100
1101 std::string TextField::AccessibleImpl::GetName()
1102 {
1103   auto self = Toolkit::TextField::DownCast(Self());
1104   return self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
1105 }
1106
1107 std::string TextField::AccessibleImpl::GetText(size_t startOffset, size_t endOffset)
1108 {
1109   if(endOffset <= startOffset)
1110   {
1111     return {};
1112   }
1113
1114   auto self = Toolkit::TextField::DownCast(Self());
1115   auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
1116
1117   if(startOffset > text.size() || endOffset > text.size())
1118   {
1119     return {};
1120   }
1121
1122   return text.substr(startOffset, endOffset - startOffset);
1123 }
1124
1125 size_t TextField::AccessibleImpl::GetCharacterCount()
1126 {
1127   auto self = Toolkit::TextField::DownCast(Self());
1128   auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
1129
1130   return text.size();
1131 }
1132
1133 size_t TextField::AccessibleImpl::GetCursorOffset()
1134 {
1135   auto self = Toolkit::TextField::DownCast(Self());
1136   return Dali::Toolkit::GetImpl(self).GetTextController()->GetCursorPosition();
1137 }
1138
1139 bool TextField::AccessibleImpl::SetCursorOffset(size_t offset)
1140 {
1141   auto self = Toolkit::TextField::DownCast(Self());
1142   auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
1143   if(offset > text.size())
1144   {
1145     return false;
1146   }
1147
1148   auto& selfImpl = Dali::Toolkit::GetImpl(self);
1149   selfImpl.GetTextController()->ResetCursorPosition(offset);
1150   selfImpl.RequestTextRelayout();
1151
1152   return true;
1153 }
1154
1155 Dali::Accessibility::Range TextField::AccessibleImpl::GetTextAtOffset(
1156   size_t offset, Dali::Accessibility::TextBoundary boundary)
1157 {
1158   auto self     = Toolkit::TextField::DownCast(Self());
1159   auto text     = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
1160   auto textSize = text.size();
1161
1162   auto range = Dali::Accessibility::Range{};
1163
1164   switch(boundary)
1165   {
1166     case Dali::Accessibility::TextBoundary::CHARACTER:
1167     {
1168       if(offset < textSize)
1169       {
1170         range.content     = text[offset];
1171         range.startOffset = offset;
1172         range.endOffset   = offset + 1;
1173       }
1174       break;
1175     }
1176     case Dali::Accessibility::TextBoundary::WORD:
1177     case Dali::Accessibility::TextBoundary::LINE:
1178     {
1179       auto textString = text.c_str();
1180       auto breaks     = std::vector<char>(textSize, 0);
1181
1182       if(boundary == Dali::Accessibility::TextBoundary::WORD)
1183       {
1184         Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
1185       }
1186       else
1187       {
1188         Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
1189       }
1190
1191       auto index   = 0u;
1192       auto counter = 0u;
1193       while(index < textSize && counter <= offset)
1194       {
1195         auto start = index;
1196         if(breaks[index])
1197         {
1198           while(breaks[index])
1199           {
1200             index++;
1201           }
1202           counter++;
1203         }
1204         else
1205         {
1206           if(boundary == Dali::Accessibility::TextBoundary::WORD)
1207           {
1208             index++;
1209           }
1210           if(boundary == Dali::Accessibility::TextBoundary::LINE)
1211           {
1212             counter++;
1213           }
1214         }
1215
1216         if((counter > 0) && ((counter - 1) == offset))
1217         {
1218           range.content     = text.substr(start, index - start + 1);
1219           range.startOffset = start;
1220           range.endOffset   = index + 1;
1221         }
1222
1223         if(boundary == Dali::Accessibility::TextBoundary::LINE)
1224         {
1225           index++;
1226         }
1227       }
1228       break;
1229     }
1230     case Dali::Accessibility::TextBoundary::SENTENCE:
1231     {
1232       /* not supported by default */
1233       break;
1234     }
1235     case Dali::Accessibility::TextBoundary::PARAGRAPH:
1236     {
1237       /* Paragraph is not supported by libunibreak library */
1238       break;
1239     }
1240     default:
1241       break;
1242   }
1243
1244   return range;
1245 }
1246
1247 Dali::Accessibility::Range TextField::AccessibleImpl::GetRangeOfSelection(size_t selectionIndex)
1248 {
1249   // Since DALi supports only one selection indexes higher than 0 are ignored
1250   if(selectionIndex > 0)
1251   {
1252     return {};
1253   }
1254
1255   auto        self       = Toolkit::TextField::DownCast(Self());
1256   auto        controller = Dali::Toolkit::GetImpl(self).GetTextController();
1257   std::string value{};
1258   controller->RetrieveSelection(value);
1259   auto indices = controller->GetSelectionIndexes();
1260
1261   return {static_cast<size_t>(indices.first), static_cast<size_t>(indices.second), value};
1262 }
1263
1264 bool TextField::AccessibleImpl::RemoveSelection(size_t selectionIndex)
1265 {
1266   // Since DALi supports only one selection indexes higher than 0 are ignored
1267   if(selectionIndex > 0)
1268   {
1269     return false;
1270   }
1271
1272   auto self = Toolkit::TextField::DownCast(Self());
1273   Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(0, 0);
1274   return true;
1275 }
1276
1277 bool TextField::AccessibleImpl::SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset)
1278 {
1279   // Since DALi supports only one selection indexes higher than 0 are ignored
1280   if(selectionIndex > 0)
1281   {
1282     return false;
1283   }
1284
1285   auto self = Toolkit::TextField::DownCast(Self());
1286   Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(startOffset, endOffset);
1287   return true;
1288 }
1289
1290 bool TextField::AccessibleImpl::CopyText(size_t startPosition, size_t endPosition)
1291 {
1292   if(endPosition <= startPosition)
1293   {
1294     return false;
1295   }
1296
1297   auto self = Toolkit::TextField::DownCast(Self());
1298   auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
1299   Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
1300
1301   return true;
1302 }
1303
1304 bool TextField::AccessibleImpl::CutText(size_t startPosition, size_t endPosition)
1305 {
1306   if(endPosition <= startPosition)
1307   {
1308     return false;
1309   }
1310
1311   auto self = Toolkit::TextField::DownCast(Self());
1312   auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
1313   Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
1314
1315   self.SetProperty(Toolkit::TextField::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
1316
1317   return true;
1318 }
1319
1320 bool TextField::AccessibleImpl::DeleteText(size_t startPosition, size_t endPosition)
1321 {
1322   if(endPosition <= startPosition)
1323   {
1324     return false;
1325   }
1326
1327   auto self = Toolkit::TextField::DownCast(Self());
1328   auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
1329
1330   self.SetProperty(Toolkit::TextField::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
1331
1332   return true;
1333 }
1334
1335 Dali::Accessibility::States TextField::AccessibleImpl::CalculateStates()
1336 {
1337   using namespace Dali::Accessibility;
1338
1339   auto states = DevelControl::AccessibleImpl::CalculateStates();
1340
1341   states[State::EDITABLE]  = true;
1342   states[State::FOCUSABLE] = true;
1343
1344   Toolkit::Control focusControl = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
1345   if(mSelf == focusControl)
1346   {
1347     states[State::FOCUSED] = true;
1348   }
1349
1350   return states;
1351 }
1352
1353 bool TextField::AccessibleImpl::InsertText(size_t startPosition, std::string text)
1354 {
1355   auto self         = Toolkit::TextField::DownCast(Self());
1356   auto insertedText = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
1357
1358   insertedText.insert(startPosition, text);
1359
1360   self.SetProperty(Toolkit::TextField::Property::TEXT, std::move(insertedText));
1361
1362   return true;
1363 }
1364
1365 bool TextField::AccessibleImpl::SetTextContents(std::string newContents)
1366 {
1367   auto self = Toolkit::TextField::DownCast(Self());
1368   self.SetProperty(Toolkit::TextField::Property::TEXT, std::move(newContents));
1369   return true;
1370 }
1371
1372 } // namespace Internal
1373
1374 } // namespace Toolkit
1375
1376 } // namespace Dali