[Tizen] Code clean up
[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   // TODO: At the moment the underline runs are only for pre-edit.
2283   mImpl->mModel->mVisualModel->mUnderlineRuns.Clear();
2284
2285   // Remove the previous InputMethodContext pre-edit.
2286   if(mImpl->mEventData->mPreEditFlag && (0u != mImpl->mEventData->mPreEditLength))
2287   {
2288     removedPrevious = RemoveText(-static_cast<int>(mImpl->mEventData->mPrimaryCursorPosition - mImpl->mEventData->mPreEditStartPosition),
2289                                  mImpl->mEventData->mPreEditLength,
2290                                  DONT_UPDATE_INPUT_STYLE);
2291
2292     mImpl->mEventData->mPrimaryCursorPosition = mImpl->mEventData->mPreEditStartPosition;
2293     mImpl->mEventData->mPreEditLength         = 0u;
2294   }
2295   else
2296   {
2297     // Remove the previous Selection.
2298     removedSelected = RemoveSelectedText();
2299   }
2300
2301   Vector<Character> utf32Characters;
2302   Length            characterCount = 0u;
2303
2304   if(!text.empty())
2305   {
2306     //  Convert text into UTF-32
2307     utf32Characters.Resize(text.size());
2308
2309     // This is a bit horrible but std::string returns a (signed) char*
2310     const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(text.c_str());
2311
2312     // Transform a text array encoded in utf8 into an array encoded in utf32.
2313     // It returns the actual number of characters.
2314     characterCount = Utf8ToUtf32(utf8, text.size(), utf32Characters.Begin());
2315     utf32Characters.Resize(characterCount);
2316
2317     DALI_ASSERT_DEBUG(text.size() >= utf32Characters.Count() && "Invalid UTF32 conversion length");
2318     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "UTF8 size %d, UTF32 size %d\n", text.size(), utf32Characters.Count());
2319
2320     // Play the input text with the TTS player.
2321     Dali::TtsPlayer player = Dali::TtsPlayer::Get(Dali::TtsPlayer::SCREEN_READER);
2322     if(player)
2323     {
2324       if(type == COMMIT && mImpl->mEventData->mPreEditToCommitFlag)
2325       {
2326         if(characterCount > 1u)
2327         {
2328           std::string ttsText = text;
2329           if(text.length() > mImpl->mEventData->mPreEditTextLength)
2330           {
2331             ttsText = text.substr(mImpl->mEventData->mPreEditTextLength);
2332           }
2333           player.Play(ttsText);
2334         }
2335       }
2336       else
2337       {
2338         player.Play(text);
2339       }
2340     }
2341   }
2342
2343   // PRE_EDIT type empty text is inserted before the preedit input is converted to commit.
2344   if(text.empty() && type == PRE_EDIT)
2345   {
2346     mImpl->mEventData->mPreEditToCommitFlag = true;
2347   }
2348
2349   if(0u != utf32Characters.Count()) // Check if Utf8ToUtf32 conversion succeeded
2350   {
2351     // The placeholder text is no longer needed
2352     if(mImpl->IsShowingPlaceholderText())
2353     {
2354       ResetText();
2355     }
2356
2357     mImpl->ChangeState(EventData::EDITING);
2358     mImpl->mEventData->mPreEditToCommitFlag = false;
2359
2360     // Handle the InputMethodContext (predicitive text) state changes
2361     if(COMMIT == type)
2362     {
2363       // InputMethodContext is no longer handling key-events
2364       mImpl->ClearPreEditFlag();
2365     }
2366     else // PRE_EDIT
2367     {
2368       if(!mImpl->mEventData->mPreEditFlag)
2369       {
2370         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Entered PreEdit state\n");
2371
2372         // Record the start of the pre-edit text
2373         mImpl->mEventData->mPreEditStartPosition = mImpl->mEventData->mPrimaryCursorPosition;
2374       }
2375
2376       mImpl->mEventData->mPreEditLength     = utf32Characters.Count();
2377       mImpl->mEventData->mPreEditTextLength = text.length();
2378       mImpl->mEventData->mPreEditFlag       = true;
2379
2380       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "mPreEditStartPosition %d mPreEditLength %d\n", mImpl->mEventData->mPreEditStartPosition, mImpl->mEventData->mPreEditLength);
2381     }
2382
2383     const Length numberOfCharactersInModel = mImpl->mModel->mLogicalModel->mText.Count();
2384
2385     // Restrict new text to fit within Maximum characters setting.
2386     Length maxSizeOfNewText = std::min((mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel), characterCount);
2387     maxLengthReached        = (characterCount > maxSizeOfNewText);
2388
2389     // The cursor position.
2390     CharacterIndex& cursorIndex = mImpl->mEventData->mPrimaryCursorPosition;
2391
2392     // Update the text's style.
2393
2394     // Updates the text style runs by adding characters.
2395     mImpl->mModel->mLogicalModel->UpdateTextStyleRuns(cursorIndex, maxSizeOfNewText);
2396
2397     // Get the character index from the cursor index.
2398     const CharacterIndex styleIndex = (cursorIndex > 0u) ? cursorIndex - 1u : 0u;
2399
2400     // Retrieve the text's style for the given index.
2401     InputStyle style;
2402     mImpl->RetrieveDefaultInputStyle(style);
2403     mImpl->mModel->mLogicalModel->RetrieveStyle(styleIndex, style);
2404
2405     // Whether to add a new text color run.
2406     const bool addColorRun = (style.textColor != mImpl->mEventData->mInputStyle.textColor) && !mImpl->mEventData->mInputStyle.isDefaultColor;
2407
2408     // Whether to add a new font run.
2409     const bool addFontNameRun   = (style.familyName != mImpl->mEventData->mInputStyle.familyName) && mImpl->mEventData->mInputStyle.isFamilyDefined;
2410     const bool addFontWeightRun = (style.weight != mImpl->mEventData->mInputStyle.weight) && mImpl->mEventData->mInputStyle.isWeightDefined;
2411     const bool addFontWidthRun  = (style.width != mImpl->mEventData->mInputStyle.width) && mImpl->mEventData->mInputStyle.isWidthDefined;
2412     const bool addFontSlantRun  = (style.slant != mImpl->mEventData->mInputStyle.slant) && mImpl->mEventData->mInputStyle.isSlantDefined;
2413     const bool addFontSizeRun   = (style.size != mImpl->mEventData->mInputStyle.size) && mImpl->mEventData->mInputStyle.isSizeDefined;
2414
2415     // Add style runs.
2416     if(addColorRun)
2417     {
2418       const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
2419       mImpl->mModel->mLogicalModel->mColorRuns.Resize(numberOfRuns + 1u);
2420
2421       ColorRun& colorRun                       = *(mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns);
2422       colorRun.color                           = mImpl->mEventData->mInputStyle.textColor;
2423       colorRun.characterRun.characterIndex     = cursorIndex;
2424       colorRun.characterRun.numberOfCharacters = maxSizeOfNewText;
2425     }
2426
2427     if(addFontNameRun ||
2428        addFontWeightRun ||
2429        addFontWidthRun ||
2430        addFontSlantRun ||
2431        addFontSizeRun)
2432     {
2433       const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mFontDescriptionRuns.Count();
2434       mImpl->mModel->mLogicalModel->mFontDescriptionRuns.Resize(numberOfRuns + 1u);
2435
2436       FontDescriptionRun& fontDescriptionRun = *(mImpl->mModel->mLogicalModel->mFontDescriptionRuns.Begin() + numberOfRuns);
2437
2438       if(addFontNameRun)
2439       {
2440         fontDescriptionRun.familyLength = mImpl->mEventData->mInputStyle.familyName.size();
2441         fontDescriptionRun.familyName   = new char[fontDescriptionRun.familyLength];
2442         memcpy(fontDescriptionRun.familyName, mImpl->mEventData->mInputStyle.familyName.c_str(), fontDescriptionRun.familyLength);
2443         fontDescriptionRun.familyDefined = true;
2444
2445         // The memory allocated for the font family name is freed when the font description is removed from the logical model.
2446       }
2447
2448       if(addFontWeightRun)
2449       {
2450         fontDescriptionRun.weight        = mImpl->mEventData->mInputStyle.weight;
2451         fontDescriptionRun.weightDefined = true;
2452       }
2453
2454       if(addFontWidthRun)
2455       {
2456         fontDescriptionRun.width        = mImpl->mEventData->mInputStyle.width;
2457         fontDescriptionRun.widthDefined = true;
2458       }
2459
2460       if(addFontSlantRun)
2461       {
2462         fontDescriptionRun.slant        = mImpl->mEventData->mInputStyle.slant;
2463         fontDescriptionRun.slantDefined = true;
2464       }
2465
2466       if(addFontSizeRun)
2467       {
2468         fontDescriptionRun.size        = static_cast<PointSize26Dot6>(mImpl->mEventData->mInputStyle.size * 64.f);
2469         fontDescriptionRun.sizeDefined = true;
2470       }
2471
2472       fontDescriptionRun.characterRun.characterIndex     = cursorIndex;
2473       fontDescriptionRun.characterRun.numberOfCharacters = maxSizeOfNewText;
2474     }
2475
2476     // Insert at current cursor position.
2477     Vector<Character>& modifyText = mImpl->mModel->mLogicalModel->mText;
2478
2479     if(cursorIndex < numberOfCharactersInModel)
2480     {
2481       modifyText.Insert(modifyText.Begin() + cursorIndex, utf32Characters.Begin(), utf32Characters.Begin() + maxSizeOfNewText);
2482     }
2483     else
2484     {
2485       modifyText.Insert(modifyText.End(), utf32Characters.Begin(), utf32Characters.Begin() + maxSizeOfNewText);
2486     }
2487
2488     // Mark the first paragraph to be updated.
2489     if(Layout::Engine::SINGLE_LINE_BOX == mImpl->mLayoutEngine.GetLayout())
2490     {
2491       mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
2492       mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
2493       mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = numberOfCharactersInModel + maxSizeOfNewText;
2494       mImpl->mTextUpdateInfo.mClearAll                   = true;
2495     }
2496     else
2497     {
2498       mImpl->mTextUpdateInfo.mCharacterIndex = std::min(cursorIndex, mImpl->mTextUpdateInfo.mCharacterIndex);
2499       mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd += maxSizeOfNewText;
2500     }
2501
2502     // Update the cursor index.
2503     cursorIndex += maxSizeOfNewText;
2504
2505     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);
2506   }
2507
2508   if((0u == mImpl->mModel->mLogicalModel->mText.Count()) &&
2509      mImpl->IsPlaceholderAvailable())
2510   {
2511     // Show place-holder if empty after removing the pre-edit text
2512     ShowPlaceholderText();
2513     mImpl->mEventData->mUpdateCursorPosition = true;
2514     mImpl->ClearPreEditFlag();
2515   }
2516   else if(removedPrevious ||
2517           removedSelected ||
2518           (0 != utf32Characters.Count()))
2519   {
2520     // Queue an inserted event
2521     mImpl->QueueModifyEvent(ModifyEvent::TEXT_INSERTED);
2522
2523     mImpl->mEventData->mUpdateCursorPosition = true;
2524     if(removedSelected)
2525     {
2526       mImpl->mEventData->mScrollAfterDelete = true;
2527     }
2528     else
2529     {
2530       mImpl->mEventData->mScrollAfterUpdatePosition = true;
2531     }
2532   }
2533
2534   if(maxLengthReached)
2535   {
2536     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "MaxLengthReached (%d)\n", mImpl->mModel->mLogicalModel->mText.Count());
2537
2538     mImpl->ResetInputMethodContext();
2539
2540     if(NULL != mImpl->mEditableControlInterface)
2541     {
2542       // Do this last since it provides callbacks into application code
2543       mImpl->mEditableControlInterface->MaxLengthReached();
2544     }
2545   }
2546 }
2547
2548 void Controller::PasteText(const std::string& stringToPaste)
2549 {
2550   InsertText(stringToPaste, Text::Controller::COMMIT);
2551   mImpl->ChangeState(EventData::EDITING);
2552   mImpl->RequestRelayout();
2553
2554   if(NULL != mImpl->mEditableControlInterface)
2555   {
2556     // Do this last since it provides callbacks into application code
2557     mImpl->mEditableControlInterface->TextChanged(true);
2558   }
2559 }
2560
2561 bool Controller::RemoveText(int                  cursorOffset,
2562                             int                  numberOfCharacters,
2563                             UpdateInputStyleType type)
2564 {
2565   bool removed = false;
2566   bool removeAll = false;
2567
2568   if(NULL == mImpl->mEventData)
2569   {
2570     return removed;
2571   }
2572
2573   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);
2574
2575   if(!mImpl->IsShowingPlaceholderText())
2576   {
2577     // Delete at current cursor position
2578     Vector<Character>& currentText    = mImpl->mModel->mLogicalModel->mText;
2579     CharacterIndex&    oldCursorIndex = mImpl->mEventData->mPrimaryCursorPosition;
2580
2581     CharacterIndex cursorIndex = 0;
2582
2583     // Validate the cursor position & number of characters
2584     if((static_cast<int>(mImpl->mEventData->mPrimaryCursorPosition) + cursorOffset) >= 0)
2585     {
2586       cursorIndex = mImpl->mEventData->mPrimaryCursorPosition + cursorOffset;
2587     }
2588
2589     if((cursorIndex + numberOfCharacters) > currentText.Count())
2590     {
2591       numberOfCharacters = currentText.Count() - cursorIndex;
2592     }
2593
2594     if((cursorIndex == 0) && (currentText.Count() - numberOfCharacters == 0))
2595     {
2596       removeAll = true;
2597     }
2598
2599     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.
2600        ((cursorIndex + numberOfCharacters) <= mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters))
2601     {
2602       // Mark the paragraphs to be updated.
2603       if(Layout::Engine::SINGLE_LINE_BOX == mImpl->mLayoutEngine.GetLayout())
2604       {
2605         mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
2606         mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
2607         mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters - numberOfCharacters;
2608         mImpl->mTextUpdateInfo.mClearAll                   = true;
2609       }
2610       else
2611       {
2612         mImpl->mTextUpdateInfo.mCharacterIndex = std::min(cursorIndex, mImpl->mTextUpdateInfo.mCharacterIndex);
2613         mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove += numberOfCharacters;
2614       }
2615
2616       // Update the input style and remove the text's style before removing the text.
2617
2618       if(UPDATE_INPUT_STYLE == type)
2619       {
2620         // Keep a copy of the current input style.
2621         InputStyle currentInputStyle;
2622         currentInputStyle.Copy(mImpl->mEventData->mInputStyle);
2623
2624         // Set first the default input style.
2625         mImpl->RetrieveDefaultInputStyle(mImpl->mEventData->mInputStyle);
2626
2627         // Update the input style.
2628         mImpl->mModel->mLogicalModel->RetrieveStyle(cursorIndex, mImpl->mEventData->mInputStyle);
2629
2630         // Compare if the input style has changed.
2631         const bool hasInputStyleChanged = !currentInputStyle.Equal(mImpl->mEventData->mInputStyle);
2632
2633         if(hasInputStyleChanged)
2634         {
2635           const InputStyle::Mask styleChangedMask = currentInputStyle.GetInputStyleChangeMask(mImpl->mEventData->mInputStyle);
2636           // Queue the input style changed signal.
2637           mImpl->mEventData->mInputStyleChangedQueue.PushBack(styleChangedMask);
2638         }
2639       }
2640
2641       // If the number of current text and the number of characters to be deleted are same,
2642       // it means all texts should be removed and all Preedit variables should be initialized.
2643       if(removeAll)
2644       {
2645         mImpl->ClearPreEditFlag();
2646         mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = 0;
2647       }
2648
2649       // Updates the text style runs by removing characters. Runs with no characters are removed.
2650       mImpl->mModel->mLogicalModel->UpdateTextStyleRuns(cursorIndex, -numberOfCharacters);
2651
2652       // Remove the characters.
2653       Vector<Character>::Iterator first = currentText.Begin() + cursorIndex;
2654       Vector<Character>::Iterator last  = first + numberOfCharacters;
2655
2656       currentText.Erase(first, last);
2657
2658       // Cursor position retreat
2659       oldCursorIndex = cursorIndex;
2660
2661       mImpl->mEventData->mScrollAfterDelete = true;
2662
2663       if(EventData::INACTIVE == mImpl->mEventData->mState)
2664       {
2665         mImpl->ChangeState(EventData::EDITING);
2666       }
2667
2668       DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveText %p removed %d\n", this, numberOfCharacters);
2669       removeAll = false;
2670       removed = true;
2671     }
2672   }
2673
2674   return removed;
2675 }
2676
2677 bool Controller::RemoveSelectedText()
2678 {
2679   bool textRemoved(false);
2680
2681   if(EventData::SELECTING == mImpl->mEventData->mState)
2682   {
2683     std::string removedString;
2684     mImpl->RetrieveSelection(removedString, true);
2685
2686     if(!removedString.empty())
2687     {
2688       textRemoved = true;
2689       mImpl->ChangeState(EventData::EDITING);
2690     }
2691   }
2692
2693   return textRemoved;
2694 }
2695
2696 // private : Relayout.
2697
2698 bool Controller::DoRelayout(const Size&    size,
2699                             OperationsMask operationsRequired,
2700                             Size&          layoutSize)
2701 {
2702   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::DoRelayout %p size %f,%f\n", this, size.width, size.height);
2703   bool viewUpdated(false);
2704
2705   // Calculate the operations to be done.
2706   const OperationsMask operations = static_cast<OperationsMask>(mImpl->mOperationsPending & operationsRequired);
2707
2708   const CharacterIndex startIndex                  = mImpl->mTextUpdateInfo.mParagraphCharacterIndex;
2709   const Length         requestedNumberOfCharacters = mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters;
2710
2711   // Get the current layout size.
2712   layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize();
2713
2714   if(NO_OPERATION != (LAYOUT & operations))
2715   {
2716     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::DoRelayout LAYOUT & operations\n");
2717
2718     // Some vectors with data needed to layout and reorder may be void
2719     // after the first time the text has been laid out.
2720     // Fill the vectors again.
2721
2722     // Calculate the number of glyphs to layout.
2723     const Vector<GlyphIndex>& charactersToGlyph        = mImpl->mModel->mVisualModel->mCharactersToGlyph;
2724     const Vector<Length>&     glyphsPerCharacter       = mImpl->mModel->mVisualModel->mGlyphsPerCharacter;
2725     const GlyphIndex* const   charactersToGlyphBuffer  = charactersToGlyph.Begin();
2726     const Length* const       glyphsPerCharacterBuffer = glyphsPerCharacter.Begin();
2727
2728     const CharacterIndex lastIndex       = startIndex + ((requestedNumberOfCharacters > 0u) ? requestedNumberOfCharacters - 1u : 0u);
2729     const GlyphIndex     startGlyphIndex = mImpl->mTextUpdateInfo.mStartGlyphIndex;
2730
2731     // Make sure the index is not out of bound
2732     if(charactersToGlyph.Count() != glyphsPerCharacter.Count() ||
2733        requestedNumberOfCharacters > charactersToGlyph.Count() ||
2734        (lastIndex > charactersToGlyph.Count() && charactersToGlyph.Count() > 0u))
2735     {
2736       std::string currentText;
2737       GetText(currentText);
2738
2739       DALI_LOG_ERROR("Controller::DoRelayout: Attempting to access invalid buffer\n");
2740       DALI_LOG_ERROR("Current text is: %s\n", currentText.c_str());
2741       DALI_LOG_ERROR("startIndex: %u, lastIndex: %u, requestedNumberOfCharacters: %u, charactersToGlyph.Count = %lu, glyphsPerCharacter.Count = %lu\n", startIndex, lastIndex, requestedNumberOfCharacters, charactersToGlyph.Count(), glyphsPerCharacter.Count());
2742
2743       return false;
2744     }
2745
2746     const Length numberOfGlyphs      = (requestedNumberOfCharacters > 0u) ? *(charactersToGlyphBuffer + lastIndex) + *(glyphsPerCharacterBuffer + lastIndex) - startGlyphIndex : 0u;
2747     const Length totalNumberOfGlyphs = mImpl->mModel->mVisualModel->mGlyphs.Count();
2748
2749     if(0u == totalNumberOfGlyphs)
2750     {
2751       if(NO_OPERATION != (UPDATE_LAYOUT_SIZE & operations))
2752       {
2753         mImpl->mModel->mVisualModel->SetLayoutSize(Size::ZERO);
2754       }
2755
2756       // Nothing else to do if there is no glyphs.
2757       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::DoRelayout no glyphs, view updated true\n");
2758       return true;
2759     }
2760
2761     // Set the layout parameters.
2762     Layout::Parameters layoutParameters(size,
2763                                         mImpl->mModel);
2764
2765     // Resize the vector of positions to have the same size than the vector of glyphs.
2766     Vector<Vector2>& glyphPositions = mImpl->mModel->mVisualModel->mGlyphPositions;
2767     glyphPositions.Resize(totalNumberOfGlyphs);
2768
2769     // Whether the last character is a new paragraph character.
2770     const Character* const textBuffer                   = mImpl->mModel->mLogicalModel->mText.Begin();
2771     mImpl->mTextUpdateInfo.mIsLastCharacterNewParagraph = TextAbstraction::IsNewParagraph(*(textBuffer + (mImpl->mModel->mLogicalModel->mText.Count() - 1u)));
2772     layoutParameters.isLastNewParagraph                 = mImpl->mTextUpdateInfo.mIsLastCharacterNewParagraph;
2773
2774     // The initial glyph and the number of glyphs to layout.
2775     layoutParameters.startGlyphIndex        = startGlyphIndex;
2776     layoutParameters.numberOfGlyphs         = numberOfGlyphs;
2777     layoutParameters.startLineIndex         = mImpl->mTextUpdateInfo.mStartLineIndex;
2778     layoutParameters.estimatedNumberOfLines = mImpl->mTextUpdateInfo.mEstimatedNumberOfLines;
2779
2780     // Update the ellipsis
2781     bool elideTextEnabled = mImpl->mModel->mElideEnabled;
2782
2783     if(NULL != mImpl->mEventData)
2784     {
2785       if(mImpl->mEventData->mPlaceholderEllipsisFlag && mImpl->IsShowingPlaceholderText())
2786       {
2787         elideTextEnabled = mImpl->mEventData->mIsPlaceholderElideEnabled;
2788       }
2789       else if(EventData::INACTIVE != mImpl->mEventData->mState)
2790       {
2791         // Disable ellipsis when editing
2792         elideTextEnabled = false;
2793       }
2794
2795       // Reset the scroll position in inactive state
2796       if(elideTextEnabled && (mImpl->mEventData->mState == EventData::INACTIVE))
2797       {
2798         ResetScrollPosition();
2799       }
2800     }
2801
2802     // Update the visual model.
2803     bool isAutoScrollEnabled = mImpl->mIsAutoScrollEnabled;
2804     Size newLayoutSize;
2805     viewUpdated                 = mImpl->mLayoutEngine.LayoutText(layoutParameters,
2806                                                   newLayoutSize,
2807                                                   elideTextEnabled,
2808                                                   isAutoScrollEnabled);
2809     mImpl->mIsAutoScrollEnabled = isAutoScrollEnabled;
2810
2811     viewUpdated = viewUpdated || (newLayoutSize != layoutSize);
2812
2813     if(viewUpdated)
2814     {
2815       layoutSize = newLayoutSize;
2816
2817       if(NO_OPERATION != (UPDATE_DIRECTION & operations))
2818       {
2819         mImpl->mIsTextDirectionRTL = false;
2820       }
2821
2822       if((NO_OPERATION != (UPDATE_DIRECTION & operations)) && !mImpl->mModel->mVisualModel->mLines.Empty())
2823       {
2824         mImpl->mIsTextDirectionRTL = mImpl->mModel->mVisualModel->mLines[0u].direction;
2825       }
2826
2827       // Sets the layout size.
2828       if(NO_OPERATION != (UPDATE_LAYOUT_SIZE & operations))
2829       {
2830         mImpl->mModel->mVisualModel->SetLayoutSize(layoutSize);
2831       }
2832     } // view updated
2833   }
2834
2835   if(NO_OPERATION != (ALIGN & operations))
2836   {
2837     // The laid-out lines.
2838     Vector<LineRun>& lines = mImpl->mModel->mVisualModel->mLines;
2839
2840     CharacterIndex alignStartIndex                  = startIndex;
2841     Length         alignRequestedNumberOfCharacters = requestedNumberOfCharacters;
2842
2843     // the whole text needs to be full aligned.
2844     // If you do not do a full aligned, only the last line of the multiline input is aligned.
2845     if(mImpl->mEventData && mImpl->mEventData->mUpdateAlignment)
2846     {
2847       alignStartIndex                     = 0u;
2848       alignRequestedNumberOfCharacters    = mImpl->mModel->mLogicalModel->mText.Count();
2849       mImpl->mEventData->mUpdateAlignment = false;
2850     }
2851
2852     // Need to align with the control's size as the text may contain lines
2853     // starting either with left to right text or right to left.
2854     mImpl->mLayoutEngine.Align(size,
2855                                alignStartIndex,
2856                                alignRequestedNumberOfCharacters,
2857                                mImpl->mModel->mHorizontalAlignment,
2858                                lines,
2859                                mImpl->mModel->mAlignmentOffset,
2860                                mImpl->mLayoutDirection,
2861                                mImpl->mModel->mMatchSystemLanguageDirection);
2862
2863     viewUpdated = true;
2864   }
2865 #if defined(DEBUG_ENABLED)
2866   std::string currentText;
2867   GetText(currentText);
2868   DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::DoRelayout [%p] mImpl->mIsTextDirectionRTL[%s] [%s]\n", this, (mImpl->mIsTextDirectionRTL) ? "true" : "false", currentText.c_str());
2869 #endif
2870   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::DoRelayout, view updated %s\n", (viewUpdated ? "true" : "false"));
2871   return viewUpdated;
2872 }
2873
2874 void Controller::CalculateVerticalOffset(const Size& controlSize)
2875 {
2876   ModelPtr&       model                 = mImpl->mModel;
2877   VisualModelPtr& visualModel           = model->mVisualModel;
2878   Size            layoutSize            = mImpl->mModel->mVisualModel->GetLayoutSize();
2879   Size            oldLayoutSize         = layoutSize;
2880   float           offsetY               = 0.f;
2881   bool            needRecalc            = false;
2882   float           defaultFontLineHeight = mImpl->GetDefaultFontLineHeight();
2883
2884   if(fabsf(layoutSize.height) < Math::MACHINE_EPSILON_1000)
2885   {
2886     // Get the line height of the default font.
2887     layoutSize.height = defaultFontLineHeight;
2888   }
2889
2890   // Whether the text control is editable
2891   const bool isEditable = NULL != mImpl->mEventData;
2892   if(isEditable && layoutSize.height != defaultFontLineHeight)
2893   {
2894     // This code prevents the wrong positioning of cursor when the layout size is bigger/smaller than defaultFontLineHeight.
2895     // This situation occurs when the size of placeholder text is different from the default text.
2896     layoutSize.height = defaultFontLineHeight;
2897     needRecalc        = true;
2898   }
2899
2900   switch(mImpl->mModel->mVerticalAlignment)
2901   {
2902     case VerticalAlignment::TOP:
2903     {
2904       mImpl->mModel->mScrollPosition.y = 0.f;
2905       offsetY                          = 0.f;
2906       break;
2907     }
2908     case VerticalAlignment::CENTER:
2909     {
2910       mImpl->mModel->mScrollPosition.y = floorf(0.5f * (controlSize.height - layoutSize.height)); // try to avoid pixel alignment.
2911       if(needRecalc) offsetY = floorf(0.5f * (layoutSize.height - oldLayoutSize.height));
2912       break;
2913     }
2914     case VerticalAlignment::BOTTOM:
2915     {
2916       mImpl->mModel->mScrollPosition.y = controlSize.height - layoutSize.height;
2917       if(needRecalc) offsetY = layoutSize.height - oldLayoutSize.height;
2918       break;
2919     }
2920   }
2921
2922   if(needRecalc)
2923   {
2924     // Update glyphPositions according to recalculation.
2925     const Length     positionCount  = visualModel->mGlyphPositions.Count();
2926     Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
2927     for(Length index = 0u; index < positionCount; index++)
2928     {
2929       glyphPositions[index].y += offsetY;
2930     }
2931   }
2932 }
2933
2934 // private : Events.
2935
2936 void Controller::ProcessModifyEvents()
2937 {
2938   EventHandler::ProcessModifyEvents(*this);
2939 }
2940
2941 void Controller::TextReplacedEvent()
2942 {
2943   EventHandler::TextReplacedEvent(*this);
2944 }
2945
2946 void Controller::TextInsertedEvent()
2947 {
2948   EventHandler::TextInsertedEvent(*this);
2949 }
2950
2951 void Controller::TextDeletedEvent()
2952 {
2953   EventHandler::TextDeletedEvent(*this);
2954 }
2955
2956 bool Controller::DeleteEvent(int keyCode)
2957 {
2958   return EventHandler::DeleteEvent(*this, keyCode);
2959 }
2960
2961 // private : Helpers.
2962
2963 void Controller::ResetText()
2964 {
2965   // Reset buffers.
2966   mImpl->mModel->mLogicalModel->mText.Clear();
2967
2968   // Reset the embedded images buffer.
2969   mImpl->mModel->mLogicalModel->ClearEmbeddedImages();
2970
2971   // We have cleared everything including the placeholder-text
2972   mImpl->PlaceholderCleared();
2973
2974   mImpl->mTextUpdateInfo.mCharacterIndex             = 0u;
2975   mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
2976   mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = 0u;
2977
2978   // Clear any previous text.
2979   mImpl->mTextUpdateInfo.mClearAll = true;
2980
2981   // The natural size needs to be re-calculated.
2982   mImpl->mRecalculateNaturalSize = true;
2983
2984   // The text direction needs to be updated.
2985   mImpl->mUpdateTextDirection = true;
2986
2987   // Apply modifications to the model
2988   mImpl->mOperationsPending = ALL_OPERATIONS;
2989 }
2990
2991 void Controller::ShowPlaceholderText()
2992 {
2993   if(mImpl->IsPlaceholderAvailable())
2994   {
2995     DALI_ASSERT_DEBUG(mImpl->mEventData && "No placeholder text available");
2996
2997     if(NULL == mImpl->mEventData)
2998     {
2999       return;
3000     }
3001
3002     mImpl->mEventData->mIsShowingPlaceholderText = true;
3003
3004     // Disable handles when showing place-holder text
3005     mImpl->mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
3006     mImpl->mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
3007     mImpl->mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
3008
3009     const char* text(NULL);
3010     size_t      size(0);
3011
3012     // TODO - Switch Placeholder text when changing state
3013     if((EventData::INACTIVE != mImpl->mEventData->mState) &&
3014        (0u != mImpl->mEventData->mPlaceholderTextActive.c_str()))
3015     {
3016       text = mImpl->mEventData->mPlaceholderTextActive.c_str();
3017       size = mImpl->mEventData->mPlaceholderTextActive.size();
3018     }
3019     else
3020     {
3021       text = mImpl->mEventData->mPlaceholderTextInactive.c_str();
3022       size = mImpl->mEventData->mPlaceholderTextInactive.size();
3023     }
3024
3025     mImpl->mTextUpdateInfo.mCharacterIndex             = 0u;
3026     mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
3027
3028     // Reset model for showing placeholder.
3029     mImpl->mModel->mLogicalModel->mText.Clear();
3030     mImpl->mModel->mVisualModel->SetTextColor(mImpl->mEventData->mPlaceholderTextColor);
3031
3032     // Convert text into UTF-32
3033     Vector<Character>& utf32Characters = mImpl->mModel->mLogicalModel->mText;
3034     utf32Characters.Resize(size);
3035
3036     // This is a bit horrible but std::string returns a (signed) char*
3037     const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(text);
3038
3039     // Transform a text array encoded in utf8 into an array encoded in utf32.
3040     // It returns the actual number of characters.
3041     const Length characterCount = Utf8ToUtf32(utf8, size, utf32Characters.Begin());
3042     utf32Characters.Resize(characterCount);
3043
3044     // The characters to be added.
3045     mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = characterCount;
3046
3047     // Reset the cursor position
3048     mImpl->mEventData->mPrimaryCursorPosition = 0;
3049
3050     // The natural size needs to be re-calculated.
3051     mImpl->mRecalculateNaturalSize = true;
3052
3053     // The text direction needs to be updated.
3054     mImpl->mUpdateTextDirection = true;
3055
3056     // Apply modifications to the model
3057     mImpl->mOperationsPending = ALL_OPERATIONS;
3058
3059     // Update the rest of the model during size negotiation
3060     mImpl->QueueModifyEvent(ModifyEvent::TEXT_REPLACED);
3061   }
3062 }
3063
3064 void Controller::ClearFontData()
3065 {
3066   if(mImpl->mFontDefaults)
3067   {
3068     mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
3069   }
3070
3071   // Set flags to update the model.
3072   mImpl->mTextUpdateInfo.mCharacterIndex             = 0u;
3073   mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
3074   mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = mImpl->mModel->mLogicalModel->mText.Count();
3075
3076   mImpl->mTextUpdateInfo.mClearAll           = true;
3077   mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
3078   mImpl->mRecalculateNaturalSize             = true;
3079
3080   mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
3081                                                           VALIDATE_FONTS |
3082                                                           SHAPE_TEXT |
3083                                                           BIDI_INFO |
3084                                                           GET_GLYPH_METRICS |
3085                                                           LAYOUT |
3086                                                           UPDATE_LAYOUT_SIZE |
3087                                                           REORDER |
3088                                                           ALIGN);
3089 }
3090
3091 void Controller::ClearStyleData()
3092 {
3093   mImpl->mModel->mLogicalModel->mColorRuns.Clear();
3094   mImpl->mModel->mLogicalModel->ClearFontDescriptionRuns();
3095 }
3096
3097 void Controller::ResetCursorPosition(CharacterIndex cursorIndex)
3098 {
3099   // Reset the cursor position
3100   if(NULL != mImpl->mEventData)
3101   {
3102     mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
3103
3104     // Update the cursor if it's in editing mode.
3105     if(EventData::IsEditingState(mImpl->mEventData->mState))
3106     {
3107       mImpl->mEventData->mUpdateCursorPosition = true;
3108     }
3109   }
3110 }
3111
3112 void Controller::ResetScrollPosition()
3113 {
3114   if(NULL != mImpl->mEventData)
3115   {
3116     // Reset the scroll position.
3117     mImpl->mModel->mScrollPosition                = Vector2::ZERO;
3118     mImpl->mEventData->mScrollAfterUpdatePosition = true;
3119   }
3120 }
3121
3122 void Controller::SetControlInterface(ControlInterface* controlInterface)
3123 {
3124   mImpl->mControlInterface = controlInterface;
3125 }
3126
3127 bool Controller::ShouldClearFocusOnEscape() const
3128 {
3129   return mImpl->mShouldClearFocusOnEscape;
3130 }
3131
3132 Actor Controller::CreateBackgroundActor()
3133 {
3134   return mImpl->CreateBackgroundActor();
3135 }
3136
3137 // private : Private contructors & copy operator.
3138
3139 Controller::Controller()
3140 : Controller(nullptr, nullptr, nullptr)
3141 {
3142 }
3143
3144 Controller::Controller(ControlInterface* controlInterface)
3145 : Controller(controlInterface, nullptr, nullptr)
3146 {
3147 }
3148
3149 Controller::Controller(ControlInterface*           controlInterface,
3150                        EditableControlInterface*   editableControlInterface,
3151                        SelectableControlInterface* selectableControlInterface)
3152 : mImpl(new Controller::Impl(controlInterface, editableControlInterface, selectableControlInterface))
3153 {
3154 }
3155
3156 // The copy constructor and operator are left unimplemented.
3157
3158 // protected : Destructor.
3159
3160 Controller::~Controller()
3161 {
3162   delete mImpl;
3163 }
3164
3165 } // namespace Text
3166
3167 } // namespace Toolkit
3168
3169 } // namespace Dali