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