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