5151ef1c6849aab9e130378ffac03014efbba1c2
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-field-property-handler.cpp
1 /*
2  * Copyright (c) 2022 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 #include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
18 #include <dali-toolkit/internal/controls/text-controls/text-field-property-handler.h>
19
20 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
21 #include <dali-toolkit/devel-api/text/rendering-backend.h>
22
23 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
24 #include <dali-toolkit/internal/text/controller/text-controller.h>
25 #include <dali-toolkit/internal/text/text-effects-style.h>
26 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
27 #include <dali-toolkit/internal/text/text-font-style.h>
28 #include <dali-toolkit/public-api/text/text-enumerations.h>
29 #include <dali/integration-api/debug.h>
30
31 #if defined(DEBUG_ENABLED)
32 extern Debug::Filter* gTextFieldLogFilter;
33 #endif
34
35 namespace Dali::Toolkit::Internal
36 {
37 const char* const TextField::PropertyHandler::IMAGE_MAP_FILENAME_STRING{"filename"};
38
39 /// Retrieves a filename from a value that is a Property::Map
40 std::string TextField::PropertyHandler::GetImageFileNameFromPropertyValue(const Property::Value& value)
41 {
42   std::string          filename;
43   const Property::Map* map = value.GetMap();
44   if(map)
45   {
46     const Property::Value* filenameValue = map->Find(TextField::PropertyHandler::IMAGE_MAP_FILENAME_STRING);
47     if(filenameValue)
48     {
49       filenameValue->Get(filename);
50     }
51   }
52   return filename;
53 }
54
55 void TextField::PropertyHandler::SetProperty(Toolkit::TextField textField, Property::Index index, const Property::Value& value)
56 {
57   TextField& impl(GetImpl(textField));
58   DALI_ASSERT_DEBUG(impl.mController && "No text controller");
59   DALI_ASSERT_DEBUG(impl.mDecorator && "No text decorator");
60
61   switch(index)
62   {
63     case Toolkit::DevelTextField::Property::RENDERING_BACKEND:
64     {
65       int backend = value.Get<int>();
66       DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p RENDERING_BACKEND %d\n", impl.mController.Get(), backend);
67
68 #ifndef ENABLE_VECTOR_BASED_TEXT_RENDERING
69       if(DevelText::RENDERING_VECTOR_BASED == backend)
70       {
71         backend = TextAbstraction::BITMAP_GLYPH; // Fallback to bitmap-based rendering
72       }
73 #endif
74       if(impl.mRenderingBackend != backend)
75       {
76         impl.mRenderingBackend = backend;
77         impl.mRenderer.Reset();
78
79         // When using the vector-based rendering, the size of the GLyphs are different
80         TextAbstraction::GlyphType glyphType = (DevelText::RENDERING_VECTOR_BASED == impl.mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH;
81         impl.mController->SetGlyphType(glyphType);
82       }
83       break;
84     }
85     case Toolkit::TextField::Property::TEXT:
86     {
87       const std::string& text = value.Get<std::string>();
88       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p TEXT %s\n", impl.mController.Get(), text.c_str());
89
90       impl.mController->SetText(text);
91       break;
92     }
93
94     case Toolkit::TextField::Property::PLACEHOLDER_TEXT:
95     {
96       const std::string& text = value.Get<std::string>();
97       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT %s\n", impl.mController.Get(), text.c_str());
98
99       impl.mController->SetPlaceholderText(Text::Controller::PLACEHOLDER_TYPE_INACTIVE, text);
100       break;
101     }
102     case Toolkit::TextField::Property::PLACEHOLDER_TEXT_FOCUSED:
103     {
104       const std::string& text = value.Get<std::string>();
105       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT_FOCUSED %s\n", impl.mController.Get(), text.c_str());
106
107       impl.mController->SetPlaceholderText(Text::Controller::PLACEHOLDER_TYPE_ACTIVE, text);
108       break;
109     }
110     case Toolkit::TextField::Property::FONT_FAMILY:
111     {
112       const std::string& fontFamily = value.Get<std::string>();
113       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str());
114       impl.mController->SetDefaultFontFamily(fontFamily);
115       break;
116     }
117     case Toolkit::TextField::Property::FONT_STYLE:
118     {
119       SetFontStyleProperty(impl.mController, value, Text::FontStyle::DEFAULT);
120       break;
121     }
122     case Toolkit::TextField::Property::POINT_SIZE:
123     {
124       const float pointSize = value.Get<float>();
125       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p POINT_SIZE %f\n", impl.mController.Get(), pointSize);
126
127       if(!Equals(impl.mController->GetDefaultFontSize(Text::Controller::POINT_SIZE), pointSize))
128       {
129         impl.mController->SetDefaultFontSize(pointSize, Text::Controller::POINT_SIZE);
130       }
131       break;
132     }
133     case Toolkit::TextField::Property::MAX_LENGTH:
134     {
135       const int max = value.Get<int>();
136       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p MAX_LENGTH %d\n", impl.mController.Get(), max);
137
138       impl.mController->SetMaximumNumberOfCharacters(max);
139       break;
140     }
141     case Toolkit::TextField::Property::EXCEED_POLICY:
142     {
143       impl.mExceedPolicy = value.Get<int>();
144
145       if(Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == impl.mExceedPolicy)
146       {
147         impl.EnableClipping();
148       }
149       else
150       {
151         UnparentAndReset(impl.mStencil);
152       }
153       impl.RequestTextRelayout();
154       break;
155     }
156
157     case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT:
158     {
159       Text::HorizontalAlignment::Type alignment(static_cast<Text::HorizontalAlignment::Type>(-1)); // Set to invalid value to ensure a valid mode does get set
160       if(Text::GetHorizontalAlignmentEnumeration(value, alignment))
161       {
162         DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p HORIZONTAL_ALIGNMENT %d\n", impl.mController.Get(), alignment);
163         impl.mController->SetHorizontalAlignment(alignment);
164       }
165       break;
166     }
167     case Toolkit::TextField::Property::VERTICAL_ALIGNMENT:
168     {
169       Toolkit::Text::VerticalAlignment::Type alignment(static_cast<Text::VerticalAlignment::Type>(-1)); // Set to invalid value to ensure a valid mode does get set
170       if(Text::GetVerticalAlignmentEnumeration(value, alignment))
171       {
172         impl.mController->SetVerticalAlignment(alignment);
173         DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p VERTICAL_ALIGNMENT %d\n", impl.mController.Get(), alignment);
174       }
175       break;
176     }
177     case Toolkit::TextField::Property::TEXT_COLOR:
178     {
179       const Vector4& textColor = value.Get<Vector4>();
180       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a);
181
182       if(impl.mController->GetDefaultColor() != textColor)
183       {
184         impl.mController->SetDefaultColor(textColor);
185         impl.mController->SetInputColor(textColor);
186         impl.mRenderer.Reset();
187       }
188       break;
189     }
190     case Toolkit::TextField::Property::PLACEHOLDER_TEXT_COLOR:
191     {
192       const Vector4& textColor = value.Get<Vector4>();
193       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a);
194
195       if(impl.mController->GetPlaceholderTextColor() != textColor)
196       {
197         impl.mController->SetPlaceholderTextColor(textColor);
198         impl.mRenderer.Reset();
199       }
200       break;
201     }
202     case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR:
203     {
204       const Vector4& color = value.Get<Vector4>();
205       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p PRIMARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a);
206
207       impl.mDecorator->SetCursorColor(Toolkit::Text::PRIMARY_CURSOR, color);
208       impl.RequestTextRelayout();
209       break;
210     }
211     case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR:
212     {
213       const Vector4& color = value.Get<Vector4>();
214       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p SECONDARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a);
215
216       impl.mDecorator->SetCursorColor(Toolkit::Text::SECONDARY_CURSOR, color);
217       impl.RequestTextRelayout();
218       break;
219     }
220     case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK:
221     {
222       const bool enable = value.Get<bool>();
223       DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p ENABLE_CURSOR_BLINK %d\n", impl.mController.Get(), enable);
224
225       impl.mController->SetEnableCursorBlink(enable);
226       impl.RequestTextRelayout();
227       break;
228     }
229     case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL:
230     {
231       const float interval = value.Get<float>();
232       DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p CURSOR_BLINK_INTERVAL %f\n", impl.mController.Get(), interval);
233
234       impl.mDecorator->SetCursorBlinkInterval(interval);
235       break;
236     }
237     case Toolkit::TextField::Property::CURSOR_BLINK_DURATION:
238     {
239       const float duration = value.Get<float>();
240       DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p CURSOR_BLINK_DURATION %f\n", impl.mController.Get(), duration);
241
242       impl.mDecorator->SetCursorBlinkDuration(duration);
243       break;
244     }
245     case Toolkit::TextField::Property::CURSOR_WIDTH:
246     {
247       const int width = value.Get<int>();
248       DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p CURSOR_WIDTH %d\n", impl.mController.Get(), width);
249
250       impl.mDecorator->SetCursorWidth(width);
251       impl.mController->GetLayoutEngine().SetCursorWidth(width);
252       break;
253     }
254     case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE:
255     {
256       const std::string imageFileName = value.Get<std::string>();
257       DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p GRAB_HANDLE_IMAGE %s\n", impl.mController.Get(), imageFileName.c_str());
258
259       if(imageFileName.size())
260       {
261         impl.mDecorator->SetHandleImage(Toolkit::Text::GRAB_HANDLE, Toolkit::Text::HANDLE_IMAGE_RELEASED, imageFileName);
262         impl.RequestTextRelayout();
263       }
264       break;
265     }
266     case Toolkit::TextField::Property::GRAB_HANDLE_PRESSED_IMAGE:
267     {
268       const std::string imageFileName = value.Get<std::string>();
269       DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p GRAB_HANDLE_PRESSED_IMAGE %s\n", impl.mController.Get(), imageFileName.c_str());
270
271       if(imageFileName.size())
272       {
273         impl.mDecorator->SetHandleImage(Toolkit::Text::GRAB_HANDLE, Toolkit::Text::HANDLE_IMAGE_PRESSED, imageFileName);
274         impl.RequestTextRelayout();
275       }
276       break;
277     }
278     case Toolkit::TextField::Property::SCROLL_THRESHOLD:
279     {
280       const float threshold = value.Get<float>();
281       DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p SCROLL_THRESHOLD %f\n", impl.mController.Get(), threshold);
282
283       impl.mDecorator->SetScrollThreshold(threshold);
284       break;
285     }
286     case Toolkit::TextField::Property::SCROLL_SPEED:
287     {
288       const float speed = value.Get<float>();
289       DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField %p SCROLL_SPEED %f\n", impl.mController.Get(), speed);
290
291       impl.mDecorator->SetScrollSpeed(speed);
292       break;
293     }
294     case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_LEFT:
295     {
296       const std::string filename = GetImageFileNameFromPropertyValue(value);
297
298       if(filename.size())
299       {
300         impl.mDecorator->SetHandleImage(Toolkit::Text::LEFT_SELECTION_HANDLE, Toolkit::Text::HANDLE_IMAGE_RELEASED, filename);
301         impl.RequestTextRelayout();
302       }
303       break;
304     }
305     case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT:
306     {
307       const std::string filename = GetImageFileNameFromPropertyValue(value);
308
309       if(filename.size())
310       {
311         impl.mDecorator->SetHandleImage(Toolkit::Text::RIGHT_SELECTION_HANDLE, Toolkit::Text::HANDLE_IMAGE_RELEASED, filename);
312         impl.RequestTextRelayout();
313       }
314       break;
315     }
316     case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
317     {
318       const std::string filename = GetImageFileNameFromPropertyValue(value);
319
320       if(filename.size())
321       {
322         impl.mDecorator->SetHandleImage(Toolkit::Text::LEFT_SELECTION_HANDLE, Toolkit::Text::HANDLE_IMAGE_PRESSED, filename);
323         impl.RequestTextRelayout();
324       }
325       break;
326     }
327     case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
328     {
329       const std::string filename = GetImageFileNameFromPropertyValue(value);
330
331       if(filename.size())
332       {
333         impl.mDecorator->SetHandleImage(Toolkit::Text::RIGHT_SELECTION_HANDLE, Toolkit::Text::HANDLE_IMAGE_PRESSED, filename);
334         impl.RequestTextRelayout();
335       }
336       break;
337     }
338     case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT:
339     {
340       const std::string filename = GetImageFileNameFromPropertyValue(value);
341
342       if(filename.size())
343       {
344         impl.mDecorator->SetHandleImage(Toolkit::Text::LEFT_SELECTION_HANDLE_MARKER,
345                                         Toolkit::Text::HANDLE_IMAGE_RELEASED,
346                                         filename);
347         impl.RequestTextRelayout();
348       }
349       break;
350     }
351     case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT:
352     {
353       const std::string filename = GetImageFileNameFromPropertyValue(value);
354
355       if(filename.size())
356       {
357         impl.mDecorator->SetHandleImage(Toolkit::Text::RIGHT_SELECTION_HANDLE_MARKER,
358                                         Toolkit::Text::HANDLE_IMAGE_RELEASED,
359                                         filename);
360         impl.RequestTextRelayout();
361       }
362       break;
363     }
364     case Toolkit::TextField::Property::SELECTION_HIGHLIGHT_COLOR:
365     {
366       const Vector4 color = value.Get<Vector4>();
367       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p SELECTION_HIGHLIGHT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a);
368
369       impl.mDecorator->SetHighlightColor(color);
370       impl.RequestTextRelayout();
371       break;
372     }
373     case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX:
374     {
375       const Rect<int>& box = value.Get<Rect<int> >();
376       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p DECORATION_BOUNDING_BOX %d,%d %dx%d\n", impl.mController.Get(), box.x, box.y, box.width, box.height);
377
378       impl.mDecorator->SetBoundingBox(box);
379       impl.RequestTextRelayout();
380       break;
381     }
382     case Toolkit::TextField::Property::INPUT_METHOD_SETTINGS:
383     {
384       const Property::Map* map = value.GetMap();
385       if(map)
386       {
387         impl.mInputMethodOptions.ApplyProperty(*map);
388       }
389       impl.mController->SetInputModePassword(impl.mInputMethodOptions.IsPassword());
390
391       Toolkit::Control control = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
392       if(control == textField)
393       {
394         impl.mInputMethodContext.ApplyOptions(impl.mInputMethodOptions);
395       }
396       break;
397     }
398     case Toolkit::TextField::Property::INPUT_COLOR:
399     {
400       const Vector4& inputColor = value.Get<Vector4>();
401       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p INPUT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), inputColor.r, inputColor.g, inputColor.b, inputColor.a);
402
403       impl.mController->SetInputColor(inputColor);
404       break;
405     }
406     case Toolkit::TextField::Property::ENABLE_MARKUP:
407     {
408       const bool enableMarkup = value.Get<bool>();
409       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ENABLE_MARKUP %d\n", impl.mController.Get(), enableMarkup);
410
411       impl.mController->SetMarkupProcessorEnabled(enableMarkup);
412       CommonTextUtils::SynchronizeTextAnchorsInParent(textField, impl.mController, impl.mAnchorActors);
413       break;
414     }
415     case Toolkit::TextField::Property::INPUT_FONT_FAMILY:
416     {
417       const std::string& fontFamily = value.Get<std::string>();
418       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p INPUT_FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str());
419       impl.mController->SetInputFontFamily(fontFamily);
420       break;
421     }
422     case Toolkit::TextField::Property::INPUT_FONT_STYLE:
423     {
424       SetFontStyleProperty(impl.mController, value, Text::FontStyle::INPUT);
425       break;
426     }
427     case Toolkit::TextField::Property::INPUT_POINT_SIZE:
428     {
429       const float pointSize = value.Get<float>();
430       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p INPUT_POINT_SIZE %f\n", impl.mController.Get(), pointSize);
431       impl.mController->SetInputFontPointSize(pointSize);
432       break;
433     }
434     case Toolkit::TextField::Property::UNDERLINE:
435     {
436       const bool update = SetUnderlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT);
437       if(update)
438       {
439         impl.mRenderer.Reset();
440       }
441       break;
442     }
443     case Toolkit::TextField::Property::INPUT_UNDERLINE:
444     {
445       const bool update = SetUnderlineProperties(impl.mController, value, Text::EffectStyle::INPUT);
446       if(update)
447       {
448         impl.mRenderer.Reset();
449       }
450       break;
451     }
452     case Toolkit::TextField::Property::SHADOW:
453     {
454       const bool update = SetShadowProperties(impl.mController, value, Text::EffectStyle::DEFAULT);
455       if(update)
456       {
457         impl.mRenderer.Reset();
458       }
459       break;
460     }
461     case Toolkit::TextField::Property::INPUT_SHADOW:
462     {
463       const bool update = SetShadowProperties(impl.mController, value, Text::EffectStyle::INPUT);
464       if(update)
465       {
466         impl.mRenderer.Reset();
467       }
468       break;
469     }
470     case Toolkit::TextField::Property::EMBOSS:
471     {
472       const bool update = SetEmbossProperties(impl.mController, value, Text::EffectStyle::DEFAULT);
473       if(update)
474       {
475         impl.mRenderer.Reset();
476       }
477       break;
478     }
479     case Toolkit::TextField::Property::INPUT_EMBOSS:
480     {
481       const bool update = SetEmbossProperties(impl.mController, value, Text::EffectStyle::INPUT);
482       if(update)
483       {
484         impl.mRenderer.Reset();
485       }
486       break;
487     }
488     case Toolkit::TextField::Property::OUTLINE:
489     {
490       const bool update = SetOutlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT);
491       if(update)
492       {
493         impl.mRenderer.Reset();
494       }
495       break;
496     }
497     case Toolkit::TextField::Property::INPUT_OUTLINE:
498     {
499       const bool update = SetOutlineProperties(impl.mController, value, Text::EffectStyle::INPUT);
500       if(update)
501       {
502         impl.mRenderer.Reset();
503       }
504       break;
505     }
506     case Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS:
507     {
508       const Property::Map* map = value.GetMap();
509       if(map)
510       {
511         impl.mController->SetHiddenInputOption(*map);
512         auto mode = map->Find(Toolkit::HiddenInput::Property::MODE);
513         if(mode && (mode->Get<int>() != Toolkit::HiddenInput::Mode::HIDE_NONE))
514         {
515           textField.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Accessibility::Role::PASSWORD_TEXT);
516         }
517         else
518         {
519           textField.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Accessibility::Role::ENTRY);
520         }
521       }
522       break;
523     }
524     case Toolkit::TextField::Property::PIXEL_SIZE:
525     {
526       const float pixelSize = value.Get<float>();
527       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p PIXEL_SIZE %f\n", impl.mController.Get(), pixelSize);
528
529       if(!Equals(impl.mController->GetDefaultFontSize(Text::Controller::PIXEL_SIZE), pixelSize))
530       {
531         impl.mController->SetDefaultFontSize(pixelSize, Text::Controller::PIXEL_SIZE);
532       }
533       break;
534     }
535     case Toolkit::TextField::Property::ENABLE_SELECTION:
536     {
537       const bool enableSelection = value.Get<bool>();
538       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ENABLE_SELECTION %d\n", impl.mController.Get(), enableSelection);
539       impl.mController->SetSelectionEnabled(enableSelection);
540       break;
541     }
542     case Toolkit::TextField::Property::PLACEHOLDER:
543     {
544       const Property::Map* map = value.GetMap();
545       if(map)
546       {
547         impl.mController->SetPlaceholderProperty(*map);
548       }
549       break;
550     }
551     case Toolkit::TextField::Property::ELLIPSIS:
552     {
553       const bool ellipsis = value.Get<bool>();
554       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ELLIPSIS %d\n", impl.mController.Get(), ellipsis);
555
556       impl.mController->SetTextElideEnabled(ellipsis);
557       break;
558     }
559     case Toolkit::DevelTextField::Property::ENABLE_SHIFT_SELECTION:
560     {
561       const bool shiftSelection = value.Get<bool>();
562       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ENABLE_SHIFT_SELECTION %d\n", impl.mController.Get(), shiftSelection);
563
564       impl.mController->SetShiftSelectionEnabled(shiftSelection);
565       break;
566     }
567     case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE:
568     {
569       const bool grabHandleEnabled = value.Get<bool>();
570       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ENABLE_GRAB_HANDLE %d\n", impl.mController.Get(), grabHandleEnabled);
571
572       impl.mController->SetGrabHandleEnabled(grabHandleEnabled);
573       break;
574     }
575     case Toolkit::DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
576     {
577       impl.mController->SetMatchLayoutDirection(value.Get<bool>() ? DevelText::MatchLayoutDirection::LOCALE : DevelText::MatchLayoutDirection::CONTENTS);
578       break;
579     }
580     case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP:
581     {
582       const bool grabHandlePopupEnabled = value.Get<bool>();
583       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ENABLE_GRAB_HANDLE_POPUP %d\n", impl.mController.Get(), grabHandlePopupEnabled);
584
585       impl.mController->SetGrabHandlePopupEnabled(grabHandlePopupEnabled);
586       break;
587     }
588     case Toolkit::DevelTextField::Property::BACKGROUND:
589     {
590       const Vector4 backgroundColor = value.Get<Vector4>();
591       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p BACKGROUND %f,%f,%f,%f\n", impl.mController.Get(), backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a);
592
593       impl.mController->SetBackgroundEnabled(true);
594       impl.mController->SetBackgroundColor(backgroundColor);
595       break;
596     }
597     case Toolkit::DevelTextField::Property::SELECTED_TEXT_START:
598     {
599       uint32_t start = static_cast<uint32_t>(value.Get<int>());
600       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p SELECTED_TEXT_START %d\n", impl.mController.Get(), start);
601       impl.SetTextSelectionRange(&start, nullptr);
602       break;
603     }
604     case Toolkit::DevelTextField::Property::SELECTED_TEXT_END:
605     {
606       uint32_t end = static_cast<uint32_t>(value.Get<int>());
607       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p SELECTED_TEXT_END %d\n", impl.mController.Get(), end);
608       impl.SetTextSelectionRange(nullptr, &end);
609       break;
610     }
611     case Toolkit::DevelTextField::Property::ENABLE_EDITING:
612     {
613       const bool editable = value.Get<bool>();
614       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p ENABLE_EDITING %d\n", impl.mController.Get(), editable);
615       impl.SetEditable(editable);
616       break;
617     }
618     case Toolkit::DevelTextField::Property::FONT_SIZE_SCALE:
619     {
620       const float scale = value.Get<float>();
621       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p FONT_SIZE_SCALE %f\n", impl.mController.Get(), scale);
622
623       if(!Equals(impl.mController->GetFontSizeScale(), scale))
624       {
625         impl.mController->SetFontSizeScale(scale);
626       }
627       break;
628     }
629     case Toolkit::DevelTextField::Property::ENABLE_FONT_SIZE_SCALE:
630     {
631       const bool enableFontSizeScale = value.Get<bool>();
632       if(!Equals(impl.mController->IsFontSizeScaleEnabled(), enableFontSizeScale))
633       {
634         impl.mController->SetFontSizeScaleEnabled(enableFontSizeScale);
635       }
636       break;
637     }
638     case Toolkit::DevelTextField::Property::PRIMARY_CURSOR_POSITION:
639     {
640       uint32_t position = static_cast<uint32_t>(value.Get<int>());
641       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p PRIMARY_CURSOR_POSITION %d\n", impl.mController.Get(), position);
642       if(impl.mController->SetPrimaryCursorPosition(position, impl.HasKeyInputFocus()))
643       {
644         impl.SetKeyInputFocus();
645       }
646       break;
647     }
648     case Toolkit::DevelTextField::Property::GRAB_HANDLE_COLOR:
649     {
650       const Vector4 color = value.Get<Vector4>();
651       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p GRAB_HANDLE_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a);
652
653       impl.mDecorator->SetHandleColor(color);
654       impl.RequestTextRelayout();
655       break;
656     }
657
658     case Toolkit::DevelTextField::Property::INPUT_FILTER:
659     {
660       const Property::Map* map = value.GetMap();
661       if(map)
662       {
663         impl.mController->SetInputFilterOption(*map);
664       }
665       break;
666     }
667     case Toolkit::DevelTextField::Property::ELLIPSIS_POSITION:
668     {
669       DevelText::EllipsisPosition::Type ellipsisPositionType(static_cast<DevelText::EllipsisPosition::Type>(-1)); // Set to invalid value to ensure a valid mode does get set
670       if(Text::GetEllipsisPositionTypeEnumeration(value, ellipsisPositionType))
671       {
672         DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p EllipsisPosition::Type %d\n", impl.mController.Get(), ellipsisPositionType);
673         impl.mController->SetEllipsisPosition(ellipsisPositionType);
674       }
675       break;
676     }
677     case Toolkit::DevelTextField::Property::STRIKETHROUGH:
678     {
679       const bool update = SetStrikethroughProperties(impl.mController, value, Text::EffectStyle::DEFAULT);
680       if(update)
681       {
682         impl.mRenderer.Reset();
683       }
684       break;
685     }
686     case Toolkit::DevelTextField::Property::INPUT_STRIKETHROUGH:
687     {
688       const bool update = SetStrikethroughProperties(impl.mController, value, Text::EffectStyle::INPUT);
689       if(update)
690       {
691         impl.mRenderer.Reset();
692       }
693       break;
694     }
695     case Toolkit::DevelTextField::Property::CHARACTER_SPACING:
696     {
697       const float characterSpacing = value.Get<float>();
698       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p CHARACTER_SPACING %d\n", impl.mController.Get(), characterSpacing);
699
700       impl.mController->SetCharacterSpacing(characterSpacing);
701       break;
702     }
703     case Toolkit::DevelTextField::Property::SELECTION_POPUP_STYLE:
704     {
705       const Property::Map* map = value.GetMap();
706       if(map)
707       {
708         impl.mDecorator->SetSelectionPopupStyle(*map);
709       }
710       break;
711     }
712     case Toolkit::DevelTextField::Property::REMOVE_FRONT_INSET:
713     {
714       const bool remove = value.Get<bool>();
715       impl.mController->SetRemoveFrontInset(remove);
716       break;
717     }
718     case Toolkit::DevelTextField::Property::REMOVE_BACK_INSET:
719     {
720       const bool remove = value.Get<bool>();
721       impl.mController->SetRemoveBackInset(remove);
722       break;
723     }
724   }
725 }
726
727 Property::Value TextField::PropertyHandler::GetProperty(Toolkit::TextField textField, Property::Index index)
728 {
729   Property::Value value;
730   TextField&      impl(GetImpl(textField));
731   DALI_ASSERT_DEBUG(impl.mController && "No text controller");
732   DALI_ASSERT_DEBUG(impl.mDecorator && "No text decorator");
733
734   switch(index)
735   {
736     case Toolkit::DevelTextField::Property::RENDERING_BACKEND:
737     {
738       value = impl.mRenderingBackend;
739       break;
740     }
741     case Toolkit::TextField::Property::TEXT:
742     {
743       std::string text;
744       impl.mController->GetText(text);
745       DALI_LOG_INFO(gTextFieldLogFilter, Debug::General, "TextField %p returning text: %s\n", impl.mController.Get(), text.c_str());
746       value = text;
747       break;
748     }
749     case Toolkit::TextField::Property::PLACEHOLDER_TEXT:
750     {
751       std::string text;
752       impl.mController->GetPlaceholderText(Text::Controller::PLACEHOLDER_TYPE_INACTIVE, text);
753       value = text;
754       break;
755     }
756     case Toolkit::TextField::Property::PLACEHOLDER_TEXT_FOCUSED:
757     {
758       std::string text;
759       impl.mController->GetPlaceholderText(Text::Controller::PLACEHOLDER_TYPE_ACTIVE, text);
760       value = text;
761       break;
762     }
763     case Toolkit::TextField::Property::FONT_FAMILY:
764     {
765       value = impl.mController->GetDefaultFontFamily();
766       break;
767     }
768     case Toolkit::TextField::Property::FONT_STYLE:
769     {
770       GetFontStyleProperty(impl.mController, value, Text::FontStyle::DEFAULT);
771       break;
772     }
773     case Toolkit::TextField::Property::POINT_SIZE:
774     {
775       value = impl.mController->GetDefaultFontSize(Text::Controller::POINT_SIZE);
776       break;
777     }
778     case Toolkit::TextField::Property::MAX_LENGTH:
779     {
780       value = impl.mController->GetMaximumNumberOfCharacters();
781       break;
782     }
783     case Toolkit::TextField::Property::EXCEED_POLICY:
784     {
785       value = impl.mExceedPolicy;
786       break;
787     }
788     case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT:
789     {
790       const char* name = Text::GetHorizontalAlignmentString(impl.mController->GetHorizontalAlignment());
791       if(name)
792       {
793         value = std::string(name);
794       }
795       break;
796     }
797     case Toolkit::TextField::Property::VERTICAL_ALIGNMENT:
798     {
799       const char* name = Text::GetVerticalAlignmentString(impl.mController->GetVerticalAlignment());
800
801       if(name)
802       {
803         value = std::string(name);
804       }
805       break;
806     }
807     case Toolkit::TextField::Property::TEXT_COLOR:
808     {
809       value = impl.mController->GetDefaultColor();
810       break;
811     }
812     case Toolkit::TextField::Property::PLACEHOLDER_TEXT_COLOR:
813     {
814       value = impl.mController->GetPlaceholderTextColor();
815       break;
816     }
817     case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR:
818     {
819       value = impl.mDecorator->GetColor(Text::PRIMARY_CURSOR);
820       break;
821     }
822     case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR:
823     {
824       value = impl.mDecorator->GetColor(Text::SECONDARY_CURSOR);
825       break;
826     }
827     case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK:
828     {
829       value = impl.mController->GetEnableCursorBlink();
830       break;
831     }
832     case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL:
833     {
834       value = impl.mDecorator->GetCursorBlinkInterval();
835       break;
836     }
837     case Toolkit::TextField::Property::CURSOR_BLINK_DURATION:
838     {
839       value = impl.mDecorator->GetCursorBlinkDuration();
840       break;
841     }
842     case Toolkit::TextField::Property::CURSOR_WIDTH:
843     {
844       value = impl.mDecorator->GetCursorWidth();
845       break;
846     }
847     case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE:
848     {
849       value = impl.mDecorator->GetHandleImage(Text::GRAB_HANDLE, Text::HANDLE_IMAGE_RELEASED);
850       break;
851     }
852     case Toolkit::TextField::Property::GRAB_HANDLE_PRESSED_IMAGE:
853     {
854       value = impl.mDecorator->GetHandleImage(Text::GRAB_HANDLE, Text::HANDLE_IMAGE_PRESSED);
855       break;
856     }
857     case Toolkit::TextField::Property::SCROLL_THRESHOLD:
858     {
859       value = impl.mDecorator->GetScrollThreshold();
860       break;
861     }
862     case Toolkit::TextField::Property::SCROLL_SPEED:
863     {
864       value = impl.mDecorator->GetScrollSpeed();
865       break;
866     }
867     case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_LEFT:
868     {
869       impl.GetHandleImagePropertyValue(value, Text::LEFT_SELECTION_HANDLE, Text::HANDLE_IMAGE_RELEASED);
870       break;
871     }
872     case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT:
873     {
874       impl.GetHandleImagePropertyValue(value, Text::RIGHT_SELECTION_HANDLE, Text::HANDLE_IMAGE_RELEASED);
875       break;
876     }
877     case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
878     {
879       impl.GetHandleImagePropertyValue(value, Text::LEFT_SELECTION_HANDLE, Text::HANDLE_IMAGE_PRESSED);
880       break;
881     }
882     case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
883     {
884       impl.GetHandleImagePropertyValue(value, Text::RIGHT_SELECTION_HANDLE, Text::HANDLE_IMAGE_PRESSED);
885       break;
886     }
887     case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT:
888     {
889       impl.GetHandleImagePropertyValue(value, Text::LEFT_SELECTION_HANDLE_MARKER, Text::HANDLE_IMAGE_RELEASED);
890       break;
891     }
892     case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT:
893     {
894       impl.GetHandleImagePropertyValue(value, Text::RIGHT_SELECTION_HANDLE_MARKER, Text::HANDLE_IMAGE_RELEASED);
895       break;
896     }
897     case Toolkit::TextField::Property::SELECTION_HIGHLIGHT_COLOR:
898     {
899       value = impl.mDecorator->GetHighlightColor();
900       break;
901     }
902     case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX:
903     {
904       Rect<int> boundingBox;
905       impl.mDecorator->GetBoundingBox(boundingBox);
906       value = boundingBox;
907       break;
908     }
909     case Toolkit::TextField::Property::INPUT_METHOD_SETTINGS:
910     {
911       Property::Map map;
912       impl.mInputMethodOptions.RetrieveProperty(map);
913       value = map;
914       break;
915     }
916     case Toolkit::TextField::Property::INPUT_COLOR:
917     {
918       value = impl.mController->GetInputColor();
919       break;
920     }
921     case Toolkit::TextField::Property::ENABLE_MARKUP:
922     {
923       value = impl.mController->IsMarkupProcessorEnabled();
924       break;
925     }
926     case Toolkit::TextField::Property::INPUT_FONT_FAMILY:
927     {
928       value = impl.mController->GetInputFontFamily();
929       break;
930     }
931     case Toolkit::TextField::Property::INPUT_FONT_STYLE:
932     {
933       GetFontStyleProperty(impl.mController, value, Text::FontStyle::INPUT);
934       break;
935     }
936     case Toolkit::TextField::Property::INPUT_POINT_SIZE:
937     {
938       value = impl.mController->GetInputFontPointSize();
939       break;
940     }
941     case Toolkit::TextField::Property::UNDERLINE:
942     {
943       GetUnderlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT);
944       break;
945     }
946     case Toolkit::TextField::Property::INPUT_UNDERLINE:
947     {
948       GetUnderlineProperties(impl.mController, value, Text::EffectStyle::INPUT);
949       break;
950     }
951     case Toolkit::TextField::Property::SHADOW:
952     {
953       GetShadowProperties(impl.mController, value, Text::EffectStyle::DEFAULT);
954       break;
955     }
956     case Toolkit::TextField::Property::INPUT_SHADOW:
957     {
958       GetShadowProperties(impl.mController, value, Text::EffectStyle::INPUT);
959       break;
960     }
961     case Toolkit::TextField::Property::EMBOSS:
962     {
963       GetEmbossProperties(impl.mController, value, Text::EffectStyle::DEFAULT);
964       break;
965     }
966     case Toolkit::TextField::Property::INPUT_EMBOSS:
967     {
968       GetEmbossProperties(impl.mController, value, Text::EffectStyle::INPUT);
969       break;
970     }
971     case Toolkit::TextField::Property::OUTLINE:
972     {
973       GetOutlineProperties(impl.mController, value, Text::EffectStyle::DEFAULT);
974       break;
975     }
976     case Toolkit::TextField::Property::INPUT_OUTLINE:
977     {
978       GetOutlineProperties(impl.mController, value, Text::EffectStyle::INPUT);
979       break;
980     }
981     case Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS:
982     {
983       Property::Map map;
984       impl.mController->GetHiddenInputOption(map);
985       value = map;
986       break;
987     }
988     case Toolkit::TextField::Property::PIXEL_SIZE:
989     {
990       value = impl.mController->GetDefaultFontSize(Text::Controller::PIXEL_SIZE);
991       break;
992     }
993     case Toolkit::TextField::Property::ENABLE_SELECTION:
994     {
995       value = impl.mController->IsSelectionEnabled();
996       break;
997     }
998     case Toolkit::TextField::Property::PLACEHOLDER:
999     {
1000       Property::Map map;
1001       impl.mController->GetPlaceholderProperty(map);
1002       value = map;
1003       break;
1004     }
1005     case Toolkit::TextField::Property::ELLIPSIS:
1006     {
1007       value = impl.mController->IsTextElideEnabled();
1008       break;
1009     }
1010     case Toolkit::DevelTextField::Property::ENABLE_SHIFT_SELECTION:
1011     {
1012       value = impl.mController->IsShiftSelectionEnabled();
1013       break;
1014     }
1015     case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE:
1016     {
1017       value = impl.mController->IsGrabHandleEnabled();
1018       break;
1019     }
1020     case Toolkit::DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
1021     {
1022       value = impl.mController->GetMatchLayoutDirection() != DevelText::MatchLayoutDirection::CONTENTS;
1023       break;
1024     }
1025     case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP:
1026     {
1027       value = impl.mController->IsGrabHandlePopupEnabled();
1028       break;
1029     }
1030     case Toolkit::DevelTextField::Property::BACKGROUND:
1031     {
1032       value = impl.mController->GetBackgroundColor();
1033       break;
1034     }
1035     case Toolkit::DevelTextField::Property::SELECTED_TEXT:
1036     {
1037       value = impl.mController->GetSelectedText();
1038       break;
1039     }
1040     case Toolkit::DevelTextField::Property::SELECTED_TEXT_START:
1041     {
1042       Uint32Pair range = impl.GetTextSelectionRange();
1043       value            = static_cast<int>(range.first);
1044       break;
1045     }
1046     case Toolkit::DevelTextField::Property::SELECTED_TEXT_END:
1047     {
1048       Uint32Pair range = impl.GetTextSelectionRange();
1049       value            = static_cast<int>(range.second);
1050       break;
1051     }
1052     case Toolkit::DevelTextField::Property::ENABLE_EDITING:
1053     {
1054       value = impl.IsEditable();
1055       break;
1056     }
1057     case Toolkit::DevelTextField::Property::FONT_SIZE_SCALE:
1058     {
1059       value = impl.mController->GetFontSizeScale();
1060       break;
1061     }
1062     case Toolkit::DevelTextField::Property::ENABLE_FONT_SIZE_SCALE:
1063     {
1064       value = impl.mController->IsFontSizeScaleEnabled();
1065       break;
1066     }
1067     case Toolkit::DevelTextField::Property::PRIMARY_CURSOR_POSITION:
1068     {
1069       value = static_cast<int>(impl.mController->GetPrimaryCursorPosition());
1070       break;
1071     }
1072     case Toolkit::DevelTextField::Property::GRAB_HANDLE_COLOR:
1073     {
1074       value = impl.mDecorator->GetHandleColor();
1075       break;
1076     }
1077     case Toolkit::DevelTextField::Property::INPUT_FILTER:
1078     {
1079       Property::Map map;
1080       impl.mController->GetInputFilterOption(map);
1081       value = map;
1082       break;
1083     }
1084     case Toolkit::DevelTextField::Property::ELLIPSIS_POSITION:
1085     {
1086       value = impl.mController->GetEllipsisPosition();
1087       break;
1088     }
1089     case Toolkit::DevelTextField::Property::STRIKETHROUGH:
1090     {
1091       GetStrikethroughProperties(impl.mController, value, Text::EffectStyle::DEFAULT);
1092       break;
1093     }
1094     case Toolkit::DevelTextField::Property::INPUT_STRIKETHROUGH:
1095     {
1096       GetStrikethroughProperties(impl.mController, value, Text::EffectStyle::INPUT);
1097       break;
1098     }
1099     case Toolkit::DevelTextField::Property::CHARACTER_SPACING:
1100     {
1101       value = impl.mController->GetCharacterSpacing();
1102       break;
1103     }
1104     case Toolkit::DevelTextField::Property::SELECTION_POPUP_STYLE:
1105     {
1106       Property::Map map;
1107       impl.mDecorator->GetSelectionPopupStyle(map);
1108       value = map;
1109       break;
1110     }
1111     case Toolkit::DevelTextField::Property::REMOVE_FRONT_INSET:
1112     {
1113       value = impl.mController->IsRemoveFrontInset();
1114       break;
1115     }
1116     case Toolkit::DevelTextField::Property::REMOVE_BACK_INSET:
1117     {
1118       value = impl.mController->IsRemoveBackInset();
1119       break;
1120     }
1121
1122   } //switch
1123   return value;
1124 }
1125
1126 } // namespace Dali::Toolkit::Internal