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