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