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