Add editable text's idler function at PostProcessor time, instead of whenever we...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / controller / text-controller.cpp
1 /*
2  * Copyright (c) 2024 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/controller/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/adaptor-framework/adaptor.h>
25 #include <dali/integration-api/debug.h>
26 #include <memory.h>
27 #include <cmath>
28 #include <limits>
29
30 // INTERNAL INCLUDES
31 #include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
32 #include <dali-toolkit/internal/text/controller/text-controller-background-actor.h>
33 #include <dali-toolkit/internal/text/controller/text-controller-event-handler.h>
34 #include <dali-toolkit/internal/text/controller/text-controller-impl.h>
35 #include <dali-toolkit/internal/text/controller/text-controller-input-font-handler.h>
36 #include <dali-toolkit/internal/text/controller/text-controller-input-properties.h>
37 #include <dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h>
38 #include <dali-toolkit/internal/text/controller/text-controller-relayouter.h>
39 #include <dali-toolkit/internal/text/controller/text-controller-spannable-handler.h>
40 #include <dali-toolkit/internal/text/controller/text-controller-text-updater.h>
41 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
42 #include <dali-toolkit/internal/text/text-geometry.h>
43 namespace
44 {
45 #if defined(DEBUG_ENABLED)
46 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
47 #endif
48
49 const char* EMPTY_STRING         = "";
50 const char* MIME_TYPE_TEXT_PLAIN = "text/plain;charset=utf-8";
51
52 template<typename Type>
53 void EnsureCreated(Type*& object)
54 {
55   if(!object)
56   {
57     object = new Type();
58   }
59 }
60
61 template<typename Type>
62 void EnsureCreated(std::unique_ptr<Type>& object)
63 {
64   if(!object)
65   {
66     object = std::unique_ptr<Type>(new Type());
67   }
68 }
69
70 template<typename Type, typename Arg1>
71 void EnsureCreated(Type*& object, Arg1 arg1)
72 {
73   if(!object)
74   {
75     object = new Type(arg1);
76   }
77 }
78
79 template<typename Type, typename Arg1, typename Arg2>
80 void EnsureCreated(Type*& object, Arg1 arg1, Arg2 arg2)
81 {
82   if(!object)
83   {
84     object = new Type(arg1, arg2);
85   }
86 }
87
88 float GetDpi()
89 {
90   static uint32_t horizontalDpi = 0u;
91   static uint32_t verticalDpi   = 0u;
92
93   // TODO : How can we know when fontClient DPI changed case?
94   if(DALI_UNLIKELY(horizontalDpi == 0u))
95   {
96     Dali::TextAbstraction::FontClient fontClient = Dali::TextAbstraction::FontClient::Get();
97     fontClient.GetDpi(horizontalDpi, verticalDpi);
98   }
99   return static_cast<float>(horizontalDpi);
100 }
101
102 float ConvertPixelToPoint(float pixel)
103 {
104   return pixel * 72.0f / GetDpi();
105 }
106
107 float ConvertPointToPixel(float point)
108 {
109   // Pixel size = Point size * DPI / 72.f
110   return point * GetDpi() / 72.0f;
111 }
112
113 void UpdateCursorPosition(Dali::Toolkit::Text::EventData* eventData)
114 {
115   if(eventData && Dali::Toolkit::Text::EventData::IsEditingState(eventData->mState))
116   {
117     // Update the cursor position if it's in editing mode
118     eventData->mDecoratorUpdated     = true;
119     eventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
120   }
121 }
122
123 } // namespace
124
125 namespace Dali::Toolkit::Text
126 {
127 void Controller::EnableTextInput(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
128 {
129   if(!decorator)
130   {
131     delete mImpl->mEventData;
132     mImpl->mEventData = NULL;
133
134     // Nothing else to do.
135     return;
136   }
137
138   EnsureCreated(mImpl->mEventData, decorator, inputMethodContext);
139 }
140
141 void Controller::SetGlyphType(TextAbstraction::GlyphType glyphType)
142 {
143   // Metrics for bitmap & vector based glyphs are different
144   mImpl->mMetrics->SetGlyphType(glyphType);
145
146   // Clear the font-specific data
147   mImpl->ClearFontData();
148
149   mImpl->RequestRelayout();
150 }
151
152 void Controller::SetMarkupProcessorEnabled(bool enable)
153 {
154   if(enable != mImpl->mMarkupProcessorEnabled)
155   {
156     //If Text was already set, call the SetText again for enabling or disabling markup
157     mImpl->mMarkupProcessorEnabled = enable;
158     std::string text;
159     GetText(text);
160     SetText(text);
161   }
162
163   mImpl->mModel->mVisualModel->SetMarkupProcessorEnabled(enable);
164 }
165
166 bool Controller::IsMarkupProcessorEnabled() const
167 {
168   return mImpl->mMarkupProcessorEnabled;
169 }
170
171 bool Controller::HasAnchors() const
172 {
173   return (mImpl->mMarkupProcessorEnabled && mImpl->mModel->mLogicalModel->mAnchors.Count() && mImpl->IsShowingRealText());
174 }
175
176 void Controller::SetAutoScrollEnabled(bool enable)
177 {
178   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);
179   mImpl->SetAutoScrollEnabled(enable);
180 }
181
182 void Controller::SetAutoScrollMaxTextureExceeded(bool exceed)
183 {
184   mImpl->mIsAutoScrollMaxTextureExceeded = exceed;
185 }
186
187 bool Controller::IsAutoScrollEnabled() const
188 {
189   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", mImpl->mIsAutoScrollEnabled ? "true" : "false");
190   return mImpl->mIsAutoScrollEnabled;
191 }
192
193 CharacterDirection Controller::GetAutoScrollDirection() const
194 {
195   return mImpl->mIsTextDirectionRTL;
196 }
197
198 float Controller::GetAutoScrollLineAlignment() const
199 {
200   float offset = 0.f;
201   if(mImpl->mModel->mVisualModel && (0u != mImpl->mModel->mVisualModel->mLines.Count()))
202   {
203     offset = (*mImpl->mModel->mVisualModel->mLines.Begin()).alignmentOffset;
204   }
205   return offset;
206 }
207
208 void Controller::SetHorizontalScrollEnabled(bool enable)
209 {
210   if(mImpl->mEventData && mImpl->mEventData->mDecorator)
211   {
212     mImpl->mEventData->mDecorator->SetHorizontalScrollEnabled(enable);
213   }
214 }
215
216 bool Controller::IsHorizontalScrollEnabled() const
217 {
218   return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled();
219 }
220
221 void Controller::SetVerticalScrollEnabled(bool enable)
222 {
223   if(mImpl->mEventData && mImpl->mEventData->mDecorator)
224   {
225     mImpl->mEventData->mDecorator->SetVerticalScrollEnabled(enable);
226   }
227 }
228
229 bool Controller::IsVerticalScrollEnabled() const
230 {
231   return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsVerticalScrollEnabled();
232 }
233
234 void Controller::SetSmoothHandlePanEnabled(bool enable)
235 {
236   if(mImpl->mEventData && mImpl->mEventData->mDecorator)
237   {
238     mImpl->mEventData->mDecorator->SetSmoothHandlePanEnabled(enable);
239   }
240 }
241
242 bool Controller::IsSmoothHandlePanEnabled() const
243 {
244   return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled();
245 }
246
247 void Controller::SetMaximumNumberOfCharacters(Length maxCharacters)
248 {
249   mImpl->mMaximumNumberOfCharacters = maxCharacters;
250 }
251
252 int Controller::GetMaximumNumberOfCharacters()
253 {
254   return mImpl->mMaximumNumberOfCharacters;
255 }
256
257 void Controller::SetEnableCursorBlink(bool enable)
258 {
259   mImpl->SetEnableCursorBlink(enable);
260 }
261
262 bool Controller::GetEnableCursorBlink() const
263 {
264   return mImpl->mEventData && mImpl->mEventData->mCursorBlinkEnabled;
265 }
266
267 void Controller::SetMultiLineEnabled(bool enable)
268 {
269   mImpl->SetMultiLineEnabled(enable);
270 }
271
272 bool Controller::IsMultiLineEnabled() const
273 {
274   return Layout::Engine::MULTI_LINE_BOX == mImpl->mLayoutEngine.GetLayout();
275 }
276
277 void Controller::SetHorizontalAlignment(Text::HorizontalAlignment::Type alignment)
278 {
279   mImpl->SetHorizontalAlignment(alignment);
280 }
281
282 Text::HorizontalAlignment::Type Controller::GetHorizontalAlignment() const
283 {
284   return mImpl->mModel->mHorizontalAlignment;
285 }
286
287 void Controller::SetVerticalAlignment(VerticalAlignment::Type alignment)
288 {
289   mImpl->SetVerticalAlignment(alignment);
290 }
291
292 VerticalAlignment::Type Controller::GetVerticalAlignment() const
293 {
294   return mImpl->mModel->mVerticalAlignment;
295 }
296
297 bool Controller::IsIgnoreSpacesAfterText() const
298 {
299   return mImpl->mModel->mIgnoreSpacesAfterText;
300 }
301
302 void Controller::SetIgnoreSpacesAfterText(bool ignore)
303 {
304   mImpl->mModel->mIgnoreSpacesAfterText = ignore;
305 }
306
307 void Controller::ChangedLayoutDirection()
308 {
309   mImpl->mIsLayoutDirectionChanged = true;
310 }
311
312 void Controller::ResetFontAndStyleData()
313 {
314   mImpl->ResetFontAndStyleData();
315 }
316
317 void Controller::SetMatchLayoutDirection(DevelText::MatchLayoutDirection type)
318 {
319   mImpl->mModel->mMatchLayoutDirection = type;
320 }
321
322 DevelText::MatchLayoutDirection Controller::GetMatchLayoutDirection() const
323 {
324   return mImpl->mModel->mMatchLayoutDirection;
325 }
326
327 void Controller::SetLayoutDirection(Dali::LayoutDirection::Type layoutDirection)
328 {
329   mImpl->mLayoutDirection = layoutDirection;
330 }
331
332 Dali::LayoutDirection::Type Controller::GetLayoutDirection(Dali::Actor& actor) const
333 {
334   return mImpl->GetLayoutDirection(actor);
335 }
336
337 bool Controller::IsShowingRealText() const
338 {
339   return mImpl->IsShowingRealText();
340 }
341
342 void Controller::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode)
343 {
344   mImpl->SetLineWrapMode(lineWrapMode);
345 }
346
347 Text::LineWrap::Mode Controller::GetLineWrapMode() const
348 {
349   return mImpl->mModel->mLineWrapMode;
350 }
351
352 void Controller::SetTextElideEnabled(bool enabled)
353 {
354   mImpl->mModel->mElideEnabled = enabled;
355   mImpl->mModel->mVisualModel->SetTextElideEnabled(enabled);
356 }
357
358 bool Controller::IsTextElideEnabled() const
359 {
360   return mImpl->mModel->mElideEnabled;
361 }
362
363 void Controller::SetTextFitEnabled(bool enabled)
364 {
365   mImpl->mTextFitEnabled = enabled;
366 }
367
368 bool Controller::IsTextFitEnabled() const
369 {
370   return mImpl->mTextFitEnabled;
371 }
372
373 void Controller::SetTextFitChanged(bool changed)
374 {
375   mImpl->mTextFitChanged = changed;
376 }
377
378 bool Controller::IsTextFitChanged() const
379 {
380   return mImpl->mTextFitChanged;
381 }
382
383 void Controller::SetCurrentLineSize(float lineSize)
384 {
385   mImpl->mCurrentLineSize = lineSize;
386 }
387
388 float Controller::GetCurrentLineSize() const
389 {
390   return mImpl->mCurrentLineSize;
391 }
392
393 void Controller::SetTextFitMinSize(float minSize, FontSizeType type)
394 {
395   mImpl->mTextFitMinSize = (type == POINT_SIZE) ? minSize : ConvertPixelToPoint(minSize);
396 }
397
398 float Controller::GetTextFitMinSize() const
399 {
400   return mImpl->mTextFitMinSize;
401 }
402
403 void Controller::SetTextFitMaxSize(float maxSize, FontSizeType type)
404 {
405   mImpl->mTextFitMaxSize = (type == POINT_SIZE) ? maxSize : ConvertPixelToPoint(maxSize);
406 }
407
408 float Controller::GetTextFitMaxSize() const
409 {
410   return mImpl->mTextFitMaxSize;
411 }
412
413 void Controller::SetTextFitStepSize(float step, FontSizeType type)
414 {
415   mImpl->mTextFitStepSize = (type == POINT_SIZE) ? step : ConvertPixelToPoint(step);
416 }
417
418 float Controller::GetTextFitStepSize() const
419 {
420   return mImpl->mTextFitStepSize;
421 }
422
423 void Controller::SetTextFitContentSize(Vector2 size)
424 {
425   mImpl->mTextFitContentSize = size;
426 }
427
428 Vector2 Controller::GetTextFitContentSize() const
429 {
430   return mImpl->mTextFitContentSize;
431 }
432
433 float Controller::GetTextFitPointSize() const
434 {
435   return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFitPointSize : 0.0f;
436 }
437
438 void Controller::SetTextFitLineSize(float lineSize)
439 {
440   mImpl->mTextFitLineSize = lineSize;
441 }
442
443 void Controller::SetTextFitArrayEnabled(bool enabled)
444 {
445   mImpl->mTextFitArrayEnabled = enabled;
446   mImpl->ClearFontData();
447   mImpl->RequestRelayout();
448 }
449
450 bool Controller::IsTextFitArrayEnabled() const
451 {
452   return mImpl->mTextFitArrayEnabled;
453 }
454
455 void Controller::SetTextFitArray(std::vector<Toolkit::DevelTextLabel::FitOption>& fitOptions)
456 {
457   mImpl->mTextFitArray = fitOptions;
458 }
459
460 std::vector<Toolkit::DevelTextLabel::FitOption>& Controller::GetTextFitArray()
461 {
462   return mImpl->mTextFitArray;
463 }
464
465 void Controller::SetPlaceholderTextElideEnabled(bool enabled)
466 {
467   PlaceholderHandler::SetPlaceholderTextElideEnabled(*this, enabled);
468 }
469
470 bool Controller::IsPlaceholderTextElideEnabled() const
471 {
472   return PlaceholderHandler::IsPlaceholderTextElideEnabled(*this);
473 }
474
475 void Controller::SetSelectionEnabled(bool enabled)
476 {
477   mImpl->mEventData->mSelectionEnabled = enabled;
478 }
479
480 bool Controller::IsSelectionEnabled() const
481 {
482   return mImpl->mEventData->mSelectionEnabled;
483 }
484
485 void Controller::SetShiftSelectionEnabled(bool enabled)
486 {
487   mImpl->mEventData->mShiftSelectionFlag = enabled;
488 }
489
490 bool Controller::IsShiftSelectionEnabled() const
491 {
492   return mImpl->mEventData->mShiftSelectionFlag;
493 }
494
495 void Controller::SetGrabHandleEnabled(bool enabled)
496 {
497   mImpl->mEventData->mGrabHandleEnabled = enabled;
498 }
499
500 bool Controller::IsGrabHandleEnabled() const
501 {
502   return mImpl->mEventData->mGrabHandleEnabled;
503 }
504
505 void Controller::SetGrabHandlePopupEnabled(bool enabled)
506 {
507   mImpl->mEventData->mGrabHandlePopupEnabled = enabled;
508 }
509
510 bool Controller::IsGrabHandlePopupEnabled() const
511 {
512   return mImpl->mEventData->mGrabHandlePopupEnabled;
513 }
514
515 void Controller::SetText(const std::string& text)
516 {
517   TextUpdater::SetText(*this, text);
518 }
519
520 void Controller::GetText(std::string& text) const
521 {
522   mImpl->GetText(text);
523 }
524
525 Length Controller::GetNumberOfCharacters() const
526 {
527   return mImpl->GetNumberOfCharacters();
528 }
529
530 void Controller::SetSpannedText(const Text::Spanned& spannedText)
531 {
532   SpannableHandler::SetSpannedText(*this, spannedText);
533 }
534
535 void Controller::SetPlaceholderText(PlaceholderType type, const std::string& text)
536 {
537   PlaceholderHandler::SetPlaceholderText(*this, type, text);
538 }
539
540 void Controller::GetPlaceholderText(PlaceholderType type, std::string& text) const
541 {
542   PlaceholderHandler::GetPlaceholderText(*this, type, text);
543 }
544
545 void Controller::UpdateAfterFontChange(const std::string& newDefaultFont)
546 {
547   mImpl->UpdateAfterFontChange(newDefaultFont);
548 }
549
550 void Controller::RetrieveSelection(std::string& selectedText) const
551 {
552   mImpl->RetrieveSelection(selectedText, false);
553 }
554
555 void Controller::SetSelection(int start, int end)
556 {
557   mImpl->SetSelection(start, end);
558 }
559
560 std::pair<int, int> Controller::GetSelectionIndexes() const
561 {
562   return mImpl->GetSelectionIndexes();
563 }
564
565 void Controller::CopyStringToClipboard(const std::string& source)
566 {
567   mImpl->CopyStringToClipboard(source);
568 }
569
570 void Controller::SendSelectionToClipboard(bool deleteAfterSending)
571 {
572   mImpl->SendSelectionToClipboard(deleteAfterSending);
573 }
574
575 void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily)
576 {
577   EnsureCreated(mImpl->mFontDefaults);
578
579   if(mImpl->mFontDefaults->mFontDescription.family != defaultFontFamily)
580   {
581     mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily;
582     DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s\n", defaultFontFamily.c_str());
583     mImpl->mFontDefaults->familyDefined = !defaultFontFamily.empty();
584
585     // Update the cursor position if it's in editing mode
586     UpdateCursorPosition(mImpl->mEventData);
587
588     // Clear the font-specific data
589     mImpl->ClearFontData();
590
591     mImpl->RequestRelayout();
592   }
593 }
594
595 std::string Controller::GetDefaultFontFamily() const
596 {
597   return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.family : EMPTY_STRING;
598 }
599
600 void Controller::SetPlaceholderFontFamily(const std::string& placeholderTextFontFamily)
601 {
602   PlaceholderHandler::SetPlaceholderFontFamily(*this, placeholderTextFontFamily);
603 }
604
605 std::string Controller::GetPlaceholderFontFamily() const
606 {
607   return PlaceholderHandler::GetPlaceholderFontFamily(*this);
608 }
609
610 void Controller::SetDefaultFontWeight(FontWeight weight)
611 {
612   EnsureCreated(mImpl->mFontDefaults);
613
614   mImpl->mFontDefaults->mFontDescription.weight = weight;
615   mImpl->mFontDefaults->weightDefined           = true;
616
617   // Update the cursor position if it's in editing mode
618   UpdateCursorPosition(mImpl->mEventData);
619
620   // Clear the font-specific data
621   mImpl->ClearFontData();
622
623   mImpl->RequestRelayout();
624 }
625
626 bool Controller::IsDefaultFontWeightDefined() const
627 {
628   return mImpl->mFontDefaults && mImpl->mFontDefaults->weightDefined;
629 }
630
631 FontWeight Controller::GetDefaultFontWeight() const
632 {
633   return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.weight : TextAbstraction::FontWeight::NORMAL;
634 }
635
636 void Controller::SetPlaceholderTextFontWeight(FontWeight weight)
637 {
638   PlaceholderHandler::SetPlaceholderTextFontWeight(*this, weight);
639 }
640
641 bool Controller::IsPlaceholderTextFontWeightDefined() const
642 {
643   return PlaceholderHandler::IsPlaceholderTextFontWeightDefined(*this);
644 }
645
646 FontWeight Controller::GetPlaceholderTextFontWeight() const
647 {
648   return PlaceholderHandler::GetPlaceholderTextFontWeight(*this);
649 }
650
651 void Controller::SetDefaultFontWidth(FontWidth width)
652 {
653   EnsureCreated(mImpl->mFontDefaults);
654
655   mImpl->mFontDefaults->mFontDescription.width = width;
656   mImpl->mFontDefaults->widthDefined           = true;
657
658   // Update the cursor position if it's in editing mode
659   UpdateCursorPosition(mImpl->mEventData);
660
661   // Clear the font-specific data
662   mImpl->ClearFontData();
663
664   mImpl->RequestRelayout();
665 }
666
667 bool Controller::IsDefaultFontWidthDefined() const
668 {
669   return mImpl->mFontDefaults && mImpl->mFontDefaults->widthDefined;
670 }
671
672 FontWidth Controller::GetDefaultFontWidth() const
673 {
674   return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.width : TextAbstraction::FontWidth::NORMAL;
675 }
676
677 void Controller::SetPlaceholderTextFontWidth(FontWidth width)
678 {
679   PlaceholderHandler::SetPlaceholderTextFontWidth(*this, width);
680 }
681
682 bool Controller::IsPlaceholderTextFontWidthDefined() const
683 {
684   return PlaceholderHandler::IsPlaceholderTextFontWidthDefined(*this);
685 }
686
687 FontWidth Controller::GetPlaceholderTextFontWidth() const
688 {
689   return PlaceholderHandler::GetPlaceholderTextFontWidth(*this);
690 }
691
692 void Controller::SetDefaultFontSlant(FontSlant slant)
693 {
694   EnsureCreated(mImpl->mFontDefaults);
695
696   mImpl->mFontDefaults->mFontDescription.slant = slant;
697   mImpl->mFontDefaults->slantDefined           = true;
698
699   // Update the cursor position if it's in editing mode
700   UpdateCursorPosition(mImpl->mEventData);
701
702   // Clear the font-specific data
703   mImpl->ClearFontData();
704
705   mImpl->RequestRelayout();
706 }
707
708 bool Controller::IsDefaultFontSlantDefined() const
709 {
710   return mImpl->mFontDefaults && mImpl->mFontDefaults->slantDefined;
711 }
712
713 FontSlant Controller::GetDefaultFontSlant() const
714 {
715   return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.slant : TextAbstraction::FontSlant::NORMAL;
716 }
717
718 void Controller::SetPlaceholderTextFontSlant(FontSlant slant)
719 {
720   PlaceholderHandler::SetPlaceholderTextFontSlant(*this, slant);
721 }
722
723 bool Controller::IsPlaceholderTextFontSlantDefined() const
724 {
725   return PlaceholderHandler::IsPlaceholderTextFontSlantDefined(*this);
726 }
727
728 FontSlant Controller::GetPlaceholderTextFontSlant() const
729 {
730   return PlaceholderHandler::GetPlaceholderTextFontSlant(*this);
731 }
732
733 void Controller::SetFontSizeScale(float scale)
734 {
735   mImpl->mFontSizeScale = scale;
736
737   // No relayout is required
738   if(!mImpl->mFontSizeScaleEnabled) return;
739
740   // Update the cursor position if it's in editing mode
741   UpdateCursorPosition(mImpl->mEventData);
742
743   // Clear the font-specific data
744   mImpl->ClearFontData();
745
746   mImpl->RequestRelayout();
747 }
748
749 float Controller::GetFontSizeScale() const
750 {
751   return mImpl->mFontDefaults ? mImpl->mFontSizeScale : 1.0f;
752 }
753
754 void Controller::SetFontSizeScaleEnabled(bool enabled)
755 {
756   mImpl->mFontSizeScaleEnabled = enabled;
757
758   // Update the cursor position if it's in editing mode
759   UpdateCursorPosition(mImpl->mEventData);
760
761   // Clear the font-specific data
762   mImpl->ClearFontData();
763
764   mImpl->RequestRelayout();
765 }
766
767 bool Controller::IsFontSizeScaleEnabled() const
768 {
769   return mImpl->mFontSizeScaleEnabled;
770 }
771
772 void Controller::SetDefaultFontSize(float fontSize, FontSizeType type)
773 {
774   EnsureCreated(mImpl->mFontDefaults);
775
776   mImpl->mFontDefaults->mDefaultPointSize = (type == POINT_SIZE) ? fontSize : ConvertPixelToPoint(fontSize);
777   mImpl->mFontDefaults->sizeDefined       = true;
778
779   // Update the cursor position if it's in editing mode
780   UpdateCursorPosition(mImpl->mEventData);
781
782   // Clear the font-specific data
783   mImpl->ClearFontData();
784
785   mImpl->RequestRelayout();
786 }
787
788 float Controller::GetDefaultFontSize(FontSizeType type) const
789 {
790   if(mImpl->mFontDefaults)
791   {
792     return (type == POINT_SIZE) ? mImpl->mFontDefaults->mDefaultPointSize : ConvertPointToPixel(mImpl->mFontDefaults->mDefaultPointSize);
793   }
794   return 0.0f;
795 }
796
797 void Controller::SetPlaceholderTextFontSize(float fontSize, FontSizeType type)
798 {
799   PlaceholderHandler::SetPlaceholderTextFontSize(*this, fontSize, type);
800 }
801
802 float Controller::GetPlaceholderTextFontSize(FontSizeType type) const
803 {
804   return PlaceholderHandler::GetPlaceholderTextFontSize(*this, type);
805 }
806
807 void Controller::SetDefaultColor(const Vector4& color)
808 {
809   mImpl->SetDefaultColor(color);
810 }
811
812 const Vector4& Controller::GetDefaultColor() const
813 {
814   return mImpl->mTextColor;
815 }
816
817 void Controller::SetAnchorColor(const Vector4& color)
818 {
819   mImpl->SetAnchorColor(color);
820 }
821
822 const Vector4& Controller::GetAnchorColor() const
823 {
824   return mImpl->GetAnchorColor();
825 }
826
827 void Controller::SetAnchorClickedColor(const Vector4& color)
828 {
829   mImpl->SetAnchorClickedColor(color);
830 }
831
832 const Vector4& Controller::GetAnchorClickedColor() const
833 {
834   return mImpl->GetAnchorClickedColor();
835 }
836
837 void Controller::SetDisabledColorOpacity(float opacity)
838 {
839   mImpl->mDisabledColorOpacity = opacity;
840 }
841
842 float Controller::GetDisabledColorOpacity() const
843 {
844   return mImpl->mDisabledColorOpacity;
845 }
846
847 void Controller::SetUserInteractionEnabled(bool enabled)
848 {
849   mImpl->SetUserInteractionEnabled(enabled);
850 }
851
852 bool Controller::IsUserInteractionEnabled() const
853 {
854   return mImpl->mIsUserInteractionEnabled;
855 }
856
857 void Controller::SetPlaceholderTextColor(const Vector4& textColor)
858 {
859   PlaceholderHandler::SetPlaceholderTextColor(*this, textColor);
860 }
861
862 const Vector4& Controller::GetPlaceholderTextColor() const
863 {
864   return PlaceholderHandler::GetPlaceholderTextColor(*this);
865 }
866
867 void Controller::SetShadowOffset(const Vector2& shadowOffset)
868 {
869   mImpl->mModel->mVisualModel->SetShadowOffset(shadowOffset);
870   mImpl->RequestRelayout();
871 }
872
873 const Vector2& Controller::GetShadowOffset() const
874 {
875   return mImpl->mModel->mVisualModel->GetShadowOffset();
876 }
877
878 void Controller::SetShadowColor(const Vector4& shadowColor)
879 {
880   mImpl->mModel->mVisualModel->SetShadowColor(shadowColor);
881   mImpl->RequestRelayout();
882 }
883
884 const Vector4& Controller::GetShadowColor() const
885 {
886   return mImpl->mModel->mVisualModel->GetShadowColor();
887 }
888
889 void Controller::SetShadowBlurRadius(const float& shadowBlurRadius)
890 {
891   if(fabsf(GetShadowBlurRadius() - shadowBlurRadius) > Math::MACHINE_EPSILON_1)
892   {
893     mImpl->mModel->mVisualModel->SetShadowBlurRadius(shadowBlurRadius);
894     mImpl->RequestRelayout();
895   }
896 }
897
898 const float& Controller::GetShadowBlurRadius() const
899 {
900   return mImpl->mModel->mVisualModel->GetShadowBlurRadius();
901 }
902
903 void Controller::SetUnderlineColor(const Vector4& color)
904 {
905   mImpl->mModel->mVisualModel->SetUnderlineColor(color);
906   mImpl->RequestRelayout();
907 }
908
909 const Vector4& Controller::GetUnderlineColor() const
910 {
911   return mImpl->mModel->mVisualModel->GetUnderlineColor();
912 }
913
914 void Controller::SetUnderlineEnabled(bool enabled)
915 {
916   mImpl->mModel->mVisualModel->SetUnderlineEnabled(enabled);
917   mImpl->RequestRelayout();
918 }
919
920 bool Controller::IsUnderlineEnabled() const
921 {
922   return mImpl->mModel->mVisualModel->IsUnderlineEnabled();
923 }
924
925 void Controller::SetUnderlineHeight(float height)
926 {
927   mImpl->mModel->mVisualModel->SetUnderlineHeight(height);
928   mImpl->RequestRelayout();
929 }
930
931 float Controller::GetUnderlineHeight() const
932 {
933   return mImpl->mModel->mVisualModel->GetUnderlineHeight();
934 }
935
936 void Controller::SetUnderlineType(Text::Underline::Type type)
937 {
938   mImpl->mModel->mVisualModel->SetUnderlineType(type);
939
940   mImpl->RequestRelayout();
941 }
942
943 Text::Underline::Type Controller::GetUnderlineType() const
944 {
945   return mImpl->mModel->mVisualModel->GetUnderlineType();
946 }
947
948 void Controller::SetDashedUnderlineWidth(float width)
949 {
950   mImpl->mModel->mVisualModel->SetDashedUnderlineWidth(width);
951
952   mImpl->RequestRelayout();
953 }
954
955 float Controller::GetDashedUnderlineWidth() const
956 {
957   return mImpl->mModel->mVisualModel->GetDashedUnderlineWidth();
958 }
959
960 void Controller::SetDashedUnderlineGap(float gap)
961 {
962   mImpl->mModel->mVisualModel->SetDashedUnderlineGap(gap);
963
964   mImpl->RequestRelayout();
965 }
966
967 float Controller::GetDashedUnderlineGap() const
968 {
969   return mImpl->mModel->mVisualModel->GetDashedUnderlineGap();
970 }
971
972 void Controller::SetOutlineColor(const Vector4& color)
973 {
974   mImpl->mModel->mVisualModel->SetOutlineColor(color);
975   mImpl->RequestRelayout();
976 }
977
978 const Vector4& Controller::GetOutlineColor() const
979 {
980   return mImpl->mModel->mVisualModel->GetOutlineColor();
981 }
982
983 void Controller::SetOutlineWidth(uint16_t width)
984 {
985   mImpl->mModel->mVisualModel->SetOutlineWidth(width);
986   mImpl->RequestRelayout();
987 }
988
989 uint16_t Controller::GetOutlineWidth() const
990 {
991   return mImpl->mModel->mVisualModel->GetOutlineWidth();
992 }
993
994 void Controller::SetBackgroundColor(const Vector4& color)
995 {
996   mImpl->mModel->mVisualModel->SetBackgroundColor(color);
997   mImpl->RequestRelayout();
998 }
999
1000 const Vector4& Controller::GetBackgroundColor() const
1001 {
1002   return mImpl->mModel->mVisualModel->GetBackgroundColor();
1003 }
1004
1005 void Controller::SetBackgroundEnabled(bool enabled)
1006 {
1007   mImpl->mModel->mVisualModel->SetBackgroundEnabled(enabled);
1008   mImpl->RequestRelayout();
1009 }
1010
1011 bool Controller::IsBackgroundEnabled() const
1012 {
1013   return mImpl->mModel->mVisualModel->IsBackgroundEnabled();
1014 }
1015
1016 void Controller::SetDefaultEmbossProperties(const std::string& embossProperties)
1017 {
1018   EnsureCreated(mImpl->mEmbossDefaults);
1019   mImpl->mEmbossDefaults->properties = embossProperties;
1020 }
1021
1022 std::string Controller::GetDefaultEmbossProperties() const
1023 {
1024   return mImpl->mEmbossDefaults ? mImpl->mEmbossDefaults->properties : EMPTY_STRING;
1025 }
1026
1027 void Controller::SetDefaultOutlineProperties(const std::string& outlineProperties)
1028 {
1029   EnsureCreated(mImpl->mOutlineDefaults);
1030   mImpl->mOutlineDefaults->properties = outlineProperties;
1031 }
1032
1033 std::string Controller::GetDefaultOutlineProperties() const
1034 {
1035   return mImpl->mOutlineDefaults ? mImpl->mOutlineDefaults->properties : EMPTY_STRING;
1036 }
1037
1038 bool Controller::SetDefaultLineSpacing(float lineSpacing)
1039 {
1040   return mImpl->SetDefaultLineSpacing(lineSpacing);
1041 }
1042
1043 float Controller::GetDefaultLineSpacing() const
1044 {
1045   return mImpl->mLayoutEngine.GetDefaultLineSpacing();
1046 }
1047
1048 bool Controller::SetDefaultLineSize(float lineSize)
1049 {
1050   return mImpl->SetDefaultLineSize(lineSize);
1051 }
1052
1053 float Controller::GetDefaultLineSize() const
1054 {
1055   return mImpl->mLayoutEngine.GetDefaultLineSize();
1056 }
1057
1058 bool Controller::SetRelativeLineSize(float relativeLineSize)
1059 {
1060   return mImpl->SetRelativeLineSize(relativeLineSize);
1061 }
1062
1063 float Controller::GetRelativeLineSize() const
1064 {
1065   return mImpl->GetRelativeLineSize();
1066 }
1067
1068 void Controller::SetInputColor(const Vector4& color)
1069 {
1070   InputProperties::SetInputColor(*this, color);
1071 }
1072
1073 const Vector4& Controller::GetInputColor() const
1074 {
1075   return InputProperties::GetInputColor(*this);
1076 }
1077
1078 void Controller::SetInputFontFamily(const std::string& fontFamily)
1079 {
1080   InputFontHandler::SetInputFontFamily(*this, fontFamily);
1081 }
1082
1083 std::string Controller::GetInputFontFamily() const
1084 {
1085   return InputFontHandler::GetInputFontFamily(*this);
1086 }
1087
1088 void Controller::SetInputFontWeight(FontWeight weight)
1089 {
1090   InputFontHandler::SetInputFontWeight(*this, weight);
1091 }
1092
1093 bool Controller::IsInputFontWeightDefined() const
1094 {
1095   return InputFontHandler::IsInputFontWeightDefined(*this);
1096 }
1097
1098 FontWeight Controller::GetInputFontWeight() const
1099 {
1100   return InputFontHandler::GetInputFontWeight(*this);
1101 }
1102
1103 void Controller::SetInputFontWidth(FontWidth width)
1104 {
1105   InputFontHandler::SetInputFontWidth(*this, width);
1106 }
1107
1108 bool Controller::IsInputFontWidthDefined() const
1109 {
1110   return InputFontHandler::IsInputFontWidthDefined(*this);
1111 }
1112
1113 FontWidth Controller::GetInputFontWidth() const
1114 {
1115   return InputFontHandler::GetInputFontWidth(*this);
1116 }
1117
1118 void Controller::SetInputFontSlant(FontSlant slant)
1119 {
1120   InputFontHandler::SetInputFontSlant(*this, slant);
1121 }
1122
1123 bool Controller::IsInputFontSlantDefined() const
1124 {
1125   return InputFontHandler::IsInputFontSlantDefined(*this);
1126 }
1127
1128 FontSlant Controller::GetInputFontSlant() const
1129 {
1130   return InputFontHandler::GetInputFontSlant(*this);
1131 }
1132
1133 void Controller::SetInputFontPointSize(float size)
1134 {
1135   InputFontHandler::SetInputFontPointSize(*this, size);
1136 }
1137
1138 float Controller::GetInputFontPointSize() const
1139 {
1140   return InputFontHandler::GetInputFontPointSize(*this);
1141 }
1142
1143 void Controller::SetInputLineSpacing(float lineSpacing)
1144 {
1145   InputProperties::SetInputLineSpacing(*this, lineSpacing);
1146 }
1147
1148 float Controller::GetInputLineSpacing() const
1149 {
1150   return InputProperties::GetInputLineSpacing(*this);
1151 }
1152
1153 void Controller::SetInputShadowProperties(const std::string& shadowProperties)
1154 {
1155   InputProperties::SetInputShadowProperties(*this, shadowProperties);
1156 }
1157
1158 std::string Controller::GetInputShadowProperties() const
1159 {
1160   return InputProperties::GetInputShadowProperties(*this);
1161 }
1162
1163 void Controller::SetInputUnderlineProperties(const std::string& underlineProperties)
1164 {
1165   InputProperties::SetInputUnderlineProperties(*this, underlineProperties);
1166 }
1167
1168 std::string Controller::GetInputUnderlineProperties() const
1169 {
1170   return InputProperties::GetInputUnderlineProperties(*this);
1171 }
1172
1173 void Controller::SetInputEmbossProperties(const std::string& embossProperties)
1174 {
1175   InputProperties::SetInputEmbossProperties(*this, embossProperties);
1176 }
1177
1178 std::string Controller::GetInputEmbossProperties() const
1179 {
1180   return InputProperties::GetInputEmbossProperties(*this);
1181 }
1182
1183 void Controller::SetInputOutlineProperties(const std::string& outlineProperties)
1184 {
1185   InputProperties::SetInputOutlineProperties(*this, outlineProperties);
1186 }
1187
1188 std::string Controller::GetInputOutlineProperties() const
1189 {
1190   return InputProperties::GetInputOutlineProperties(*this);
1191 }
1192
1193 void Controller::SetInputModePassword(bool passwordInput)
1194 {
1195   InputProperties::SetInputModePassword(*this, passwordInput);
1196 }
1197
1198 bool Controller::IsInputModePassword()
1199 {
1200   return InputProperties::IsInputModePassword(*this);
1201 }
1202
1203 void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action)
1204 {
1205   if(mImpl->mEventData)
1206   {
1207     mImpl->mEventData->mDoubleTapAction = action;
1208   }
1209 }
1210
1211 Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
1212 {
1213   return mImpl->mEventData ? mImpl->mEventData->mDoubleTapAction : NoTextTap::NO_ACTION;
1214 }
1215
1216 void Controller::SetNoTextLongPressAction(NoTextTap::Action action)
1217 {
1218   if(mImpl->mEventData)
1219   {
1220     mImpl->mEventData->mLongPressAction = action;
1221   }
1222 }
1223
1224 Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
1225 {
1226   return mImpl->mEventData ? mImpl->mEventData->mLongPressAction : NoTextTap::NO_ACTION;
1227 }
1228
1229 bool Controller::IsUnderlineSetByString()
1230 {
1231   return mImpl->mUnderlineSetByString;
1232 }
1233
1234 void Controller::UnderlineSetByString(bool setByString)
1235 {
1236   mImpl->mUnderlineSetByString = setByString;
1237 }
1238
1239 bool Controller::IsShadowSetByString()
1240 {
1241   return mImpl->mShadowSetByString;
1242 }
1243
1244 void Controller::ShadowSetByString(bool setByString)
1245 {
1246   mImpl->mShadowSetByString = setByString;
1247 }
1248
1249 bool Controller::IsOutlineSetByString()
1250 {
1251   return mImpl->mOutlineSetByString;
1252 }
1253
1254 void Controller::OutlineSetByString(bool setByString)
1255 {
1256   mImpl->mOutlineSetByString = setByString;
1257 }
1258
1259 bool Controller::IsFontStyleSetByString()
1260 {
1261   return mImpl->mFontStyleSetByString;
1262 }
1263
1264 void Controller::FontStyleSetByString(bool setByString)
1265 {
1266   mImpl->mFontStyleSetByString = setByString;
1267 }
1268
1269 void Controller::SetStrikethroughHeight(float height)
1270 {
1271   mImpl->mModel->mVisualModel->SetStrikethroughHeight(height);
1272
1273   mImpl->RequestRelayout();
1274 }
1275
1276 float Controller::GetStrikethroughHeight() const
1277 {
1278   return mImpl->mModel->mVisualModel->GetStrikethroughHeight();
1279 }
1280
1281 void Controller::SetStrikethroughColor(const Vector4& color)
1282 {
1283   mImpl->mModel->mVisualModel->SetStrikethroughColor(color);
1284
1285   mImpl->RequestRelayout();
1286 }
1287
1288 const Vector4& Controller::GetStrikethroughColor() const
1289 {
1290   return mImpl->mModel->mVisualModel->GetStrikethroughColor();
1291 }
1292
1293 void Controller::SetStrikethroughEnabled(bool enabled)
1294 {
1295   mImpl->mModel->mVisualModel->SetStrikethroughEnabled(enabled);
1296
1297   mImpl->RequestRelayout();
1298 }
1299
1300 bool Controller::IsStrikethroughEnabled() const
1301 {
1302   return mImpl->mModel->mVisualModel->IsStrikethroughEnabled();
1303 }
1304
1305 void Controller::SetInputStrikethroughProperties(const std::string& strikethroughProperties)
1306 {
1307   if(NULL != mImpl->mEventData)
1308   {
1309     mImpl->mEventData->mInputStyle.strikethroughProperties = strikethroughProperties;
1310   }
1311 }
1312
1313 std::string Controller::GetInputStrikethroughProperties() const
1314 {
1315   return (NULL != mImpl->mEventData) ? mImpl->mEventData->mInputStyle.strikethroughProperties : EMPTY_STRING;
1316 }
1317
1318 bool Controller::IsStrikethroughSetByString()
1319 {
1320   return mImpl->mStrikethroughSetByString;
1321 }
1322
1323 void Controller::StrikethroughSetByString(bool setByString)
1324 {
1325   mImpl->mStrikethroughSetByString = setByString;
1326 }
1327
1328 Layout::Engine& Controller::GetLayoutEngine()
1329 {
1330   return mImpl->mLayoutEngine;
1331 }
1332
1333 View& Controller::GetView()
1334 {
1335   return mImpl->mView;
1336 }
1337
1338 Vector3 Controller::GetNaturalSize()
1339 {
1340   return Relayouter::GetNaturalSize(*this);
1341 }
1342
1343 bool Controller::CheckForTextFit(float pointSize, Size& layoutSize)
1344 {
1345   return Relayouter::CheckForTextFit(*this, pointSize, layoutSize);
1346 }
1347
1348 void Controller::FitPointSizeforLayout(Size layoutSize)
1349 {
1350   Relayouter::FitPointSizeforLayout(*this, layoutSize);
1351 }
1352
1353 void Controller::FitArrayPointSizeforLayout(Size layoutSize)
1354 {
1355   Relayouter::FitArrayPointSizeforLayout(*this, layoutSize);
1356 }
1357
1358 float Controller::GetHeightForWidth(float width)
1359 {
1360   return Relayouter::GetHeightForWidth(*this, width);
1361 }
1362
1363 int Controller::GetLineCount(float width)
1364 {
1365   GetHeightForWidth(width);
1366   return mImpl->mModel->GetNumberOfLines();
1367 }
1368
1369 const ModelInterface* Controller::GetTextModel() const
1370 {
1371   return mImpl->mModel.Get();
1372 }
1373
1374 float Controller::GetScrollAmountByUserInput()
1375 {
1376   float scrollAmount = 0.0f;
1377
1378   if(NULL != mImpl->mEventData && mImpl->mEventData->mCheckScrollAmount)
1379   {
1380     scrollAmount                          = mImpl->mModel->mScrollPosition.y - mImpl->mModel->mScrollPositionLast.y;
1381     mImpl->mEventData->mCheckScrollAmount = false;
1382   }
1383   return scrollAmount;
1384 }
1385
1386 bool Controller::GetTextScrollInfo(float& scrollPosition, float& controlHeight, float& layoutHeight)
1387 {
1388   const Vector2& layout = mImpl->mModel->mVisualModel->GetLayoutSize();
1389   bool           isScrolled;
1390
1391   controlHeight  = mImpl->mModel->mVisualModel->mControlSize.height;
1392   layoutHeight   = layout.height;
1393   scrollPosition = mImpl->mModel->mScrollPosition.y;
1394   isScrolled     = !Equals(mImpl->mModel->mScrollPosition.y, mImpl->mModel->mScrollPositionLast.y, Math::MACHINE_EPSILON_1);
1395   return isScrolled;
1396 }
1397
1398 void Controller::SetHiddenInputOption(const Property::Map& options)
1399 {
1400   EnsureCreated<HiddenText, Controller*>(mImpl->mHiddenInput, this);
1401   mImpl->mHiddenInput->SetProperties(options);
1402 }
1403
1404 void Controller::GetHiddenInputOption(Property::Map& options)
1405 {
1406   if(mImpl->mHiddenInput)
1407   {
1408     mImpl->mHiddenInput->GetProperties(options);
1409   }
1410 }
1411
1412 void Controller::SetInputFilterOption(const Property::Map& options)
1413 {
1414   EnsureCreated(mImpl->mInputFilter);
1415   mImpl->mInputFilter->SetProperties(options);
1416 }
1417
1418 void Controller::GetInputFilterOption(Property::Map& options)
1419 {
1420   if(mImpl->mInputFilter)
1421   {
1422     mImpl->mInputFilter->GetProperties(options);
1423   }
1424 }
1425
1426 void Controller::SetPlaceholderProperty(const Property::Map& map)
1427 {
1428   PlaceholderHandler::SetPlaceholderProperty(*this, map);
1429 }
1430
1431 void Controller::GetPlaceholderProperty(Property::Map& map)
1432 {
1433   PlaceholderHandler::GetPlaceholderProperty(*this, map);
1434 }
1435
1436 Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
1437 {
1438   // Make sure the model is up-to-date before layouting
1439   EventHandler::ProcessModifyEvents(*this);
1440
1441   return mImpl->GetTextDirection();
1442 }
1443
1444 Toolkit::DevelText::VerticalLineAlignment::Type Controller::GetVerticalLineAlignment() const
1445 {
1446   return mImpl->mModel->GetVerticalLineAlignment();
1447 }
1448
1449 void Controller::SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignment::Type alignment)
1450 {
1451   mImpl->mModel->mVerticalLineAlignment = alignment;
1452 }
1453
1454 Toolkit::DevelText::EllipsisPosition::Type Controller::GetEllipsisPosition() const
1455 {
1456   return mImpl->mModel->GetEllipsisPosition();
1457 }
1458
1459 void Controller::SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition)
1460 {
1461   mImpl->mModel->mEllipsisPosition = ellipsisPosition;
1462   mImpl->mModel->mVisualModel->SetEllipsisPosition(ellipsisPosition);
1463 }
1464
1465 void Controller::SetCharacterSpacing(float characterSpacing)
1466 {
1467   mImpl->mModel->mVisualModel->SetCharacterSpacing(characterSpacing);
1468
1469   mImpl->RelayoutAllCharacters();
1470   mImpl->RequestRelayout();
1471 }
1472
1473 const float Controller::GetCharacterSpacing() const
1474 {
1475   return mImpl->mModel->mVisualModel->GetCharacterSpacing();
1476 }
1477
1478 void Controller::SetVisualTransformOffset(Vector2 offset)
1479 {
1480   mImpl->mModel->mVisualTransformOffset = offset;
1481 }
1482
1483 Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
1484 {
1485   return Relayouter::Relayout(*this, size, layoutDirection);
1486 }
1487
1488 void Controller::RequestRelayout()
1489 {
1490   mImpl->RequestRelayout();
1491 }
1492
1493 Vector<Vector2> Controller::GetTextSize(CharacterIndex startIndex, CharacterIndex endIndex)
1494 {
1495   Vector<Vector2> sizesList;
1496   Vector<Vector2> positionsList;
1497
1498   GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList);
1499   return sizesList;
1500 }
1501
1502 Vector<Vector2> Controller::GetTextPosition(CharacterIndex startIndex, CharacterIndex endIndex)
1503 {
1504   Vector<Vector2> sizesList;
1505   Vector<Vector2> positionsList;
1506
1507   GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList);
1508   return positionsList;
1509 }
1510
1511 Rect<float> Controller::GetLineBoundingRectangle(const uint32_t lineIndex)
1512 {
1513   return GetLineBoundingRect(mImpl->mModel, lineIndex);
1514 }
1515
1516 Rect<float> Controller::GetCharacterBoundingRectangle(const uint32_t charIndex)
1517 {
1518   return GetCharacterBoundingRect(mImpl->mModel, charIndex);
1519 }
1520
1521 int Controller::GetCharacterIndexAtPosition(float visualX, float visualY)
1522 {
1523   return GetCharIndexAtPosition(mImpl->mModel, visualX, visualY);
1524 }
1525
1526 Rect<> Controller::GetTextBoundingRectangle(CharacterIndex startIndex, CharacterIndex endIndex)
1527 {
1528   Vector<Vector2> sizeList;
1529   Vector<Vector2> positionList;
1530
1531   GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizeList, positionList);
1532
1533   if(sizeList.Empty() || sizeList.Size() != positionList.Size())
1534   {
1535     return {0, 0, 0, 0};
1536   }
1537
1538   auto controlWidth = mImpl->mModel->mVisualModel->mControlSize.width;
1539   auto minX         = positionList[0].x;
1540   auto minY         = positionList[0].y;
1541   auto maxRight     = positionList[0].x + sizeList[0].x;
1542   auto maxBottom    = positionList[0].y + sizeList[0].y;
1543
1544   for(unsigned int i = 1; i < sizeList.Size(); i++)
1545   {
1546     minX      = std::min(minX, positionList[i].x);
1547     minY      = std::min(minY, positionList[i].y);
1548     maxRight  = std::max(maxRight, positionList[i].x + sizeList[i].x);
1549     maxBottom = std::max(maxBottom, positionList[i].y + sizeList[i].y);
1550   }
1551
1552   if(minX < 0.0f)
1553   {
1554     minX = 0.0f;
1555   }
1556
1557   if(maxRight > controlWidth)
1558   {
1559     maxRight = controlWidth;
1560   }
1561
1562   return {minX, minY, maxRight - minX, maxBottom - minY};
1563 }
1564
1565 bool Controller::IsInputStyleChangedSignalsQueueEmpty()
1566 {
1567   return mImpl->IsInputStyleChangedSignalsQueueEmpty();
1568 }
1569
1570 void Controller::RequestProcessInputStyleChangedSignals()
1571 {
1572   if(Dali::Adaptor::IsAvailable() && !mImpl->mProcessorRegistered)
1573   {
1574     mImpl->mProcessorRegistered = true;
1575     Dali::Adaptor::Get().RegisterProcessor(*this, true);
1576   }
1577 }
1578
1579 void Controller::OnIdleSignal()
1580 {
1581   if(mImpl->mIdleCallback)
1582   {
1583     mImpl->mIdleCallback = NULL;
1584
1585     mImpl->ProcessInputStyleChangedSignals();
1586   }
1587 }
1588
1589 void Controller::KeyboardFocusGainEvent()
1590 {
1591   EventHandler::KeyboardFocusGainEvent(*this);
1592 }
1593
1594 void Controller::KeyboardFocusLostEvent()
1595 {
1596   EventHandler::KeyboardFocusLostEvent(*this);
1597 }
1598
1599 bool Controller::KeyEvent(const Dali::KeyEvent& keyEvent)
1600 {
1601   return EventHandler::KeyEvent(*this, keyEvent);
1602 }
1603
1604 void Controller::AnchorEvent(float x, float y)
1605 {
1606   EventHandler::AnchorEvent(*this, x, y);
1607 }
1608
1609 void Controller::TapEvent(unsigned int tapCount, float x, float y)
1610 {
1611   EventHandler::TapEvent(*this, tapCount, x, y);
1612 }
1613
1614 void Controller::PanEvent(GestureState state, const Vector2& displacement)
1615 {
1616   EventHandler::PanEvent(*this, state, displacement);
1617 }
1618
1619 void Controller::LongPressEvent(GestureState state, float x, float y)
1620 {
1621   EventHandler::LongPressEvent(*this, state, x, y);
1622 }
1623
1624 void Controller::SelectEvent(float x, float y, SelectionType selectType)
1625 {
1626   EventHandler::SelectEvent(*this, x, y, selectType);
1627 }
1628
1629 void Controller::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
1630 {
1631   if(mImpl->mEventData)
1632   {
1633     mImpl->mEventData->mCheckScrollAmount     = true;
1634     mImpl->mEventData->mIsLeftHandleSelected  = true;
1635     mImpl->mEventData->mIsRightHandleSelected = true;
1636     mImpl->SetTextSelectionRange(start, end);
1637     mImpl->RequestRelayout();
1638     EventHandler::KeyboardFocusGainEvent(*this);
1639   }
1640 }
1641
1642 Uint32Pair Controller::GetTextSelectionRange() const
1643 {
1644   return mImpl->GetTextSelectionRange();
1645 }
1646
1647 CharacterIndex Controller::GetPrimaryCursorPosition() const
1648 {
1649   return mImpl->GetPrimaryCursorPosition();
1650 }
1651
1652 bool Controller::SetPrimaryCursorPosition(CharacterIndex index, bool focused)
1653 {
1654   if(mImpl->mEventData)
1655   {
1656     mImpl->mEventData->mCheckScrollAmount     = true;
1657     mImpl->mEventData->mIsLeftHandleSelected  = true;
1658     mImpl->mEventData->mIsRightHandleSelected = true;
1659     mImpl->mEventData->mCheckScrollAmount     = true;
1660     if(mImpl->SetPrimaryCursorPosition(index, focused) && focused)
1661     {
1662       EventHandler::KeyboardFocusGainEvent(*this);
1663       return true;
1664     }
1665   }
1666   return false;
1667 }
1668
1669 void Controller::SelectWholeText()
1670 {
1671   EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::ALL);
1672 }
1673
1674 void Controller::SelectNone()
1675 {
1676   EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::NONE);
1677 }
1678
1679 void Controller::SelectText(const uint32_t start, const uint32_t end)
1680 {
1681   EventHandler::SelectEvent(*this, start, end, SelectionType::RANGE);
1682 }
1683
1684 string Controller::GetSelectedText() const
1685 {
1686   return mImpl->GetSelectedText();
1687 }
1688
1689 string Controller::CopyText()
1690 {
1691   return mImpl->CopyText();
1692 }
1693
1694 string Controller::CutText()
1695 {
1696   return mImpl->CutText();
1697 }
1698
1699 void Controller::PasteClipboardItemEvent(uint32_t id, const char* mimeType, const char* data)
1700 {
1701   // Upon receiving the data, it is important to disconnect the signal
1702   // to avoid potential unintended pasting caused by subsequent requests.
1703   mImpl->mClipboard.DataReceivedSignal().Disconnect(this, &Controller::PasteClipboardItemEvent);
1704
1705   // If the id is 0u, it is an invalid response.
1706   // text-controller allows only plain text type.
1707   if(id != 0u && !strncmp(mimeType, MIME_TYPE_TEXT_PLAIN, strlen(MIME_TYPE_TEXT_PLAIN)))
1708   {
1709     EventHandler::PasteClipboardItemEvent(*this, data);
1710   }
1711 }
1712
1713 void Controller::PasteText()
1714 {
1715   if(mImpl->EnsureClipboardCreated())
1716   {
1717     // Connect the signal before calling GetData() of the clipboard.
1718     mImpl->mClipboard.DataReceivedSignal().Connect(this, &Controller::PasteClipboardItemEvent);
1719
1720     // Request clipboard service to retrieve an item.
1721     uint id = mImpl->mClipboard.GetData(MIME_TYPE_TEXT_PLAIN);
1722     if(id == 0u)
1723     {
1724       // If the return id is 0u, the signal is not emitted, we must disconnect signal here.
1725       mImpl->mClipboard.DataReceivedSignal().Disconnect(this, &Controller::PasteClipboardItemEvent);
1726     }
1727   }
1728 }
1729
1730 InputMethodContext::CallbackData Controller::OnInputMethodContextEvent(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
1731 {
1732   return EventHandler::OnInputMethodContextEvent(*this, inputMethodContext, inputMethodContextEvent);
1733 }
1734
1735 void Controller::GetTargetSize(Vector2& targetSize)
1736 {
1737   targetSize = mImpl->mModel->mVisualModel->mControlSize;
1738 }
1739
1740 void Controller::AddDecoration(Actor& actor, DecorationType type, bool needsClipping)
1741 {
1742   if(mImpl->mEditableControlInterface)
1743   {
1744     mImpl->mEditableControlInterface->AddDecoration(actor, type, needsClipping);
1745   }
1746 }
1747
1748 bool Controller::IsEditable() const
1749 {
1750   return mImpl->IsEditable();
1751 }
1752
1753 void Controller::SetEditable(bool editable)
1754 {
1755   mImpl->SetEditable(editable);
1756 }
1757
1758 void Controller::ScrollBy(Vector2 scroll)
1759 {
1760   mImpl->ScrollBy(scroll);
1761 }
1762
1763 bool Controller::IsScrollable(const Vector2& displacement)
1764 {
1765   return mImpl->IsScrollable(displacement);
1766 }
1767
1768 float Controller::GetHorizontalScrollPosition()
1769 {
1770   return mImpl->GetHorizontalScrollPosition();
1771 }
1772
1773 float Controller::GetVerticalScrollPosition()
1774 {
1775   return mImpl->GetVerticalScrollPosition();
1776 }
1777
1778 void Controller::DecorationEvent(HandleType handleType, HandleState state, float x, float y)
1779 {
1780   EventHandler::DecorationEvent(*this, handleType, state, x, y);
1781 }
1782
1783 void Controller::TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button)
1784 {
1785   EventHandler::TextPopupButtonTouched(*this, button);
1786 }
1787
1788 void Controller::DisplayTimeExpired()
1789 {
1790   mImpl->mEventData->mUpdateCursorPosition = true;
1791   // Apply modifications to the model
1792   mImpl->mOperationsPending = ALL_OPERATIONS;
1793
1794   mImpl->RequestRelayout();
1795 }
1796
1797 void Controller::ResetCursorPosition(CharacterIndex cursorIndex)
1798 {
1799   // Reset the cursor position
1800   if(NULL != mImpl->mEventData)
1801   {
1802     mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
1803
1804     // Update the cursor if it's in editing mode.
1805     if(EventData::IsEditingState(mImpl->mEventData->mState))
1806     {
1807       mImpl->mEventData->mUpdateCursorPosition = true;
1808     }
1809   }
1810 }
1811
1812 CharacterIndex Controller::GetCursorPosition()
1813 {
1814   return mImpl->mEventData ? mImpl->mEventData->mPrimaryCursorPosition : 0;
1815 }
1816
1817 void Controller::SetControlInterface(ControlInterface* controlInterface)
1818 {
1819   mImpl->mControlInterface = controlInterface;
1820 }
1821
1822 void Controller::SetAnchorControlInterface(AnchorControlInterface* anchorControlInterface)
1823 {
1824   mImpl->mAnchorControlInterface = anchorControlInterface;
1825 }
1826
1827 bool Controller::ShouldClearFocusOnEscape() const
1828 {
1829   return mImpl->mShouldClearFocusOnEscape;
1830 }
1831
1832 Actor Controller::CreateBackgroundActor()
1833 {
1834   return CreateControllerBackgroundActor(mImpl->mView, mImpl->mModel->mVisualModel, mImpl->mModel->mLogicalModel, mImpl->mShaderBackground);
1835 }
1836
1837 void Controller::GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors)
1838 {
1839   mImpl->GetAnchorActors(anchorActors);
1840 }
1841
1842 int Controller::GetAnchorIndex(size_t characterOffset)
1843 {
1844   return mImpl->GetAnchorIndex(characterOffset);
1845 }
1846
1847 void Controller::Process(bool postProcess)
1848 {
1849   if(Dali::Adaptor::IsAvailable() && mImpl->mProcessorRegistered)
1850   {
1851     Dali::Adaptor& adaptor = Dali::Adaptor::Get();
1852
1853     adaptor.UnregisterProcessor(*this, true);
1854     mImpl->mProcessorRegistered = false;
1855
1856     if(NULL == mImpl->mIdleCallback)
1857     {
1858       // @note: The callback manager takes the ownership of the callback object.
1859       mImpl->mIdleCallback = MakeCallback(this, &Controller::OnIdleSignal);
1860       if(DALI_UNLIKELY(!adaptor.AddIdle(mImpl->mIdleCallback, false)))
1861       {
1862         DALI_LOG_ERROR("Fail to add idle callback for text controller style changed signals queue. Skip these callbacks\n");
1863
1864         // Clear queue forcely.
1865         if(mImpl->mEventData)
1866         {
1867           mImpl->mEventData->mInputStyleChangedQueue.Clear();
1868         }
1869
1870         // Set the pointer to null as the callback manager deletes the callback even AddIdle failed.
1871         mImpl->mIdleCallback = NULL;
1872       }
1873     }
1874   }
1875 }
1876
1877 Controller::Controller(ControlInterface*           controlInterface,
1878                        EditableControlInterface*   editableControlInterface,
1879                        SelectableControlInterface* selectableControlInterface,
1880                        AnchorControlInterface*     anchorControlInterface)
1881 : mImpl(new Controller::Impl(controlInterface, editableControlInterface, selectableControlInterface, anchorControlInterface))
1882 {
1883 }
1884
1885 Controller::~Controller()
1886 {
1887   if(Dali::Adaptor::IsAvailable())
1888   {
1889     if(mImpl->mProcessorRegistered)
1890     {
1891       Dali::Adaptor::Get().UnregisterProcessor(*this, true);
1892     }
1893     if(mImpl->mIdleCallback)
1894     {
1895       Dali::Adaptor::Get().RemoveIdle(mImpl->mIdleCallback);
1896     }
1897   }
1898 }
1899
1900 } // namespace Dali::Toolkit::Text