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