Fix editable text font size update issue
[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   if(mImpl->mEventData && EventData::INACTIVE != mImpl->mEventData->mState)
788   {
789     SetInputFontPointSize(fontSize, true);
790   }
791 }
792
793 float Controller::GetDefaultFontSize(FontSizeType type) const
794 {
795   if(mImpl->mFontDefaults)
796   {
797     return (type == POINT_SIZE) ? mImpl->mFontDefaults->mDefaultPointSize : ConvertPointToPixel(mImpl->mFontDefaults->mDefaultPointSize);
798   }
799   return 0.0f;
800 }
801
802 void Controller::SetPlaceholderTextFontSize(float fontSize, FontSizeType type)
803 {
804   PlaceholderHandler::SetPlaceholderTextFontSize(*this, fontSize, type);
805 }
806
807 float Controller::GetPlaceholderTextFontSize(FontSizeType type) const
808 {
809   return PlaceholderHandler::GetPlaceholderTextFontSize(*this, type);
810 }
811
812 void Controller::SetDefaultColor(const Vector4& color)
813 {
814   mImpl->SetDefaultColor(color);
815 }
816
817 const Vector4& Controller::GetDefaultColor() const
818 {
819   return mImpl->mTextColor;
820 }
821
822 void Controller::SetAnchorColor(const Vector4& color)
823 {
824   mImpl->SetAnchorColor(color);
825 }
826
827 const Vector4& Controller::GetAnchorColor() const
828 {
829   return mImpl->GetAnchorColor();
830 }
831
832 void Controller::SetAnchorClickedColor(const Vector4& color)
833 {
834   mImpl->SetAnchorClickedColor(color);
835 }
836
837 const Vector4& Controller::GetAnchorClickedColor() const
838 {
839   return mImpl->GetAnchorClickedColor();
840 }
841
842 void Controller::SetDisabledColorOpacity(float opacity)
843 {
844   mImpl->mDisabledColorOpacity = opacity;
845 }
846
847 float Controller::GetDisabledColorOpacity() const
848 {
849   return mImpl->mDisabledColorOpacity;
850 }
851
852 void Controller::SetUserInteractionEnabled(bool enabled)
853 {
854   mImpl->SetUserInteractionEnabled(enabled);
855 }
856
857 bool Controller::IsUserInteractionEnabled() const
858 {
859   return mImpl->mIsUserInteractionEnabled;
860 }
861
862 void Controller::SetPlaceholderTextColor(const Vector4& textColor)
863 {
864   PlaceholderHandler::SetPlaceholderTextColor(*this, textColor);
865 }
866
867 const Vector4& Controller::GetPlaceholderTextColor() const
868 {
869   return PlaceholderHandler::GetPlaceholderTextColor(*this);
870 }
871
872 void Controller::SetShadowOffset(const Vector2& shadowOffset)
873 {
874   mImpl->mModel->mVisualModel->SetShadowOffset(shadowOffset);
875   mImpl->RequestRelayout();
876 }
877
878 const Vector2& Controller::GetShadowOffset() const
879 {
880   return mImpl->mModel->mVisualModel->GetShadowOffset();
881 }
882
883 void Controller::SetShadowColor(const Vector4& shadowColor)
884 {
885   mImpl->mModel->mVisualModel->SetShadowColor(shadowColor);
886   mImpl->RequestRelayout();
887 }
888
889 const Vector4& Controller::GetShadowColor() const
890 {
891   return mImpl->mModel->mVisualModel->GetShadowColor();
892 }
893
894 void Controller::SetShadowBlurRadius(const float& shadowBlurRadius)
895 {
896   if(fabsf(GetShadowBlurRadius() - shadowBlurRadius) > Math::MACHINE_EPSILON_1)
897   {
898     mImpl->mModel->mVisualModel->SetShadowBlurRadius(shadowBlurRadius);
899     mImpl->RequestRelayout();
900   }
901 }
902
903 const float& Controller::GetShadowBlurRadius() const
904 {
905   return mImpl->mModel->mVisualModel->GetShadowBlurRadius();
906 }
907
908 void Controller::SetUnderlineColor(const Vector4& color)
909 {
910   mImpl->mModel->mVisualModel->SetUnderlineColor(color);
911   mImpl->RequestRelayout();
912 }
913
914 const Vector4& Controller::GetUnderlineColor() const
915 {
916   return mImpl->mModel->mVisualModel->GetUnderlineColor();
917 }
918
919 void Controller::SetUnderlineEnabled(bool enabled)
920 {
921   mImpl->mModel->mVisualModel->SetUnderlineEnabled(enabled);
922   mImpl->RequestRelayout();
923 }
924
925 bool Controller::IsUnderlineEnabled() const
926 {
927   return mImpl->mModel->mVisualModel->IsUnderlineEnabled();
928 }
929
930 void Controller::SetUnderlineHeight(float height)
931 {
932   mImpl->mModel->mVisualModel->SetUnderlineHeight(height);
933   mImpl->RequestRelayout();
934 }
935
936 float Controller::GetUnderlineHeight() const
937 {
938   return mImpl->mModel->mVisualModel->GetUnderlineHeight();
939 }
940
941 void Controller::SetUnderlineType(Text::Underline::Type type)
942 {
943   mImpl->mModel->mVisualModel->SetUnderlineType(type);
944
945   mImpl->RequestRelayout();
946 }
947
948 Text::Underline::Type Controller::GetUnderlineType() const
949 {
950   return mImpl->mModel->mVisualModel->GetUnderlineType();
951 }
952
953 void Controller::SetDashedUnderlineWidth(float width)
954 {
955   mImpl->mModel->mVisualModel->SetDashedUnderlineWidth(width);
956
957   mImpl->RequestRelayout();
958 }
959
960 float Controller::GetDashedUnderlineWidth() const
961 {
962   return mImpl->mModel->mVisualModel->GetDashedUnderlineWidth();
963 }
964
965 void Controller::SetDashedUnderlineGap(float gap)
966 {
967   mImpl->mModel->mVisualModel->SetDashedUnderlineGap(gap);
968
969   mImpl->RequestRelayout();
970 }
971
972 float Controller::GetDashedUnderlineGap() const
973 {
974   return mImpl->mModel->mVisualModel->GetDashedUnderlineGap();
975 }
976
977 void Controller::SetOutlineColor(const Vector4& color)
978 {
979   mImpl->mModel->mVisualModel->SetOutlineColor(color);
980   mImpl->RequestRelayout();
981 }
982
983 const Vector4& Controller::GetOutlineColor() const
984 {
985   return mImpl->mModel->mVisualModel->GetOutlineColor();
986 }
987
988 void Controller::SetOutlineWidth(uint16_t width)
989 {
990   mImpl->mModel->mVisualModel->SetOutlineWidth(width);
991   mImpl->RequestRelayout();
992 }
993
994 uint16_t Controller::GetOutlineWidth() const
995 {
996   return mImpl->mModel->mVisualModel->GetOutlineWidth();
997 }
998
999 void Controller::SetBackgroundColor(const Vector4& color)
1000 {
1001   mImpl->mModel->mVisualModel->SetBackgroundColor(color);
1002   mImpl->RequestRelayout();
1003 }
1004
1005 const Vector4& Controller::GetBackgroundColor() const
1006 {
1007   return mImpl->mModel->mVisualModel->GetBackgroundColor();
1008 }
1009
1010 void Controller::SetBackgroundEnabled(bool enabled)
1011 {
1012   mImpl->mModel->mVisualModel->SetBackgroundEnabled(enabled);
1013   mImpl->RequestRelayout();
1014 }
1015
1016 bool Controller::IsBackgroundEnabled() const
1017 {
1018   return mImpl->mModel->mVisualModel->IsBackgroundEnabled();
1019 }
1020
1021 void Controller::SetDefaultEmbossProperties(const std::string& embossProperties)
1022 {
1023   EnsureCreated(mImpl->mEmbossDefaults);
1024   mImpl->mEmbossDefaults->properties = embossProperties;
1025 }
1026
1027 std::string Controller::GetDefaultEmbossProperties() const
1028 {
1029   return mImpl->mEmbossDefaults ? mImpl->mEmbossDefaults->properties : EMPTY_STRING;
1030 }
1031
1032 void Controller::SetDefaultOutlineProperties(const std::string& outlineProperties)
1033 {
1034   EnsureCreated(mImpl->mOutlineDefaults);
1035   mImpl->mOutlineDefaults->properties = outlineProperties;
1036 }
1037
1038 std::string Controller::GetDefaultOutlineProperties() const
1039 {
1040   return mImpl->mOutlineDefaults ? mImpl->mOutlineDefaults->properties : EMPTY_STRING;
1041 }
1042
1043 bool Controller::SetDefaultLineSpacing(float lineSpacing)
1044 {
1045   return mImpl->SetDefaultLineSpacing(lineSpacing);
1046 }
1047
1048 float Controller::GetDefaultLineSpacing() const
1049 {
1050   return mImpl->mLayoutEngine.GetDefaultLineSpacing();
1051 }
1052
1053 bool Controller::SetDefaultLineSize(float lineSize)
1054 {
1055   return mImpl->SetDefaultLineSize(lineSize);
1056 }
1057
1058 float Controller::GetDefaultLineSize() const
1059 {
1060   return mImpl->mLayoutEngine.GetDefaultLineSize();
1061 }
1062
1063 bool Controller::SetRelativeLineSize(float relativeLineSize)
1064 {
1065   return mImpl->SetRelativeLineSize(relativeLineSize);
1066 }
1067
1068 float Controller::GetRelativeLineSize() const
1069 {
1070   return mImpl->GetRelativeLineSize();
1071 }
1072
1073 void Controller::SetInputColor(const Vector4& color)
1074 {
1075   InputProperties::SetInputColor(*this, color);
1076 }
1077
1078 const Vector4& Controller::GetInputColor() const
1079 {
1080   return InputProperties::GetInputColor(*this);
1081 }
1082
1083 void Controller::SetInputFontFamily(const std::string& fontFamily)
1084 {
1085   InputFontHandler::SetInputFontFamily(*this, fontFamily);
1086 }
1087
1088 std::string Controller::GetInputFontFamily() const
1089 {
1090   return InputFontHandler::GetInputFontFamily(*this);
1091 }
1092
1093 void Controller::SetInputFontWeight(FontWeight weight)
1094 {
1095   InputFontHandler::SetInputFontWeight(*this, weight);
1096 }
1097
1098 bool Controller::IsInputFontWeightDefined() const
1099 {
1100   return InputFontHandler::IsInputFontWeightDefined(*this);
1101 }
1102
1103 FontWeight Controller::GetInputFontWeight() const
1104 {
1105   return InputFontHandler::GetInputFontWeight(*this);
1106 }
1107
1108 void Controller::SetInputFontWidth(FontWidth width)
1109 {
1110   InputFontHandler::SetInputFontWidth(*this, width);
1111 }
1112
1113 bool Controller::IsInputFontWidthDefined() const
1114 {
1115   return InputFontHandler::IsInputFontWidthDefined(*this);
1116 }
1117
1118 FontWidth Controller::GetInputFontWidth() const
1119 {
1120   return InputFontHandler::GetInputFontWidth(*this);
1121 }
1122
1123 void Controller::SetInputFontSlant(FontSlant slant)
1124 {
1125   InputFontHandler::SetInputFontSlant(*this, slant);
1126 }
1127
1128 bool Controller::IsInputFontSlantDefined() const
1129 {
1130   return InputFontHandler::IsInputFontSlantDefined(*this);
1131 }
1132
1133 FontSlant Controller::GetInputFontSlant() const
1134 {
1135   return InputFontHandler::GetInputFontSlant(*this);
1136 }
1137
1138 void Controller::SetInputFontPointSize(float size, bool defaultFontSizeUpdated)
1139 {
1140   InputFontHandler::SetInputFontPointSize(*this, size, defaultFontSizeUpdated);
1141 }
1142
1143 float Controller::GetInputFontPointSize() const
1144 {
1145   return InputFontHandler::GetInputFontPointSize(*this);
1146 }
1147
1148 void Controller::SetInputLineSpacing(float lineSpacing)
1149 {
1150   InputProperties::SetInputLineSpacing(*this, lineSpacing);
1151 }
1152
1153 float Controller::GetInputLineSpacing() const
1154 {
1155   return InputProperties::GetInputLineSpacing(*this);
1156 }
1157
1158 void Controller::SetInputShadowProperties(const std::string& shadowProperties)
1159 {
1160   InputProperties::SetInputShadowProperties(*this, shadowProperties);
1161 }
1162
1163 std::string Controller::GetInputShadowProperties() const
1164 {
1165   return InputProperties::GetInputShadowProperties(*this);
1166 }
1167
1168 void Controller::SetInputUnderlineProperties(const std::string& underlineProperties)
1169 {
1170   InputProperties::SetInputUnderlineProperties(*this, underlineProperties);
1171 }
1172
1173 std::string Controller::GetInputUnderlineProperties() const
1174 {
1175   return InputProperties::GetInputUnderlineProperties(*this);
1176 }
1177
1178 void Controller::SetInputEmbossProperties(const std::string& embossProperties)
1179 {
1180   InputProperties::SetInputEmbossProperties(*this, embossProperties);
1181 }
1182
1183 std::string Controller::GetInputEmbossProperties() const
1184 {
1185   return InputProperties::GetInputEmbossProperties(*this);
1186 }
1187
1188 void Controller::SetInputOutlineProperties(const std::string& outlineProperties)
1189 {
1190   InputProperties::SetInputOutlineProperties(*this, outlineProperties);
1191 }
1192
1193 std::string Controller::GetInputOutlineProperties() const
1194 {
1195   return InputProperties::GetInputOutlineProperties(*this);
1196 }
1197
1198 void Controller::SetInputModePassword(bool passwordInput)
1199 {
1200   InputProperties::SetInputModePassword(*this, passwordInput);
1201 }
1202
1203 bool Controller::IsInputModePassword()
1204 {
1205   return InputProperties::IsInputModePassword(*this);
1206 }
1207
1208 void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action)
1209 {
1210   if(mImpl->mEventData)
1211   {
1212     mImpl->mEventData->mDoubleTapAction = action;
1213   }
1214 }
1215
1216 Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
1217 {
1218   return mImpl->mEventData ? mImpl->mEventData->mDoubleTapAction : NoTextTap::NO_ACTION;
1219 }
1220
1221 void Controller::SetNoTextLongPressAction(NoTextTap::Action action)
1222 {
1223   if(mImpl->mEventData)
1224   {
1225     mImpl->mEventData->mLongPressAction = action;
1226   }
1227 }
1228
1229 Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
1230 {
1231   return mImpl->mEventData ? mImpl->mEventData->mLongPressAction : NoTextTap::NO_ACTION;
1232 }
1233
1234 bool Controller::IsUnderlineSetByString()
1235 {
1236   return mImpl->mUnderlineSetByString;
1237 }
1238
1239 void Controller::UnderlineSetByString(bool setByString)
1240 {
1241   mImpl->mUnderlineSetByString = setByString;
1242 }
1243
1244 bool Controller::IsShadowSetByString()
1245 {
1246   return mImpl->mShadowSetByString;
1247 }
1248
1249 void Controller::ShadowSetByString(bool setByString)
1250 {
1251   mImpl->mShadowSetByString = setByString;
1252 }
1253
1254 bool Controller::IsOutlineSetByString()
1255 {
1256   return mImpl->mOutlineSetByString;
1257 }
1258
1259 void Controller::OutlineSetByString(bool setByString)
1260 {
1261   mImpl->mOutlineSetByString = setByString;
1262 }
1263
1264 bool Controller::IsFontStyleSetByString()
1265 {
1266   return mImpl->mFontStyleSetByString;
1267 }
1268
1269 void Controller::FontStyleSetByString(bool setByString)
1270 {
1271   mImpl->mFontStyleSetByString = setByString;
1272 }
1273
1274 void Controller::SetStrikethroughHeight(float height)
1275 {
1276   mImpl->mModel->mVisualModel->SetStrikethroughHeight(height);
1277
1278   mImpl->RequestRelayout();
1279 }
1280
1281 float Controller::GetStrikethroughHeight() const
1282 {
1283   return mImpl->mModel->mVisualModel->GetStrikethroughHeight();
1284 }
1285
1286 void Controller::SetStrikethroughColor(const Vector4& color)
1287 {
1288   mImpl->mModel->mVisualModel->SetStrikethroughColor(color);
1289
1290   mImpl->RequestRelayout();
1291 }
1292
1293 const Vector4& Controller::GetStrikethroughColor() const
1294 {
1295   return mImpl->mModel->mVisualModel->GetStrikethroughColor();
1296 }
1297
1298 void Controller::SetStrikethroughEnabled(bool enabled)
1299 {
1300   mImpl->mModel->mVisualModel->SetStrikethroughEnabled(enabled);
1301
1302   mImpl->RequestRelayout();
1303 }
1304
1305 bool Controller::IsStrikethroughEnabled() const
1306 {
1307   return mImpl->mModel->mVisualModel->IsStrikethroughEnabled();
1308 }
1309
1310 void Controller::SetInputStrikethroughProperties(const std::string& strikethroughProperties)
1311 {
1312   if(NULL != mImpl->mEventData)
1313   {
1314     mImpl->mEventData->mInputStyle.strikethroughProperties = strikethroughProperties;
1315   }
1316 }
1317
1318 std::string Controller::GetInputStrikethroughProperties() const
1319 {
1320   return (NULL != mImpl->mEventData) ? mImpl->mEventData->mInputStyle.strikethroughProperties : EMPTY_STRING;
1321 }
1322
1323 bool Controller::IsStrikethroughSetByString()
1324 {
1325   return mImpl->mStrikethroughSetByString;
1326 }
1327
1328 void Controller::StrikethroughSetByString(bool setByString)
1329 {
1330   mImpl->mStrikethroughSetByString = setByString;
1331 }
1332
1333 Layout::Engine& Controller::GetLayoutEngine()
1334 {
1335   return mImpl->mLayoutEngine;
1336 }
1337
1338 View& Controller::GetView()
1339 {
1340   return mImpl->mView;
1341 }
1342
1343 Vector3 Controller::GetNaturalSize()
1344 {
1345   return Relayouter::GetNaturalSize(*this);
1346 }
1347
1348 bool Controller::CheckForTextFit(float pointSize, Size& layoutSize)
1349 {
1350   return Relayouter::CheckForTextFit(*this, pointSize, layoutSize);
1351 }
1352
1353 void Controller::FitPointSizeforLayout(Size layoutSize)
1354 {
1355   Relayouter::FitPointSizeforLayout(*this, layoutSize);
1356 }
1357
1358 void Controller::FitArrayPointSizeforLayout(Size layoutSize)
1359 {
1360   Relayouter::FitArrayPointSizeforLayout(*this, layoutSize);
1361 }
1362
1363 float Controller::GetHeightForWidth(float width)
1364 {
1365   return Relayouter::GetHeightForWidth(*this, width);
1366 }
1367
1368 int Controller::GetLineCount(float width)
1369 {
1370   GetHeightForWidth(width);
1371   return mImpl->mModel->GetNumberOfLines();
1372 }
1373
1374 const ModelInterface* Controller::GetTextModel() const
1375 {
1376   return mImpl->mModel.Get();
1377 }
1378
1379 float Controller::GetScrollAmountByUserInput()
1380 {
1381   float scrollAmount = 0.0f;
1382
1383   if(NULL != mImpl->mEventData && mImpl->mEventData->mCheckScrollAmount)
1384   {
1385     scrollAmount                          = mImpl->mModel->mScrollPosition.y - mImpl->mModel->mScrollPositionLast.y;
1386     mImpl->mEventData->mCheckScrollAmount = false;
1387   }
1388   return scrollAmount;
1389 }
1390
1391 bool Controller::GetTextScrollInfo(float& scrollPosition, float& controlHeight, float& layoutHeight)
1392 {
1393   const Vector2& layout = mImpl->mModel->mVisualModel->GetLayoutSize();
1394   bool           isScrolled;
1395
1396   controlHeight  = mImpl->mModel->mVisualModel->mControlSize.height;
1397   layoutHeight   = layout.height;
1398   scrollPosition = mImpl->mModel->mScrollPosition.y;
1399   isScrolled     = !Equals(mImpl->mModel->mScrollPosition.y, mImpl->mModel->mScrollPositionLast.y, Math::MACHINE_EPSILON_1);
1400   return isScrolled;
1401 }
1402
1403 void Controller::SetHiddenInputOption(const Property::Map& options)
1404 {
1405   EnsureCreated<HiddenText, Controller*>(mImpl->mHiddenInput, this);
1406   mImpl->mHiddenInput->SetProperties(options);
1407 }
1408
1409 void Controller::GetHiddenInputOption(Property::Map& options)
1410 {
1411   if(mImpl->mHiddenInput)
1412   {
1413     mImpl->mHiddenInput->GetProperties(options);
1414   }
1415 }
1416
1417 void Controller::SetInputFilterOption(const Property::Map& options)
1418 {
1419   EnsureCreated(mImpl->mInputFilter);
1420   mImpl->mInputFilter->SetProperties(options);
1421 }
1422
1423 void Controller::GetInputFilterOption(Property::Map& options)
1424 {
1425   if(mImpl->mInputFilter)
1426   {
1427     mImpl->mInputFilter->GetProperties(options);
1428   }
1429 }
1430
1431 void Controller::SetPlaceholderProperty(const Property::Map& map)
1432 {
1433   PlaceholderHandler::SetPlaceholderProperty(*this, map);
1434 }
1435
1436 void Controller::GetPlaceholderProperty(Property::Map& map)
1437 {
1438   PlaceholderHandler::GetPlaceholderProperty(*this, map);
1439 }
1440
1441 Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
1442 {
1443   // Make sure the model is up-to-date before layouting
1444   EventHandler::ProcessModifyEvents(*this);
1445
1446   return mImpl->GetTextDirection();
1447 }
1448
1449 Toolkit::DevelText::VerticalLineAlignment::Type Controller::GetVerticalLineAlignment() const
1450 {
1451   return mImpl->mModel->GetVerticalLineAlignment();
1452 }
1453
1454 void Controller::SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignment::Type alignment)
1455 {
1456   mImpl->mModel->mVerticalLineAlignment = alignment;
1457 }
1458
1459 Toolkit::DevelText::EllipsisPosition::Type Controller::GetEllipsisPosition() const
1460 {
1461   return mImpl->mModel->GetEllipsisPosition();
1462 }
1463
1464 void Controller::SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition)
1465 {
1466   mImpl->mModel->mEllipsisPosition = ellipsisPosition;
1467   mImpl->mModel->mVisualModel->SetEllipsisPosition(ellipsisPosition);
1468 }
1469
1470 void Controller::SetCharacterSpacing(float characterSpacing)
1471 {
1472   mImpl->mModel->mVisualModel->SetCharacterSpacing(characterSpacing);
1473
1474   mImpl->RelayoutAllCharacters();
1475   mImpl->RequestRelayout();
1476 }
1477
1478 const float Controller::GetCharacterSpacing() const
1479 {
1480   return mImpl->mModel->mVisualModel->GetCharacterSpacing();
1481 }
1482
1483 void Controller::SetVisualTransformOffset(Vector2 offset)
1484 {
1485   mImpl->mModel->mVisualTransformOffset = offset;
1486 }
1487
1488 Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
1489 {
1490   return Relayouter::Relayout(*this, size, layoutDirection);
1491 }
1492
1493 void Controller::RequestRelayout()
1494 {
1495   mImpl->RequestRelayout();
1496 }
1497
1498 Vector<Vector2> Controller::GetTextSize(CharacterIndex startIndex, CharacterIndex endIndex)
1499 {
1500   Vector<Vector2> sizesList;
1501   Vector<Vector2> positionsList;
1502
1503   GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList);
1504   return sizesList;
1505 }
1506
1507 Vector<Vector2> Controller::GetTextPosition(CharacterIndex startIndex, CharacterIndex endIndex)
1508 {
1509   Vector<Vector2> sizesList;
1510   Vector<Vector2> positionsList;
1511
1512   GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList);
1513   return positionsList;
1514 }
1515
1516 Rect<float> Controller::GetLineBoundingRectangle(const uint32_t lineIndex)
1517 {
1518   return GetLineBoundingRect(mImpl->mModel, lineIndex);
1519 }
1520
1521 Rect<float> Controller::GetCharacterBoundingRectangle(const uint32_t charIndex)
1522 {
1523   return GetCharacterBoundingRect(mImpl->mModel, charIndex);
1524 }
1525
1526 int Controller::GetCharacterIndexAtPosition(float visualX, float visualY)
1527 {
1528   return GetCharIndexAtPosition(mImpl->mModel, visualX, visualY);
1529 }
1530
1531 Rect<> Controller::GetTextBoundingRectangle(CharacterIndex startIndex, CharacterIndex endIndex)
1532 {
1533   Vector<Vector2> sizeList;
1534   Vector<Vector2> positionList;
1535
1536   GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizeList, positionList);
1537
1538   if(sizeList.Empty() || sizeList.Size() != positionList.Size())
1539   {
1540     return {0, 0, 0, 0};
1541   }
1542
1543   auto controlWidth = mImpl->mModel->mVisualModel->mControlSize.width;
1544   auto minX         = positionList[0].x;
1545   auto minY         = positionList[0].y;
1546   auto maxRight     = positionList[0].x + sizeList[0].x;
1547   auto maxBottom    = positionList[0].y + sizeList[0].y;
1548
1549   for(unsigned int i = 1; i < sizeList.Size(); i++)
1550   {
1551     minX      = std::min(minX, positionList[i].x);
1552     minY      = std::min(minY, positionList[i].y);
1553     maxRight  = std::max(maxRight, positionList[i].x + sizeList[i].x);
1554     maxBottom = std::max(maxBottom, positionList[i].y + sizeList[i].y);
1555   }
1556
1557   if(minX < 0.0f)
1558   {
1559     minX = 0.0f;
1560   }
1561
1562   if(maxRight > controlWidth)
1563   {
1564     maxRight = controlWidth;
1565   }
1566
1567   return {minX, minY, maxRight - minX, maxBottom - minY};
1568 }
1569
1570 bool Controller::IsInputStyleChangedSignalsQueueEmpty()
1571 {
1572   return mImpl->IsInputStyleChangedSignalsQueueEmpty();
1573 }
1574
1575 void Controller::RequestProcessInputStyleChangedSignals()
1576 {
1577   if(Dali::Adaptor::IsAvailable() && !mImpl->mProcessorRegistered)
1578   {
1579     mImpl->mProcessorRegistered = true;
1580     Dali::Adaptor::Get().RegisterProcessor(*this, true);
1581   }
1582 }
1583
1584 void Controller::OnIdleSignal()
1585 {
1586   if(mImpl->mIdleCallback)
1587   {
1588     mImpl->mIdleCallback = NULL;
1589
1590     mImpl->ProcessInputStyleChangedSignals();
1591   }
1592 }
1593
1594 void Controller::KeyboardFocusGainEvent()
1595 {
1596   EventHandler::KeyboardFocusGainEvent(*this);
1597 }
1598
1599 void Controller::KeyboardFocusLostEvent()
1600 {
1601   EventHandler::KeyboardFocusLostEvent(*this);
1602 }
1603
1604 bool Controller::KeyEvent(const Dali::KeyEvent& keyEvent)
1605 {
1606   return EventHandler::KeyEvent(*this, keyEvent);
1607 }
1608
1609 void Controller::AnchorEvent(float x, float y)
1610 {
1611   EventHandler::AnchorEvent(*this, x, y);
1612 }
1613
1614 void Controller::TapEvent(unsigned int tapCount, float x, float y)
1615 {
1616   EventHandler::TapEvent(*this, tapCount, x, y);
1617 }
1618
1619 void Controller::PanEvent(GestureState state, const Vector2& displacement)
1620 {
1621   EventHandler::PanEvent(*this, state, displacement);
1622 }
1623
1624 void Controller::LongPressEvent(GestureState state, float x, float y)
1625 {
1626   EventHandler::LongPressEvent(*this, state, x, y);
1627 }
1628
1629 void Controller::SelectEvent(float x, float y, SelectionType selectType)
1630 {
1631   EventHandler::SelectEvent(*this, x, y, selectType);
1632 }
1633
1634 void Controller::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
1635 {
1636   if(mImpl->mEventData)
1637   {
1638     mImpl->mEventData->mCheckScrollAmount     = true;
1639     mImpl->mEventData->mIsLeftHandleSelected  = true;
1640     mImpl->mEventData->mIsRightHandleSelected = true;
1641     mImpl->SetTextSelectionRange(start, end);
1642     mImpl->RequestRelayout();
1643     EventHandler::KeyboardFocusGainEvent(*this);
1644   }
1645 }
1646
1647 Uint32Pair Controller::GetTextSelectionRange() const
1648 {
1649   return mImpl->GetTextSelectionRange();
1650 }
1651
1652 CharacterIndex Controller::GetPrimaryCursorPosition() const
1653 {
1654   return mImpl->GetPrimaryCursorPosition();
1655 }
1656
1657 bool Controller::SetPrimaryCursorPosition(CharacterIndex index, bool focused)
1658 {
1659   if(mImpl->mEventData)
1660   {
1661     mImpl->mEventData->mCheckScrollAmount     = true;
1662     mImpl->mEventData->mIsLeftHandleSelected  = true;
1663     mImpl->mEventData->mIsRightHandleSelected = true;
1664     mImpl->mEventData->mCheckScrollAmount     = true;
1665     if(mImpl->SetPrimaryCursorPosition(index, focused) && focused)
1666     {
1667       EventHandler::KeyboardFocusGainEvent(*this);
1668       return true;
1669     }
1670   }
1671   return false;
1672 }
1673
1674 void Controller::SelectWholeText()
1675 {
1676   EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::ALL);
1677 }
1678
1679 void Controller::SelectNone()
1680 {
1681   EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::NONE);
1682 }
1683
1684 void Controller::SelectText(const uint32_t start, const uint32_t end)
1685 {
1686   EventHandler::SelectEvent(*this, start, end, SelectionType::RANGE);
1687 }
1688
1689 string Controller::GetSelectedText() const
1690 {
1691   return mImpl->GetSelectedText();
1692 }
1693
1694 string Controller::CopyText()
1695 {
1696   return mImpl->CopyText();
1697 }
1698
1699 string Controller::CutText()
1700 {
1701   return mImpl->CutText();
1702 }
1703
1704 void Controller::PasteClipboardItemEvent(uint32_t id, const char* mimeType, const char* data)
1705 {
1706   // Upon receiving the data, it is important to disconnect the signal
1707   // to avoid potential unintended pasting caused by subsequent requests.
1708   mImpl->mClipboard.DataReceivedSignal().Disconnect(this, &Controller::PasteClipboardItemEvent);
1709
1710   // If the id is 0u, it is an invalid response.
1711   // text-controller allows only plain text type.
1712   if(id != 0u && !strncmp(mimeType, MIME_TYPE_TEXT_PLAIN, strlen(MIME_TYPE_TEXT_PLAIN)))
1713   {
1714     EventHandler::PasteClipboardItemEvent(*this, data);
1715   }
1716 }
1717
1718 void Controller::PasteText()
1719 {
1720   if(mImpl->EnsureClipboardCreated())
1721   {
1722     // Connect the signal before calling GetData() of the clipboard.
1723     mImpl->mClipboard.DataReceivedSignal().Connect(this, &Controller::PasteClipboardItemEvent);
1724
1725     // Request clipboard service to retrieve an item.
1726     uint id = mImpl->mClipboard.GetData(MIME_TYPE_TEXT_PLAIN);
1727     if(id == 0u)
1728     {
1729       // If the return id is 0u, the signal is not emitted, we must disconnect signal here.
1730       mImpl->mClipboard.DataReceivedSignal().Disconnect(this, &Controller::PasteClipboardItemEvent);
1731     }
1732   }
1733 }
1734
1735 InputMethodContext::CallbackData Controller::OnInputMethodContextEvent(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
1736 {
1737   return EventHandler::OnInputMethodContextEvent(*this, inputMethodContext, inputMethodContextEvent);
1738 }
1739
1740 void Controller::GetTargetSize(Vector2& targetSize)
1741 {
1742   targetSize = mImpl->mModel->mVisualModel->mControlSize;
1743 }
1744
1745 void Controller::AddDecoration(Actor& actor, DecorationType type, bool needsClipping)
1746 {
1747   if(mImpl->mEditableControlInterface)
1748   {
1749     mImpl->mEditableControlInterface->AddDecoration(actor, type, needsClipping);
1750   }
1751 }
1752
1753 bool Controller::IsEditable() const
1754 {
1755   return mImpl->IsEditable();
1756 }
1757
1758 void Controller::SetEditable(bool editable)
1759 {
1760   mImpl->SetEditable(editable);
1761 }
1762
1763 void Controller::ScrollBy(Vector2 scroll)
1764 {
1765   mImpl->ScrollBy(scroll);
1766 }
1767
1768 bool Controller::IsScrollable(const Vector2& displacement)
1769 {
1770   return mImpl->IsScrollable(displacement);
1771 }
1772
1773 float Controller::GetHorizontalScrollPosition()
1774 {
1775   return mImpl->GetHorizontalScrollPosition();
1776 }
1777
1778 float Controller::GetVerticalScrollPosition()
1779 {
1780   return mImpl->GetVerticalScrollPosition();
1781 }
1782
1783 void Controller::DecorationEvent(HandleType handleType, HandleState state, float x, float y)
1784 {
1785   EventHandler::DecorationEvent(*this, handleType, state, x, y);
1786 }
1787
1788 void Controller::TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button)
1789 {
1790   EventHandler::TextPopupButtonTouched(*this, button);
1791 }
1792
1793 void Controller::DisplayTimeExpired()
1794 {
1795   mImpl->mEventData->mUpdateCursorPosition = true;
1796   // Apply modifications to the model
1797   mImpl->mOperationsPending = ALL_OPERATIONS;
1798
1799   mImpl->RequestRelayout();
1800 }
1801
1802 void Controller::ResetCursorPosition(CharacterIndex cursorIndex)
1803 {
1804   // Reset the cursor position
1805   if(NULL != mImpl->mEventData)
1806   {
1807     mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
1808
1809     // Update the cursor if it's in editing mode.
1810     if(EventData::IsEditingState(mImpl->mEventData->mState))
1811     {
1812       mImpl->mEventData->mUpdateCursorPosition = true;
1813     }
1814   }
1815 }
1816
1817 CharacterIndex Controller::GetCursorPosition()
1818 {
1819   return mImpl->mEventData ? mImpl->mEventData->mPrimaryCursorPosition : 0;
1820 }
1821
1822 void Controller::SetControlInterface(ControlInterface* controlInterface)
1823 {
1824   mImpl->mControlInterface = controlInterface;
1825 }
1826
1827 void Controller::SetAnchorControlInterface(AnchorControlInterface* anchorControlInterface)
1828 {
1829   mImpl->mAnchorControlInterface = anchorControlInterface;
1830 }
1831
1832 bool Controller::ShouldClearFocusOnEscape() const
1833 {
1834   return mImpl->mShouldClearFocusOnEscape;
1835 }
1836
1837 Actor Controller::CreateBackgroundActor()
1838 {
1839   return CreateControllerBackgroundActor(mImpl->mView, mImpl->mModel->mVisualModel, mImpl->mModel->mLogicalModel, mImpl->mShaderBackground);
1840 }
1841
1842 void Controller::GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors)
1843 {
1844   mImpl->GetAnchorActors(anchorActors);
1845 }
1846
1847 int Controller::GetAnchorIndex(size_t characterOffset)
1848 {
1849   return mImpl->GetAnchorIndex(characterOffset);
1850 }
1851
1852 void Controller::Process(bool postProcess)
1853 {
1854   if(Dali::Adaptor::IsAvailable() && mImpl->mProcessorRegistered)
1855   {
1856     Dali::Adaptor& adaptor = Dali::Adaptor::Get();
1857
1858     adaptor.UnregisterProcessor(*this, true);
1859     mImpl->mProcessorRegistered = false;
1860
1861     if(NULL == mImpl->mIdleCallback)
1862     {
1863       // @note: The callback manager takes the ownership of the callback object.
1864       mImpl->mIdleCallback = MakeCallback(this, &Controller::OnIdleSignal);
1865       if(DALI_UNLIKELY(!adaptor.AddIdle(mImpl->mIdleCallback, false)))
1866       {
1867         DALI_LOG_ERROR("Fail to add idle callback for text controller style changed signals queue. Skip these callbacks\n");
1868
1869         // Clear queue forcely.
1870         if(mImpl->mEventData)
1871         {
1872           mImpl->mEventData->mInputStyleChangedQueue.Clear();
1873         }
1874
1875         // Set the pointer to null as the callback manager deletes the callback even AddIdle failed.
1876         mImpl->mIdleCallback = NULL;
1877       }
1878     }
1879   }
1880 }
1881
1882 Controller::Controller(ControlInterface*           controlInterface,
1883                        EditableControlInterface*   editableControlInterface,
1884                        SelectableControlInterface* selectableControlInterface,
1885                        AnchorControlInterface*     anchorControlInterface)
1886 : mImpl(new Controller::Impl(controlInterface, editableControlInterface, selectableControlInterface, anchorControlInterface))
1887 {
1888 }
1889
1890 Controller::~Controller()
1891 {
1892   if(Dali::Adaptor::IsAvailable())
1893   {
1894     if(mImpl->mProcessorRegistered)
1895     {
1896       Dali::Adaptor::Get().UnregisterProcessor(*this, true);
1897     }
1898     if(mImpl->mIdleCallback)
1899     {
1900       Dali::Adaptor::Get().RemoveIdle(mImpl->mIdleCallback);
1901     }
1902   }
1903 }
1904
1905 } // namespace Dali::Toolkit::Text