[Tizen] Add to play inserted text using tts player
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/text/text-controller.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/adaptor-framework/tts-player.h>
24 #include <memory.h>
25 #include <cmath>
26 #include <limits>
27
28 // INTERNAL INCLUDES
29 #include <dali-toolkit/internal/text/character-set-conversion.h>
30 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
31 #include <dali-toolkit/internal/text/markup-processor.h>
32 #include <dali-toolkit/internal/text/text-controller-event-handler.h>
33 #include <dali-toolkit/internal/text/text-controller-impl.h>
34 #include <dali-toolkit/internal/text/text-controller-input-font-handler.h>
35 #include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
36 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
37
38 namespace
39 {
40 #if defined(DEBUG_ENABLED)
41 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
42 #endif
43
44 const float MAX_FLOAT = std::numeric_limits<float>::max();
45
46 const std::string EMPTY_STRING("");
47
48 float ConvertToEven(float value)
49 {
50   int intValue(static_cast<int>(value));
51   return static_cast<float>(intValue + (intValue & 1));
52 }
53
54 int ConvertPixelToPint(float pixel)
55 {
56   unsigned int                      horizontalDpi = 0u;
57   unsigned int                      verticalDpi   = 0u;
58   Dali::TextAbstraction::FontClient fontClient    = Dali::TextAbstraction::FontClient::Get();
59   fontClient.GetDpi(horizontalDpi, verticalDpi);
60
61   return (pixel * 72.f) / static_cast<float>(horizontalDpi);
62 }
63
64 } // namespace
65
66 namespace Dali
67 {
68 namespace Toolkit
69 {
70 namespace Text
71 {
72 // public : Constructor.
73
74 ControllerPtr Controller::New()
75 {
76   return ControllerPtr(new Controller());
77 }
78
79 ControllerPtr Controller::New(ControlInterface* controlInterface)
80 {
81   return ControllerPtr(new Controller(controlInterface));
82 }
83
84 ControllerPtr Controller::New(ControlInterface*           controlInterface,
85                               EditableControlInterface*   editableControlInterface,
86                               SelectableControlInterface* selectableControlInterface)
87 {
88   return ControllerPtr(new Controller(controlInterface,
89                                       editableControlInterface,
90                                       selectableControlInterface));
91 }
92
93 // public : Configure the text controller.
94
95 void Controller::EnableTextInput(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
96 {
97   if(!decorator)
98   {
99     delete mImpl->mEventData;
100     mImpl->mEventData = NULL;
101
102     // Nothing else to do.
103     return;
104   }
105
106   if(NULL == mImpl->mEventData)
107   {
108     mImpl->mEventData = new EventData(decorator, inputMethodContext);
109   }
110 }
111
112 void Controller::SetGlyphType(TextAbstraction::GlyphType glyphType)
113 {
114   // Metrics for bitmap & vector based glyphs are different
115   mImpl->mMetrics->SetGlyphType(glyphType);
116
117   // Clear the font-specific data
118   ClearFontData();
119
120   mImpl->RequestRelayout();
121 }
122
123 void Controller::SetMarkupProcessorEnabled(bool enable)
124 {
125   if(enable != mImpl->mMarkupProcessorEnabled)
126   {
127     //If Text was already set, call the SetText again for enabling or disabling markup
128     mImpl->mMarkupProcessorEnabled = enable;
129     std::string text;
130     GetText(text);
131     SetText(text);
132   }
133 }
134
135 bool Controller::IsMarkupProcessorEnabled() const
136 {
137   return mImpl->mMarkupProcessorEnabled;
138 }
139
140 void Controller::SetAutoScrollEnabled(bool enable)
141 {
142   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);
143
144   if(mImpl->mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX)
145   {
146     if(enable)
147     {
148       DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n");
149       mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
150                                                               LAYOUT |
151                                                               ALIGN |
152                                                               UPDATE_LAYOUT_SIZE |
153                                                               UPDATE_DIRECTION |
154                                                               REORDER);
155     }
156     else
157     {
158       DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled Disabling autoscroll\n");
159       mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
160                                                               LAYOUT |
161                                                               ALIGN |
162                                                               UPDATE_LAYOUT_SIZE |
163                                                               REORDER);
164     }
165
166     mImpl->mIsAutoScrollEnabled = enable;
167     mImpl->RequestRelayout();
168   }
169   else
170   {
171     DALI_LOG_WARNING("Attempted AutoScrolling on a non SINGLE_LINE_BOX, request ignored\n");
172     mImpl->mIsAutoScrollEnabled = false;
173   }
174 }
175
176 bool Controller::IsAutoScrollEnabled() const
177 {
178   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", mImpl->mIsAutoScrollEnabled ? "true" : "false");
179
180   return mImpl->mIsAutoScrollEnabled;
181 }
182
183 CharacterDirection Controller::GetAutoScrollDirection() const
184 {
185   return mImpl->mIsTextDirectionRTL;
186 }
187
188 float Controller::GetAutoScrollLineAlignment() const
189 {
190   float offset = 0.f;
191
192   if(mImpl->mModel->mVisualModel &&
193      (0u != mImpl->mModel->mVisualModel->mLines.Count()))
194   {
195     offset = (*mImpl->mModel->mVisualModel->mLines.Begin()).alignmentOffset;
196   }
197
198   return offset;
199 }
200
201 void Controller::SetHorizontalScrollEnabled(bool enable)
202 {
203   if((NULL != mImpl->mEventData) &&
204      mImpl->mEventData->mDecorator)
205   {
206     mImpl->mEventData->mDecorator->SetHorizontalScrollEnabled(enable);
207   }
208 }
209 bool Controller::IsHorizontalScrollEnabled() const
210 {
211   if((NULL != mImpl->mEventData) &&
212      mImpl->mEventData->mDecorator)
213   {
214     return mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled();
215   }
216
217   return false;
218 }
219
220 void Controller::SetVerticalScrollEnabled(bool enable)
221 {
222   if((NULL != mImpl->mEventData) &&
223      mImpl->mEventData->mDecorator)
224   {
225     if(mImpl->mEventData->mDecorator)
226     {
227       mImpl->mEventData->mDecorator->SetVerticalScrollEnabled(enable);
228     }
229   }
230 }
231
232 bool Controller::IsVerticalScrollEnabled() const
233 {
234   if((NULL != mImpl->mEventData) &&
235      mImpl->mEventData->mDecorator)
236   {
237     return mImpl->mEventData->mDecorator->IsVerticalScrollEnabled();
238   }
239
240   return false;
241 }
242
243 void Controller::SetSmoothHandlePanEnabled(bool enable)
244 {
245   if((NULL != mImpl->mEventData) &&
246      mImpl->mEventData->mDecorator)
247   {
248     mImpl->mEventData->mDecorator->SetSmoothHandlePanEnabled(enable);
249   }
250 }
251
252 bool Controller::IsSmoothHandlePanEnabled() const
253 {
254   if((NULL != mImpl->mEventData) &&
255      mImpl->mEventData->mDecorator)
256   {
257     return mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled();
258   }
259
260   return false;
261 }
262
263 void Controller::SetMaximumNumberOfCharacters(Length maxCharacters)
264 {
265   mImpl->mMaximumNumberOfCharacters = maxCharacters;
266 }
267
268 int Controller::GetMaximumNumberOfCharacters()
269 {
270   return mImpl->mMaximumNumberOfCharacters;
271 }
272
273 void Controller::SetEnableCursorBlink(bool enable)
274 {
275   DALI_ASSERT_DEBUG(NULL != mImpl->mEventData && "TextInput disabled");
276
277   if(NULL != mImpl->mEventData)
278   {
279     mImpl->mEventData->mCursorBlinkEnabled = enable;
280
281     if(!enable &&
282        mImpl->mEventData->mDecorator)
283     {
284       mImpl->mEventData->mDecorator->StopCursorBlink();
285     }
286   }
287 }
288
289 bool Controller::GetEnableCursorBlink() const
290 {
291   if(NULL != mImpl->mEventData)
292   {
293     return mImpl->mEventData->mCursorBlinkEnabled;
294   }
295
296   return false;
297 }
298
299 void Controller::SetMultiLineEnabled(bool enable)
300 {
301   const Layout::Engine::Type layout = enable ? Layout::Engine::MULTI_LINE_BOX : Layout::Engine::SINGLE_LINE_BOX;
302
303   if(layout != mImpl->mLayoutEngine.GetLayout())
304   {
305     // Set the layout type.
306     mImpl->mLayoutEngine.SetLayout(layout);
307
308     // Set the flags to redo the layout operations
309     const OperationsMask layoutOperations = static_cast<OperationsMask>(LAYOUT |
310                                                                         UPDATE_LAYOUT_SIZE |
311                                                                         ALIGN |
312                                                                         REORDER);
313
314     mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
315     mImpl->mOperationsPending                  = static_cast<OperationsMask>(mImpl->mOperationsPending | layoutOperations);
316
317     // Need to recalculate natural size
318     mImpl->mRecalculateNaturalSize = true;
319
320     mImpl->RequestRelayout();
321   }
322 }
323
324 bool Controller::IsMultiLineEnabled() const
325 {
326   return Layout::Engine::MULTI_LINE_BOX == mImpl->mLayoutEngine.GetLayout();
327 }
328
329 void Controller::SetHorizontalAlignment(Text::HorizontalAlignment::Type alignment)
330 {
331   if(alignment != mImpl->mModel->mHorizontalAlignment)
332   {
333     // Set the alignment.
334     mImpl->mModel->mHorizontalAlignment = alignment;
335
336     // Set the flag to redo the alignment operation.
337     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | ALIGN);
338
339     if(mImpl->mEventData)
340     {
341       mImpl->mEventData->mUpdateAlignment = true;
342
343       // Update the cursor if it's in editing mode
344       if(EventData::IsEditingState(mImpl->mEventData->mState))
345       {
346         mImpl->ChangeState(EventData::EDITING);
347         mImpl->mEventData->mUpdateCursorPosition = true;
348       }
349     }
350
351     mImpl->RequestRelayout();
352   }
353 }
354
355 Text::HorizontalAlignment::Type Controller::GetHorizontalAlignment() const
356 {
357   return mImpl->mModel->mHorizontalAlignment;
358 }
359
360 void Controller::SetVerticalAlignment(VerticalAlignment::Type alignment)
361 {
362   if(alignment != mImpl->mModel->mVerticalAlignment)
363   {
364     // Set the alignment.
365     mImpl->mModel->mVerticalAlignment = alignment;
366
367     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | ALIGN);
368
369     mImpl->RequestRelayout();
370   }
371 }
372
373 VerticalAlignment::Type Controller::GetVerticalAlignment() const
374 {
375   return mImpl->mModel->mVerticalAlignment;
376 }
377
378 bool Controller::IsIgnoreSpacesAfterText() const
379 {
380   return mImpl->mModel->mIgnoreSpacesAfterText;
381 }
382
383 void Controller::SetIgnoreSpacesAfterText(bool ignore)
384 {
385   mImpl->mModel->mIgnoreSpacesAfterText = ignore;
386 }
387
388 bool Controller::IsMatchSystemLanguageDirection() const
389 {
390   return mImpl->mModel->mMatchSystemLanguageDirection;
391 }
392
393 void Controller::SetMatchSystemLanguageDirection(bool match)
394 {
395   mImpl->mModel->mMatchSystemLanguageDirection = match;
396 }
397
398 void Controller::SetLayoutDirection(Dali::LayoutDirection::Type layoutDirection)
399 {
400   mImpl->mLayoutDirection = layoutDirection;
401 }
402
403 bool Controller::IsShowingRealText() const
404 {
405   return mImpl->IsShowingRealText();
406 }
407
408 void Controller::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode)
409 {
410   if(lineWrapMode != mImpl->mModel->mLineWrapMode)
411   {
412     // Set the text wrap mode.
413     mImpl->mModel->mLineWrapMode = lineWrapMode;
414
415     // Update Text layout for applying wrap mode
416     mImpl->mOperationsPending                          = static_cast<OperationsMask>(mImpl->mOperationsPending |
417                                                             ALIGN |
418                                                             LAYOUT |
419                                                             UPDATE_LAYOUT_SIZE |
420                                                             REORDER);
421     mImpl->mTextUpdateInfo.mCharacterIndex             = 0u;
422     mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
423     mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = mImpl->mModel->mLogicalModel->mText.Count();
424
425     // Request relayout
426     mImpl->RequestRelayout();
427   }
428 }
429
430 Text::LineWrap::Mode Controller::GetLineWrapMode() const
431 {
432   return mImpl->mModel->mLineWrapMode;
433 }
434
435 void Controller::SetTextElideEnabled(bool enabled)
436 {
437   mImpl->mModel->mElideEnabled = enabled;
438 }
439
440 bool Controller::IsTextElideEnabled() const
441 {
442   return mImpl->mModel->mElideEnabled;
443 }
444
445 void Controller::SetTextFitEnabled(bool enabled)
446 {
447   mImpl->mTextFitEnabled = enabled;
448 }
449
450 bool Controller::IsTextFitEnabled() const
451 {
452   return mImpl->mTextFitEnabled;
453 }
454
455 void Controller::SetTextFitMinSize(float minSize, FontSizeType type)
456 {
457   switch(type)
458   {
459     case POINT_SIZE:
460     {
461       mImpl->mTextFitMinSize = minSize;
462       break;
463     }
464     case PIXEL_SIZE:
465     {
466       mImpl->mTextFitMinSize = ConvertPixelToPint(minSize);
467       break;
468     }
469   }
470 }
471
472 float Controller::GetTextFitMinSize() const
473 {
474   return mImpl->mTextFitMinSize;
475 }
476
477 void Controller::SetTextFitMaxSize(float maxSize, FontSizeType type)
478 {
479   switch(type)
480   {
481     case POINT_SIZE:
482     {
483       mImpl->mTextFitMaxSize = maxSize;
484       break;
485     }
486     case PIXEL_SIZE:
487     {
488       mImpl->mTextFitMaxSize = ConvertPixelToPint(maxSize);
489       break;
490     }
491   }
492 }
493
494 float Controller::GetTextFitMaxSize() const
495 {
496   return mImpl->mTextFitMaxSize;
497 }
498
499 void Controller::SetTextFitStepSize(float step, FontSizeType type)
500 {
501   switch(type)
502   {
503     case POINT_SIZE:
504     {
505       mImpl->mTextFitStepSize = step;
506       break;
507     }
508     case PIXEL_SIZE:
509     {
510       mImpl->mTextFitStepSize = ConvertPixelToPint(step);
511       break;
512     }
513   }
514 }
515
516 float Controller::GetTextFitStepSize() const
517 {
518   return mImpl->mTextFitStepSize;
519 }
520
521 void Controller::SetTextFitContentSize(Vector2 size)
522 {
523   mImpl->mTextFitContentSize = size;
524 }
525
526 Vector2 Controller::GetTextFitContentSize() const
527 {
528   return mImpl->mTextFitContentSize;
529 }
530
531 void Controller::SetPlaceholderTextElideEnabled(bool enabled)
532 {
533   PlaceholderHandler::SetPlaceholderTextElideEnabled(*this, enabled);
534 }
535
536 bool Controller::IsPlaceholderTextElideEnabled() const
537 {
538   return PlaceholderHandler::IsPlaceholderTextElideEnabled(*this);
539 }
540
541 void Controller::SetSelectionEnabled(bool enabled)
542 {
543   mImpl->mEventData->mSelectionEnabled = enabled;
544 }
545
546 bool Controller::IsSelectionEnabled() const
547 {
548   return mImpl->mEventData->mSelectionEnabled;
549 }
550
551 void Controller::SetShiftSelectionEnabled(bool enabled)
552 {
553   mImpl->mEventData->mShiftSelectionFlag = enabled;
554 }
555
556 bool Controller::IsShiftSelectionEnabled() const
557 {
558   return mImpl->mEventData->mShiftSelectionFlag;
559 }
560
561 void Controller::SetGrabHandleEnabled(bool enabled)
562 {
563   mImpl->mEventData->mGrabHandleEnabled = enabled;
564 }
565
566 bool Controller::IsGrabHandleEnabled() const
567 {
568   return mImpl->mEventData->mGrabHandleEnabled;
569 }
570
571 void Controller::SetGrabHandlePopupEnabled(bool enabled)
572 {
573   mImpl->mEventData->mGrabHandlePopupEnabled = enabled;
574 }
575
576 bool Controller::IsGrabHandlePopupEnabled() const
577 {
578   return mImpl->mEventData->mGrabHandlePopupEnabled;
579 }
580
581 // public : Update
582
583 void Controller::SetText(const std::string& text)
584 {
585   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::SetText\n");
586
587   // Reset keyboard as text changed
588   mImpl->ResetInputMethodContext();
589
590   // Remove the previously set text and style.
591   ResetText();
592
593   // Remove the style.
594   ClearStyleData();
595
596   CharacterIndex lastCursorIndex = 0u;
597
598   if(NULL != mImpl->mEventData)
599   {
600     // If popup shown then hide it by switching to Editing state
601     if((EventData::SELECTING == mImpl->mEventData->mState) ||
602        (EventData::EDITING_WITH_POPUP == mImpl->mEventData->mState) ||
603        (EventData::EDITING_WITH_GRAB_HANDLE == mImpl->mEventData->mState) ||
604        (EventData::EDITING_WITH_PASTE_POPUP == mImpl->mEventData->mState))
605     {
606       mImpl->ChangeState(EventData::EDITING);
607     }
608   }
609
610   if(!text.empty())
611   {
612     mImpl->mModel->mVisualModel->SetTextColor(mImpl->mTextColor);
613
614     MarkupProcessData markupProcessData(mImpl->mModel->mLogicalModel->mColorRuns,
615                                         mImpl->mModel->mLogicalModel->mFontDescriptionRuns,
616                                         mImpl->mModel->mLogicalModel->mEmbeddedItems);
617
618     Length         textSize = 0u;
619     const uint8_t* utf8     = NULL;
620     if(mImpl->mMarkupProcessorEnabled)
621     {
622       ProcessMarkupString(text, markupProcessData);
623       textSize = markupProcessData.markupProcessedText.size();
624
625       // This is a bit horrible but std::string returns a (signed) char*
626       utf8 = reinterpret_cast<const uint8_t*>(markupProcessData.markupProcessedText.c_str());
627     }
628     else
629     {
630       textSize = text.size();
631
632       // This is a bit horrible but std::string returns a (signed) char*
633       utf8 = reinterpret_cast<const uint8_t*>(text.c_str());
634     }
635
636     //  Convert text into UTF-32
637     Vector<Character>& utf32Characters = mImpl->mModel->mLogicalModel->mText;
638     utf32Characters.Resize(textSize);
639
640     // Transform a text array encoded in utf8 into an array encoded in utf32.
641     // It returns the actual number of characters.
642     Length characterCount = Utf8ToUtf32(utf8, textSize, utf32Characters.Begin());
643     utf32Characters.Resize(characterCount);
644
645     DALI_ASSERT_DEBUG(textSize >= characterCount && "Invalid UTF32 conversion length");
646     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::SetText %p UTF8 size %d, UTF32 size %d\n", this, textSize, mImpl->mModel->mLogicalModel->mText.Count());
647
648     // The characters to be added.
649     mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
650
651     // To reset the cursor position
652     lastCursorIndex = characterCount;
653
654     // Update the rest of the model during size negotiation
655     mImpl->QueueModifyEvent(ModifyEvent::TEXT_REPLACED);
656
657     // The natural size needs to be re-calculated.
658     mImpl->mRecalculateNaturalSize = true;
659
660     // The text direction needs to be updated.
661     mImpl->mUpdateTextDirection = true;
662
663     // Apply modifications to the model
664     mImpl->mOperationsPending = ALL_OPERATIONS;
665   }
666   else
667   {
668     ShowPlaceholderText();
669   }
670
671   // Resets the cursor position.
672   ResetCursorPosition(lastCursorIndex);
673
674   // Scrolls the text to make the cursor visible.
675   ResetScrollPosition();
676
677   mImpl->RequestRelayout();
678
679   if(NULL != mImpl->mEventData)
680   {
681     // Cancel previously queued events
682     mImpl->mEventData->mEventQueue.clear();
683   }
684
685   // Do this last since it provides callbacks into application code.
686   if(NULL != mImpl->mEditableControlInterface)
687   {
688     mImpl->mEditableControlInterface->TextChanged(true);
689   }
690 }
691
692 void Controller::GetText(std::string& text) const
693 {
694   if(!mImpl->IsShowingPlaceholderText())
695   {
696     // Retrieves the text string.
697     mImpl->GetText(0u, text);
698   }
699   else
700   {
701     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::GetText %p empty (but showing placeholder)\n", this);
702   }
703 }
704
705 void Controller::SetPlaceholderText(PlaceholderType type, const std::string& text)
706 {
707   PlaceholderHandler::SetPlaceholderText(*this, type, text);
708 }
709
710 void Controller::GetPlaceholderText(PlaceholderType type, std::string& text) const
711 {
712   PlaceholderHandler::GetPlaceholderText(*this, type, text);
713 }
714
715 void Controller::UpdateAfterFontChange(const std::string& newDefaultFont)
716 {
717   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::UpdateAfterFontChange\n");
718
719   if(!mImpl->mFontDefaults->familyDefined) // If user defined font then should not update when system font changes
720   {
721     DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange newDefaultFont(%s)\n", newDefaultFont.c_str());
722     mImpl->mFontDefaults->mFontDescription.family = newDefaultFont;
723
724     ClearFontData();
725
726     mImpl->RequestRelayout();
727   }
728 }
729
730 // public : Default style & Input style
731
732 void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily)
733 {
734   if(NULL == mImpl->mFontDefaults)
735   {
736     mImpl->mFontDefaults = new FontDefaults();
737   }
738
739   mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily;
740   DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s\n", defaultFontFamily.c_str());
741   mImpl->mFontDefaults->familyDefined = !defaultFontFamily.empty();
742
743   if(mImpl->mEventData)
744   {
745     // Update the cursor position if it's in editing mode
746     if(EventData::IsEditingState(mImpl->mEventData->mState))
747     {
748       mImpl->mEventData->mDecoratorUpdated     = true;
749       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font family is updated.
750     }
751   }
752
753   // Clear the font-specific data
754   ClearFontData();
755
756   mImpl->RequestRelayout();
757 }
758
759 const std::string& Controller::GetDefaultFontFamily() const
760 {
761   if(NULL != mImpl->mFontDefaults)
762   {
763     return mImpl->mFontDefaults->mFontDescription.family;
764   }
765
766   return EMPTY_STRING;
767 }
768
769 void Controller::SetPlaceholderFontFamily(const std::string& placeholderTextFontFamily)
770 {
771   PlaceholderHandler::SetPlaceholderFontFamily(*this, placeholderTextFontFamily);
772 }
773
774 const std::string& Controller::GetPlaceholderFontFamily() const
775 {
776   return PlaceholderHandler::GetPlaceholderFontFamily(*this);
777 }
778
779 void Controller::SetDefaultFontWeight(FontWeight weight)
780 {
781   if(NULL == mImpl->mFontDefaults)
782   {
783     mImpl->mFontDefaults = new FontDefaults();
784   }
785
786   mImpl->mFontDefaults->mFontDescription.weight = weight;
787   mImpl->mFontDefaults->weightDefined           = true;
788
789   if(mImpl->mEventData)
790   {
791     // Update the cursor position if it's in editing mode
792     if(EventData::IsEditingState(mImpl->mEventData->mState))
793     {
794       mImpl->mEventData->mDecoratorUpdated     = true;
795       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font weight is updated.
796     }
797   }
798
799   // Clear the font-specific data
800   ClearFontData();
801
802   mImpl->RequestRelayout();
803 }
804
805 bool Controller::IsDefaultFontWeightDefined() const
806 {
807   if(NULL != mImpl->mFontDefaults)
808   {
809     return mImpl->mFontDefaults->weightDefined;
810   }
811
812   return false;
813 }
814
815 FontWeight Controller::GetDefaultFontWeight() const
816 {
817   if(NULL != mImpl->mFontDefaults)
818   {
819     return mImpl->mFontDefaults->mFontDescription.weight;
820   }
821
822   return TextAbstraction::FontWeight::NORMAL;
823 }
824
825 void Controller::SetPlaceholderTextFontWeight(FontWeight weight)
826 {
827   PlaceholderHandler::SetPlaceholderTextFontWeight(*this, weight);
828 }
829
830 bool Controller::IsPlaceholderTextFontWeightDefined() const
831 {
832   return PlaceholderHandler::IsPlaceholderTextFontWeightDefined(*this);
833   ;
834 }
835
836 FontWeight Controller::GetPlaceholderTextFontWeight() const
837 {
838   return PlaceholderHandler::GetPlaceholderTextFontWeight(*this);
839 }
840
841 void Controller::SetDefaultFontWidth(FontWidth width)
842 {
843   if(NULL == mImpl->mFontDefaults)
844   {
845     mImpl->mFontDefaults = new FontDefaults();
846   }
847
848   mImpl->mFontDefaults->mFontDescription.width = width;
849   mImpl->mFontDefaults->widthDefined           = true;
850
851   if(mImpl->mEventData)
852   {
853     // Update the cursor position if it's in editing mode
854     if(EventData::IsEditingState(mImpl->mEventData->mState))
855     {
856       mImpl->mEventData->mDecoratorUpdated     = true;
857       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font width is updated.
858     }
859   }
860
861   // Clear the font-specific data
862   ClearFontData();
863
864   mImpl->RequestRelayout();
865 }
866
867 bool Controller::IsDefaultFontWidthDefined() const
868 {
869   if(NULL != mImpl->mFontDefaults)
870   {
871     return mImpl->mFontDefaults->widthDefined;
872   }
873
874   return false;
875 }
876
877 FontWidth Controller::GetDefaultFontWidth() const
878 {
879   if(NULL != mImpl->mFontDefaults)
880   {
881     return mImpl->mFontDefaults->mFontDescription.width;
882   }
883
884   return TextAbstraction::FontWidth::NORMAL;
885 }
886
887 void Controller::SetPlaceholderTextFontWidth(FontWidth width)
888 {
889   PlaceholderHandler::SetPlaceholderTextFontWidth(*this, width);
890 }
891
892 bool Controller::IsPlaceholderTextFontWidthDefined() const
893 {
894   return PlaceholderHandler::IsPlaceholderTextFontWidthDefined(*this);
895 }
896
897 FontWidth Controller::GetPlaceholderTextFontWidth() const
898 {
899   return PlaceholderHandler::GetPlaceholderTextFontWidth(*this);
900 }
901
902 void Controller::SetDefaultFontSlant(FontSlant slant)
903 {
904   if(NULL == mImpl->mFontDefaults)
905   {
906     mImpl->mFontDefaults = new FontDefaults();
907   }
908
909   mImpl->mFontDefaults->mFontDescription.slant = slant;
910   mImpl->mFontDefaults->slantDefined           = true;
911
912   if(mImpl->mEventData)
913   {
914     // Update the cursor position if it's in editing mode
915     if(EventData::IsEditingState(mImpl->mEventData->mState))
916     {
917       mImpl->mEventData->mDecoratorUpdated     = true;
918       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font slant is updated.
919     }
920   }
921
922   // Clear the font-specific data
923   ClearFontData();
924
925   mImpl->RequestRelayout();
926 }
927
928 bool Controller::IsDefaultFontSlantDefined() const
929 {
930   if(NULL != mImpl->mFontDefaults)
931   {
932     return mImpl->mFontDefaults->slantDefined;
933   }
934   return false;
935 }
936
937 FontSlant Controller::GetDefaultFontSlant() const
938 {
939   if(NULL != mImpl->mFontDefaults)
940   {
941     return mImpl->mFontDefaults->mFontDescription.slant;
942   }
943
944   return TextAbstraction::FontSlant::NORMAL;
945 }
946
947 void Controller::SetPlaceholderTextFontSlant(FontSlant slant)
948 {
949   PlaceholderHandler::SetPlaceholderTextFontSlant(*this, slant);
950 }
951
952 bool Controller::IsPlaceholderTextFontSlantDefined() const
953 {
954   return PlaceholderHandler::IsPlaceholderTextFontSlantDefined(*this);
955 }
956
957 FontSlant Controller::GetPlaceholderTextFontSlant() const
958 {
959   return PlaceholderHandler::GetPlaceholderTextFontSlant(*this);
960 }
961
962 void Controller::SetDefaultFontSize(float fontSize, FontSizeType type)
963 {
964   if(NULL == mImpl->mFontDefaults)
965   {
966     mImpl->mFontDefaults = new FontDefaults();
967   }
968
969   switch(type)
970   {
971     case POINT_SIZE:
972     {
973       mImpl->mFontDefaults->mDefaultPointSize = fontSize;
974       mImpl->mFontDefaults->sizeDefined       = true;
975       break;
976     }
977     case PIXEL_SIZE:
978     {
979       // Point size = Pixel size * 72.f / DPI
980       unsigned int                horizontalDpi = 0u;
981       unsigned int                verticalDpi   = 0u;
982       TextAbstraction::FontClient fontClient    = TextAbstraction::FontClient::Get();
983       fontClient.GetDpi(horizontalDpi, verticalDpi);
984
985       mImpl->mFontDefaults->mDefaultPointSize = (fontSize * 72.f) / static_cast<float>(horizontalDpi);
986       mImpl->mFontDefaults->sizeDefined       = true;
987       break;
988     }
989   }
990
991   if(mImpl->mEventData)
992   {
993     // Update the cursor position if it's in editing mode
994     if(EventData::IsEditingState(mImpl->mEventData->mState))
995     {
996       mImpl->mEventData->mDecoratorUpdated     = true;
997       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
998     }
999   }
1000
1001   // Clear the font-specific data
1002   ClearFontData();
1003
1004   mImpl->RequestRelayout();
1005 }
1006
1007 float Controller::GetDefaultFontSize(FontSizeType type) const
1008 {
1009   float value = 0.0f;
1010   if(NULL != mImpl->mFontDefaults)
1011   {
1012     switch(type)
1013     {
1014       case POINT_SIZE:
1015       {
1016         value = mImpl->mFontDefaults->mDefaultPointSize;
1017         break;
1018       }
1019       case PIXEL_SIZE:
1020       {
1021         // Pixel size = Point size * DPI / 72.f
1022         unsigned int                horizontalDpi = 0u;
1023         unsigned int                verticalDpi   = 0u;
1024         TextAbstraction::FontClient fontClient    = TextAbstraction::FontClient::Get();
1025         fontClient.GetDpi(horizontalDpi, verticalDpi);
1026
1027         value = mImpl->mFontDefaults->mDefaultPointSize * static_cast<float>(horizontalDpi) / 72.f;
1028         break;
1029       }
1030     }
1031     return value;
1032   }
1033
1034   return value;
1035 }
1036
1037 void Controller::SetPlaceholderTextFontSize(float fontSize, FontSizeType type)
1038 {
1039   PlaceholderHandler::SetPlaceholderTextFontSize(*this, fontSize, type);
1040 }
1041
1042 float Controller::GetPlaceholderTextFontSize(FontSizeType type) const
1043 {
1044   return PlaceholderHandler::GetPlaceholderTextFontSize(*this, type);
1045 }
1046
1047 void Controller::SetDefaultColor(const Vector4& color)
1048 {
1049   mImpl->mTextColor = color;
1050
1051   if(!mImpl->IsShowingPlaceholderText())
1052   {
1053     mImpl->mModel->mVisualModel->SetTextColor(color);
1054
1055     mImpl->mModel->mLogicalModel->mColorRuns.Clear();
1056
1057     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
1058
1059     mImpl->RequestRelayout();
1060   }
1061 }
1062
1063 const Vector4& Controller::GetDefaultColor() const
1064 {
1065   return mImpl->mTextColor;
1066 }
1067
1068 void Controller::SetPlaceholderTextColor(const Vector4& textColor)
1069 {
1070   PlaceholderHandler::SetPlaceholderTextColor(*this, textColor);
1071 }
1072
1073 const Vector4& Controller::GetPlaceholderTextColor() const
1074 {
1075   return PlaceholderHandler::GetPlaceholderTextColor(*this);
1076 }
1077
1078 void Controller::SetShadowOffset(const Vector2& shadowOffset)
1079 {
1080   mImpl->mModel->mVisualModel->SetShadowOffset(shadowOffset);
1081
1082   mImpl->RequestRelayout();
1083 }
1084
1085 const Vector2& Controller::GetShadowOffset() const
1086 {
1087   return mImpl->mModel->mVisualModel->GetShadowOffset();
1088 }
1089
1090 void Controller::SetShadowColor(const Vector4& shadowColor)
1091 {
1092   mImpl->mModel->mVisualModel->SetShadowColor(shadowColor);
1093
1094   mImpl->RequestRelayout();
1095 }
1096
1097 const Vector4& Controller::GetShadowColor() const
1098 {
1099   return mImpl->mModel->mVisualModel->GetShadowColor();
1100 }
1101
1102 void Controller::SetShadowBlurRadius(const float& shadowBlurRadius)
1103 {
1104   if(fabsf(GetShadowBlurRadius() - shadowBlurRadius) > Math::MACHINE_EPSILON_1)
1105   {
1106     mImpl->mModel->mVisualModel->SetShadowBlurRadius(shadowBlurRadius);
1107
1108     mImpl->RequestRelayout();
1109   }
1110 }
1111
1112 const float& Controller::GetShadowBlurRadius() const
1113 {
1114   return mImpl->mModel->mVisualModel->GetShadowBlurRadius();
1115 }
1116
1117 void Controller::SetUnderlineColor(const Vector4& color)
1118 {
1119   mImpl->mModel->mVisualModel->SetUnderlineColor(color);
1120
1121   mImpl->RequestRelayout();
1122 }
1123
1124 const Vector4& Controller::GetUnderlineColor() const
1125 {
1126   return mImpl->mModel->mVisualModel->GetUnderlineColor();
1127 }
1128
1129 void Controller::SetUnderlineEnabled(bool enabled)
1130 {
1131   mImpl->mModel->mVisualModel->SetUnderlineEnabled(enabled);
1132
1133   mImpl->RequestRelayout();
1134 }
1135
1136 bool Controller::IsUnderlineEnabled() const
1137 {
1138   return mImpl->mModel->mVisualModel->IsUnderlineEnabled();
1139 }
1140
1141 void Controller::SetUnderlineHeight(float height)
1142 {
1143   mImpl->mModel->mVisualModel->SetUnderlineHeight(height);
1144
1145   mImpl->RequestRelayout();
1146 }
1147
1148 float Controller::GetUnderlineHeight() const
1149 {
1150   return mImpl->mModel->mVisualModel->GetUnderlineHeight();
1151 }
1152
1153 void Controller::SetOutlineColor(const Vector4& color)
1154 {
1155   mImpl->mModel->mVisualModel->SetOutlineColor(color);
1156
1157   mImpl->RequestRelayout();
1158 }
1159
1160 const Vector4& Controller::GetOutlineColor() const
1161 {
1162   return mImpl->mModel->mVisualModel->GetOutlineColor();
1163 }
1164
1165 void Controller::SetOutlineWidth(uint16_t width)
1166 {
1167   mImpl->mModel->mVisualModel->SetOutlineWidth(width);
1168
1169   mImpl->RequestRelayout();
1170 }
1171
1172 uint16_t Controller::GetOutlineWidth() const
1173 {
1174   return mImpl->mModel->mVisualModel->GetOutlineWidth();
1175 }
1176
1177 void Controller::SetBackgroundColor(const Vector4& color)
1178 {
1179   mImpl->mModel->mVisualModel->SetBackgroundColor(color);
1180
1181   mImpl->RequestRelayout();
1182 }
1183
1184 const Vector4& Controller::GetBackgroundColor() const
1185 {
1186   return mImpl->mModel->mVisualModel->GetBackgroundColor();
1187 }
1188
1189 void Controller::SetBackgroundEnabled(bool enabled)
1190 {
1191   mImpl->mModel->mVisualModel->SetBackgroundEnabled(enabled);
1192
1193   mImpl->RequestRelayout();
1194 }
1195
1196 bool Controller::IsBackgroundEnabled() const
1197 {
1198   return mImpl->mModel->mVisualModel->IsBackgroundEnabled();
1199 }
1200
1201 void Controller::SetDefaultEmbossProperties(const std::string& embossProperties)
1202 {
1203   if(NULL == mImpl->mEmbossDefaults)
1204   {
1205     mImpl->mEmbossDefaults = new EmbossDefaults();
1206   }
1207
1208   mImpl->mEmbossDefaults->properties = embossProperties;
1209 }
1210
1211 const std::string& Controller::GetDefaultEmbossProperties() const
1212 {
1213   if(NULL != mImpl->mEmbossDefaults)
1214   {
1215     return mImpl->mEmbossDefaults->properties;
1216   }
1217
1218   return EMPTY_STRING;
1219 }
1220
1221 void Controller::SetDefaultOutlineProperties(const std::string& outlineProperties)
1222 {
1223   if(NULL == mImpl->mOutlineDefaults)
1224   {
1225     mImpl->mOutlineDefaults = new OutlineDefaults();
1226   }
1227
1228   mImpl->mOutlineDefaults->properties = outlineProperties;
1229 }
1230
1231 const std::string& Controller::GetDefaultOutlineProperties() const
1232 {
1233   if(NULL != mImpl->mOutlineDefaults)
1234   {
1235     return mImpl->mOutlineDefaults->properties;
1236   }
1237
1238   return EMPTY_STRING;
1239 }
1240
1241 bool Controller::SetDefaultLineSpacing(float lineSpacing)
1242 {
1243   if(std::fabs(lineSpacing - mImpl->mLayoutEngine.GetDefaultLineSpacing()) > Math::MACHINE_EPSILON_1000)
1244   {
1245     mImpl->mLayoutEngine.SetDefaultLineSpacing(lineSpacing);
1246     mImpl->mRecalculateNaturalSize = true;
1247     return true;
1248   }
1249   return false;
1250 }
1251
1252 float Controller::GetDefaultLineSpacing() const
1253 {
1254   return mImpl->mLayoutEngine.GetDefaultLineSpacing();
1255 }
1256
1257 bool Controller::SetDefaultLineSize(float lineSize)
1258 {
1259   if(std::fabs(lineSize - mImpl->mLayoutEngine.GetDefaultLineSize()) > Math::MACHINE_EPSILON_1000)
1260   {
1261     mImpl->mLayoutEngine.SetDefaultLineSize(lineSize);
1262     mImpl->mRecalculateNaturalSize = true;
1263     return true;
1264   }
1265   return false;
1266 }
1267
1268 float Controller::GetDefaultLineSize() const
1269 {
1270   return mImpl->mLayoutEngine.GetDefaultLineSize();
1271 }
1272
1273 void Controller::SetInputColor(const Vector4& color)
1274 {
1275   if(NULL != mImpl->mEventData)
1276   {
1277     mImpl->mEventData->mInputStyle.textColor      = color;
1278     mImpl->mEventData->mInputStyle.isDefaultColor = false;
1279
1280     if(EventData::SELECTING == mImpl->mEventData->mState || EventData::EDITING == mImpl->mEventData->mState || EventData::INACTIVE == mImpl->mEventData->mState)
1281     {
1282       if(EventData::SELECTING == mImpl->mEventData->mState)
1283       {
1284         const bool handlesCrossed = mImpl->mEventData->mLeftSelectionPosition > mImpl->mEventData->mRightSelectionPosition;
1285
1286         // Get start and end position of selection
1287         const CharacterIndex startOfSelectedText  = handlesCrossed ? mImpl->mEventData->mRightSelectionPosition : mImpl->mEventData->mLeftSelectionPosition;
1288         const Length         lengthOfSelectedText = (handlesCrossed ? mImpl->mEventData->mLeftSelectionPosition : mImpl->mEventData->mRightSelectionPosition) - startOfSelectedText;
1289
1290         // Add the color run.
1291         const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
1292         mImpl->mModel->mLogicalModel->mColorRuns.Resize(numberOfRuns + 1u);
1293
1294         ColorRun& colorRun                       = *(mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns);
1295         colorRun.color                           = color;
1296         colorRun.characterRun.characterIndex     = startOfSelectedText;
1297         colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
1298
1299         mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
1300         mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
1301         mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
1302       }
1303       else
1304       {
1305         mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
1306         mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
1307         mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = mImpl->mModel->mLogicalModel->mText.Count();
1308       }
1309
1310       // Request to relayout.
1311       mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
1312       mImpl->RequestRelayout();
1313     }
1314   }
1315 }
1316
1317 const Vector4& Controller::GetInputColor() const
1318 {
1319   if(NULL != mImpl->mEventData)
1320   {
1321     return mImpl->mEventData->mInputStyle.textColor;
1322   }
1323
1324   // Return the default text's color if there is no EventData.
1325   return mImpl->mTextColor;
1326 }
1327
1328 void Controller::SetInputFontFamily(const std::string& fontFamily)
1329 {
1330   InputFontHandler::SetInputFontFamily(*this, fontFamily);
1331 }
1332
1333 const std::string& Controller::GetInputFontFamily() const
1334 {
1335   return InputFontHandler::GetInputFontFamily(*this);
1336 }
1337
1338 void Controller::SetInputFontWeight(FontWeight weight)
1339 {
1340   InputFontHandler::SetInputFontWeight(*this, weight);
1341 }
1342
1343 bool Controller::IsInputFontWeightDefined() const
1344 {
1345   return InputFontHandler::IsInputFontWeightDefined(*this);
1346 }
1347
1348 FontWeight Controller::GetInputFontWeight() const
1349 {
1350   return InputFontHandler::GetInputFontWeight(*this);
1351 }
1352
1353 void Controller::SetInputFontWidth(FontWidth width)
1354 {
1355   InputFontHandler::SetInputFontWidth(*this, width);
1356 }
1357
1358 bool Controller::IsInputFontWidthDefined() const
1359 {
1360   return InputFontHandler::IsInputFontWidthDefined(*this);
1361 }
1362
1363 FontWidth Controller::GetInputFontWidth() const
1364 {
1365   return InputFontHandler::GetInputFontWidth(*this);
1366 }
1367
1368 void Controller::SetInputFontSlant(FontSlant slant)
1369 {
1370   InputFontHandler::SetInputFontSlant(*this, slant);
1371 }
1372
1373 bool Controller::IsInputFontSlantDefined() const
1374 {
1375   return InputFontHandler::IsInputFontSlantDefined(*this);
1376 }
1377
1378 FontSlant Controller::GetInputFontSlant() const
1379 {
1380   return InputFontHandler::GetInputFontSlant(*this);
1381 }
1382
1383 void Controller::SetInputFontPointSize(float size)
1384 {
1385   InputFontHandler::SetInputFontPointSize(*this, size);
1386 }
1387
1388 float Controller::GetInputFontPointSize() const
1389 {
1390   return InputFontHandler::GetInputFontPointSize(*this);
1391 }
1392
1393 void Controller::SetInputLineSpacing(float lineSpacing)
1394 {
1395   if(NULL != mImpl->mEventData)
1396   {
1397     mImpl->mEventData->mInputStyle.lineSpacing          = lineSpacing;
1398     mImpl->mEventData->mInputStyle.isLineSpacingDefined = true;
1399   }
1400 }
1401
1402 float Controller::GetInputLineSpacing() const
1403 {
1404   if(NULL != mImpl->mEventData)
1405   {
1406     return mImpl->mEventData->mInputStyle.lineSpacing;
1407   }
1408
1409   return 0.f;
1410 }
1411
1412 void Controller::SetInputShadowProperties(const std::string& shadowProperties)
1413 {
1414   if(NULL != mImpl->mEventData)
1415   {
1416     mImpl->mEventData->mInputStyle.shadowProperties = shadowProperties;
1417   }
1418 }
1419
1420 const std::string& Controller::GetInputShadowProperties() const
1421 {
1422   if(NULL != mImpl->mEventData)
1423   {
1424     return mImpl->mEventData->mInputStyle.shadowProperties;
1425   }
1426
1427   return EMPTY_STRING;
1428 }
1429
1430 void Controller::SetInputUnderlineProperties(const std::string& underlineProperties)
1431 {
1432   if(NULL != mImpl->mEventData)
1433   {
1434     mImpl->mEventData->mInputStyle.underlineProperties = underlineProperties;
1435   }
1436 }
1437
1438 const std::string& Controller::GetInputUnderlineProperties() const
1439 {
1440   if(NULL != mImpl->mEventData)
1441   {
1442     return mImpl->mEventData->mInputStyle.underlineProperties;
1443   }
1444
1445   return EMPTY_STRING;
1446 }
1447
1448 void Controller::SetInputEmbossProperties(const std::string& embossProperties)
1449 {
1450   if(NULL != mImpl->mEventData)
1451   {
1452     mImpl->mEventData->mInputStyle.embossProperties = embossProperties;
1453   }
1454 }
1455
1456 const std::string& Controller::GetInputEmbossProperties() const
1457 {
1458   if(NULL != mImpl->mEventData)
1459   {
1460     return mImpl->mEventData->mInputStyle.embossProperties;
1461   }
1462
1463   return GetDefaultEmbossProperties();
1464 }
1465
1466 void Controller::SetInputOutlineProperties(const std::string& outlineProperties)
1467 {
1468   if(NULL != mImpl->mEventData)
1469   {
1470     mImpl->mEventData->mInputStyle.outlineProperties = outlineProperties;
1471   }
1472 }
1473
1474 const std::string& Controller::GetInputOutlineProperties() const
1475 {
1476   if(NULL != mImpl->mEventData)
1477   {
1478     return mImpl->mEventData->mInputStyle.outlineProperties;
1479   }
1480
1481   return GetDefaultOutlineProperties();
1482 }
1483
1484 void Controller::SetInputModePassword(bool passwordInput)
1485 {
1486   if(NULL != mImpl->mEventData)
1487   {
1488     mImpl->mEventData->mPasswordInput = passwordInput;
1489   }
1490 }
1491
1492 bool Controller::IsInputModePassword()
1493 {
1494   if(NULL != mImpl->mEventData)
1495   {
1496     return mImpl->mEventData->mPasswordInput;
1497   }
1498   return false;
1499 }
1500
1501 void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action)
1502 {
1503   if(NULL != mImpl->mEventData)
1504   {
1505     mImpl->mEventData->mDoubleTapAction = action;
1506   }
1507 }
1508
1509 Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
1510 {
1511   NoTextTap::Action action = NoTextTap::NO_ACTION;
1512
1513   if(NULL != mImpl->mEventData)
1514   {
1515     action = mImpl->mEventData->mDoubleTapAction;
1516   }
1517
1518   return action;
1519 }
1520
1521 void Controller::SetNoTextLongPressAction(NoTextTap::Action action)
1522 {
1523   if(NULL != mImpl->mEventData)
1524   {
1525     mImpl->mEventData->mLongPressAction = action;
1526   }
1527 }
1528
1529 Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
1530 {
1531   NoTextTap::Action action = NoTextTap::NO_ACTION;
1532
1533   if(NULL != mImpl->mEventData)
1534   {
1535     action = mImpl->mEventData->mLongPressAction;
1536   }
1537
1538   return action;
1539 }
1540
1541 bool Controller::IsUnderlineSetByString()
1542 {
1543   return mImpl->mUnderlineSetByString;
1544 }
1545
1546 void Controller::UnderlineSetByString(bool setByString)
1547 {
1548   mImpl->mUnderlineSetByString = setByString;
1549 }
1550
1551 bool Controller::IsShadowSetByString()
1552 {
1553   return mImpl->mShadowSetByString;
1554 }
1555
1556 void Controller::ShadowSetByString(bool setByString)
1557 {
1558   mImpl->mShadowSetByString = setByString;
1559 }
1560
1561 bool Controller::IsOutlineSetByString()
1562 {
1563   return mImpl->mOutlineSetByString;
1564 }
1565
1566 void Controller::OutlineSetByString(bool setByString)
1567 {
1568   mImpl->mOutlineSetByString = setByString;
1569 }
1570
1571 bool Controller::IsFontStyleSetByString()
1572 {
1573   return mImpl->mFontStyleSetByString;
1574 }
1575
1576 void Controller::FontStyleSetByString(bool setByString)
1577 {
1578   mImpl->mFontStyleSetByString = setByString;
1579 }
1580
1581 // public : Queries & retrieves.
1582
1583 Layout::Engine& Controller::GetLayoutEngine()
1584 {
1585   return mImpl->mLayoutEngine;
1586 }
1587
1588 View& Controller::GetView()
1589 {
1590   return mImpl->mView;
1591 }
1592
1593 Vector3 Controller::GetNaturalSize()
1594 {
1595   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetNaturalSize\n");
1596   Vector3 naturalSize;
1597
1598   // Make sure the model is up-to-date before layouting
1599   ProcessModifyEvents();
1600
1601   if(mImpl->mRecalculateNaturalSize)
1602   {
1603     // Operations that can be done only once until the text changes.
1604     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
1605                                                                           GET_SCRIPTS |
1606                                                                           VALIDATE_FONTS |
1607                                                                           GET_LINE_BREAKS |
1608                                                                           BIDI_INFO |
1609                                                                           SHAPE_TEXT |
1610                                                                           GET_GLYPH_METRICS);
1611
1612     // Set the update info to relayout the whole text.
1613     mImpl->mTextUpdateInfo.mParagraphCharacterIndex     = 0u;
1614     mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
1615
1616     // Make sure the model is up-to-date before layouting
1617     mImpl->UpdateModel(onlyOnceOperations);
1618
1619     // Layout the text for the new width.
1620     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | LAYOUT | REORDER);
1621
1622     // Store the actual control's size to restore later.
1623     const Size actualControlSize = mImpl->mModel->mVisualModel->mControlSize;
1624
1625     DoRelayout(Size(MAX_FLOAT, MAX_FLOAT),
1626                static_cast<OperationsMask>(onlyOnceOperations |
1627                                            LAYOUT | REORDER),
1628                naturalSize.GetVectorXY());
1629
1630     // Do not do again the only once operations.
1631     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending & ~onlyOnceOperations);
1632
1633     // Do the size related operations again.
1634     const OperationsMask sizeOperations = static_cast<OperationsMask>(LAYOUT |
1635                                                                       ALIGN |
1636                                                                       REORDER);
1637     mImpl->mOperationsPending           = static_cast<OperationsMask>(mImpl->mOperationsPending | sizeOperations);
1638
1639     // Stores the natural size to avoid recalculate it again
1640     // unless the text/style changes.
1641     mImpl->mModel->mVisualModel->SetNaturalSize(naturalSize.GetVectorXY());
1642
1643     mImpl->mRecalculateNaturalSize = false;
1644
1645     // Clear the update info. This info will be set the next time the text is updated.
1646     mImpl->mTextUpdateInfo.Clear();
1647     mImpl->mTextUpdateInfo.mClearAll = true;
1648
1649     // Restore the actual control's size.
1650     mImpl->mModel->mVisualModel->mControlSize = actualControlSize;
1651
1652     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize calculated %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z);
1653   }
1654   else
1655   {
1656     naturalSize = mImpl->mModel->mVisualModel->GetNaturalSize();
1657
1658     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize cached %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z);
1659   }
1660
1661   naturalSize.x = ConvertToEven(naturalSize.x);
1662   naturalSize.y = ConvertToEven(naturalSize.y);
1663
1664   return naturalSize;
1665 }
1666
1667 bool Controller::CheckForTextFit(float pointSize, Size& layoutSize)
1668 {
1669   Size textSize;
1670   mImpl->mFontDefaults->mFitPointSize = pointSize;
1671   mImpl->mFontDefaults->sizeDefined   = true;
1672   ClearFontData();
1673
1674   // Operations that can be done only once until the text changes.
1675   const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
1676                                                                         GET_SCRIPTS |
1677                                                                         VALIDATE_FONTS |
1678                                                                         GET_LINE_BREAKS |
1679                                                                         BIDI_INFO |
1680                                                                         SHAPE_TEXT |
1681                                                                         GET_GLYPH_METRICS);
1682
1683   mImpl->mTextUpdateInfo.mParagraphCharacterIndex     = 0u;
1684   mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
1685
1686   // Make sure the model is up-to-date before layouting
1687   mImpl->UpdateModel(onlyOnceOperations);
1688
1689   DoRelayout(Size(layoutSize.width, MAX_FLOAT),
1690              static_cast<OperationsMask>(onlyOnceOperations | LAYOUT),
1691              textSize);
1692
1693   // Clear the update info. This info will be set the next time the text is updated.
1694   mImpl->mTextUpdateInfo.Clear();
1695   mImpl->mTextUpdateInfo.mClearAll = true;
1696
1697   if(textSize.width > layoutSize.width || textSize.height > layoutSize.height)
1698   {
1699     return false;
1700   }
1701   return true;
1702 }
1703
1704 void Controller::FitPointSizeforLayout(Size layoutSize)
1705 {
1706   const OperationsMask operations = mImpl->mOperationsPending;
1707   if(NO_OPERATION != (UPDATE_LAYOUT_SIZE & operations) || mImpl->mTextFitContentSize != layoutSize)
1708   {
1709     bool  actualellipsis = mImpl->mModel->mElideEnabled;
1710     float minPointSize   = mImpl->mTextFitMinSize;
1711     float maxPointSize   = mImpl->mTextFitMaxSize;
1712     float pointInterval  = mImpl->mTextFitStepSize;
1713
1714     mImpl->mModel->mElideEnabled = false;
1715     Vector<float> pointSizeArray;
1716
1717     // check zero value
1718     if(pointInterval < 1.f)
1719     {
1720       mImpl->mTextFitStepSize = pointInterval = 1.0f;
1721     }
1722
1723     pointSizeArray.Reserve(static_cast<unsigned int>(ceil((maxPointSize - minPointSize) / pointInterval)));
1724
1725     for(float i = minPointSize; i < maxPointSize; i += pointInterval)
1726     {
1727       pointSizeArray.PushBack(i);
1728     }
1729
1730     pointSizeArray.PushBack(maxPointSize);
1731
1732     int bestSizeIndex = 0;
1733     int min           = bestSizeIndex + 1;
1734     int max           = pointSizeArray.Size() - 1;
1735     while(min <= max)
1736     {
1737       int destI = (min + max) / 2;
1738
1739       if(CheckForTextFit(pointSizeArray[destI], layoutSize))
1740       {
1741         bestSizeIndex = min;
1742         min           = destI + 1;
1743       }
1744       else
1745       {
1746         max           = destI - 1;
1747         bestSizeIndex = max;
1748       }
1749     }
1750
1751     mImpl->mModel->mElideEnabled        = actualellipsis;
1752     mImpl->mFontDefaults->mFitPointSize = pointSizeArray[bestSizeIndex];
1753     mImpl->mFontDefaults->sizeDefined   = true;
1754     ClearFontData();
1755   }
1756 }
1757
1758 float Controller::GetHeightForWidth(float width)
1759 {
1760   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetHeightForWidth %p width %f\n", this, width);
1761   // Make sure the model is up-to-date before layouting
1762   ProcessModifyEvents();
1763
1764   Size layoutSize;
1765   if(fabsf(width - mImpl->mModel->mVisualModel->mControlSize.width) > Math::MACHINE_EPSILON_1000 ||
1766      mImpl->mTextUpdateInfo.mFullRelayoutNeeded ||
1767      mImpl->mTextUpdateInfo.mClearAll)
1768   {
1769     // Operations that can be done only once until the text changes.
1770     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
1771                                                                           GET_SCRIPTS |
1772                                                                           VALIDATE_FONTS |
1773                                                                           GET_LINE_BREAKS |
1774                                                                           BIDI_INFO |
1775                                                                           SHAPE_TEXT |
1776                                                                           GET_GLYPH_METRICS);
1777
1778     // Set the update info to relayout the whole text.
1779     mImpl->mTextUpdateInfo.mParagraphCharacterIndex     = 0u;
1780     mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
1781
1782     // Make sure the model is up-to-date before layouting
1783     mImpl->UpdateModel(onlyOnceOperations);
1784
1785     // Layout the text for the new width.
1786     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | LAYOUT);
1787
1788     // Store the actual control's width.
1789     const float actualControlWidth = mImpl->mModel->mVisualModel->mControlSize.width;
1790
1791     DoRelayout(Size(width, MAX_FLOAT),
1792                static_cast<OperationsMask>(onlyOnceOperations |
1793                                            LAYOUT),
1794                layoutSize);
1795
1796     // Do not do again the only once operations.
1797     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending & ~onlyOnceOperations);
1798
1799     // Do the size related operations again.
1800     const OperationsMask sizeOperations = static_cast<OperationsMask>(LAYOUT |
1801                                                                       ALIGN |
1802                                                                       REORDER);
1803
1804     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | sizeOperations);
1805
1806     // Clear the update info. This info will be set the next time the text is updated.
1807     mImpl->mTextUpdateInfo.Clear();
1808     mImpl->mTextUpdateInfo.mClearAll = true;
1809
1810     // Restore the actual control's width.
1811     mImpl->mModel->mVisualModel->mControlSize.width = actualControlWidth;
1812
1813     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth calculated %f\n", layoutSize.height);
1814   }
1815   else
1816   {
1817     layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize();
1818     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth cached %f\n", layoutSize.height);
1819   }
1820
1821   return layoutSize.height;
1822 }
1823
1824 int Controller::GetLineCount(float width)
1825 {
1826   GetHeightForWidth(width);
1827   int numberofLines = mImpl->mModel->GetNumberOfLines();
1828   return numberofLines;
1829 }
1830
1831 const ModelInterface* const Controller::GetTextModel() const
1832 {
1833   return mImpl->mModel.Get();
1834 }
1835
1836 float Controller::GetScrollAmountByUserInput()
1837 {
1838   float scrollAmount = 0.0f;
1839
1840   if(NULL != mImpl->mEventData && mImpl->mEventData->mCheckScrollAmount)
1841   {
1842     scrollAmount                          = mImpl->mModel->mScrollPosition.y - mImpl->mModel->mScrollPositionLast.y;
1843     mImpl->mEventData->mCheckScrollAmount = false;
1844   }
1845   return scrollAmount;
1846 }
1847
1848 bool Controller::GetTextScrollInfo(float& scrollPosition, float& controlHeight, float& layoutHeight)
1849 {
1850   const Vector2& layout = mImpl->mModel->mVisualModel->GetLayoutSize();
1851   bool           isScrolled;
1852
1853   controlHeight  = mImpl->mModel->mVisualModel->mControlSize.height;
1854   layoutHeight   = layout.height;
1855   scrollPosition = mImpl->mModel->mScrollPosition.y;
1856   isScrolled     = !Equals(mImpl->mModel->mScrollPosition.y, mImpl->mModel->mScrollPositionLast.y, Math::MACHINE_EPSILON_1);
1857   return isScrolled;
1858 }
1859
1860 void Controller::SetHiddenInputOption(const Property::Map& options)
1861 {
1862   if(NULL == mImpl->mHiddenInput)
1863   {
1864     mImpl->mHiddenInput = new HiddenText(this);
1865   }
1866   mImpl->mHiddenInput->SetProperties(options);
1867 }
1868
1869 void Controller::GetHiddenInputOption(Property::Map& options)
1870 {
1871   if(NULL != mImpl->mHiddenInput)
1872   {
1873     mImpl->mHiddenInput->GetProperties(options);
1874   }
1875 }
1876
1877 void Controller::SetPlaceholderProperty(const Property::Map& map)
1878 {
1879   PlaceholderHandler::SetPlaceholderProperty(*this, map);
1880 }
1881
1882 void Controller::GetPlaceholderProperty(Property::Map& map)
1883 {
1884   PlaceholderHandler::GetPlaceholderProperty(*this, map);
1885 }
1886
1887 Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
1888 {
1889   // Make sure the model is up-to-date before layouting
1890   ProcessModifyEvents();
1891
1892   if(mImpl->mUpdateTextDirection)
1893   {
1894     // Operations that can be done only once until the text changes.
1895     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
1896                                                                           GET_SCRIPTS |
1897                                                                           VALIDATE_FONTS |
1898                                                                           GET_LINE_BREAKS |
1899                                                                           BIDI_INFO |
1900                                                                           SHAPE_TEXT |
1901                                                                           GET_GLYPH_METRICS);
1902
1903     // Set the update info to relayout the whole text.
1904     mImpl->mTextUpdateInfo.mParagraphCharacterIndex     = 0u;
1905     mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
1906
1907     // Make sure the model is up-to-date before layouting
1908     mImpl->UpdateModel(onlyOnceOperations);
1909
1910     Vector3 naturalSize;
1911     DoRelayout(Size(MAX_FLOAT, MAX_FLOAT),
1912                static_cast<OperationsMask>(onlyOnceOperations |
1913                                            LAYOUT | REORDER | UPDATE_DIRECTION),
1914                naturalSize.GetVectorXY());
1915
1916     // Do not do again the only once operations.
1917     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending & ~onlyOnceOperations);
1918
1919     // Clear the update info. This info will be set the next time the text is updated.
1920     mImpl->mTextUpdateInfo.Clear();
1921
1922     // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT.
1923     mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
1924
1925     mImpl->mUpdateTextDirection = false;
1926   }
1927
1928   return mImpl->mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT;
1929 }
1930
1931 Toolkit::DevelText::VerticalLineAlignment::Type Controller::GetVerticalLineAlignment() const
1932 {
1933   return mImpl->mModel->GetVerticalLineAlignment();
1934 }
1935
1936 void Controller::SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignment::Type alignment)
1937 {
1938   mImpl->mModel->mVerticalLineAlignment = alignment;
1939 }
1940
1941 // public : Relayout.
1942
1943 Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
1944 {
1945   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f, autoScroll[%s]\n", this, size.width, size.height, mImpl->mIsAutoScrollEnabled ? "true" : "false");
1946
1947   UpdateTextType updateTextType = NONE_UPDATED;
1948
1949   if((size.width < Math::MACHINE_EPSILON_1000) || (size.height < Math::MACHINE_EPSILON_1000))
1950   {
1951     if(0u != mImpl->mModel->mVisualModel->mGlyphPositions.Count())
1952     {
1953       mImpl->mModel->mVisualModel->mGlyphPositions.Clear();
1954       updateTextType = MODEL_UPDATED;
1955     }
1956
1957     // Clear the update info. This info will be set the next time the text is updated.
1958     mImpl->mTextUpdateInfo.Clear();
1959
1960     // Not worth to relayout if width or height is equal to zero.
1961     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::Relayout (skipped)\n");
1962
1963     return updateTextType;
1964   }
1965
1966   // Whether a new size has been set.
1967   const bool newSize = (size != mImpl->mModel->mVisualModel->mControlSize);
1968
1969   if(newSize)
1970   {
1971     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "new size (previous size %f,%f)\n", mImpl->mModel->mVisualModel->mControlSize.width, mImpl->mModel->mVisualModel->mControlSize.height);
1972
1973     if((0 == mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd) &&
1974        (0 == mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters) &&
1975        ((mImpl->mModel->mVisualModel->mControlSize.width < Math::MACHINE_EPSILON_1000) || (mImpl->mModel->mVisualModel->mControlSize.height < Math::MACHINE_EPSILON_1000)))
1976     {
1977       mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
1978     }
1979
1980     // Layout operations that need to be done if the size changes.
1981     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
1982                                                             LAYOUT |
1983                                                             ALIGN |
1984                                                             UPDATE_LAYOUT_SIZE |
1985                                                             REORDER);
1986     // Set the update info to relayout the whole text.
1987     mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
1988     mImpl->mTextUpdateInfo.mCharacterIndex     = 0u;
1989
1990     // Store the size used to layout the text.
1991     mImpl->mModel->mVisualModel->mControlSize = size;
1992   }
1993
1994   // Whether there are modify events.
1995   if(0u != mImpl->mModifyEvents.Count())
1996   {
1997     // Style operations that need to be done if the text is modified.
1998     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
1999                                                             COLOR);
2000   }
2001
2002   // Set the update info to elide the text.
2003   if(mImpl->mModel->mElideEnabled ||
2004      ((NULL != mImpl->mEventData) && mImpl->mEventData->mIsPlaceholderElideEnabled))
2005   {
2006     // Update Text layout for applying elided
2007     mImpl->mOperationsPending                  = static_cast<OperationsMask>(mImpl->mOperationsPending |
2008                                                             ALIGN |
2009                                                             LAYOUT |
2010                                                             UPDATE_LAYOUT_SIZE |
2011                                                             REORDER);
2012     mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
2013     mImpl->mTextUpdateInfo.mCharacterIndex     = 0u;
2014   }
2015
2016   if(mImpl->mModel->mMatchSystemLanguageDirection && mImpl->mLayoutDirection != layoutDirection)
2017   {
2018     // Clear the update info. This info will be set the next time the text is updated.
2019     mImpl->mTextUpdateInfo.mClearAll = true;
2020     // Apply modifications to the model
2021     // Shape the text again is needed because characters like '()[]{}' have to be mirrored and the glyphs generated again.
2022     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
2023                                                             GET_GLYPH_METRICS |
2024                                                             SHAPE_TEXT |
2025                                                             UPDATE_DIRECTION |
2026                                                             LAYOUT |
2027                                                             BIDI_INFO |
2028                                                             REORDER);
2029     mImpl->mLayoutDirection   = layoutDirection;
2030   }
2031
2032   // Make sure the model is up-to-date before layouting.
2033   ProcessModifyEvents();
2034   bool updated = mImpl->UpdateModel(mImpl->mOperationsPending);
2035
2036   // Layout the text.
2037   Size layoutSize;
2038   updated = DoRelayout(size,
2039                        mImpl->mOperationsPending,
2040                        layoutSize) ||
2041             updated;
2042
2043   if(updated)
2044   {
2045     updateTextType = MODEL_UPDATED;
2046   }
2047
2048   // Do not re-do any operation until something changes.
2049   mImpl->mOperationsPending          = NO_OPERATION;
2050   mImpl->mModel->mScrollPositionLast = mImpl->mModel->mScrollPosition;
2051
2052   // Whether the text control is editable
2053   const bool isEditable = NULL != mImpl->mEventData;
2054
2055   // Keep the current offset as it will be used to update the decorator's positions (if the size changes).
2056   Vector2 offset;
2057   if(newSize && isEditable)
2058   {
2059     offset = mImpl->mModel->mScrollPosition;
2060   }
2061
2062   if(!isEditable || !IsMultiLineEnabled())
2063   {
2064     // After doing the text layout, the vertical offset to place the actor in the desired position can be calculated.
2065     CalculateVerticalOffset(size);
2066   }
2067
2068   if(isEditable)
2069   {
2070     if(newSize)
2071     {
2072       // If there is a new size, the scroll position needs to be clamped.
2073       mImpl->ClampHorizontalScroll(layoutSize);
2074
2075       // Update the decorator's positions is needed if there is a new size.
2076       mImpl->mEventData->mDecorator->UpdatePositions(mImpl->mModel->mScrollPosition - offset);
2077     }
2078
2079     // Move the cursor, grab handle etc.
2080     if(mImpl->ProcessInputEvents())
2081     {
2082       updateTextType = static_cast<UpdateTextType>(updateTextType | DECORATOR_UPDATED);
2083     }
2084   }
2085
2086   // Clear the update info. This info will be set the next time the text is updated.
2087   mImpl->mTextUpdateInfo.Clear();
2088   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::Relayout\n");
2089
2090   return updateTextType;
2091 }
2092
2093 void Controller::RequestRelayout()
2094 {
2095   mImpl->RequestRelayout();
2096 }
2097
2098 // public : Input style change signals.
2099
2100 bool Controller::IsInputStyleChangedSignalsQueueEmpty()
2101 {
2102   return (NULL == mImpl->mEventData) || (0u == mImpl->mEventData->mInputStyleChangedQueue.Count());
2103 }
2104
2105 void Controller::ProcessInputStyleChangedSignals()
2106 {
2107   if(NULL == mImpl->mEventData)
2108   {
2109     // Nothing to do.
2110     return;
2111   }
2112
2113   for(Vector<InputStyle::Mask>::ConstIterator it    = mImpl->mEventData->mInputStyleChangedQueue.Begin(),
2114                                               endIt = mImpl->mEventData->mInputStyleChangedQueue.End();
2115       it != endIt;
2116       ++it)
2117   {
2118     const InputStyle::Mask mask = *it;
2119
2120     if(NULL != mImpl->mEditableControlInterface)
2121     {
2122       // Emit the input style changed signal.
2123       mImpl->mEditableControlInterface->InputStyleChanged(mask);
2124     }
2125   }
2126
2127   mImpl->mEventData->mInputStyleChangedQueue.Clear();
2128 }
2129
2130 // public : Text-input Event Queuing.
2131
2132 void Controller::KeyboardFocusGainEvent()
2133 {
2134   EventHandler::KeyboardFocusGainEvent(*this);
2135 }
2136
2137 void Controller::KeyboardFocusLostEvent()
2138 {
2139   EventHandler::KeyboardFocusLostEvent(*this);
2140 }
2141
2142 bool Controller::KeyEvent(const Dali::KeyEvent& keyEvent)
2143 {
2144   return EventHandler::KeyEvent(*this, keyEvent);
2145 }
2146
2147 void Controller::TapEvent(unsigned int tapCount, float x, float y)
2148 {
2149   EventHandler::TapEvent(*this, tapCount, x, y);
2150 }
2151
2152 void Controller::PanEvent(GestureState state, const Vector2& displacement)
2153 {
2154   EventHandler::PanEvent(*this, state, displacement);
2155 }
2156
2157 void Controller::LongPressEvent(GestureState state, float x, float y)
2158 {
2159   EventHandler::LongPressEvent(*this, state, x, y);
2160 }
2161
2162 void Controller::SelectEvent(float x, float y, SelectionType selectType)
2163 {
2164   EventHandler::SelectEvent(*this, x, y, selectType);
2165 }
2166
2167 void Controller::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
2168 {
2169   if(mImpl->mEventData)
2170   {
2171     mImpl->mEventData->mCheckScrollAmount     = true;
2172     mImpl->mEventData->mIsLeftHandleSelected  = true;
2173     mImpl->mEventData->mIsRightHandleSelected = true;
2174     mImpl->SetTextSelectionRange(start, end);
2175     mImpl->RequestRelayout();
2176     KeyboardFocusGainEvent();
2177   }
2178 }
2179
2180 Uint32Pair Controller::GetTextSelectionRange() const
2181 {
2182   return mImpl->GetTextSelectionRange();
2183 }
2184
2185 void Controller::SelectWholeText()
2186 {
2187   SelectEvent(0.f, 0.f, SelectionType::ALL);
2188 }
2189
2190 void Controller::SelectNone()
2191 {
2192   SelectEvent(0.f, 0.f, SelectionType::NONE);
2193 }
2194
2195 string Controller::GetSelectedText() const
2196 {
2197   string text;
2198   if(EventData::SELECTING == mImpl->mEventData->mState)
2199   {
2200     mImpl->RetrieveSelection(text, false);
2201   }
2202   return text;
2203 }
2204
2205 InputMethodContext::CallbackData Controller::OnInputMethodContextEvent(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
2206 {
2207   return EventHandler::OnInputMethodContextEvent(*this, inputMethodContext, inputMethodContextEvent);
2208 }
2209
2210 void Controller::PasteClipboardItemEvent()
2211 {
2212   EventHandler::PasteClipboardItemEvent(*this);
2213 }
2214
2215 // protected : Inherit from Text::Decorator::ControllerInterface.
2216
2217 void Controller::GetTargetSize(Vector2& targetSize)
2218 {
2219   targetSize = mImpl->mModel->mVisualModel->mControlSize;
2220 }
2221
2222 void Controller::AddDecoration(Actor& actor, bool needsClipping)
2223 {
2224   if(NULL != mImpl->mEditableControlInterface)
2225   {
2226     mImpl->mEditableControlInterface->AddDecoration(actor, needsClipping);
2227   }
2228 }
2229
2230 bool Controller::IsEditable() const
2231 {
2232   return mImpl->IsEditable();
2233 }
2234
2235 void Controller::SetEditable(bool editable)
2236 {
2237   mImpl->SetEditable(editable);
2238   if(mImpl->mEventData && mImpl->mEventData->mDecorator)
2239   {
2240     mImpl->mEventData->mDecorator->SetEditable(editable);
2241   }
2242 }
2243
2244 void Controller::DecorationEvent(HandleType handleType, HandleState state, float x, float y)
2245 {
2246   EventHandler::DecorationEvent(*this, handleType, state, x, y);
2247 }
2248
2249 // protected : Inherit from TextSelectionPopup::TextPopupButtonCallbackInterface.
2250
2251 void Controller::TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button)
2252 {
2253   EventHandler::TextPopupButtonTouched(*this, button);
2254 }
2255
2256 void Controller::DisplayTimeExpired()
2257 {
2258   mImpl->mEventData->mUpdateCursorPosition = true;
2259   // Apply modifications to the model
2260   mImpl->mOperationsPending = ALL_OPERATIONS;
2261
2262   mImpl->RequestRelayout();
2263 }
2264
2265 // private : Update.
2266
2267 void Controller::InsertText(const std::string& text, Controller::InsertType type)
2268 {
2269   bool removedPrevious  = false;
2270   bool removedSelected  = false;
2271   bool maxLengthReached = false;
2272
2273   DALI_ASSERT_DEBUG(NULL != mImpl->mEventData && "Unexpected InsertText")
2274
2275   if(NULL == mImpl->mEventData)
2276   {
2277     return;
2278   }
2279
2280   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::InsertText %p %s (%s) mPrimaryCursorPosition %d mPreEditFlag %d mPreEditStartPosition %d mPreEditLength %d\n", this, text.c_str(), (COMMIT == type ? "COMMIT" : "PRE_EDIT"), mImpl->mEventData->mPrimaryCursorPosition, mImpl->mEventData->mPreEditFlag, mImpl->mEventData->mPreEditStartPosition, mImpl->mEventData->mPreEditLength);
2281
2282   // Play the input text with the TTS player.
2283   Dali::TtsPlayer player = Dali::TtsPlayer::Get(Dali::TtsPlayer::SCREEN_READER);
2284   if (player)
2285   {
2286     player.Play(text);
2287   }
2288
2289   // TODO: At the moment the underline runs are only for pre-edit.
2290   mImpl->mModel->mVisualModel->mUnderlineRuns.Clear();
2291
2292   // Remove the previous InputMethodContext pre-edit.
2293   if(mImpl->mEventData->mPreEditFlag && (0u != mImpl->mEventData->mPreEditLength))
2294   {
2295     removedPrevious = RemoveText(-static_cast<int>(mImpl->mEventData->mPrimaryCursorPosition - mImpl->mEventData->mPreEditStartPosition),
2296                                  mImpl->mEventData->mPreEditLength,
2297                                  DONT_UPDATE_INPUT_STYLE);
2298
2299     mImpl->mEventData->mPrimaryCursorPosition = mImpl->mEventData->mPreEditStartPosition;
2300     mImpl->mEventData->mPreEditLength         = 0u;
2301   }
2302   else
2303   {
2304     // Remove the previous Selection.
2305     removedSelected = RemoveSelectedText();
2306   }
2307
2308   Vector<Character> utf32Characters;
2309   Length            characterCount = 0u;
2310
2311   if(!text.empty())
2312   {
2313     //  Convert text into UTF-32
2314     utf32Characters.Resize(text.size());
2315
2316     // This is a bit horrible but std::string returns a (signed) char*
2317     const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(text.c_str());
2318
2319     // Transform a text array encoded in utf8 into an array encoded in utf32.
2320     // It returns the actual number of characters.
2321     characterCount = Utf8ToUtf32(utf8, text.size(), utf32Characters.Begin());
2322     utf32Characters.Resize(characterCount);
2323
2324     DALI_ASSERT_DEBUG(text.size() >= utf32Characters.Count() && "Invalid UTF32 conversion length");
2325     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "UTF8 size %d, UTF32 size %d\n", text.size(), utf32Characters.Count());
2326   }
2327
2328   if(0u != utf32Characters.Count()) // Check if Utf8ToUtf32 conversion succeeded
2329   {
2330     // The placeholder text is no longer needed
2331     if(mImpl->IsShowingPlaceholderText())
2332     {
2333       ResetText();
2334     }
2335
2336     mImpl->ChangeState(EventData::EDITING);
2337
2338     // Handle the InputMethodContext (predicitive text) state changes
2339     if(COMMIT == type)
2340     {
2341       // InputMethodContext is no longer handling key-events
2342       mImpl->ClearPreEditFlag();
2343     }
2344     else // PRE_EDIT
2345     {
2346       if(!mImpl->mEventData->mPreEditFlag)
2347       {
2348         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Entered PreEdit state\n");
2349
2350         // Record the start of the pre-edit text
2351         mImpl->mEventData->mPreEditStartPosition = mImpl->mEventData->mPrimaryCursorPosition;
2352       }
2353
2354       mImpl->mEventData->mPreEditLength = utf32Characters.Count();
2355       mImpl->mEventData->mPreEditFlag   = true;
2356
2357       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "mPreEditStartPosition %d mPreEditLength %d\n", mImpl->mEventData->mPreEditStartPosition, mImpl->mEventData->mPreEditLength);
2358     }
2359
2360     const Length numberOfCharactersInModel = mImpl->mModel->mLogicalModel->mText.Count();
2361
2362     // Restrict new text to fit within Maximum characters setting.
2363     Length maxSizeOfNewText = std::min((mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel), characterCount);
2364     maxLengthReached        = (characterCount > maxSizeOfNewText);
2365
2366     // The cursor position.
2367     CharacterIndex& cursorIndex = mImpl->mEventData->mPrimaryCursorPosition;
2368
2369     // Update the text's style.
2370
2371     // Updates the text style runs by adding characters.
2372     mImpl->mModel->mLogicalModel->UpdateTextStyleRuns(cursorIndex, maxSizeOfNewText);
2373
2374     // Get the character index from the cursor index.
2375     const CharacterIndex styleIndex = (cursorIndex > 0u) ? cursorIndex - 1u : 0u;
2376
2377     // Retrieve the text's style for the given index.
2378     InputStyle style;
2379     mImpl->RetrieveDefaultInputStyle(style);
2380     mImpl->mModel->mLogicalModel->RetrieveStyle(styleIndex, style);
2381
2382     // Whether to add a new text color run.
2383     const bool addColorRun = (style.textColor != mImpl->mEventData->mInputStyle.textColor) && !mImpl->mEventData->mInputStyle.isDefaultColor;
2384
2385     // Whether to add a new font run.
2386     const bool addFontNameRun   = (style.familyName != mImpl->mEventData->mInputStyle.familyName) && mImpl->mEventData->mInputStyle.isFamilyDefined;
2387     const bool addFontWeightRun = (style.weight != mImpl->mEventData->mInputStyle.weight) && mImpl->mEventData->mInputStyle.isWeightDefined;
2388     const bool addFontWidthRun  = (style.width != mImpl->mEventData->mInputStyle.width) && mImpl->mEventData->mInputStyle.isWidthDefined;
2389     const bool addFontSlantRun  = (style.slant != mImpl->mEventData->mInputStyle.slant) && mImpl->mEventData->mInputStyle.isSlantDefined;
2390     const bool addFontSizeRun   = (style.size != mImpl->mEventData->mInputStyle.size) && mImpl->mEventData->mInputStyle.isSizeDefined;
2391
2392     // Add style runs.
2393     if(addColorRun)
2394     {
2395       const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
2396       mImpl->mModel->mLogicalModel->mColorRuns.Resize(numberOfRuns + 1u);
2397
2398       ColorRun& colorRun                       = *(mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns);
2399       colorRun.color                           = mImpl->mEventData->mInputStyle.textColor;
2400       colorRun.characterRun.characterIndex     = cursorIndex;
2401       colorRun.characterRun.numberOfCharacters = maxSizeOfNewText;
2402     }
2403
2404     if(addFontNameRun ||
2405        addFontWeightRun ||
2406        addFontWidthRun ||
2407        addFontSlantRun ||
2408        addFontSizeRun)
2409     {
2410       const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mFontDescriptionRuns.Count();
2411       mImpl->mModel->mLogicalModel->mFontDescriptionRuns.Resize(numberOfRuns + 1u);
2412
2413       FontDescriptionRun& fontDescriptionRun = *(mImpl->mModel->mLogicalModel->mFontDescriptionRuns.Begin() + numberOfRuns);
2414
2415       if(addFontNameRun)
2416       {
2417         fontDescriptionRun.familyLength = mImpl->mEventData->mInputStyle.familyName.size();
2418         fontDescriptionRun.familyName   = new char[fontDescriptionRun.familyLength];
2419         memcpy(fontDescriptionRun.familyName, mImpl->mEventData->mInputStyle.familyName.c_str(), fontDescriptionRun.familyLength);
2420         fontDescriptionRun.familyDefined = true;
2421
2422         // The memory allocated for the font family name is freed when the font description is removed from the logical model.
2423       }
2424
2425       if(addFontWeightRun)
2426       {
2427         fontDescriptionRun.weight        = mImpl->mEventData->mInputStyle.weight;
2428         fontDescriptionRun.weightDefined = true;
2429       }
2430
2431       if(addFontWidthRun)
2432       {
2433         fontDescriptionRun.width        = mImpl->mEventData->mInputStyle.width;
2434         fontDescriptionRun.widthDefined = true;
2435       }
2436
2437       if(addFontSlantRun)
2438       {
2439         fontDescriptionRun.slant        = mImpl->mEventData->mInputStyle.slant;
2440         fontDescriptionRun.slantDefined = true;
2441       }
2442
2443       if(addFontSizeRun)
2444       {
2445         fontDescriptionRun.size        = static_cast<PointSize26Dot6>(mImpl->mEventData->mInputStyle.size * 64.f);
2446         fontDescriptionRun.sizeDefined = true;
2447       }
2448
2449       fontDescriptionRun.characterRun.characterIndex     = cursorIndex;
2450       fontDescriptionRun.characterRun.numberOfCharacters = maxSizeOfNewText;
2451     }
2452
2453     // Insert at current cursor position.
2454     Vector<Character>& modifyText = mImpl->mModel->mLogicalModel->mText;
2455
2456     if(cursorIndex < numberOfCharactersInModel)
2457     {
2458       modifyText.Insert(modifyText.Begin() + cursorIndex, utf32Characters.Begin(), utf32Characters.Begin() + maxSizeOfNewText);
2459     }
2460     else
2461     {
2462       modifyText.Insert(modifyText.End(), utf32Characters.Begin(), utf32Characters.Begin() + maxSizeOfNewText);
2463     }
2464
2465     // Mark the first paragraph to be updated.
2466     if(Layout::Engine::SINGLE_LINE_BOX == mImpl->mLayoutEngine.GetLayout())
2467     {
2468       mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
2469       mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
2470       mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = numberOfCharactersInModel + maxSizeOfNewText;
2471       mImpl->mTextUpdateInfo.mClearAll                   = true;
2472     }
2473     else
2474     {
2475       mImpl->mTextUpdateInfo.mCharacterIndex = std::min(cursorIndex, mImpl->mTextUpdateInfo.mCharacterIndex);
2476       mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd += maxSizeOfNewText;
2477     }
2478
2479     // Update the cursor index.
2480     cursorIndex += maxSizeOfNewText;
2481
2482     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Inserted %d characters, new size %d new cursor %d\n", maxSizeOfNewText, mImpl->mModel->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition);
2483   }
2484
2485   if((0u == mImpl->mModel->mLogicalModel->mText.Count()) &&
2486      mImpl->IsPlaceholderAvailable())
2487   {
2488     // Show place-holder if empty after removing the pre-edit text
2489     ShowPlaceholderText();
2490     mImpl->mEventData->mUpdateCursorPosition = true;
2491     mImpl->ClearPreEditFlag();
2492   }
2493   else if(removedPrevious ||
2494           removedSelected ||
2495           (0 != utf32Characters.Count()))
2496   {
2497     // Queue an inserted event
2498     mImpl->QueueModifyEvent(ModifyEvent::TEXT_INSERTED);
2499
2500     mImpl->mEventData->mUpdateCursorPosition = true;
2501     if(removedSelected)
2502     {
2503       mImpl->mEventData->mScrollAfterDelete = true;
2504     }
2505     else
2506     {
2507       mImpl->mEventData->mScrollAfterUpdatePosition = true;
2508     }
2509   }
2510
2511   if(maxLengthReached)
2512   {
2513     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "MaxLengthReached (%d)\n", mImpl->mModel->mLogicalModel->mText.Count());
2514
2515     mImpl->ResetInputMethodContext();
2516
2517     if(NULL != mImpl->mEditableControlInterface)
2518     {
2519       // Do this last since it provides callbacks into application code
2520       mImpl->mEditableControlInterface->MaxLengthReached();
2521     }
2522   }
2523 }
2524
2525 void Controller::PasteText(const std::string& stringToPaste)
2526 {
2527   InsertText(stringToPaste, Text::Controller::COMMIT);
2528   mImpl->ChangeState(EventData::EDITING);
2529   mImpl->RequestRelayout();
2530
2531   if(NULL != mImpl->mEditableControlInterface)
2532   {
2533     // Do this last since it provides callbacks into application code
2534     mImpl->mEditableControlInterface->TextChanged(true);
2535   }
2536 }
2537
2538 bool Controller::RemoveText(int                  cursorOffset,
2539                             int                  numberOfCharacters,
2540                             UpdateInputStyleType type)
2541 {
2542   bool removed = false;
2543   bool removeAll = false;
2544
2545   if(NULL == mImpl->mEventData)
2546   {
2547     return removed;
2548   }
2549
2550   DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveText %p mText.Count() %d cursor %d cursorOffset %d numberOfCharacters %d\n", this, mImpl->mModel->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition, cursorOffset, numberOfCharacters);
2551
2552   if(!mImpl->IsShowingPlaceholderText())
2553   {
2554     // Delete at current cursor position
2555     Vector<Character>& currentText    = mImpl->mModel->mLogicalModel->mText;
2556     CharacterIndex&    oldCursorIndex = mImpl->mEventData->mPrimaryCursorPosition;
2557
2558     CharacterIndex cursorIndex = 0;
2559
2560     // Validate the cursor position & number of characters
2561     if((static_cast<int>(mImpl->mEventData->mPrimaryCursorPosition) + cursorOffset) >= 0)
2562     {
2563       cursorIndex = mImpl->mEventData->mPrimaryCursorPosition + cursorOffset;
2564     }
2565
2566     if((cursorIndex + numberOfCharacters) > currentText.Count())
2567     {
2568       numberOfCharacters = currentText.Count() - cursorIndex;
2569     }
2570
2571     if((cursorIndex == 0) && (currentText.Count() - numberOfCharacters == 0))
2572     {
2573       removeAll = true;
2574     }
2575
2576     if(mImpl->mEventData->mPreEditFlag || removeAll || // If the preedit flag is enabled, it means two (or more) of them came together i.e. when two keys have been pressed at the same time.
2577        ((cursorIndex + numberOfCharacters) <= mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters))
2578     {
2579       // Mark the paragraphs to be updated.
2580       if(Layout::Engine::SINGLE_LINE_BOX == mImpl->mLayoutEngine.GetLayout())
2581       {
2582         mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
2583         mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
2584         mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters - numberOfCharacters;
2585         mImpl->mTextUpdateInfo.mClearAll                   = true;
2586       }
2587       else
2588       {
2589         mImpl->mTextUpdateInfo.mCharacterIndex = std::min(cursorIndex, mImpl->mTextUpdateInfo.mCharacterIndex);
2590         mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove += numberOfCharacters;
2591       }
2592
2593       // Update the input style and remove the text's style before removing the text.
2594
2595       if(UPDATE_INPUT_STYLE == type)
2596       {
2597         // Keep a copy of the current input style.
2598         InputStyle currentInputStyle;
2599         currentInputStyle.Copy(mImpl->mEventData->mInputStyle);
2600
2601         // Set first the default input style.
2602         mImpl->RetrieveDefaultInputStyle(mImpl->mEventData->mInputStyle);
2603
2604         // Update the input style.
2605         mImpl->mModel->mLogicalModel->RetrieveStyle(cursorIndex, mImpl->mEventData->mInputStyle);
2606
2607         // Compare if the input style has changed.
2608         const bool hasInputStyleChanged = !currentInputStyle.Equal(mImpl->mEventData->mInputStyle);
2609
2610         if(hasInputStyleChanged)
2611         {
2612           const InputStyle::Mask styleChangedMask = currentInputStyle.GetInputStyleChangeMask(mImpl->mEventData->mInputStyle);
2613           // Queue the input style changed signal.
2614           mImpl->mEventData->mInputStyleChangedQueue.PushBack(styleChangedMask);
2615         }
2616       }
2617
2618       // If the number of current text and the number of characters to be deleted are same,
2619       // it means all texts should be removed and all Preedit variables should be initialized.
2620       if(removeAll)
2621       {
2622         mImpl->ClearPreEditFlag();
2623         mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = 0;
2624       }
2625
2626       // Updates the text style runs by removing characters. Runs with no characters are removed.
2627       mImpl->mModel->mLogicalModel->UpdateTextStyleRuns(cursorIndex, -numberOfCharacters);
2628
2629       // Remove the characters.
2630       Vector<Character>::Iterator first = currentText.Begin() + cursorIndex;
2631       Vector<Character>::Iterator last  = first + numberOfCharacters;
2632
2633       currentText.Erase(first, last);
2634
2635       // Cursor position retreat
2636       oldCursorIndex = cursorIndex;
2637
2638       mImpl->mEventData->mScrollAfterDelete = true;
2639
2640       if(EventData::INACTIVE == mImpl->mEventData->mState)
2641       {
2642         mImpl->ChangeState(EventData::EDITING);
2643       }
2644
2645       DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveText %p removed %d\n", this, numberOfCharacters);
2646       removeAll = false;
2647       removed = true;
2648     }
2649   }
2650
2651   return removed;
2652 }
2653
2654 bool Controller::RemoveSelectedText()
2655 {
2656   bool textRemoved(false);
2657
2658   if(EventData::SELECTING == mImpl->mEventData->mState)
2659   {
2660     std::string removedString;
2661     mImpl->RetrieveSelection(removedString, true);
2662
2663     if(!removedString.empty())
2664     {
2665       textRemoved = true;
2666       mImpl->ChangeState(EventData::EDITING);
2667     }
2668   }
2669
2670   return textRemoved;
2671 }
2672
2673 // private : Relayout.
2674
2675 bool Controller::DoRelayout(const Size&    size,
2676                             OperationsMask operationsRequired,
2677                             Size&          layoutSize)
2678 {
2679   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::DoRelayout %p size %f,%f\n", this, size.width, size.height);
2680   bool viewUpdated(false);
2681
2682   // Calculate the operations to be done.
2683   const OperationsMask operations = static_cast<OperationsMask>(mImpl->mOperationsPending & operationsRequired);
2684
2685   const CharacterIndex startIndex                  = mImpl->mTextUpdateInfo.mParagraphCharacterIndex;
2686   const Length         requestedNumberOfCharacters = mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters;
2687
2688   // Get the current layout size.
2689   layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize();
2690
2691   if(NO_OPERATION != (LAYOUT & operations))
2692   {
2693     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::DoRelayout LAYOUT & operations\n");
2694
2695     // Some vectors with data needed to layout and reorder may be void
2696     // after the first time the text has been laid out.
2697     // Fill the vectors again.
2698
2699     // Calculate the number of glyphs to layout.
2700     const Vector<GlyphIndex>& charactersToGlyph        = mImpl->mModel->mVisualModel->mCharactersToGlyph;
2701     const Vector<Length>&     glyphsPerCharacter       = mImpl->mModel->mVisualModel->mGlyphsPerCharacter;
2702     const GlyphIndex* const   charactersToGlyphBuffer  = charactersToGlyph.Begin();
2703     const Length* const       glyphsPerCharacterBuffer = glyphsPerCharacter.Begin();
2704
2705     const CharacterIndex lastIndex       = startIndex + ((requestedNumberOfCharacters > 0u) ? requestedNumberOfCharacters - 1u : 0u);
2706     const GlyphIndex     startGlyphIndex = mImpl->mTextUpdateInfo.mStartGlyphIndex;
2707
2708     // Make sure the index is not out of bound
2709     if(charactersToGlyph.Count() != glyphsPerCharacter.Count() ||
2710        requestedNumberOfCharacters > charactersToGlyph.Count() ||
2711        (lastIndex > charactersToGlyph.Count() && charactersToGlyph.Count() > 0u))
2712     {
2713       std::string currentText;
2714       GetText(currentText);
2715
2716       DALI_LOG_ERROR("Controller::DoRelayout: Attempting to access invalid buffer\n");
2717       DALI_LOG_ERROR("Current text is: %s\n", currentText.c_str());
2718       DALI_LOG_ERROR("startIndex: %u, lastIndex: %u, requestedNumberOfCharacters: %u, charactersToGlyph.Count = %lu, glyphsPerCharacter.Count = %lu\n", startIndex, lastIndex, requestedNumberOfCharacters, charactersToGlyph.Count(), glyphsPerCharacter.Count());
2719
2720       return false;
2721     }
2722
2723     const Length numberOfGlyphs      = (requestedNumberOfCharacters > 0u) ? *(charactersToGlyphBuffer + lastIndex) + *(glyphsPerCharacterBuffer + lastIndex) - startGlyphIndex : 0u;
2724     const Length totalNumberOfGlyphs = mImpl->mModel->mVisualModel->mGlyphs.Count();
2725
2726     if(0u == totalNumberOfGlyphs)
2727     {
2728       if(NO_OPERATION != (UPDATE_LAYOUT_SIZE & operations))
2729       {
2730         mImpl->mModel->mVisualModel->SetLayoutSize(Size::ZERO);
2731       }
2732
2733       // Nothing else to do if there is no glyphs.
2734       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::DoRelayout no glyphs, view updated true\n");
2735       return true;
2736     }
2737
2738     // Set the layout parameters.
2739     Layout::Parameters layoutParameters(size,
2740                                         mImpl->mModel);
2741
2742     // Resize the vector of positions to have the same size than the vector of glyphs.
2743     Vector<Vector2>& glyphPositions = mImpl->mModel->mVisualModel->mGlyphPositions;
2744     glyphPositions.Resize(totalNumberOfGlyphs);
2745
2746     // Whether the last character is a new paragraph character.
2747     const Character* const textBuffer                   = mImpl->mModel->mLogicalModel->mText.Begin();
2748     mImpl->mTextUpdateInfo.mIsLastCharacterNewParagraph = TextAbstraction::IsNewParagraph(*(textBuffer + (mImpl->mModel->mLogicalModel->mText.Count() - 1u)));
2749     layoutParameters.isLastNewParagraph                 = mImpl->mTextUpdateInfo.mIsLastCharacterNewParagraph;
2750
2751     // The initial glyph and the number of glyphs to layout.
2752     layoutParameters.startGlyphIndex        = startGlyphIndex;
2753     layoutParameters.numberOfGlyphs         = numberOfGlyphs;
2754     layoutParameters.startLineIndex         = mImpl->mTextUpdateInfo.mStartLineIndex;
2755     layoutParameters.estimatedNumberOfLines = mImpl->mTextUpdateInfo.mEstimatedNumberOfLines;
2756
2757     // Update the ellipsis
2758     bool elideTextEnabled = mImpl->mModel->mElideEnabled;
2759
2760     if(NULL != mImpl->mEventData)
2761     {
2762       if(mImpl->mEventData->mPlaceholderEllipsisFlag && mImpl->IsShowingPlaceholderText())
2763       {
2764         elideTextEnabled = mImpl->mEventData->mIsPlaceholderElideEnabled;
2765       }
2766       else if(EventData::INACTIVE != mImpl->mEventData->mState)
2767       {
2768         // Disable ellipsis when editing
2769         elideTextEnabled = false;
2770       }
2771
2772       // Reset the scroll position in inactive state
2773       if(elideTextEnabled && (mImpl->mEventData->mState == EventData::INACTIVE))
2774       {
2775         ResetScrollPosition();
2776       }
2777     }
2778
2779     // Update the visual model.
2780     bool isAutoScrollEnabled = mImpl->mIsAutoScrollEnabled;
2781     Size newLayoutSize;
2782     viewUpdated                 = mImpl->mLayoutEngine.LayoutText(layoutParameters,
2783                                                   newLayoutSize,
2784                                                   elideTextEnabled,
2785                                                   isAutoScrollEnabled);
2786     mImpl->mIsAutoScrollEnabled = isAutoScrollEnabled;
2787
2788     viewUpdated = viewUpdated || (newLayoutSize != layoutSize);
2789
2790     if(viewUpdated)
2791     {
2792       layoutSize = newLayoutSize;
2793
2794       if(NO_OPERATION != (UPDATE_DIRECTION & operations))
2795       {
2796         mImpl->mIsTextDirectionRTL = false;
2797       }
2798
2799       if((NO_OPERATION != (UPDATE_DIRECTION & operations)) && !mImpl->mModel->mVisualModel->mLines.Empty())
2800       {
2801         mImpl->mIsTextDirectionRTL = mImpl->mModel->mVisualModel->mLines[0u].direction;
2802       }
2803
2804       // Sets the layout size.
2805       if(NO_OPERATION != (UPDATE_LAYOUT_SIZE & operations))
2806       {
2807         mImpl->mModel->mVisualModel->SetLayoutSize(layoutSize);
2808       }
2809     } // view updated
2810   }
2811
2812   if(NO_OPERATION != (ALIGN & operations))
2813   {
2814     // The laid-out lines.
2815     Vector<LineRun>& lines = mImpl->mModel->mVisualModel->mLines;
2816
2817     CharacterIndex alignStartIndex                  = startIndex;
2818     Length         alignRequestedNumberOfCharacters = requestedNumberOfCharacters;
2819
2820     // the whole text needs to be full aligned.
2821     // If you do not do a full aligned, only the last line of the multiline input is aligned.
2822     if(mImpl->mEventData && mImpl->mEventData->mUpdateAlignment)
2823     {
2824       alignStartIndex                     = 0u;
2825       alignRequestedNumberOfCharacters    = mImpl->mModel->mLogicalModel->mText.Count();
2826       mImpl->mEventData->mUpdateAlignment = false;
2827     }
2828
2829     // Need to align with the control's size as the text may contain lines
2830     // starting either with left to right text or right to left.
2831     mImpl->mLayoutEngine.Align(size,
2832                                alignStartIndex,
2833                                alignRequestedNumberOfCharacters,
2834                                mImpl->mModel->mHorizontalAlignment,
2835                                lines,
2836                                mImpl->mModel->mAlignmentOffset,
2837                                mImpl->mLayoutDirection,
2838                                mImpl->mModel->mMatchSystemLanguageDirection);
2839
2840     viewUpdated = true;
2841   }
2842 #if defined(DEBUG_ENABLED)
2843   std::string currentText;
2844   GetText(currentText);
2845   DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::DoRelayout [%p] mImpl->mIsTextDirectionRTL[%s] [%s]\n", this, (mImpl->mIsTextDirectionRTL) ? "true" : "false", currentText.c_str());
2846 #endif
2847   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::DoRelayout, view updated %s\n", (viewUpdated ? "true" : "false"));
2848   return viewUpdated;
2849 }
2850
2851 void Controller::CalculateVerticalOffset(const Size& controlSize)
2852 {
2853   ModelPtr&       model                 = mImpl->mModel;
2854   VisualModelPtr& visualModel           = model->mVisualModel;
2855   Size            layoutSize            = mImpl->mModel->mVisualModel->GetLayoutSize();
2856   Size            oldLayoutSize         = layoutSize;
2857   float           offsetY               = 0.f;
2858   bool            needRecalc            = false;
2859   float           defaultFontLineHeight = mImpl->GetDefaultFontLineHeight();
2860
2861   if(fabsf(layoutSize.height) < Math::MACHINE_EPSILON_1000)
2862   {
2863     // Get the line height of the default font.
2864     layoutSize.height = defaultFontLineHeight;
2865   }
2866
2867   // Whether the text control is editable
2868   const bool isEditable = NULL != mImpl->mEventData;
2869   if(isEditable && layoutSize.height != defaultFontLineHeight)
2870   {
2871     // This code prevents the wrong positioning of cursor when the layout size is bigger/smaller than defaultFontLineHeight.
2872     // This situation occurs when the size of placeholder text is different from the default text.
2873     layoutSize.height = defaultFontLineHeight;
2874     needRecalc        = true;
2875   }
2876
2877   switch(mImpl->mModel->mVerticalAlignment)
2878   {
2879     case VerticalAlignment::TOP:
2880     {
2881       mImpl->mModel->mScrollPosition.y = 0.f;
2882       offsetY                          = 0.f;
2883       break;
2884     }
2885     case VerticalAlignment::CENTER:
2886     {
2887       mImpl->mModel->mScrollPosition.y = floorf(0.5f * (controlSize.height - layoutSize.height)); // try to avoid pixel alignment.
2888       if(needRecalc) offsetY = floorf(0.5f * (layoutSize.height - oldLayoutSize.height));
2889       break;
2890     }
2891     case VerticalAlignment::BOTTOM:
2892     {
2893       mImpl->mModel->mScrollPosition.y = controlSize.height - layoutSize.height;
2894       if(needRecalc) offsetY = layoutSize.height - oldLayoutSize.height;
2895       break;
2896     }
2897   }
2898
2899   if(needRecalc)
2900   {
2901     // Update glyphPositions according to recalculation.
2902     const Length     positionCount  = visualModel->mGlyphPositions.Count();
2903     Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
2904     for(Length index = 0u; index < positionCount; index++)
2905     {
2906       glyphPositions[index].y += offsetY;
2907     }
2908   }
2909 }
2910
2911 // private : Events.
2912
2913 void Controller::ProcessModifyEvents()
2914 {
2915   EventHandler::ProcessModifyEvents(*this);
2916 }
2917
2918 void Controller::TextReplacedEvent()
2919 {
2920   EventHandler::TextReplacedEvent(*this);
2921 }
2922
2923 void Controller::TextInsertedEvent()
2924 {
2925   EventHandler::TextInsertedEvent(*this);
2926 }
2927
2928 void Controller::TextDeletedEvent()
2929 {
2930   EventHandler::TextDeletedEvent(*this);
2931 }
2932
2933 bool Controller::DeleteEvent(int keyCode)
2934 {
2935   return EventHandler::DeleteEvent(*this, keyCode);
2936 }
2937
2938 // private : Helpers.
2939
2940 void Controller::ResetText()
2941 {
2942   // Reset buffers.
2943   mImpl->mModel->mLogicalModel->mText.Clear();
2944
2945   // Reset the embedded images buffer.
2946   mImpl->mModel->mLogicalModel->ClearEmbeddedImages();
2947
2948   // We have cleared everything including the placeholder-text
2949   mImpl->PlaceholderCleared();
2950
2951   mImpl->mTextUpdateInfo.mCharacterIndex             = 0u;
2952   mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
2953   mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = 0u;
2954
2955   // Clear any previous text.
2956   mImpl->mTextUpdateInfo.mClearAll = true;
2957
2958   // The natural size needs to be re-calculated.
2959   mImpl->mRecalculateNaturalSize = true;
2960
2961   // The text direction needs to be updated.
2962   mImpl->mUpdateTextDirection = true;
2963
2964   // Apply modifications to the model
2965   mImpl->mOperationsPending = ALL_OPERATIONS;
2966 }
2967
2968 void Controller::ShowPlaceholderText()
2969 {
2970   if(mImpl->IsPlaceholderAvailable())
2971   {
2972     DALI_ASSERT_DEBUG(mImpl->mEventData && "No placeholder text available");
2973
2974     if(NULL == mImpl->mEventData)
2975     {
2976       return;
2977     }
2978
2979     mImpl->mEventData->mIsShowingPlaceholderText = true;
2980
2981     // Disable handles when showing place-holder text
2982     mImpl->mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
2983     mImpl->mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
2984     mImpl->mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
2985
2986     const char* text(NULL);
2987     size_t      size(0);
2988
2989     // TODO - Switch Placeholder text when changing state
2990     if((EventData::INACTIVE != mImpl->mEventData->mState) &&
2991        (0u != mImpl->mEventData->mPlaceholderTextActive.c_str()))
2992     {
2993       text = mImpl->mEventData->mPlaceholderTextActive.c_str();
2994       size = mImpl->mEventData->mPlaceholderTextActive.size();
2995     }
2996     else
2997     {
2998       text = mImpl->mEventData->mPlaceholderTextInactive.c_str();
2999       size = mImpl->mEventData->mPlaceholderTextInactive.size();
3000     }
3001
3002     mImpl->mTextUpdateInfo.mCharacterIndex             = 0u;
3003     mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
3004
3005     // Reset model for showing placeholder.
3006     mImpl->mModel->mLogicalModel->mText.Clear();
3007     mImpl->mModel->mVisualModel->SetTextColor(mImpl->mEventData->mPlaceholderTextColor);
3008
3009     // Convert text into UTF-32
3010     Vector<Character>& utf32Characters = mImpl->mModel->mLogicalModel->mText;
3011     utf32Characters.Resize(size);
3012
3013     // This is a bit horrible but std::string returns a (signed) char*
3014     const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(text);
3015
3016     // Transform a text array encoded in utf8 into an array encoded in utf32.
3017     // It returns the actual number of characters.
3018     const Length characterCount = Utf8ToUtf32(utf8, size, utf32Characters.Begin());
3019     utf32Characters.Resize(characterCount);
3020
3021     // The characters to be added.
3022     mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = characterCount;
3023
3024     // Reset the cursor position
3025     mImpl->mEventData->mPrimaryCursorPosition = 0;
3026
3027     // The natural size needs to be re-calculated.
3028     mImpl->mRecalculateNaturalSize = true;
3029
3030     // The text direction needs to be updated.
3031     mImpl->mUpdateTextDirection = true;
3032
3033     // Apply modifications to the model
3034     mImpl->mOperationsPending = ALL_OPERATIONS;
3035
3036     // Update the rest of the model during size negotiation
3037     mImpl->QueueModifyEvent(ModifyEvent::TEXT_REPLACED);
3038   }
3039 }
3040
3041 void Controller::ClearFontData()
3042 {
3043   if(mImpl->mFontDefaults)
3044   {
3045     mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
3046   }
3047
3048   // Set flags to update the model.
3049   mImpl->mTextUpdateInfo.mCharacterIndex             = 0u;
3050   mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
3051   mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = mImpl->mModel->mLogicalModel->mText.Count();
3052
3053   mImpl->mTextUpdateInfo.mClearAll           = true;
3054   mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
3055   mImpl->mRecalculateNaturalSize             = true;
3056
3057   mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
3058                                                           VALIDATE_FONTS |
3059                                                           SHAPE_TEXT |
3060                                                           BIDI_INFO |
3061                                                           GET_GLYPH_METRICS |
3062                                                           LAYOUT |
3063                                                           UPDATE_LAYOUT_SIZE |
3064                                                           REORDER |
3065                                                           ALIGN);
3066 }
3067
3068 void Controller::ClearStyleData()
3069 {
3070   mImpl->mModel->mLogicalModel->mColorRuns.Clear();
3071   mImpl->mModel->mLogicalModel->ClearFontDescriptionRuns();
3072 }
3073
3074 void Controller::ResetCursorPosition(CharacterIndex cursorIndex)
3075 {
3076   // Reset the cursor position
3077   if(NULL != mImpl->mEventData)
3078   {
3079     mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
3080
3081     // Update the cursor if it's in editing mode.
3082     if(EventData::IsEditingState(mImpl->mEventData->mState))
3083     {
3084       mImpl->mEventData->mUpdateCursorPosition = true;
3085     }
3086   }
3087 }
3088
3089 void Controller::ResetScrollPosition()
3090 {
3091   if(NULL != mImpl->mEventData)
3092   {
3093     // Reset the scroll position.
3094     mImpl->mModel->mScrollPosition                = Vector2::ZERO;
3095     mImpl->mEventData->mScrollAfterUpdatePosition = true;
3096   }
3097 }
3098
3099 void Controller::SetControlInterface(ControlInterface* controlInterface)
3100 {
3101   mImpl->mControlInterface = controlInterface;
3102 }
3103
3104 bool Controller::ShouldClearFocusOnEscape() const
3105 {
3106   return mImpl->mShouldClearFocusOnEscape;
3107 }
3108
3109 Actor Controller::CreateBackgroundActor()
3110 {
3111   return mImpl->CreateBackgroundActor();
3112 }
3113
3114 // private : Private contructors & copy operator.
3115
3116 Controller::Controller()
3117 : Controller(nullptr, nullptr, nullptr)
3118 {
3119 }
3120
3121 Controller::Controller(ControlInterface* controlInterface)
3122 : Controller(controlInterface, nullptr, nullptr)
3123 {
3124 }
3125
3126 Controller::Controller(ControlInterface*           controlInterface,
3127                        EditableControlInterface*   editableControlInterface,
3128                        SelectableControlInterface* selectableControlInterface)
3129 : mImpl(new Controller::Impl(controlInterface, editableControlInterface, selectableControlInterface))
3130 {
3131 }
3132
3133 // The copy constructor and operator are left unimplemented.
3134
3135 // protected : Destructor.
3136
3137 Controller::~Controller()
3138 {
3139   delete mImpl;
3140 }
3141
3142 } // namespace Text
3143
3144 } // namespace Toolkit
3145
3146 } // namespace Dali