[dali_2.3.25] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / controller / text-controller.cpp
1 /*
2  * Copyright (c) 2024 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/text/controller/text-controller.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
23 #include <dali/devel-api/adaptor-framework/window-devel.h>
24 #include <dali/integration-api/adaptor-framework/adaptor.h>
25 #include <dali/integration-api/debug.h>
26 #include <memory.h>
27 #include <cmath>
28 #include <limits>
29
30 // INTERNAL INCLUDES
31 #include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
32 #include <dali-toolkit/internal/text/controller/text-controller-background-actor.h>
33 #include <dali-toolkit/internal/text/controller/text-controller-event-handler.h>
34 #include <dali-toolkit/internal/text/controller/text-controller-impl.h>
35 #include <dali-toolkit/internal/text/controller/text-controller-input-font-handler.h>
36 #include <dali-toolkit/internal/text/controller/text-controller-input-properties.h>
37 #include <dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h>
38 #include <dali-toolkit/internal/text/controller/text-controller-relayouter.h>
39 #include <dali-toolkit/internal/text/controller/text-controller-spannable-handler.h>
40 #include <dali-toolkit/internal/text/controller/text-controller-text-updater.h>
41 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
42 #include <dali-toolkit/internal/text/text-geometry.h>
43 namespace
44 {
45 #if defined(DEBUG_ENABLED)
46 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
47 #endif
48
49 const char* EMPTY_STRING         = "";
50 const char* MIME_TYPE_TEXT_PLAIN = "text/plain;charset=utf-8";
51 const char* MIME_TYPE_HTML       = "application/xhtml+xml";
52
53 template<typename Type>
54 void EnsureCreated(Type*& object)
55 {
56   if(!object)
57   {
58     object = new Type();
59   }
60 }
61
62 template<typename Type>
63 void EnsureCreated(std::unique_ptr<Type>& object)
64 {
65   if(!object)
66   {
67     object = std::unique_ptr<Type>(new Type());
68   }
69 }
70
71 template<typename Type, typename Arg1>
72 void EnsureCreated(Type*& object, Arg1 arg1)
73 {
74   if(!object)
75   {
76     object = new Type(arg1);
77   }
78 }
79
80 template<typename Type, typename Arg1, typename Arg2>
81 void EnsureCreated(Type*& object, Arg1 arg1, Arg2 arg2)
82 {
83   if(!object)
84   {
85     object = new Type(arg1, arg2);
86   }
87 }
88
89 float GetDpi()
90 {
91   static uint32_t horizontalDpi = 0u;
92   static uint32_t verticalDpi   = 0u;
93
94   // TODO : How can we know when fontClient DPI changed case?
95   if(DALI_UNLIKELY(horizontalDpi == 0u))
96   {
97     Dali::TextAbstraction::FontClient fontClient = Dali::TextAbstraction::FontClient::Get();
98     fontClient.GetDpi(horizontalDpi, verticalDpi);
99   }
100   return static_cast<float>(horizontalDpi);
101 }
102
103 float ConvertPixelToPoint(float pixel)
104 {
105   return pixel * 72.0f / GetDpi();
106 }
107
108 float ConvertPointToPixel(float point)
109 {
110   // Pixel size = Point size * DPI / 72.f
111   return point * GetDpi() / 72.0f;
112 }
113
114 void UpdateCursorPosition(Dali::Toolkit::Text::EventData* eventData)
115 {
116   if(eventData && Dali::Toolkit::Text::EventData::IsEditingState(eventData->mState))
117   {
118     // Update the cursor position if it's in editing mode
119     eventData->mDecoratorUpdated     = true;
120     eventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
121   }
122 }
123
124 } // namespace
125
126 namespace Dali::Toolkit::Text
127 {
128 void Controller::EnableTextInput(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
129 {
130   if(!decorator)
131   {
132     delete mImpl->mEventData;
133     mImpl->mEventData = NULL;
134
135     // Nothing else to do.
136     return;
137   }
138
139   EnsureCreated(mImpl->mEventData, decorator, inputMethodContext);
140 }
141
142 void Controller::SetGlyphType(TextAbstraction::GlyphType glyphType)
143 {
144   // Metrics for bitmap & vector based glyphs are different
145   mImpl->mMetrics->SetGlyphType(glyphType);
146
147   // Clear the font-specific data
148   mImpl->ClearFontData();
149
150   mImpl->RequestRelayout();
151 }
152
153 void Controller::SetMarkupProcessorEnabled(bool enable)
154 {
155   if(enable != mImpl->mMarkupProcessorEnabled)
156   {
157     //If Text was already set, call the SetText again for enabling or disabling markup
158     mImpl->mMarkupProcessorEnabled = enable;
159     std::string text;
160     GetText(text);
161     SetText(text);
162   }
163
164   mImpl->mModel->mVisualModel->SetMarkupProcessorEnabled(enable);
165 }
166
167 bool Controller::IsMarkupProcessorEnabled() const
168 {
169   return mImpl->mMarkupProcessorEnabled;
170 }
171
172 bool Controller::HasAnchors() const
173 {
174   return (mImpl->mMarkupProcessorEnabled && mImpl->mModel->mLogicalModel->mAnchors.Count() && mImpl->IsShowingRealText());
175 }
176
177 void Controller::SetAutoScrollEnabled(bool enable)
178 {
179   DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled[%s] SingleBox[%s]-> [%p]\n", (enable) ? "true" : "false", (mImpl->mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX) ? "true" : "false", this);
180   mImpl->SetAutoScrollEnabled(enable);
181 }
182
183 void Controller::SetAutoScrollMaxTextureExceeded(bool exceed)
184 {
185   mImpl->mIsAutoScrollMaxTextureExceeded = exceed;
186 }
187
188 bool Controller::IsAutoScrollEnabled() const
189 {
190   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", mImpl->mIsAutoScrollEnabled ? "true" : "false");
191   return mImpl->mIsAutoScrollEnabled;
192 }
193
194 CharacterDirection Controller::GetAutoScrollDirection() const
195 {
196   return mImpl->mIsTextDirectionRTL;
197 }
198
199 float Controller::GetAutoScrollLineAlignment() const
200 {
201   float offset = 0.f;
202   if(mImpl->mModel->mVisualModel && (0u != mImpl->mModel->mVisualModel->mLines.Count()))
203   {
204     offset = (*mImpl->mModel->mVisualModel->mLines.Begin()).alignmentOffset;
205   }
206   return offset;
207 }
208
209 void Controller::SetHorizontalScrollEnabled(bool enable)
210 {
211   if(mImpl->mEventData && mImpl->mEventData->mDecorator)
212   {
213     mImpl->mEventData->mDecorator->SetHorizontalScrollEnabled(enable);
214   }
215 }
216
217 bool Controller::IsHorizontalScrollEnabled() const
218 {
219   return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled();
220 }
221
222 void Controller::SetVerticalScrollEnabled(bool enable)
223 {
224   if(mImpl->mEventData && mImpl->mEventData->mDecorator)
225   {
226     mImpl->mEventData->mDecorator->SetVerticalScrollEnabled(enable);
227   }
228 }
229
230 bool Controller::IsVerticalScrollEnabled() const
231 {
232   return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsVerticalScrollEnabled();
233 }
234
235 void Controller::SetSmoothHandlePanEnabled(bool enable)
236 {
237   if(mImpl->mEventData && mImpl->mEventData->mDecorator)
238   {
239     mImpl->mEventData->mDecorator->SetSmoothHandlePanEnabled(enable);
240   }
241 }
242
243 bool Controller::IsSmoothHandlePanEnabled() const
244 {
245   return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled();
246 }
247
248 void Controller::SetMaximumNumberOfCharacters(Length maxCharacters)
249 {
250   mImpl->mMaximumNumberOfCharacters = maxCharacters;
251 }
252
253 int Controller::GetMaximumNumberOfCharacters()
254 {
255   return mImpl->mMaximumNumberOfCharacters;
256 }
257
258 void Controller::SetEnableCursorBlink(bool enable)
259 {
260   mImpl->SetEnableCursorBlink(enable);
261 }
262
263 bool Controller::GetEnableCursorBlink() const
264 {
265   return mImpl->mEventData && mImpl->mEventData->mCursorBlinkEnabled;
266 }
267
268 void Controller::SetMultiLineEnabled(bool enable)
269 {
270   mImpl->SetMultiLineEnabled(enable);
271 }
272
273 bool Controller::IsMultiLineEnabled() const
274 {
275   return Layout::Engine::MULTI_LINE_BOX == mImpl->mLayoutEngine.GetLayout();
276 }
277
278 void Controller::SetHorizontalAlignment(Text::HorizontalAlignment::Type alignment)
279 {
280   mImpl->SetHorizontalAlignment(alignment);
281 }
282
283 Text::HorizontalAlignment::Type Controller::GetHorizontalAlignment() const
284 {
285   return mImpl->mModel->mHorizontalAlignment;
286 }
287
288 void Controller::SetVerticalAlignment(VerticalAlignment::Type alignment)
289 {
290   mImpl->SetVerticalAlignment(alignment);
291 }
292
293 VerticalAlignment::Type Controller::GetVerticalAlignment() const
294 {
295   return mImpl->mModel->mVerticalAlignment;
296 }
297
298 bool Controller::IsIgnoreSpacesAfterText() const
299 {
300   return mImpl->mModel->mIgnoreSpacesAfterText;
301 }
302
303 void Controller::SetIgnoreSpacesAfterText(bool ignore)
304 {
305   mImpl->mModel->mIgnoreSpacesAfterText = ignore;
306 }
307
308 bool Controller::IsRemoveFrontInset() const
309 {
310   return mImpl->mModel->mRemoveFrontInset;
311 }
312
313 void Controller::SetRemoveFrontInset(bool remove)
314 {
315   mImpl->mModel->mRemoveFrontInset = remove;
316 }
317
318 bool Controller::IsRemoveBackInset() const
319 {
320   return mImpl->mModel->mRemoveBackInset;
321 }
322
323 void Controller::SetRemoveBackInset(bool remove)
324 {
325   mImpl->mModel->mRemoveBackInset = remove;
326 }
327
328 bool Controller::IsTextCutout() const
329 {
330   return mImpl->mTextCutout;
331 }
332
333 void Controller::SetTextCutout(bool cutout)
334 {
335   if(cutout != mImpl->mTextCutout)
336   {
337     mImpl->mModel->mVisualModel->SetCutoutEnabled(cutout);
338     mImpl->mTextCutout = cutout;
339     mImpl->RequestRelayout();
340   }
341 }
342
343 void Controller::ChangedLayoutDirection()
344 {
345   mImpl->mIsLayoutDirectionChanged = true;
346 }
347
348 void Controller::ResetFontAndStyleData()
349 {
350   mImpl->ResetFontAndStyleData();
351 }
352
353 void Controller::SetMatchLayoutDirection(DevelText::MatchLayoutDirection type)
354 {
355   mImpl->mModel->mMatchLayoutDirection = type;
356 }
357
358 DevelText::MatchLayoutDirection Controller::GetMatchLayoutDirection() const
359 {
360   return mImpl->mModel->mMatchLayoutDirection;
361 }
362
363 void Controller::SetLayoutDirection(Dali::LayoutDirection::Type layoutDirection)
364 {
365   mImpl->mLayoutDirection = layoutDirection;
366 }
367
368 Dali::LayoutDirection::Type Controller::GetLayoutDirection(Dali::Actor& actor) const
369 {
370   return mImpl->GetLayoutDirection(actor);
371 }
372
373 bool Controller::IsShowingRealText() const
374 {
375   return mImpl->IsShowingRealText();
376 }
377
378 void Controller::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode)
379 {
380   mImpl->SetLineWrapMode(lineWrapMode);
381 }
382
383 Text::LineWrap::Mode Controller::GetLineWrapMode() const
384 {
385   return mImpl->mModel->mLineWrapMode;
386 }
387
388 void Controller::SetTextElideEnabled(bool enabled)
389 {
390   mImpl->mModel->mElideEnabled = enabled;
391   mImpl->mModel->mVisualModel->SetTextElideEnabled(enabled);
392 }
393
394 bool Controller::IsTextElideEnabled() const
395 {
396   return mImpl->mModel->mElideEnabled;
397 }
398
399 void Controller::SetTextFitEnabled(bool enabled)
400 {
401   mImpl->mTextFitEnabled = enabled;
402 }
403
404 bool Controller::IsTextFitEnabled() const
405 {
406   return mImpl->mTextFitEnabled;
407 }
408
409 void Controller::SetTextFitChanged(bool changed)
410 {
411   mImpl->mTextFitChanged = changed;
412 }
413
414 bool Controller::IsTextFitChanged() const
415 {
416   return mImpl->mTextFitChanged;
417 }
418
419 void Controller::SetCurrentLineSize(float lineSize)
420 {
421   mImpl->mCurrentLineSize = lineSize;
422 }
423
424 float Controller::GetCurrentLineSize() const
425 {
426   return mImpl->mCurrentLineSize;
427 }
428
429 void Controller::SetTextFitMinSize(float minSize, FontSizeType type)
430 {
431   mImpl->mTextFitMinSize = (type == POINT_SIZE) ? minSize : ConvertPixelToPoint(minSize);
432 }
433
434 float Controller::GetTextFitMinSize() const
435 {
436   return mImpl->mTextFitMinSize;
437 }
438
439 void Controller::SetTextFitMaxSize(float maxSize, FontSizeType type)
440 {
441   mImpl->mTextFitMaxSize = (type == POINT_SIZE) ? maxSize : ConvertPixelToPoint(maxSize);
442 }
443
444 float Controller::GetTextFitMaxSize() const
445 {
446   return mImpl->mTextFitMaxSize;
447 }
448
449 void Controller::SetTextFitStepSize(float step, FontSizeType type)
450 {
451   mImpl->mTextFitStepSize = (type == POINT_SIZE) ? step : ConvertPixelToPoint(step);
452 }
453
454 float Controller::GetTextFitStepSize() const
455 {
456   return mImpl->mTextFitStepSize;
457 }
458
459 void Controller::SetTextFitContentSize(Vector2 size)
460 {
461   mImpl->mTextFitContentSize = size;
462 }
463
464 Vector2 Controller::GetTextFitContentSize() const
465 {
466   return mImpl->mTextFitContentSize;
467 }
468
469 float Controller::GetTextFitPointSize() const
470 {
471   return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFitPointSize : 0.0f;
472 }
473
474 void Controller::SetTextFitLineSize(float lineSize)
475 {
476   mImpl->mTextFitLineSize = lineSize;
477 }
478
479 void Controller::SetTextFitArrayEnabled(bool enabled)
480 {
481   mImpl->mTextFitArrayEnabled = enabled;
482   mImpl->ClearFontData();
483   mImpl->RequestRelayout();
484 }
485
486 bool Controller::IsTextFitArrayEnabled() const
487 {
488   return mImpl->mTextFitArrayEnabled;
489 }
490
491 void Controller::SetTextFitArray(std::vector<Toolkit::DevelTextLabel::FitOption>& fitOptions)
492 {
493   mImpl->mTextFitArray = fitOptions;
494 }
495
496 std::vector<Toolkit::DevelTextLabel::FitOption>& Controller::GetTextFitArray()
497 {
498   return mImpl->mTextFitArray;
499 }
500
501 void Controller::SetPlaceholderTextElideEnabled(bool enabled)
502 {
503   PlaceholderHandler::SetPlaceholderTextElideEnabled(*this, enabled);
504 }
505
506 bool Controller::IsPlaceholderTextElideEnabled() const
507 {
508   return PlaceholderHandler::IsPlaceholderTextElideEnabled(*this);
509 }
510
511 void Controller::SetSelectionEnabled(bool enabled)
512 {
513   mImpl->mEventData->mSelectionEnabled = enabled;
514 }
515
516 bool Controller::IsSelectionEnabled() const
517 {
518   return mImpl->mEventData->mSelectionEnabled;
519 }
520
521 void Controller::SetShiftSelectionEnabled(bool enabled)
522 {
523   mImpl->mEventData->mShiftSelectionFlag = enabled;
524 }
525
526 bool Controller::IsShiftSelectionEnabled() const
527 {
528   return mImpl->mEventData->mShiftSelectionFlag;
529 }
530
531 void Controller::SetGrabHandleEnabled(bool enabled)
532 {
533   mImpl->mEventData->mGrabHandleEnabled = enabled;
534 }
535
536 bool Controller::IsGrabHandleEnabled() const
537 {
538   return mImpl->mEventData->mGrabHandleEnabled;
539 }
540
541 void Controller::SetGrabHandlePopupEnabled(bool enabled)
542 {
543   mImpl->mEventData->mGrabHandlePopupEnabled = enabled;
544 }
545
546 bool Controller::IsGrabHandlePopupEnabled() const
547 {
548   return mImpl->mEventData->mGrabHandlePopupEnabled;
549 }
550
551 void Controller::SetText(const std::string& text)
552 {
553   TextUpdater::SetText(*this, text);
554 }
555
556 void Controller::GetText(std::string& text) const
557 {
558   mImpl->GetText(text);
559 }
560
561 Length Controller::GetNumberOfCharacters() const
562 {
563   return mImpl->GetNumberOfCharacters();
564 }
565
566 void Controller::SetSpannedText(const Text::Spanned& spannedText)
567 {
568   SpannableHandler::SetSpannedText(*this, spannedText);
569 }
570
571 void Controller::SetPlaceholderText(PlaceholderType type, const std::string& text)
572 {
573   PlaceholderHandler::SetPlaceholderText(*this, type, text);
574 }
575
576 void Controller::GetPlaceholderText(PlaceholderType type, std::string& text) const
577 {
578   PlaceholderHandler::GetPlaceholderText(*this, type, text);
579 }
580
581 void Controller::UpdateAfterFontChange(const std::string& newDefaultFont)
582 {
583   mImpl->UpdateAfterFontChange(newDefaultFont);
584 }
585
586 void Controller::RetrieveSelection(std::string& selectedText) const
587 {
588   mImpl->RetrieveSelection(selectedText, false);
589 }
590
591 void Controller::SetSelection(int start, int end)
592 {
593   mImpl->SetSelection(start, end);
594 }
595
596 std::pair<int, int> Controller::GetSelectionIndexes() const
597 {
598   return mImpl->GetSelectionIndexes();
599 }
600
601 void Controller::CopyStringToClipboard(const std::string& source)
602 {
603   mImpl->CopyStringToClipboard(source);
604 }
605
606 void Controller::SendSelectionToClipboard(bool deleteAfterSending)
607 {
608   mImpl->SendSelectionToClipboard(deleteAfterSending);
609 }
610
611 void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily)
612 {
613   EnsureCreated(mImpl->mFontDefaults);
614
615   if(mImpl->mFontDefaults->mFontDescription.family != defaultFontFamily)
616   {
617     mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily;
618     DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s\n", defaultFontFamily.c_str());
619     mImpl->mFontDefaults->familyDefined = !defaultFontFamily.empty();
620
621     // Update the cursor position if it's in editing mode
622     UpdateCursorPosition(mImpl->mEventData);
623
624     // Clear the font-specific data
625     mImpl->ClearFontData();
626
627     mImpl->RequestRelayout();
628   }
629 }
630
631 std::string Controller::GetDefaultFontFamily() const
632 {
633   return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.family : EMPTY_STRING;
634 }
635
636 void Controller::SetPlaceholderFontFamily(const std::string& placeholderTextFontFamily)
637 {
638   PlaceholderHandler::SetPlaceholderFontFamily(*this, placeholderTextFontFamily);
639 }
640
641 std::string Controller::GetPlaceholderFontFamily() const
642 {
643   return PlaceholderHandler::GetPlaceholderFontFamily(*this);
644 }
645
646 void Controller::SetDefaultFontWeight(FontWeight weight)
647 {
648   EnsureCreated(mImpl->mFontDefaults);
649
650   mImpl->mFontDefaults->mFontDescription.weight = weight;
651   mImpl->mFontDefaults->weightDefined           = true;
652
653   // Update the cursor position if it's in editing mode
654   UpdateCursorPosition(mImpl->mEventData);
655
656   // Clear the font-specific data
657   mImpl->ClearFontData();
658
659   mImpl->RequestRelayout();
660 }
661
662 bool Controller::IsDefaultFontWeightDefined() const
663 {
664   return mImpl->mFontDefaults && mImpl->mFontDefaults->weightDefined;
665 }
666
667 FontWeight Controller::GetDefaultFontWeight() const
668 {
669   return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.weight : TextAbstraction::FontWeight::NORMAL;
670 }
671
672 void Controller::SetPlaceholderTextFontWeight(FontWeight weight)
673 {
674   PlaceholderHandler::SetPlaceholderTextFontWeight(*this, weight);
675 }
676
677 bool Controller::IsPlaceholderTextFontWeightDefined() const
678 {
679   return PlaceholderHandler::IsPlaceholderTextFontWeightDefined(*this);
680 }
681
682 FontWeight Controller::GetPlaceholderTextFontWeight() const
683 {
684   return PlaceholderHandler::GetPlaceholderTextFontWeight(*this);
685 }
686
687 void Controller::SetDefaultFontWidth(FontWidth width)
688 {
689   EnsureCreated(mImpl->mFontDefaults);
690
691   mImpl->mFontDefaults->mFontDescription.width = width;
692   mImpl->mFontDefaults->widthDefined           = true;
693
694   // Update the cursor position if it's in editing mode
695   UpdateCursorPosition(mImpl->mEventData);
696
697   // Clear the font-specific data
698   mImpl->ClearFontData();
699
700   mImpl->RequestRelayout();
701 }
702
703 bool Controller::IsDefaultFontWidthDefined() const
704 {
705   return mImpl->mFontDefaults && mImpl->mFontDefaults->widthDefined;
706 }
707
708 FontWidth Controller::GetDefaultFontWidth() const
709 {
710   return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.width : TextAbstraction::FontWidth::NORMAL;
711 }
712
713 void Controller::SetPlaceholderTextFontWidth(FontWidth width)
714 {
715   PlaceholderHandler::SetPlaceholderTextFontWidth(*this, width);
716 }
717
718 bool Controller::IsPlaceholderTextFontWidthDefined() const
719 {
720   return PlaceholderHandler::IsPlaceholderTextFontWidthDefined(*this);
721 }
722
723 FontWidth Controller::GetPlaceholderTextFontWidth() const
724 {
725   return PlaceholderHandler::GetPlaceholderTextFontWidth(*this);
726 }
727
728 void Controller::SetDefaultFontSlant(FontSlant slant)
729 {
730   EnsureCreated(mImpl->mFontDefaults);
731
732   mImpl->mFontDefaults->mFontDescription.slant = slant;
733   mImpl->mFontDefaults->slantDefined           = true;
734
735   // Update the cursor position if it's in editing mode
736   UpdateCursorPosition(mImpl->mEventData);
737
738   // Clear the font-specific data
739   mImpl->ClearFontData();
740
741   mImpl->RequestRelayout();
742 }
743
744 bool Controller::IsDefaultFontSlantDefined() const
745 {
746   return mImpl->mFontDefaults && mImpl->mFontDefaults->slantDefined;
747 }
748
749 FontSlant Controller::GetDefaultFontSlant() const
750 {
751   return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.slant : TextAbstraction::FontSlant::NORMAL;
752 }
753
754 void Controller::SetPlaceholderTextFontSlant(FontSlant slant)
755 {
756   PlaceholderHandler::SetPlaceholderTextFontSlant(*this, slant);
757 }
758
759 bool Controller::IsPlaceholderTextFontSlantDefined() const
760 {
761   return PlaceholderHandler::IsPlaceholderTextFontSlantDefined(*this);
762 }
763
764 FontSlant Controller::GetPlaceholderTextFontSlant() const
765 {
766   return PlaceholderHandler::GetPlaceholderTextFontSlant(*this);
767 }
768
769 void Controller::SetFontSizeScale(float scale)
770 {
771   mImpl->mFontSizeScale = scale;
772
773   // No relayout is required
774   if(!mImpl->mFontSizeScaleEnabled) return;
775
776   // Update the cursor position if it's in editing mode
777   UpdateCursorPosition(mImpl->mEventData);
778
779   // Clear the font-specific data
780   mImpl->ClearFontData();
781
782   mImpl->RequestRelayout();
783 }
784
785 float Controller::GetFontSizeScale() const
786 {
787   return mImpl->mFontDefaults ? mImpl->mFontSizeScale : 1.0f;
788 }
789
790 void Controller::SetFontSizeScaleEnabled(bool enabled)
791 {
792   mImpl->mFontSizeScaleEnabled = enabled;
793
794   // Update the cursor position if it's in editing mode
795   UpdateCursorPosition(mImpl->mEventData);
796
797   // Clear the font-specific data
798   mImpl->ClearFontData();
799
800   mImpl->RequestRelayout();
801 }
802
803 bool Controller::IsFontSizeScaleEnabled() const
804 {
805   return mImpl->mFontSizeScaleEnabled;
806 }
807
808 void Controller::SetDefaultFontSize(float fontSize, FontSizeType type)
809 {
810   EnsureCreated(mImpl->mFontDefaults);
811
812   mImpl->mFontDefaults->mDefaultPointSize = (type == POINT_SIZE) ? fontSize : ConvertPixelToPoint(fontSize);
813   mImpl->mFontDefaults->sizeDefined       = true;
814
815   // Update the cursor position if it's in editing mode
816   UpdateCursorPosition(mImpl->mEventData);
817
818   // Clear the font-specific data
819   mImpl->ClearFontData();
820
821   mImpl->RequestRelayout();
822
823   if(mImpl->mEventData && EventData::INACTIVE != mImpl->mEventData->mState)
824   {
825     SetInputFontPointSize(fontSize, true);
826   }
827 }
828
829 float Controller::GetDefaultFontSize(FontSizeType type) const
830 {
831   if(mImpl->mFontDefaults)
832   {
833     return (type == POINT_SIZE) ? mImpl->mFontDefaults->mDefaultPointSize : ConvertPointToPixel(mImpl->mFontDefaults->mDefaultPointSize);
834   }
835   return 0.0f;
836 }
837
838 void Controller::SetPlaceholderTextFontSize(float fontSize, FontSizeType type)
839 {
840   PlaceholderHandler::SetPlaceholderTextFontSize(*this, fontSize, type);
841 }
842
843 float Controller::GetPlaceholderTextFontSize(FontSizeType type) const
844 {
845   return PlaceholderHandler::GetPlaceholderTextFontSize(*this, type);
846 }
847
848 void Controller::SetDefaultColor(const Vector4& color)
849 {
850   mImpl->SetDefaultColor(color);
851 }
852
853 const Vector4& Controller::GetDefaultColor() const
854 {
855   return mImpl->mTextColor;
856 }
857
858 void Controller::SetAnchorColor(const Vector4& color)
859 {
860   mImpl->SetAnchorColor(color);
861 }
862
863 const Vector4& Controller::GetAnchorColor() const
864 {
865   return mImpl->GetAnchorColor();
866 }
867
868 void Controller::SetAnchorClickedColor(const Vector4& color)
869 {
870   mImpl->SetAnchorClickedColor(color);
871 }
872
873 const Vector4& Controller::GetAnchorClickedColor() const
874 {
875   return mImpl->GetAnchorClickedColor();
876 }
877
878 void Controller::SetDisabledColorOpacity(float opacity)
879 {
880   mImpl->mDisabledColorOpacity = opacity;
881 }
882
883 float Controller::GetDisabledColorOpacity() const
884 {
885   return mImpl->mDisabledColorOpacity;
886 }
887
888 void Controller::SetUserInteractionEnabled(bool enabled)
889 {
890   mImpl->SetUserInteractionEnabled(enabled);
891 }
892
893 bool Controller::IsUserInteractionEnabled() const
894 {
895   return mImpl->mIsUserInteractionEnabled;
896 }
897
898 void Controller::SetPlaceholderTextColor(const Vector4& textColor)
899 {
900   PlaceholderHandler::SetPlaceholderTextColor(*this, textColor);
901 }
902
903 const Vector4& Controller::GetPlaceholderTextColor() const
904 {
905   return PlaceholderHandler::GetPlaceholderTextColor(*this);
906 }
907
908 void Controller::SetShadowOffset(const Vector2& shadowOffset)
909 {
910   mImpl->mModel->mVisualModel->SetShadowOffset(shadowOffset);
911   mImpl->RequestRelayout();
912 }
913
914 const Vector2& Controller::GetShadowOffset() const
915 {
916   return mImpl->mModel->mVisualModel->GetShadowOffset();
917 }
918
919 void Controller::SetShadowColor(const Vector4& shadowColor)
920 {
921   mImpl->mModel->mVisualModel->SetShadowColor(shadowColor);
922   mImpl->RequestRelayout();
923 }
924
925 const Vector4& Controller::GetShadowColor() const
926 {
927   return mImpl->mModel->mVisualModel->GetShadowColor();
928 }
929
930 void Controller::SetShadowBlurRadius(const float& shadowBlurRadius)
931 {
932   if(fabsf(GetShadowBlurRadius() - shadowBlurRadius) > Math::MACHINE_EPSILON_1)
933   {
934     mImpl->mModel->mVisualModel->SetShadowBlurRadius(shadowBlurRadius);
935     mImpl->RequestRelayout();
936   }
937 }
938
939 const float& Controller::GetShadowBlurRadius() const
940 {
941   return mImpl->mModel->mVisualModel->GetShadowBlurRadius();
942 }
943
944 void Controller::SetUnderlineColor(const Vector4& color)
945 {
946   mImpl->mModel->mVisualModel->SetUnderlineColor(color);
947   mImpl->RequestRelayout();
948 }
949
950 const Vector4& Controller::GetUnderlineColor() const
951 {
952   return mImpl->mModel->mVisualModel->GetUnderlineColor();
953 }
954
955 void Controller::SetUnderlineEnabled(bool enabled)
956 {
957   mImpl->mModel->mVisualModel->SetUnderlineEnabled(enabled);
958   mImpl->RequestRelayout();
959 }
960
961 bool Controller::IsUnderlineEnabled() const
962 {
963   return mImpl->mModel->mVisualModel->IsUnderlineEnabled();
964 }
965
966 void Controller::SetUnderlineHeight(float height)
967 {
968   mImpl->mModel->mVisualModel->SetUnderlineHeight(height);
969   mImpl->RequestRelayout();
970 }
971
972 float Controller::GetUnderlineHeight() const
973 {
974   return mImpl->mModel->mVisualModel->GetUnderlineHeight();
975 }
976
977 void Controller::SetUnderlineType(Text::Underline::Type type)
978 {
979   mImpl->mModel->mVisualModel->SetUnderlineType(type);
980
981   mImpl->RequestRelayout();
982 }
983
984 Text::Underline::Type Controller::GetUnderlineType() const
985 {
986   return mImpl->mModel->mVisualModel->GetUnderlineType();
987 }
988
989 void Controller::SetDashedUnderlineWidth(float width)
990 {
991   mImpl->mModel->mVisualModel->SetDashedUnderlineWidth(width);
992
993   mImpl->RequestRelayout();
994 }
995
996 float Controller::GetDashedUnderlineWidth() const
997 {
998   return mImpl->mModel->mVisualModel->GetDashedUnderlineWidth();
999 }
1000
1001 void Controller::SetDashedUnderlineGap(float gap)
1002 {
1003   mImpl->mModel->mVisualModel->SetDashedUnderlineGap(gap);
1004
1005   mImpl->RequestRelayout();
1006 }
1007
1008 float Controller::GetDashedUnderlineGap() const
1009 {
1010   return mImpl->mModel->mVisualModel->GetDashedUnderlineGap();
1011 }
1012
1013 void Controller::SetOutlineOffset(const Vector2& outlineOffset)
1014 {
1015   mImpl->mModel->mVisualModel->SetOutlineOffset(outlineOffset);
1016   mImpl->RequestRelayout();
1017 }
1018
1019 const Vector2& Controller::GetOutlineOffset() const
1020 {
1021   return mImpl->mModel->mVisualModel->GetOutlineOffset();
1022 }
1023
1024 void Controller::SetOutlineColor(const Vector4& color)
1025 {
1026   mImpl->mModel->mVisualModel->SetOutlineColor(color);
1027   mImpl->RequestRelayout();
1028 }
1029
1030 const Vector4& Controller::GetOutlineColor() const
1031 {
1032   return mImpl->mModel->mVisualModel->GetOutlineColor();
1033 }
1034
1035 void Controller::SetOutlineWidth(uint16_t width)
1036 {
1037   mImpl->mModel->mVisualModel->SetOutlineWidth(width);
1038   mImpl->RequestRelayout();
1039 }
1040
1041 uint16_t Controller::GetOutlineWidth() const
1042 {
1043   return mImpl->mModel->mVisualModel->GetOutlineWidth();
1044 }
1045
1046 void Controller::SetOutlineBlurRadius(const float& outlineBlurRadius)
1047 {
1048   if(fabsf(GetOutlineBlurRadius() - outlineBlurRadius) > Math::MACHINE_EPSILON_1)
1049   {
1050     mImpl->mModel->mVisualModel->SetOutlineBlurRadius(outlineBlurRadius);
1051     mImpl->RequestRelayout();
1052   }
1053 }
1054
1055 const float& Controller::GetOutlineBlurRadius() const
1056 {
1057   return mImpl->mModel->mVisualModel->GetOutlineBlurRadius();
1058 }
1059
1060 void Controller::SetBackgroundColor(const Vector4& color)
1061 {
1062   mImpl->mModel->mVisualModel->SetBackgroundColor(color);
1063   mImpl->RequestRelayout();
1064 }
1065
1066 const Vector4& Controller::GetBackgroundColor() const
1067 {
1068   return mImpl->mModel->mVisualModel->GetBackgroundColor();
1069 }
1070
1071 void Controller::SetBackgroundEnabled(bool enabled)
1072 {
1073   mImpl->mModel->mVisualModel->SetBackgroundEnabled(enabled);
1074   mImpl->RequestRelayout();
1075 }
1076
1077 bool Controller::IsBackgroundEnabled() const
1078 {
1079   return mImpl->mModel->mVisualModel->IsBackgroundEnabled();
1080 }
1081
1082 void Controller::SetDefaultEmbossProperties(const std::string& embossProperties)
1083 {
1084   EnsureCreated(mImpl->mEmbossDefaults);
1085   mImpl->mEmbossDefaults->properties = embossProperties;
1086 }
1087
1088 std::string Controller::GetDefaultEmbossProperties() const
1089 {
1090   return mImpl->mEmbossDefaults ? mImpl->mEmbossDefaults->properties : EMPTY_STRING;
1091 }
1092
1093 void Controller::SetDefaultOutlineProperties(const std::string& outlineProperties)
1094 {
1095   EnsureCreated(mImpl->mOutlineDefaults);
1096   mImpl->mOutlineDefaults->properties = outlineProperties;
1097 }
1098
1099 std::string Controller::GetDefaultOutlineProperties() const
1100 {
1101   return mImpl->mOutlineDefaults ? mImpl->mOutlineDefaults->properties : EMPTY_STRING;
1102 }
1103
1104 bool Controller::SetDefaultLineSpacing(float lineSpacing)
1105 {
1106   return mImpl->SetDefaultLineSpacing(lineSpacing);
1107 }
1108
1109 float Controller::GetDefaultLineSpacing() const
1110 {
1111   return mImpl->mLayoutEngine.GetDefaultLineSpacing();
1112 }
1113
1114 bool Controller::SetDefaultLineSize(float lineSize)
1115 {
1116   return mImpl->SetDefaultLineSize(lineSize);
1117 }
1118
1119 float Controller::GetDefaultLineSize() const
1120 {
1121   return mImpl->mLayoutEngine.GetDefaultLineSize();
1122 }
1123
1124 bool Controller::SetRelativeLineSize(float relativeLineSize)
1125 {
1126   return mImpl->SetRelativeLineSize(relativeLineSize);
1127 }
1128
1129 float Controller::GetRelativeLineSize() const
1130 {
1131   return mImpl->GetRelativeLineSize();
1132 }
1133
1134 void Controller::SetInputColor(const Vector4& color)
1135 {
1136   InputProperties::SetInputColor(*this, color);
1137 }
1138
1139 const Vector4& Controller::GetInputColor() const
1140 {
1141   return InputProperties::GetInputColor(*this);
1142 }
1143
1144 void Controller::SetInputFontFamily(const std::string& fontFamily)
1145 {
1146   InputFontHandler::SetInputFontFamily(*this, fontFamily);
1147 }
1148
1149 std::string Controller::GetInputFontFamily() const
1150 {
1151   return InputFontHandler::GetInputFontFamily(*this);
1152 }
1153
1154 void Controller::SetInputFontWeight(FontWeight weight)
1155 {
1156   InputFontHandler::SetInputFontWeight(*this, weight);
1157 }
1158
1159 bool Controller::IsInputFontWeightDefined() const
1160 {
1161   return InputFontHandler::IsInputFontWeightDefined(*this);
1162 }
1163
1164 FontWeight Controller::GetInputFontWeight() const
1165 {
1166   return InputFontHandler::GetInputFontWeight(*this);
1167 }
1168
1169 void Controller::SetInputFontWidth(FontWidth width)
1170 {
1171   InputFontHandler::SetInputFontWidth(*this, width);
1172 }
1173
1174 bool Controller::IsInputFontWidthDefined() const
1175 {
1176   return InputFontHandler::IsInputFontWidthDefined(*this);
1177 }
1178
1179 FontWidth Controller::GetInputFontWidth() const
1180 {
1181   return InputFontHandler::GetInputFontWidth(*this);
1182 }
1183
1184 void Controller::SetInputFontSlant(FontSlant slant)
1185 {
1186   InputFontHandler::SetInputFontSlant(*this, slant);
1187 }
1188
1189 bool Controller::IsInputFontSlantDefined() const
1190 {
1191   return InputFontHandler::IsInputFontSlantDefined(*this);
1192 }
1193
1194 FontSlant Controller::GetInputFontSlant() const
1195 {
1196   return InputFontHandler::GetInputFontSlant(*this);
1197 }
1198
1199 void Controller::SetInputFontPointSize(float size, bool defaultFontSizeUpdated)
1200 {
1201   InputFontHandler::SetInputFontPointSize(*this, size, defaultFontSizeUpdated);
1202 }
1203
1204 float Controller::GetInputFontPointSize() const
1205 {
1206   return InputFontHandler::GetInputFontPointSize(*this);
1207 }
1208
1209 void Controller::SetInputLineSpacing(float lineSpacing)
1210 {
1211   InputProperties::SetInputLineSpacing(*this, lineSpacing);
1212 }
1213
1214 float Controller::GetInputLineSpacing() const
1215 {
1216   return InputProperties::GetInputLineSpacing(*this);
1217 }
1218
1219 void Controller::SetInputShadowProperties(const std::string& shadowProperties)
1220 {
1221   InputProperties::SetInputShadowProperties(*this, shadowProperties);
1222 }
1223
1224 std::string Controller::GetInputShadowProperties() const
1225 {
1226   return InputProperties::GetInputShadowProperties(*this);
1227 }
1228
1229 void Controller::SetInputUnderlineProperties(const std::string& underlineProperties)
1230 {
1231   InputProperties::SetInputUnderlineProperties(*this, underlineProperties);
1232 }
1233
1234 std::string Controller::GetInputUnderlineProperties() const
1235 {
1236   return InputProperties::GetInputUnderlineProperties(*this);
1237 }
1238
1239 void Controller::SetInputEmbossProperties(const std::string& embossProperties)
1240 {
1241   InputProperties::SetInputEmbossProperties(*this, embossProperties);
1242 }
1243
1244 std::string Controller::GetInputEmbossProperties() const
1245 {
1246   return InputProperties::GetInputEmbossProperties(*this);
1247 }
1248
1249 void Controller::SetInputOutlineProperties(const std::string& outlineProperties)
1250 {
1251   InputProperties::SetInputOutlineProperties(*this, outlineProperties);
1252 }
1253
1254 std::string Controller::GetInputOutlineProperties() const
1255 {
1256   return InputProperties::GetInputOutlineProperties(*this);
1257 }
1258
1259 void Controller::SetInputModePassword(bool passwordInput)
1260 {
1261   InputProperties::SetInputModePassword(*this, passwordInput);
1262 }
1263
1264 bool Controller::IsInputModePassword()
1265 {
1266   return InputProperties::IsInputModePassword(*this);
1267 }
1268
1269 void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action)
1270 {
1271   if(mImpl->mEventData)
1272   {
1273     mImpl->mEventData->mDoubleTapAction = action;
1274   }
1275 }
1276
1277 Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
1278 {
1279   return mImpl->mEventData ? mImpl->mEventData->mDoubleTapAction : NoTextTap::NO_ACTION;
1280 }
1281
1282 void Controller::SetNoTextLongPressAction(NoTextTap::Action action)
1283 {
1284   if(mImpl->mEventData)
1285   {
1286     mImpl->mEventData->mLongPressAction = action;
1287   }
1288 }
1289
1290 Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
1291 {
1292   return mImpl->mEventData ? mImpl->mEventData->mLongPressAction : NoTextTap::NO_ACTION;
1293 }
1294
1295 bool Controller::IsUnderlineSetByString()
1296 {
1297   return mImpl->mUnderlineSetByString;
1298 }
1299
1300 void Controller::UnderlineSetByString(bool setByString)
1301 {
1302   mImpl->mUnderlineSetByString = setByString;
1303 }
1304
1305 bool Controller::IsShadowSetByString()
1306 {
1307   return mImpl->mShadowSetByString;
1308 }
1309
1310 void Controller::ShadowSetByString(bool setByString)
1311 {
1312   mImpl->mShadowSetByString = setByString;
1313 }
1314
1315 bool Controller::IsOutlineSetByString()
1316 {
1317   return mImpl->mOutlineSetByString;
1318 }
1319
1320 void Controller::OutlineSetByString(bool setByString)
1321 {
1322   mImpl->mOutlineSetByString = setByString;
1323 }
1324
1325 bool Controller::IsFontStyleSetByString()
1326 {
1327   return mImpl->mFontStyleSetByString;
1328 }
1329
1330 void Controller::FontStyleSetByString(bool setByString)
1331 {
1332   mImpl->mFontStyleSetByString = setByString;
1333 }
1334
1335 void Controller::SetStrikethroughHeight(float height)
1336 {
1337   mImpl->mModel->mVisualModel->SetStrikethroughHeight(height);
1338
1339   mImpl->RequestRelayout();
1340 }
1341
1342 float Controller::GetStrikethroughHeight() const
1343 {
1344   return mImpl->mModel->mVisualModel->GetStrikethroughHeight();
1345 }
1346
1347 void Controller::SetStrikethroughColor(const Vector4& color)
1348 {
1349   mImpl->mModel->mVisualModel->SetStrikethroughColor(color);
1350
1351   mImpl->RequestRelayout();
1352 }
1353
1354 const Vector4& Controller::GetStrikethroughColor() const
1355 {
1356   return mImpl->mModel->mVisualModel->GetStrikethroughColor();
1357 }
1358
1359 void Controller::SetStrikethroughEnabled(bool enabled)
1360 {
1361   mImpl->mModel->mVisualModel->SetStrikethroughEnabled(enabled);
1362
1363   mImpl->RequestRelayout();
1364 }
1365
1366 bool Controller::IsStrikethroughEnabled() const
1367 {
1368   return mImpl->mModel->mVisualModel->IsStrikethroughEnabled();
1369 }
1370
1371 void Controller::SetInputStrikethroughProperties(const std::string& strikethroughProperties)
1372 {
1373   if(NULL != mImpl->mEventData)
1374   {
1375     mImpl->mEventData->mInputStyle.strikethroughProperties = strikethroughProperties;
1376   }
1377 }
1378
1379 std::string Controller::GetInputStrikethroughProperties() const
1380 {
1381   return (NULL != mImpl->mEventData) ? mImpl->mEventData->mInputStyle.strikethroughProperties : EMPTY_STRING;
1382 }
1383
1384 bool Controller::IsStrikethroughSetByString()
1385 {
1386   return mImpl->mStrikethroughSetByString;
1387 }
1388
1389 void Controller::StrikethroughSetByString(bool setByString)
1390 {
1391   mImpl->mStrikethroughSetByString = setByString;
1392 }
1393
1394 Layout::Engine& Controller::GetLayoutEngine()
1395 {
1396   return mImpl->mLayoutEngine;
1397 }
1398
1399 View& Controller::GetView()
1400 {
1401   return mImpl->mView;
1402 }
1403
1404 Vector3 Controller::GetNaturalSize()
1405 {
1406   return Relayouter::GetNaturalSize(*this);
1407 }
1408
1409 bool Controller::CheckForTextFit(float pointSize, Size& layoutSize)
1410 {
1411   return Relayouter::CheckForTextFit(*this, pointSize, layoutSize);
1412 }
1413
1414 void Controller::FitPointSizeforLayout(Size layoutSize)
1415 {
1416   Relayouter::FitPointSizeforLayout(*this, layoutSize);
1417 }
1418
1419 void Controller::FitArrayPointSizeforLayout(Size layoutSize)
1420 {
1421   Relayouter::FitArrayPointSizeforLayout(*this, layoutSize);
1422 }
1423
1424 float Controller::GetHeightForWidth(float width)
1425 {
1426   return Relayouter::GetHeightForWidth(*this, width);
1427 }
1428
1429 int Controller::GetLineCount(float width)
1430 {
1431   GetHeightForWidth(width);
1432   return mImpl->mModel->GetNumberOfLines();
1433 }
1434
1435 const ModelInterface* Controller::GetTextModel() const
1436 {
1437   return mImpl->mModel.Get();
1438 }
1439
1440 float Controller::GetScrollAmountByUserInput()
1441 {
1442   float scrollAmount = 0.0f;
1443
1444   if(NULL != mImpl->mEventData && mImpl->mEventData->mCheckScrollAmount)
1445   {
1446     scrollAmount                          = mImpl->mModel->mScrollPosition.y - mImpl->mModel->mScrollPositionLast.y;
1447     mImpl->mEventData->mCheckScrollAmount = false;
1448   }
1449   return scrollAmount;
1450 }
1451
1452 bool Controller::GetTextScrollInfo(float& scrollPosition, float& controlHeight, float& layoutHeight)
1453 {
1454   const Vector2& layout = mImpl->mModel->mVisualModel->GetLayoutSize();
1455   bool           isScrolled;
1456
1457   controlHeight  = mImpl->mModel->mVisualModel->mControlSize.height;
1458   layoutHeight   = layout.height;
1459   scrollPosition = mImpl->mModel->mScrollPosition.y;
1460   isScrolled     = !Equals(mImpl->mModel->mScrollPosition.y, mImpl->mModel->mScrollPositionLast.y, Math::MACHINE_EPSILON_1);
1461   return isScrolled;
1462 }
1463
1464 void Controller::SetHiddenInputOption(const Property::Map& options)
1465 {
1466   EnsureCreated<HiddenText, Controller*>(mImpl->mHiddenInput, this);
1467   mImpl->mHiddenInput->SetProperties(options);
1468 }
1469
1470 void Controller::GetHiddenInputOption(Property::Map& options)
1471 {
1472   if(mImpl->mHiddenInput)
1473   {
1474     mImpl->mHiddenInput->GetProperties(options);
1475   }
1476 }
1477
1478 void Controller::SetInputFilterOption(const Property::Map& options)
1479 {
1480   EnsureCreated(mImpl->mInputFilter);
1481   mImpl->mInputFilter->SetProperties(options);
1482 }
1483
1484 void Controller::GetInputFilterOption(Property::Map& options)
1485 {
1486   if(mImpl->mInputFilter)
1487   {
1488     mImpl->mInputFilter->GetProperties(options);
1489   }
1490 }
1491
1492 void Controller::SetPlaceholderProperty(const Property::Map& map)
1493 {
1494   PlaceholderHandler::SetPlaceholderProperty(*this, map);
1495 }
1496
1497 void Controller::GetPlaceholderProperty(Property::Map& map)
1498 {
1499   PlaceholderHandler::GetPlaceholderProperty(*this, map);
1500 }
1501
1502 Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
1503 {
1504   // Make sure the model is up-to-date before layouting
1505   EventHandler::ProcessModifyEvents(*this);
1506
1507   return mImpl->GetTextDirection();
1508 }
1509
1510 Toolkit::DevelText::VerticalLineAlignment::Type Controller::GetVerticalLineAlignment() const
1511 {
1512   return mImpl->mModel->GetVerticalLineAlignment();
1513 }
1514
1515 void Controller::SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignment::Type alignment)
1516 {
1517   mImpl->mModel->mVerticalLineAlignment = alignment;
1518 }
1519
1520 Toolkit::DevelText::EllipsisPosition::Type Controller::GetEllipsisPosition() const
1521 {
1522   return mImpl->mModel->GetEllipsisPosition();
1523 }
1524
1525 void Controller::SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition)
1526 {
1527   mImpl->mModel->mEllipsisPosition = ellipsisPosition;
1528   mImpl->mModel->mVisualModel->SetEllipsisPosition(ellipsisPosition);
1529 }
1530
1531 void Controller::SetCharacterSpacing(float characterSpacing)
1532 {
1533   mImpl->mModel->mVisualModel->SetCharacterSpacing(characterSpacing);
1534
1535   mImpl->RelayoutAllCharacters();
1536   mImpl->RequestRelayout();
1537 }
1538
1539 const float Controller::GetCharacterSpacing() const
1540 {
1541   return mImpl->mModel->mVisualModel->GetCharacterSpacing();
1542 }
1543
1544 void Controller::SetVisualTransformOffset(Vector2 offset)
1545 {
1546   mImpl->mModel->mVisualTransformOffset = offset;
1547 }
1548
1549 void Controller::SetBackgroundWithCutoutEnabled(bool cutout)
1550 {
1551   mImpl->mModel->mVisualModel->SetBackgroundWithCutoutEnabled(cutout);
1552   RequestRelayout();
1553 }
1554
1555 bool Controller::IsBackgroundWithCutoutEnabled() const
1556 {
1557   return mImpl->mModel->mVisualModel->IsBackgroundWithCutoutEnabled();
1558 }
1559
1560 void Controller::SetBackgroundColorWithCutout(const Vector4& color)
1561 {
1562   mImpl->mModel->mVisualModel->SetBackgroundColorWithCutout(color);
1563   mImpl->RequestRelayout();
1564 }
1565
1566 const Vector4 Controller::GetBackgroundColorWithCutout() const
1567 {
1568   return mImpl->mModel->mVisualModel->GetBackgroundColorWithCutout();
1569 }
1570
1571 Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
1572 {
1573   return Relayouter::Relayout(*this, size, layoutDirection);
1574 }
1575
1576 void Controller::RequestRelayout()
1577 {
1578   mImpl->RequestRelayout();
1579 }
1580
1581 Vector<Vector2> Controller::GetTextSize(CharacterIndex startIndex, CharacterIndex endIndex)
1582 {
1583   Vector<Vector2> sizesList;
1584   Vector<Vector2> positionsList;
1585
1586   GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList);
1587   return sizesList;
1588 }
1589
1590 Vector<Vector2> Controller::GetTextPosition(CharacterIndex startIndex, CharacterIndex endIndex)
1591 {
1592   Vector<Vector2> sizesList;
1593   Vector<Vector2> positionsList;
1594
1595   GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList);
1596   return positionsList;
1597 }
1598
1599 Rect<float> Controller::GetLineBoundingRectangle(const uint32_t lineIndex)
1600 {
1601   return GetLineBoundingRect(mImpl->mModel, lineIndex);
1602 }
1603
1604 Rect<float> Controller::GetCharacterBoundingRectangle(const uint32_t charIndex)
1605 {
1606   return GetCharacterBoundingRect(mImpl->mModel, charIndex);
1607 }
1608
1609 int Controller::GetCharacterIndexAtPosition(float visualX, float visualY)
1610 {
1611   return GetCharIndexAtPosition(mImpl->mModel, visualX, visualY);
1612 }
1613
1614 Rect<> Controller::GetTextBoundingRectangle(CharacterIndex startIndex, CharacterIndex endIndex)
1615 {
1616   Vector<Vector2> sizeList;
1617   Vector<Vector2> positionList;
1618
1619   GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizeList, positionList);
1620
1621   if(sizeList.Empty() || sizeList.Size() != positionList.Size())
1622   {
1623     return {0, 0, 0, 0};
1624   }
1625
1626   auto controlWidth = mImpl->mModel->mVisualModel->mControlSize.width;
1627   auto minX         = positionList[0].x;
1628   auto minY         = positionList[0].y;
1629   auto maxRight     = positionList[0].x + sizeList[0].x;
1630   auto maxBottom    = positionList[0].y + sizeList[0].y;
1631
1632   for(unsigned int i = 1; i < sizeList.Size(); i++)
1633   {
1634     minX      = std::min(minX, positionList[i].x);
1635     minY      = std::min(minY, positionList[i].y);
1636     maxRight  = std::max(maxRight, positionList[i].x + sizeList[i].x);
1637     maxBottom = std::max(maxBottom, positionList[i].y + sizeList[i].y);
1638   }
1639
1640   if(minX < 0.0f)
1641   {
1642     minX = 0.0f;
1643   }
1644
1645   if(maxRight > controlWidth)
1646   {
1647     maxRight = controlWidth;
1648   }
1649
1650   return {minX, minY, maxRight - minX, maxBottom - minY};
1651 }
1652
1653 bool Controller::IsInputStyleChangedSignalsQueueEmpty()
1654 {
1655   return mImpl->IsInputStyleChangedSignalsQueueEmpty();
1656 }
1657
1658 void Controller::RequestProcessInputStyleChangedSignals()
1659 {
1660   if(Dali::Adaptor::IsAvailable() && !mImpl->mProcessorRegistered)
1661   {
1662     mImpl->mProcessorRegistered = true;
1663     Dali::Adaptor::Get().RegisterProcessor(*this, true);
1664   }
1665 }
1666
1667 void Controller::OnIdleSignal()
1668 {
1669   if(mImpl->mIdleCallback)
1670   {
1671     mImpl->mIdleCallback = NULL;
1672
1673     mImpl->ProcessInputStyleChangedSignals();
1674   }
1675 }
1676
1677 void Controller::KeyboardFocusGainEvent()
1678 {
1679   EventHandler::KeyboardFocusGainEvent(*this);
1680 }
1681
1682 void Controller::KeyboardFocusLostEvent()
1683 {
1684   EventHandler::KeyboardFocusLostEvent(*this);
1685 }
1686
1687 bool Controller::KeyEvent(const Dali::KeyEvent& keyEvent)
1688 {
1689   return EventHandler::KeyEvent(*this, keyEvent);
1690 }
1691
1692 void Controller::AnchorEvent(float x, float y)
1693 {
1694   EventHandler::AnchorEvent(*this, x, y);
1695 }
1696
1697 void Controller::TapEvent(unsigned int tapCount, float x, float y)
1698 {
1699   EventHandler::TapEvent(*this, tapCount, x, y);
1700 }
1701
1702 void Controller::PanEvent(GestureState state, const Vector2& displacement)
1703 {
1704   EventHandler::PanEvent(*this, state, displacement);
1705 }
1706
1707 void Controller::LongPressEvent(GestureState state, float x, float y)
1708 {
1709   EventHandler::LongPressEvent(*this, state, x, y);
1710 }
1711
1712 void Controller::SelectEvent(float x, float y, SelectionType selectType)
1713 {
1714   EventHandler::SelectEvent(*this, x, y, selectType);
1715 }
1716
1717 void Controller::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
1718 {
1719   if(mImpl->mEventData)
1720   {
1721     mImpl->mEventData->mCheckScrollAmount     = true;
1722     mImpl->mEventData->mIsLeftHandleSelected  = true;
1723     mImpl->mEventData->mIsRightHandleSelected = true;
1724     mImpl->SetTextSelectionRange(start, end);
1725     mImpl->RequestRelayout();
1726     EventHandler::KeyboardFocusGainEvent(*this);
1727   }
1728 }
1729
1730 Uint32Pair Controller::GetTextSelectionRange() const
1731 {
1732   return mImpl->GetTextSelectionRange();
1733 }
1734
1735 CharacterIndex Controller::GetPrimaryCursorPosition() const
1736 {
1737   return mImpl->GetPrimaryCursorPosition();
1738 }
1739
1740 bool Controller::SetPrimaryCursorPosition(CharacterIndex index, bool focused)
1741 {
1742   if(mImpl->mEventData)
1743   {
1744     mImpl->mEventData->mCheckScrollAmount     = true;
1745     mImpl->mEventData->mIsLeftHandleSelected  = true;
1746     mImpl->mEventData->mIsRightHandleSelected = true;
1747     mImpl->mEventData->mCheckScrollAmount     = true;
1748     if(mImpl->SetPrimaryCursorPosition(index, focused) && focused)
1749     {
1750       EventHandler::KeyboardFocusGainEvent(*this);
1751       return true;
1752     }
1753   }
1754   return false;
1755 }
1756
1757 void Controller::SelectWholeText()
1758 {
1759   EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::ALL);
1760 }
1761
1762 void Controller::SelectNone()
1763 {
1764   EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::NONE);
1765 }
1766
1767 void Controller::SelectText(const uint32_t start, const uint32_t end)
1768 {
1769   EventHandler::SelectEvent(*this, start, end, SelectionType::RANGE);
1770 }
1771
1772 string Controller::GetSelectedText() const
1773 {
1774   return mImpl->GetSelectedText();
1775 }
1776
1777 string Controller::CopyText()
1778 {
1779   return mImpl->CopyText();
1780 }
1781
1782 string Controller::CutText()
1783 {
1784   return mImpl->CutText();
1785 }
1786
1787 void Controller::PasteClipboardItemEvent(uint32_t id, const char* mimeType, const char* data)
1788 {
1789   // Upon receiving the data, it is important to disconnect the signal
1790   // to avoid potential unintended pasting caused by subsequent requests.
1791   mImpl->mClipboard.DataReceivedSignal().Disconnect(this, &Controller::PasteClipboardItemEvent);
1792
1793   // If the id is 0u, it is an invalid response.
1794   if(id == 0u)
1795   {
1796     return;
1797   }
1798
1799   // text-controller allows only plain text type.
1800   if(!strncmp(mimeType, MIME_TYPE_TEXT_PLAIN, strlen(MIME_TYPE_TEXT_PLAIN)))
1801   {
1802     EventHandler::PasteClipboardItemEvent(*this, data);
1803   }
1804   else if(!strncmp(mimeType, MIME_TYPE_HTML, strlen(MIME_TYPE_HTML)))
1805   {
1806     // This does not mean that text controls can parse html.
1807     // This is temporary code, as text controls do not support html type data.
1808     // Simply remove the tags inside the angle brackets.
1809     // Once multiple types and data can be stored in the clipboard, this code should be removed.
1810     std::regex reg("<[^>]*>");
1811     std::string result = regex_replace(data, reg, "");
1812
1813     EventHandler::PasteClipboardItemEvent(*this, result.c_str());
1814   }
1815 }
1816
1817 void Controller::PasteText()
1818 {
1819   if(mImpl->EnsureClipboardCreated())
1820   {
1821     // Connect the signal before calling GetData() of the clipboard.
1822     mImpl->mClipboard.DataReceivedSignal().Connect(this, &Controller::PasteClipboardItemEvent);
1823
1824     // If there is no plain text type data on the clipboard, request html type data.
1825     std::string mimeType = mImpl->mClipboard.HasType(MIME_TYPE_TEXT_PLAIN) ? MIME_TYPE_TEXT_PLAIN : MIME_TYPE_HTML;
1826
1827     // Request clipboard service to retrieve an item.
1828     uint id = mImpl->mClipboard.GetData(mimeType);
1829     if(id == 0u)
1830     {
1831       // If the return id is 0u, the signal is not emitted, we must disconnect signal here.
1832       mImpl->mClipboard.DataReceivedSignal().Disconnect(this, &Controller::PasteClipboardItemEvent);
1833     }
1834   }
1835 }
1836
1837 InputMethodContext::CallbackData Controller::OnInputMethodContextEvent(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
1838 {
1839   return EventHandler::OnInputMethodContextEvent(*this, inputMethodContext, inputMethodContextEvent);
1840 }
1841
1842 void Controller::GetTargetSize(Vector2& targetSize)
1843 {
1844   targetSize = mImpl->mModel->mVisualModel->mControlSize;
1845 }
1846
1847 void Controller::AddDecoration(Actor& actor, DecorationType type, bool needsClipping)
1848 {
1849   if(mImpl->mEditableControlInterface)
1850   {
1851     mImpl->mEditableControlInterface->AddDecoration(actor, type, needsClipping);
1852   }
1853 }
1854
1855 bool Controller::IsEditable() const
1856 {
1857   return mImpl->IsEditable();
1858 }
1859
1860 void Controller::SetEditable(bool editable)
1861 {
1862   mImpl->SetEditable(editable);
1863 }
1864
1865 void Controller::ScrollBy(Vector2 scroll)
1866 {
1867   mImpl->ScrollBy(scroll);
1868 }
1869
1870 bool Controller::IsScrollable(const Vector2& displacement)
1871 {
1872   return mImpl->IsScrollable(displacement);
1873 }
1874
1875 float Controller::GetHorizontalScrollPosition()
1876 {
1877   return mImpl->GetHorizontalScrollPosition();
1878 }
1879
1880 float Controller::GetVerticalScrollPosition()
1881 {
1882   return mImpl->GetVerticalScrollPosition();
1883 }
1884
1885 void Controller::DecorationEvent(HandleType handleType, HandleState state, float x, float y)
1886 {
1887   EventHandler::DecorationEvent(*this, handleType, state, x, y);
1888 }
1889
1890 void Controller::TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button)
1891 {
1892   EventHandler::TextPopupButtonTouched(*this, button);
1893 }
1894
1895 void Controller::DisplayTimeExpired()
1896 {
1897   mImpl->mEventData->mUpdateCursorPosition = true;
1898   // Apply modifications to the model
1899   mImpl->mOperationsPending = ALL_OPERATIONS;
1900
1901   mImpl->RequestRelayout();
1902 }
1903
1904 void Controller::ResetCursorPosition(CharacterIndex cursorIndex)
1905 {
1906   // Reset the cursor position
1907   if(NULL != mImpl->mEventData)
1908   {
1909     mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
1910
1911     // Update the cursor if it's in editing mode.
1912     if(EventData::IsEditingState(mImpl->mEventData->mState))
1913     {
1914       mImpl->mEventData->mUpdateCursorPosition = true;
1915     }
1916   }
1917 }
1918
1919 CharacterIndex Controller::GetCursorPosition()
1920 {
1921   return mImpl->mEventData ? mImpl->mEventData->mPrimaryCursorPosition : 0;
1922 }
1923
1924 void Controller::SetControlInterface(ControlInterface* controlInterface)
1925 {
1926   mImpl->mControlInterface = controlInterface;
1927 }
1928
1929 void Controller::SetAnchorControlInterface(AnchorControlInterface* anchorControlInterface)
1930 {
1931   mImpl->mAnchorControlInterface = anchorControlInterface;
1932 }
1933
1934 bool Controller::ShouldClearFocusOnEscape() const
1935 {
1936   return mImpl->mShouldClearFocusOnEscape;
1937 }
1938
1939 Actor Controller::CreateBackgroundActor()
1940 {
1941   return CreateControllerBackgroundActor(mImpl->mView, mImpl->mModel->mVisualModel, mImpl->mModel->mLogicalModel, mImpl->mShaderBackground);
1942 }
1943
1944 void Controller::GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors)
1945 {
1946   mImpl->GetAnchorActors(anchorActors);
1947 }
1948
1949 int Controller::GetAnchorIndex(size_t characterOffset)
1950 {
1951   return mImpl->GetAnchorIndex(characterOffset);
1952 }
1953
1954 void Controller::Process(bool postProcess)
1955 {
1956   if(Dali::Adaptor::IsAvailable() && mImpl->mProcessorRegistered)
1957   {
1958     Dali::Adaptor& adaptor = Dali::Adaptor::Get();
1959
1960     adaptor.UnregisterProcessor(*this, true);
1961     mImpl->mProcessorRegistered = false;
1962
1963     if(NULL == mImpl->mIdleCallback)
1964     {
1965       // @note: The callback manager takes the ownership of the callback object.
1966       mImpl->mIdleCallback = MakeCallback(this, &Controller::OnIdleSignal);
1967       if(DALI_UNLIKELY(!adaptor.AddIdle(mImpl->mIdleCallback, false)))
1968       {
1969         DALI_LOG_ERROR("Fail to add idle callback for text controller style changed signals queue. Skip these callbacks\n");
1970
1971         // Clear queue forcely.
1972         if(mImpl->mEventData)
1973         {
1974           mImpl->mEventData->mInputStyleChangedQueue.Clear();
1975         }
1976
1977         // Set the pointer to null as the callback manager deletes the callback even AddIdle failed.
1978         mImpl->mIdleCallback = NULL;
1979       }
1980     }
1981   }
1982 }
1983
1984 Controller::Controller(ControlInterface*           controlInterface,
1985                        EditableControlInterface*   editableControlInterface,
1986                        SelectableControlInterface* selectableControlInterface,
1987                        AnchorControlInterface*     anchorControlInterface)
1988 : mImpl(new Controller::Impl(controlInterface, editableControlInterface, selectableControlInterface, anchorControlInterface))
1989 {
1990 }
1991
1992 Controller::~Controller()
1993 {
1994   if(Dali::Adaptor::IsAvailable())
1995   {
1996     if(mImpl->mProcessorRegistered)
1997     {
1998       Dali::Adaptor::Get().UnregisterProcessor(*this, true);
1999     }
2000     if(mImpl->mIdleCallback)
2001     {
2002       Dali::Adaptor::Get().RemoveIdle(mImpl->mIdleCallback);
2003     }
2004   }
2005 }
2006
2007 } // namespace Dali::Toolkit::Text