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