Add text wrapping hyphen mode support
[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       const bool handlesCrossed = mImpl->mEventData->mLeftSelectionPosition > mImpl->mEventData->mRightSelectionPosition;
1238
1239       // Get start and end position of selection
1240       const CharacterIndex startOfSelectedText  = handlesCrossed ? mImpl->mEventData->mRightSelectionPosition : mImpl->mEventData->mLeftSelectionPosition;
1241       const Length         lengthOfSelectedText = (handlesCrossed ? mImpl->mEventData->mLeftSelectionPosition : mImpl->mEventData->mRightSelectionPosition) - startOfSelectedText;
1242
1243       // Add the color run.
1244       const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
1245       mImpl->mModel->mLogicalModel->mColorRuns.Resize(numberOfRuns + 1u);
1246
1247       ColorRun& colorRun                       = *(mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns);
1248       colorRun.color                           = color;
1249       colorRun.characterRun.characterIndex     = startOfSelectedText;
1250       colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
1251
1252       // Request to relayout.
1253       mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
1254       mImpl->RequestRelayout();
1255
1256       mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
1257       mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
1258       mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
1259     }
1260   }
1261 }
1262
1263 const Vector4& Controller::GetInputColor() const
1264 {
1265   if(NULL != mImpl->mEventData)
1266   {
1267     return mImpl->mEventData->mInputStyle.textColor;
1268   }
1269
1270   // Return the default text's color if there is no EventData.
1271   return mImpl->mTextColor;
1272 }
1273
1274 void Controller::SetInputFontFamily(const std::string& fontFamily)
1275 {
1276   InputFontHandler::SetInputFontFamily(*this, fontFamily);
1277 }
1278
1279 const std::string& Controller::GetInputFontFamily() const
1280 {
1281   return InputFontHandler::GetInputFontFamily(*this);
1282 }
1283
1284 void Controller::SetInputFontWeight(FontWeight weight)
1285 {
1286   InputFontHandler::SetInputFontWeight(*this, weight);
1287 }
1288
1289 bool Controller::IsInputFontWeightDefined() const
1290 {
1291   return InputFontHandler::IsInputFontWeightDefined(*this);
1292 }
1293
1294 FontWeight Controller::GetInputFontWeight() const
1295 {
1296   return InputFontHandler::GetInputFontWeight(*this);
1297 }
1298
1299 void Controller::SetInputFontWidth(FontWidth width)
1300 {
1301   InputFontHandler::SetInputFontWidth(*this, width);
1302 }
1303
1304 bool Controller::IsInputFontWidthDefined() const
1305 {
1306   return InputFontHandler::IsInputFontWidthDefined(*this);
1307 }
1308
1309 FontWidth Controller::GetInputFontWidth() const
1310 {
1311   return InputFontHandler::GetInputFontWidth(*this);
1312 }
1313
1314 void Controller::SetInputFontSlant(FontSlant slant)
1315 {
1316   InputFontHandler::SetInputFontSlant(*this, slant);
1317 }
1318
1319 bool Controller::IsInputFontSlantDefined() const
1320 {
1321   return InputFontHandler::IsInputFontSlantDefined(*this);
1322 }
1323
1324 FontSlant Controller::GetInputFontSlant() const
1325 {
1326   return InputFontHandler::GetInputFontSlant(*this);
1327 }
1328
1329 void Controller::SetInputFontPointSize(float size)
1330 {
1331   InputFontHandler::SetInputFontPointSize(*this, size);
1332 }
1333
1334 float Controller::GetInputFontPointSize() const
1335 {
1336   return InputFontHandler::GetInputFontPointSize(*this);
1337 }
1338
1339 void Controller::SetInputLineSpacing(float lineSpacing)
1340 {
1341   if(NULL != mImpl->mEventData)
1342   {
1343     mImpl->mEventData->mInputStyle.lineSpacing          = lineSpacing;
1344     mImpl->mEventData->mInputStyle.isLineSpacingDefined = true;
1345   }
1346 }
1347
1348 float Controller::GetInputLineSpacing() const
1349 {
1350   if(NULL != mImpl->mEventData)
1351   {
1352     return mImpl->mEventData->mInputStyle.lineSpacing;
1353   }
1354
1355   return 0.f;
1356 }
1357
1358 void Controller::SetInputShadowProperties(const std::string& shadowProperties)
1359 {
1360   if(NULL != mImpl->mEventData)
1361   {
1362     mImpl->mEventData->mInputStyle.shadowProperties = shadowProperties;
1363   }
1364 }
1365
1366 const std::string& Controller::GetInputShadowProperties() const
1367 {
1368   if(NULL != mImpl->mEventData)
1369   {
1370     return mImpl->mEventData->mInputStyle.shadowProperties;
1371   }
1372
1373   return EMPTY_STRING;
1374 }
1375
1376 void Controller::SetInputUnderlineProperties(const std::string& underlineProperties)
1377 {
1378   if(NULL != mImpl->mEventData)
1379   {
1380     mImpl->mEventData->mInputStyle.underlineProperties = underlineProperties;
1381   }
1382 }
1383
1384 const std::string& Controller::GetInputUnderlineProperties() const
1385 {
1386   if(NULL != mImpl->mEventData)
1387   {
1388     return mImpl->mEventData->mInputStyle.underlineProperties;
1389   }
1390
1391   return EMPTY_STRING;
1392 }
1393
1394 void Controller::SetInputEmbossProperties(const std::string& embossProperties)
1395 {
1396   if(NULL != mImpl->mEventData)
1397   {
1398     mImpl->mEventData->mInputStyle.embossProperties = embossProperties;
1399   }
1400 }
1401
1402 const std::string& Controller::GetInputEmbossProperties() const
1403 {
1404   if(NULL != mImpl->mEventData)
1405   {
1406     return mImpl->mEventData->mInputStyle.embossProperties;
1407   }
1408
1409   return GetDefaultEmbossProperties();
1410 }
1411
1412 void Controller::SetInputOutlineProperties(const std::string& outlineProperties)
1413 {
1414   if(NULL != mImpl->mEventData)
1415   {
1416     mImpl->mEventData->mInputStyle.outlineProperties = outlineProperties;
1417   }
1418 }
1419
1420 const std::string& Controller::GetInputOutlineProperties() const
1421 {
1422   if(NULL != mImpl->mEventData)
1423   {
1424     return mImpl->mEventData->mInputStyle.outlineProperties;
1425   }
1426
1427   return GetDefaultOutlineProperties();
1428 }
1429
1430 void Controller::SetInputModePassword(bool passwordInput)
1431 {
1432   if(NULL != mImpl->mEventData)
1433   {
1434     mImpl->mEventData->mPasswordInput = passwordInput;
1435   }
1436 }
1437
1438 bool Controller::IsInputModePassword()
1439 {
1440   if(NULL != mImpl->mEventData)
1441   {
1442     return mImpl->mEventData->mPasswordInput;
1443   }
1444   return false;
1445 }
1446
1447 void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action)
1448 {
1449   if(NULL != mImpl->mEventData)
1450   {
1451     mImpl->mEventData->mDoubleTapAction = action;
1452   }
1453 }
1454
1455 Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
1456 {
1457   NoTextTap::Action action = NoTextTap::NO_ACTION;
1458
1459   if(NULL != mImpl->mEventData)
1460   {
1461     action = mImpl->mEventData->mDoubleTapAction;
1462   }
1463
1464   return action;
1465 }
1466
1467 void Controller::SetNoTextLongPressAction(NoTextTap::Action action)
1468 {
1469   if(NULL != mImpl->mEventData)
1470   {
1471     mImpl->mEventData->mLongPressAction = action;
1472   }
1473 }
1474
1475 Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
1476 {
1477   NoTextTap::Action action = NoTextTap::NO_ACTION;
1478
1479   if(NULL != mImpl->mEventData)
1480   {
1481     action = mImpl->mEventData->mLongPressAction;
1482   }
1483
1484   return action;
1485 }
1486
1487 bool Controller::IsUnderlineSetByString()
1488 {
1489   return mImpl->mUnderlineSetByString;
1490 }
1491
1492 void Controller::UnderlineSetByString(bool setByString)
1493 {
1494   mImpl->mUnderlineSetByString = setByString;
1495 }
1496
1497 bool Controller::IsShadowSetByString()
1498 {
1499   return mImpl->mShadowSetByString;
1500 }
1501
1502 void Controller::ShadowSetByString(bool setByString)
1503 {
1504   mImpl->mShadowSetByString = setByString;
1505 }
1506
1507 bool Controller::IsOutlineSetByString()
1508 {
1509   return mImpl->mOutlineSetByString;
1510 }
1511
1512 void Controller::OutlineSetByString(bool setByString)
1513 {
1514   mImpl->mOutlineSetByString = setByString;
1515 }
1516
1517 bool Controller::IsFontStyleSetByString()
1518 {
1519   return mImpl->mFontStyleSetByString;
1520 }
1521
1522 void Controller::FontStyleSetByString(bool setByString)
1523 {
1524   mImpl->mFontStyleSetByString = setByString;
1525 }
1526
1527 // public : Queries & retrieves.
1528
1529 Layout::Engine& Controller::GetLayoutEngine()
1530 {
1531   return mImpl->mLayoutEngine;
1532 }
1533
1534 View& Controller::GetView()
1535 {
1536   return mImpl->mView;
1537 }
1538
1539 Vector3 Controller::GetNaturalSize()
1540 {
1541   return Relayouter::GetNaturalSize(*this);
1542 }
1543
1544 bool Controller::CheckForTextFit(float pointSize, Size& layoutSize)
1545 {
1546   return Relayouter::CheckForTextFit(*this, pointSize, layoutSize);
1547 }
1548
1549 void Controller::FitPointSizeforLayout(Size layoutSize)
1550 {
1551   Relayouter::FitPointSizeforLayout(*this, layoutSize);
1552 }
1553
1554 float Controller::GetHeightForWidth(float width)
1555 {
1556   return Relayouter::GetHeightForWidth(*this, width);
1557 }
1558
1559 int Controller::GetLineCount(float width)
1560 {
1561   GetHeightForWidth(width);
1562   int numberofLines = mImpl->mModel->GetNumberOfLines();
1563   return numberofLines;
1564 }
1565
1566 const ModelInterface* const Controller::GetTextModel() const
1567 {
1568   return mImpl->mModel.Get();
1569 }
1570
1571 float Controller::GetScrollAmountByUserInput()
1572 {
1573   float scrollAmount = 0.0f;
1574
1575   if(NULL != mImpl->mEventData && mImpl->mEventData->mCheckScrollAmount)
1576   {
1577     scrollAmount                          = mImpl->mModel->mScrollPosition.y - mImpl->mModel->mScrollPositionLast.y;
1578     mImpl->mEventData->mCheckScrollAmount = false;
1579   }
1580   return scrollAmount;
1581 }
1582
1583 bool Controller::GetTextScrollInfo(float& scrollPosition, float& controlHeight, float& layoutHeight)
1584 {
1585   const Vector2& layout = mImpl->mModel->mVisualModel->GetLayoutSize();
1586   bool           isScrolled;
1587
1588   controlHeight  = mImpl->mModel->mVisualModel->mControlSize.height;
1589   layoutHeight   = layout.height;
1590   scrollPosition = mImpl->mModel->mScrollPosition.y;
1591   isScrolled     = !Equals(mImpl->mModel->mScrollPosition.y, mImpl->mModel->mScrollPositionLast.y, Math::MACHINE_EPSILON_1);
1592   return isScrolled;
1593 }
1594
1595 void Controller::SetHiddenInputOption(const Property::Map& options)
1596 {
1597   if(NULL == mImpl->mHiddenInput)
1598   {
1599     mImpl->mHiddenInput = new HiddenText(this);
1600   }
1601   mImpl->mHiddenInput->SetProperties(options);
1602 }
1603
1604 void Controller::GetHiddenInputOption(Property::Map& options)
1605 {
1606   if(NULL != mImpl->mHiddenInput)
1607   {
1608     mImpl->mHiddenInput->GetProperties(options);
1609   }
1610 }
1611
1612 void Controller::SetPlaceholderProperty(const Property::Map& map)
1613 {
1614   PlaceholderHandler::SetPlaceholderProperty(*this, map);
1615 }
1616
1617 void Controller::GetPlaceholderProperty(Property::Map& map)
1618 {
1619   PlaceholderHandler::GetPlaceholderProperty(*this, map);
1620 }
1621
1622 Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
1623 {
1624   // Make sure the model is up-to-date before layouting
1625   ProcessModifyEvents();
1626
1627   if(mImpl->mUpdateTextDirection)
1628   {
1629     // Operations that can be done only once until the text changes.
1630     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
1631                                                                           GET_SCRIPTS |
1632                                                                           VALIDATE_FONTS |
1633                                                                           GET_LINE_BREAKS |
1634                                                                           BIDI_INFO |
1635                                                                           SHAPE_TEXT |
1636                                                                           GET_GLYPH_METRICS);
1637
1638     // Set the update info to relayout the whole text.
1639     mImpl->mTextUpdateInfo.mParagraphCharacterIndex     = 0u;
1640     mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
1641
1642     // Make sure the model is up-to-date before layouting
1643     mImpl->UpdateModel(onlyOnceOperations);
1644
1645     Vector3 naturalSize;
1646     DoRelayout(Size(MAX_FLOAT, MAX_FLOAT),
1647                static_cast<OperationsMask>(onlyOnceOperations |
1648                                            LAYOUT | REORDER | UPDATE_DIRECTION),
1649                naturalSize.GetVectorXY());
1650
1651     // Do not do again the only once operations.
1652     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending & ~onlyOnceOperations);
1653
1654     // Clear the update info. This info will be set the next time the text is updated.
1655     mImpl->mTextUpdateInfo.Clear();
1656
1657     // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT.
1658     mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
1659
1660     mImpl->mUpdateTextDirection = false;
1661   }
1662
1663   return mImpl->mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT;
1664 }
1665
1666 Toolkit::DevelText::VerticalLineAlignment::Type Controller::GetVerticalLineAlignment() const
1667 {
1668   return mImpl->mModel->GetVerticalLineAlignment();
1669 }
1670
1671 void Controller::SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignment::Type alignment)
1672 {
1673   mImpl->mModel->mVerticalLineAlignment = alignment;
1674 }
1675
1676 // public : Relayout.
1677
1678 Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
1679 {
1680   return Relayouter::Relayout(*this, size, layoutDirection);
1681 }
1682
1683 void Controller::RequestRelayout()
1684 {
1685   mImpl->RequestRelayout();
1686 }
1687
1688 // public : Input style change signals.
1689
1690 bool Controller::IsInputStyleChangedSignalsQueueEmpty()
1691 {
1692   return (NULL == mImpl->mEventData) || (0u == mImpl->mEventData->mInputStyleChangedQueue.Count());
1693 }
1694
1695 void Controller::ProcessInputStyleChangedSignals()
1696 {
1697   if(NULL == mImpl->mEventData)
1698   {
1699     // Nothing to do.
1700     return;
1701   }
1702
1703   for(Vector<InputStyle::Mask>::ConstIterator it    = mImpl->mEventData->mInputStyleChangedQueue.Begin(),
1704                                               endIt = mImpl->mEventData->mInputStyleChangedQueue.End();
1705       it != endIt;
1706       ++it)
1707   {
1708     const InputStyle::Mask mask = *it;
1709
1710     if(NULL != mImpl->mEditableControlInterface)
1711     {
1712       // Emit the input style changed signal.
1713       mImpl->mEditableControlInterface->InputStyleChanged(mask);
1714     }
1715   }
1716
1717   mImpl->mEventData->mInputStyleChangedQueue.Clear();
1718 }
1719
1720 // public : Text-input Event Queuing.
1721
1722 void Controller::KeyboardFocusGainEvent()
1723 {
1724   EventHandler::KeyboardFocusGainEvent(*this);
1725 }
1726
1727 void Controller::KeyboardFocusLostEvent()
1728 {
1729   EventHandler::KeyboardFocusLostEvent(*this);
1730 }
1731
1732 bool Controller::KeyEvent(const Dali::KeyEvent& keyEvent)
1733 {
1734   return EventHandler::KeyEvent(*this, keyEvent);
1735 }
1736
1737 void Controller::AnchorEvent(float x, float y)
1738 {
1739   EventHandler::AnchorEvent(*this, x, y);
1740 }
1741
1742 void Controller::TapEvent(unsigned int tapCount, float x, float y)
1743 {
1744   EventHandler::TapEvent(*this, tapCount, x, y);
1745 }
1746
1747 void Controller::PanEvent(GestureState state, const Vector2& displacement)
1748 {
1749   EventHandler::PanEvent(*this, state, displacement);
1750 }
1751
1752 void Controller::LongPressEvent(GestureState state, float x, float y)
1753 {
1754   EventHandler::LongPressEvent(*this, state, x, y);
1755 }
1756
1757 void Controller::SelectEvent(float x, float y, SelectionType selectType)
1758 {
1759   EventHandler::SelectEvent(*this, x, y, selectType);
1760 }
1761
1762 void Controller::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
1763 {
1764   if(mImpl->mEventData)
1765   {
1766     mImpl->mEventData->mCheckScrollAmount     = true;
1767     mImpl->mEventData->mIsLeftHandleSelected  = true;
1768     mImpl->mEventData->mIsRightHandleSelected = true;
1769     mImpl->SetTextSelectionRange(start, end);
1770     mImpl->RequestRelayout();
1771     KeyboardFocusGainEvent();
1772   }
1773 }
1774
1775 Uint32Pair Controller::GetTextSelectionRange() const
1776 {
1777   return mImpl->GetTextSelectionRange();
1778 }
1779
1780 CharacterIndex Controller::GetPrimaryCursorPosition() const
1781 {
1782   return mImpl->GetPrimaryCursorPosition();
1783 }
1784
1785 bool Controller::SetPrimaryCursorPosition(CharacterIndex index)
1786 {
1787   if(mImpl->mEventData)
1788   {
1789     mImpl->mEventData->mCheckScrollAmount     = true;
1790     mImpl->mEventData->mIsLeftHandleSelected  = true;
1791     mImpl->mEventData->mIsRightHandleSelected = true;
1792     mImpl->mEventData->mCheckScrollAmount     = true;
1793     if(mImpl->SetPrimaryCursorPosition(index))
1794     {
1795       KeyboardFocusGainEvent();
1796       return true;
1797     }
1798   }
1799   return false;
1800 }
1801
1802 void Controller::SelectWholeText()
1803 {
1804   SelectEvent(0.f, 0.f, SelectionType::ALL);
1805 }
1806
1807 void Controller::SelectNone()
1808 {
1809   SelectEvent(0.f, 0.f, SelectionType::NONE);
1810 }
1811
1812 string Controller::GetSelectedText() const
1813 {
1814   string text;
1815   if(EventData::SELECTING == mImpl->mEventData->mState)
1816   {
1817     mImpl->RetrieveSelection(text, false);
1818   }
1819   return text;
1820 }
1821
1822 InputMethodContext::CallbackData Controller::OnInputMethodContextEvent(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
1823 {
1824   return EventHandler::OnInputMethodContextEvent(*this, inputMethodContext, inputMethodContextEvent);
1825 }
1826
1827 void Controller::PasteClipboardItemEvent()
1828 {
1829   EventHandler::PasteClipboardItemEvent(*this);
1830 }
1831
1832 // protected : Inherit from Text::Decorator::ControllerInterface.
1833
1834 void Controller::GetTargetSize(Vector2& targetSize)
1835 {
1836   targetSize = mImpl->mModel->mVisualModel->mControlSize;
1837 }
1838
1839 void Controller::AddDecoration(Actor& actor, bool needsClipping)
1840 {
1841   if(NULL != mImpl->mEditableControlInterface)
1842   {
1843     mImpl->mEditableControlInterface->AddDecoration(actor, needsClipping);
1844   }
1845 }
1846
1847 bool Controller::IsEditable() const
1848 {
1849   return mImpl->IsEditable();
1850 }
1851
1852 void Controller::SetEditable(bool editable)
1853 {
1854   mImpl->SetEditable(editable);
1855   if(mImpl->mEventData && mImpl->mEventData->mDecorator)
1856   {
1857     mImpl->mEventData->mDecorator->SetEditable(editable);
1858   }
1859 }
1860
1861 void Controller::ScrollBy(Vector2 scroll)
1862 {
1863   if(mImpl->mEventData && (fabs(scroll.x) > Math::MACHINE_EPSILON_0 || fabs(scroll.y) > Math::MACHINE_EPSILON_0))
1864   {
1865     const Vector2& layoutSize    = mImpl->mModel->mVisualModel->GetLayoutSize();
1866     const Vector2  currentScroll = mImpl->mModel->mScrollPosition;
1867
1868     scroll.x = -scroll.x;
1869     scroll.y = -scroll.y;
1870
1871     if(fabs(scroll.x) > Math::MACHINE_EPSILON_0)
1872     {
1873       mImpl->mModel->mScrollPosition.x += scroll.x;
1874       mImpl->ClampHorizontalScroll(layoutSize);
1875     }
1876
1877     if(fabs(scroll.y) > Math::MACHINE_EPSILON_0)
1878     {
1879       mImpl->mModel->mScrollPosition.y += scroll.y;
1880       mImpl->ClampVerticalScroll(layoutSize);
1881     }
1882
1883     if(mImpl->mModel->mScrollPosition != currentScroll)
1884     {
1885       mImpl->mEventData->mDecorator->UpdatePositions(mImpl->mModel->mScrollPosition - currentScroll);
1886       mImpl->RequestRelayout();
1887     }
1888   }
1889 }
1890
1891 float Controller::GetHorizontalScrollPosition()
1892 {
1893   if(mImpl->mEventData)
1894   {
1895     //scroll values are negative internally so we convert them to positive numbers
1896     return -mImpl->mModel->mScrollPosition.x;
1897   }
1898   return 0;
1899 }
1900
1901 float Controller::GetVerticalScrollPosition()
1902 {
1903   if(mImpl->mEventData)
1904   {
1905     //scroll values are negative internally so we convert them to positive numbers
1906     return -mImpl->mModel->mScrollPosition.y;
1907   }
1908   return 0;
1909 }
1910
1911 void Controller::DecorationEvent(HandleType handleType, HandleState state, float x, float y)
1912 {
1913   EventHandler::DecorationEvent(*this, handleType, state, x, y);
1914 }
1915
1916 // protected : Inherit from TextSelectionPopup::TextPopupButtonCallbackInterface.
1917
1918 void Controller::TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button)
1919 {
1920   EventHandler::TextPopupButtonTouched(*this, button);
1921 }
1922
1923 void Controller::DisplayTimeExpired()
1924 {
1925   mImpl->mEventData->mUpdateCursorPosition = true;
1926   // Apply modifications to the model
1927   mImpl->mOperationsPending = ALL_OPERATIONS;
1928
1929   mImpl->RequestRelayout();
1930 }
1931
1932 // private : Update.
1933
1934 void Controller::InsertText(const std::string& text, Controller::InsertType type)
1935 {
1936   TextUpdater::InsertText(*this, text, type);
1937 }
1938
1939 void Controller::PasteText(const std::string& stringToPaste)
1940 {
1941   TextUpdater::PasteText(*this, stringToPaste);
1942 }
1943
1944 bool Controller::RemoveText(int                  cursorOffset,
1945                             int                  numberOfCharacters,
1946                             UpdateInputStyleType type)
1947 {
1948   return TextUpdater::RemoveText(*this, cursorOffset, numberOfCharacters, type);
1949 }
1950
1951 bool Controller::RemoveSelectedText()
1952 {
1953   return TextUpdater::RemoveSelectedText(*this);
1954 }
1955
1956 void Controller::InsertTextAnchor(int            numberOfCharacters,
1957                                   CharacterIndex previousCursorIndex)
1958 {
1959   TextUpdater::InsertTextAnchor(*this, numberOfCharacters, previousCursorIndex);
1960 }
1961
1962 void Controller::RemoveTextAnchor(int            cursorOffset,
1963                                   int            numberOfCharacters,
1964                                   CharacterIndex previousCursorIndex)
1965 {
1966   TextUpdater::RemoveTextAnchor(*this, cursorOffset, numberOfCharacters, previousCursorIndex);
1967 }
1968
1969 // private : Relayout.
1970
1971 bool Controller::DoRelayout(const Size&    size,
1972                             OperationsMask operationsRequired,
1973                             Size&          layoutSize)
1974 {
1975   return Relayouter::DoRelayout(*this, size, operationsRequired, layoutSize);
1976 }
1977
1978 void Controller::CalculateVerticalOffset(const Size& controlSize)
1979 {
1980   Relayouter::CalculateVerticalOffset(*this, controlSize);
1981 }
1982
1983 // private : Events.
1984
1985 void Controller::ProcessModifyEvents()
1986 {
1987   EventHandler::ProcessModifyEvents(*this);
1988 }
1989
1990 void Controller::TextReplacedEvent()
1991 {
1992   EventHandler::TextReplacedEvent(*this);
1993 }
1994
1995 void Controller::TextInsertedEvent()
1996 {
1997   EventHandler::TextInsertedEvent(*this);
1998 }
1999
2000 void Controller::TextDeletedEvent()
2001 {
2002   EventHandler::TextDeletedEvent(*this);
2003 }
2004
2005 bool Controller::DeleteEvent(int keyCode)
2006 {
2007   return EventHandler::DeleteEvent(*this, keyCode);
2008 }
2009
2010 // private : Helpers.
2011
2012 void Controller::ResetText()
2013 {
2014   TextUpdater::ResetText(*this);
2015 }
2016
2017 void Controller::ShowPlaceholderText()
2018 {
2019   PlaceholderHandler::ShowPlaceholderText(*this);
2020 }
2021
2022 void Controller::ClearFontData()
2023 {
2024   if(mImpl->mFontDefaults)
2025   {
2026     mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
2027   }
2028
2029   // Set flags to update the model.
2030   mImpl->mTextUpdateInfo.mCharacterIndex             = 0u;
2031   mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
2032   mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = mImpl->mModel->mLogicalModel->mText.Count();
2033
2034   mImpl->mTextUpdateInfo.mClearAll           = true;
2035   mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
2036   mImpl->mRecalculateNaturalSize             = true;
2037
2038   mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
2039                                                           VALIDATE_FONTS |
2040                                                           SHAPE_TEXT |
2041                                                           BIDI_INFO |
2042                                                           GET_GLYPH_METRICS |
2043                                                           LAYOUT |
2044                                                           UPDATE_LAYOUT_SIZE |
2045                                                           REORDER |
2046                                                           ALIGN);
2047 }
2048
2049 void Controller::ClearStyleData()
2050 {
2051   mImpl->mModel->mLogicalModel->mColorRuns.Clear();
2052   mImpl->mModel->mLogicalModel->ClearFontDescriptionRuns();
2053 }
2054
2055 void Controller::ResetCursorPosition(CharacterIndex cursorIndex)
2056 {
2057   // Reset the cursor position
2058   if(NULL != mImpl->mEventData)
2059   {
2060     mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
2061
2062     // Update the cursor if it's in editing mode.
2063     if(EventData::IsEditingState(mImpl->mEventData->mState))
2064     {
2065       mImpl->mEventData->mUpdateCursorPosition = true;
2066     }
2067   }
2068 }
2069
2070 CharacterIndex Controller::GetCursorPosition()
2071 {
2072   if(!mImpl->mEventData)
2073     return 0;
2074
2075   return mImpl->mEventData->mPrimaryCursorPosition;
2076 }
2077
2078 void Controller::ResetScrollPosition()
2079 {
2080   if(NULL != mImpl->mEventData)
2081   {
2082     // Reset the scroll position.
2083     mImpl->mModel->mScrollPosition                = Vector2::ZERO;
2084     mImpl->mEventData->mScrollAfterUpdatePosition = true;
2085   }
2086 }
2087
2088 void Controller::SetControlInterface(ControlInterface* controlInterface)
2089 {
2090   mImpl->mControlInterface = controlInterface;
2091 }
2092
2093 void Controller::SetAnchorControlInterface(AnchorControlInterface* anchorControlInterface)
2094 {
2095   mImpl->mAnchorControlInterface = anchorControlInterface;
2096 }
2097
2098 bool Controller::ShouldClearFocusOnEscape() const
2099 {
2100   return mImpl->mShouldClearFocusOnEscape;
2101 }
2102
2103 Actor Controller::CreateBackgroundActor()
2104 {
2105   return mImpl->CreateBackgroundActor();
2106 }
2107
2108 // private : Private contructors & copy operator.
2109
2110 Controller::Controller()
2111 : Controller(nullptr, nullptr, nullptr, nullptr)
2112 {
2113 }
2114
2115 Controller::Controller(ControlInterface* controlInterface)
2116 : Controller(controlInterface, nullptr, nullptr, nullptr)
2117 {
2118 }
2119
2120 Controller::Controller(ControlInterface*           controlInterface,
2121                        EditableControlInterface*   editableControlInterface,
2122                        SelectableControlInterface* selectableControlInterface,
2123                        AnchorControlInterface*     anchorControlInterface)
2124 : mImpl(new Controller::Impl(controlInterface, editableControlInterface, selectableControlInterface, anchorControlInterface))
2125 {
2126 }
2127
2128 // The copy constructor and operator are left unimplemented.
2129
2130 // protected : Destructor.
2131
2132 Controller::~Controller()
2133 {
2134   delete mImpl;
2135 }
2136
2137 } // namespace Text
2138
2139 } // namespace Toolkit
2140
2141 } // namespace Dali