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