Fix Coverity issue
[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 void Controller::RetrieveSelection( std::string& selectedText ) const
737 {
738   mImpl->RetrieveSelection( selectedText, false );
739 }
740
741 void Controller::SetSelection( int start, int end )
742 {
743   mImpl->SetSelection( start, end );
744 }
745
746 std::pair< int, int > Controller::GetSelectionIndexes() const
747 {
748   return mImpl->GetSelectionIndexes();
749 }
750
751 void Controller::CopyStringToClipboard( const std::string& source )
752 {
753   mImpl->CopyStringToClipboard( source );
754 }
755
756 void Controller::SendSelectionToClipboard( bool deleteAfterSending )
757 {
758   mImpl->SendSelectionToClipboard( deleteAfterSending );
759 }
760
761 // public : Default style & Input style
762
763 void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily )
764 {
765   if( NULL == mImpl->mFontDefaults )
766   {
767     mImpl->mFontDefaults = new FontDefaults();
768   }
769
770   mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily;
771   DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s\n", defaultFontFamily.c_str());
772   mImpl->mFontDefaults->familyDefined = !defaultFontFamily.empty();
773
774   if( mImpl->mEventData )
775   {
776     // Update the cursor position if it's in editing mode
777     if( EventData::IsEditingState( mImpl->mEventData->mState ) )
778     {
779       mImpl->mEventData->mDecoratorUpdated = true;
780       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font family is updated.
781     }
782   }
783
784   // Clear the font-specific data
785   ClearFontData();
786
787   mImpl->RequestRelayout();
788 }
789
790 const std::string& Controller::GetDefaultFontFamily() const
791 {
792   if( NULL != mImpl->mFontDefaults )
793   {
794     return mImpl->mFontDefaults->mFontDescription.family;
795   }
796
797   return EMPTY_STRING;
798 }
799
800 void Controller::SetPlaceholderFontFamily( const std::string& placeholderTextFontFamily )
801 {
802   PlaceholderHandler::SetPlaceholderFontFamily(*this, placeholderTextFontFamily);
803 }
804
805 const std::string& Controller::GetPlaceholderFontFamily() const
806 {
807   return PlaceholderHandler::GetPlaceholderFontFamily(*this);
808 }
809
810 void Controller::SetDefaultFontWeight( FontWeight weight )
811 {
812   if( NULL == mImpl->mFontDefaults )
813   {
814     mImpl->mFontDefaults = new FontDefaults();
815   }
816
817   mImpl->mFontDefaults->mFontDescription.weight = weight;
818   mImpl->mFontDefaults->weightDefined = true;
819
820   if( mImpl->mEventData )
821   {
822     // Update the cursor position if it's in editing mode
823     if( EventData::IsEditingState( mImpl->mEventData->mState ) )
824     {
825       mImpl->mEventData->mDecoratorUpdated = true;
826       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font weight is updated.
827     }
828   }
829
830   // Clear the font-specific data
831   ClearFontData();
832
833   mImpl->RequestRelayout();
834 }
835
836 bool Controller::IsDefaultFontWeightDefined() const
837 {
838   if( NULL != mImpl->mFontDefaults )
839   {
840     return mImpl->mFontDefaults->weightDefined;
841   }
842
843   return false;
844 }
845
846 FontWeight Controller::GetDefaultFontWeight() const
847 {
848   if( NULL != mImpl->mFontDefaults )
849   {
850     return mImpl->mFontDefaults->mFontDescription.weight;
851   }
852
853   return TextAbstraction::FontWeight::NORMAL;
854 }
855
856 void Controller::SetPlaceholderTextFontWeight( FontWeight weight )
857 {
858   PlaceholderHandler::SetPlaceholderTextFontWeight(*this, weight);
859 }
860
861 bool Controller::IsPlaceholderTextFontWeightDefined() const
862 {
863   return PlaceholderHandler::IsPlaceholderTextFontWeightDefined(*this);;
864 }
865
866 FontWeight Controller::GetPlaceholderTextFontWeight() const
867 {
868   return PlaceholderHandler::GetPlaceholderTextFontWeight(*this);
869 }
870
871 void Controller::SetDefaultFontWidth( FontWidth width )
872 {
873   if( NULL == mImpl->mFontDefaults )
874   {
875     mImpl->mFontDefaults = new FontDefaults();
876   }
877
878   mImpl->mFontDefaults->mFontDescription.width = width;
879   mImpl->mFontDefaults->widthDefined = true;
880
881   if( mImpl->mEventData )
882   {
883     // Update the cursor position if it's in editing mode
884     if( EventData::IsEditingState( mImpl->mEventData->mState ) )
885     {
886       mImpl->mEventData->mDecoratorUpdated = true;
887       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font width is updated.
888     }
889   }
890
891   // Clear the font-specific data
892   ClearFontData();
893
894   mImpl->RequestRelayout();
895 }
896
897 bool Controller::IsDefaultFontWidthDefined() const
898 {
899   if( NULL != mImpl->mFontDefaults )
900   {
901     return mImpl->mFontDefaults->widthDefined;
902   }
903
904   return false;
905 }
906
907 FontWidth Controller::GetDefaultFontWidth() const
908 {
909   if( NULL != mImpl->mFontDefaults )
910   {
911     return mImpl->mFontDefaults->mFontDescription.width;
912   }
913
914   return TextAbstraction::FontWidth::NORMAL;
915 }
916
917 void Controller::SetPlaceholderTextFontWidth( FontWidth width )
918 {
919   PlaceholderHandler::SetPlaceholderTextFontWidth(*this, width);
920 }
921
922 bool Controller::IsPlaceholderTextFontWidthDefined() const
923 {
924   return PlaceholderHandler::IsPlaceholderTextFontWidthDefined(*this);
925 }
926
927 FontWidth Controller::GetPlaceholderTextFontWidth() const
928 {
929   return PlaceholderHandler::GetPlaceholderTextFontWidth(*this);
930 }
931
932 void Controller::SetDefaultFontSlant( FontSlant slant )
933 {
934   if( NULL == mImpl->mFontDefaults )
935   {
936     mImpl->mFontDefaults = new FontDefaults();
937   }
938
939   mImpl->mFontDefaults->mFontDescription.slant = slant;
940   mImpl->mFontDefaults->slantDefined = true;
941
942   if( mImpl->mEventData )
943   {
944     // Update the cursor position if it's in editing mode
945     if( EventData::IsEditingState( mImpl->mEventData->mState ) )
946     {
947       mImpl->mEventData->mDecoratorUpdated = true;
948       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font slant is updated.
949     }
950   }
951
952   // Clear the font-specific data
953   ClearFontData();
954
955   mImpl->RequestRelayout();
956 }
957
958 bool Controller::IsDefaultFontSlantDefined() const
959 {
960   if( NULL != mImpl->mFontDefaults )
961   {
962     return mImpl->mFontDefaults->slantDefined;
963   }
964   return false;
965 }
966
967 FontSlant Controller::GetDefaultFontSlant() const
968 {
969   if( NULL != mImpl->mFontDefaults )
970   {
971     return mImpl->mFontDefaults->mFontDescription.slant;
972   }
973
974   return TextAbstraction::FontSlant::NORMAL;
975 }
976
977 void Controller::SetPlaceholderTextFontSlant( FontSlant slant )
978 {
979   PlaceholderHandler::SetPlaceholderTextFontSlant(*this, slant);
980 }
981
982 bool Controller::IsPlaceholderTextFontSlantDefined() const
983 {
984   return PlaceholderHandler::IsPlaceholderTextFontSlantDefined(*this);
985 }
986
987 FontSlant Controller::GetPlaceholderTextFontSlant() const
988 {
989   return PlaceholderHandler::GetPlaceholderTextFontSlant(*this);
990 }
991
992 void Controller::SetFontSizeScale( float scale )
993 {
994   mImpl->mFontSizeScale = scale;
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::GetFontSizeScale() const
1013 {
1014   if( nullptr != mImpl->mFontDefaults )
1015   {
1016     return mImpl->mFontSizeScale;
1017   }
1018
1019   return 1.f;
1020 }
1021
1022 void Controller::SetDefaultFontSize( float fontSize, FontSizeType type )
1023 {
1024   if( NULL == mImpl->mFontDefaults )
1025   {
1026     mImpl->mFontDefaults = new FontDefaults();
1027   }
1028
1029   switch( type )
1030   {
1031     case POINT_SIZE:
1032     {
1033       mImpl->mFontDefaults->mDefaultPointSize = fontSize;
1034       mImpl->mFontDefaults->sizeDefined = true;
1035       break;
1036     }
1037     case PIXEL_SIZE:
1038     {
1039       // Point size = Pixel size * 72.f / DPI
1040       unsigned int horizontalDpi = 0u;
1041       unsigned int verticalDpi = 0u;
1042       TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
1043       fontClient.GetDpi( horizontalDpi, verticalDpi );
1044
1045       mImpl->mFontDefaults->mDefaultPointSize = ( fontSize * 72.f ) / static_cast< float >( horizontalDpi );
1046       mImpl->mFontDefaults->sizeDefined = true;
1047       break;
1048     }
1049   }
1050
1051   if( mImpl->mEventData )
1052   {
1053     // Update the cursor position if it's in editing mode
1054     if( EventData::IsEditingState( mImpl->mEventData->mState ) )
1055     {
1056       mImpl->mEventData->mDecoratorUpdated = true;
1057       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
1058     }
1059   }
1060
1061   // Clear the font-specific data
1062   ClearFontData();
1063
1064   mImpl->RequestRelayout();
1065 }
1066
1067 float Controller::GetDefaultFontSize( FontSizeType type ) const
1068 {
1069   float value = 0.0f;
1070   if( NULL != mImpl->mFontDefaults )
1071   {
1072     switch( type )
1073     {
1074       case POINT_SIZE:
1075       {
1076         value = mImpl->mFontDefaults->mDefaultPointSize;
1077         break;
1078       }
1079       case PIXEL_SIZE:
1080       {
1081         // Pixel size = Point size * DPI / 72.f
1082         unsigned int horizontalDpi = 0u;
1083         unsigned int verticalDpi = 0u;
1084         TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
1085         fontClient.GetDpi( horizontalDpi, verticalDpi );
1086
1087         value = mImpl->mFontDefaults->mDefaultPointSize * static_cast< float >( horizontalDpi ) / 72.f;
1088         break;
1089       }
1090     }
1091     return value;
1092   }
1093
1094   return value;
1095 }
1096
1097 void Controller::SetPlaceholderTextFontSize( float fontSize, FontSizeType type )
1098 {
1099   PlaceholderHandler::SetPlaceholderTextFontSize(*this, fontSize, type);
1100 }
1101
1102 float Controller::GetPlaceholderTextFontSize( FontSizeType type ) const
1103 {
1104   return PlaceholderHandler::GetPlaceholderTextFontSize(*this, type);
1105 }
1106
1107 void Controller::SetDefaultColor( const Vector4& color )
1108 {
1109   mImpl->mTextColor = color;
1110
1111   if( !mImpl->IsShowingPlaceholderText() )
1112   {
1113     mImpl->mModel->mVisualModel->SetTextColor( color );
1114
1115     mImpl->mModel->mLogicalModel->mColorRuns.Clear();
1116
1117     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | COLOR );
1118
1119     mImpl->RequestRelayout();
1120   }
1121 }
1122
1123 const Vector4& Controller::GetDefaultColor() const
1124 {
1125   return mImpl->mTextColor;
1126 }
1127
1128 void Controller::SetPlaceholderTextColor( const Vector4& textColor )
1129 {
1130   PlaceholderHandler::SetPlaceholderTextColor(*this, textColor);
1131 }
1132
1133 const Vector4& Controller::GetPlaceholderTextColor() const
1134 {
1135   return PlaceholderHandler::GetPlaceholderTextColor(*this);
1136 }
1137
1138 void Controller::SetShadowOffset( const Vector2& shadowOffset )
1139 {
1140   mImpl->mModel->mVisualModel->SetShadowOffset( shadowOffset );
1141
1142   mImpl->RequestRelayout();
1143 }
1144
1145 const Vector2& Controller::GetShadowOffset() const
1146 {
1147   return mImpl->mModel->mVisualModel->GetShadowOffset();
1148 }
1149
1150 void Controller::SetShadowColor( const Vector4& shadowColor )
1151 {
1152   mImpl->mModel->mVisualModel->SetShadowColor( shadowColor );
1153
1154   mImpl->RequestRelayout();
1155 }
1156
1157 const Vector4& Controller::GetShadowColor() const
1158 {
1159   return mImpl->mModel->mVisualModel->GetShadowColor();
1160 }
1161
1162 void Controller::SetShadowBlurRadius( const float& shadowBlurRadius )
1163 {
1164   if ( fabsf( GetShadowBlurRadius() - shadowBlurRadius ) > Math::MACHINE_EPSILON_1 )
1165   {
1166     mImpl->mModel->mVisualModel->SetShadowBlurRadius( shadowBlurRadius );
1167
1168     mImpl->RequestRelayout();
1169   }
1170 }
1171
1172 const float& Controller::GetShadowBlurRadius() const
1173 {
1174   return mImpl->mModel->mVisualModel->GetShadowBlurRadius();
1175 }
1176
1177 void Controller::SetUnderlineColor( const Vector4& color )
1178 {
1179   mImpl->mModel->mVisualModel->SetUnderlineColor( color );
1180
1181   mImpl->RequestRelayout();
1182 }
1183
1184 const Vector4& Controller::GetUnderlineColor() const
1185 {
1186   return mImpl->mModel->mVisualModel->GetUnderlineColor();
1187 }
1188
1189 void Controller::SetUnderlineEnabled( bool enabled )
1190 {
1191   mImpl->mModel->mVisualModel->SetUnderlineEnabled( enabled );
1192
1193   mImpl->RequestRelayout();
1194 }
1195
1196 bool Controller::IsUnderlineEnabled() const
1197 {
1198   return mImpl->mModel->mVisualModel->IsUnderlineEnabled();
1199 }
1200
1201 void Controller::SetUnderlineHeight( float height )
1202 {
1203   mImpl->mModel->mVisualModel->SetUnderlineHeight( height );
1204
1205   mImpl->RequestRelayout();
1206 }
1207
1208 float Controller::GetUnderlineHeight() const
1209 {
1210   return mImpl->mModel->mVisualModel->GetUnderlineHeight();
1211 }
1212
1213 void Controller::SetOutlineColor( const Vector4& color )
1214 {
1215   mImpl->mModel->mVisualModel->SetOutlineColor( color );
1216
1217   mImpl->RequestRelayout();
1218 }
1219
1220 const Vector4& Controller::GetOutlineColor() const
1221 {
1222   return mImpl->mModel->mVisualModel->GetOutlineColor();
1223 }
1224
1225 void Controller::SetOutlineWidth( uint16_t width )
1226 {
1227   mImpl->mModel->mVisualModel->SetOutlineWidth( width );
1228
1229   mImpl->RequestRelayout();
1230 }
1231
1232 uint16_t Controller::GetOutlineWidth() const
1233 {
1234   return mImpl->mModel->mVisualModel->GetOutlineWidth();
1235 }
1236
1237 void Controller::SetBackgroundColor( const Vector4& color )
1238 {
1239   mImpl->mModel->mVisualModel->SetBackgroundColor( color );
1240
1241   mImpl->RequestRelayout();
1242 }
1243
1244 const Vector4& Controller::GetBackgroundColor() const
1245 {
1246   return mImpl->mModel->mVisualModel->GetBackgroundColor();
1247 }
1248
1249 void Controller::SetBackgroundEnabled( bool enabled )
1250 {
1251   mImpl->mModel->mVisualModel->SetBackgroundEnabled( enabled );
1252
1253   mImpl->RequestRelayout();
1254 }
1255
1256 bool Controller::IsBackgroundEnabled() const
1257 {
1258   return mImpl->mModel->mVisualModel->IsBackgroundEnabled();
1259 }
1260
1261 void Controller::SetDefaultEmbossProperties( const std::string& embossProperties )
1262 {
1263   if( NULL == mImpl->mEmbossDefaults )
1264   {
1265     mImpl->mEmbossDefaults = new EmbossDefaults();
1266   }
1267
1268   mImpl->mEmbossDefaults->properties = embossProperties;
1269 }
1270
1271 const std::string& Controller::GetDefaultEmbossProperties() const
1272 {
1273   if( NULL != mImpl->mEmbossDefaults )
1274   {
1275     return mImpl->mEmbossDefaults->properties;
1276   }
1277
1278   return EMPTY_STRING;
1279 }
1280
1281 void Controller::SetDefaultOutlineProperties( const std::string& outlineProperties )
1282 {
1283   if( NULL == mImpl->mOutlineDefaults )
1284   {
1285     mImpl->mOutlineDefaults = new OutlineDefaults();
1286   }
1287
1288   mImpl->mOutlineDefaults->properties = outlineProperties;
1289 }
1290
1291 const std::string& Controller::GetDefaultOutlineProperties() const
1292 {
1293   if( NULL != mImpl->mOutlineDefaults )
1294   {
1295     return mImpl->mOutlineDefaults->properties;
1296   }
1297
1298   return EMPTY_STRING;
1299 }
1300
1301 bool Controller::SetDefaultLineSpacing( float lineSpacing )
1302 {
1303   if( std::fabs( lineSpacing - mImpl->mLayoutEngine.GetDefaultLineSpacing() ) > Math::MACHINE_EPSILON_1000 )
1304   {
1305     mImpl->mLayoutEngine.SetDefaultLineSpacing(lineSpacing);
1306     mImpl->mRecalculateNaturalSize = true;
1307     return true;
1308   }
1309   return false;
1310 }
1311
1312 float Controller::GetDefaultLineSpacing() const
1313 {
1314   return mImpl->mLayoutEngine.GetDefaultLineSpacing();
1315 }
1316
1317 bool Controller::SetDefaultLineSize( float lineSize )
1318 {
1319   if( std::fabs( lineSize - mImpl->mLayoutEngine.GetDefaultLineSize() ) > Math::MACHINE_EPSILON_1000 )
1320   {
1321     mImpl->mLayoutEngine.SetDefaultLineSize(lineSize);
1322     mImpl->mRecalculateNaturalSize = true;
1323     return true;
1324   }
1325   return false;
1326 }
1327
1328 float Controller::GetDefaultLineSize() const
1329 {
1330   return mImpl->mLayoutEngine.GetDefaultLineSize();
1331 }
1332
1333 void Controller::SetInputColor( const Vector4& color )
1334 {
1335   if( NULL != mImpl->mEventData )
1336   {
1337     mImpl->mEventData->mInputStyle.textColor = color;
1338     mImpl->mEventData->mInputStyle.isDefaultColor = false;
1339
1340     if( EventData::SELECTING == mImpl->mEventData->mState || EventData::EDITING == mImpl->mEventData->mState || EventData::INACTIVE == mImpl->mEventData->mState )
1341     {
1342       const bool handlesCrossed = mImpl->mEventData->mLeftSelectionPosition > mImpl->mEventData->mRightSelectionPosition;
1343
1344       // Get start and end position of selection
1345       const CharacterIndex startOfSelectedText = handlesCrossed ? mImpl->mEventData->mRightSelectionPosition : mImpl->mEventData->mLeftSelectionPosition;
1346       const Length lengthOfSelectedText = ( handlesCrossed ? mImpl->mEventData->mLeftSelectionPosition : mImpl->mEventData->mRightSelectionPosition ) - startOfSelectedText;
1347
1348       // Add the color run.
1349       const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
1350       mImpl->mModel->mLogicalModel->mColorRuns.Resize( numberOfRuns + 1u );
1351
1352       ColorRun& colorRun = *( mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns );
1353       colorRun.color = color;
1354       colorRun.characterRun.characterIndex = startOfSelectedText;
1355       colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
1356
1357       // Request to relayout.
1358       mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | COLOR );
1359       mImpl->RequestRelayout();
1360
1361       mImpl->mTextUpdateInfo.mCharacterIndex = startOfSelectedText;
1362       mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
1363       mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = lengthOfSelectedText;
1364     }
1365   }
1366 }
1367
1368 const Vector4& Controller::GetInputColor() const
1369 {
1370   if( NULL != mImpl->mEventData )
1371   {
1372     return mImpl->mEventData->mInputStyle.textColor;
1373   }
1374
1375   // Return the default text's color if there is no EventData.
1376   return mImpl->mTextColor;
1377
1378 }
1379
1380 void Controller::SetInputFontFamily( const std::string& fontFamily )
1381 {
1382   InputFontHandler::SetInputFontFamily(*this, fontFamily);
1383 }
1384
1385 const std::string& Controller::GetInputFontFamily() const
1386 {
1387   return InputFontHandler::GetInputFontFamily(*this);
1388 }
1389
1390 void Controller::SetInputFontWeight( FontWeight weight )
1391 {
1392   InputFontHandler::SetInputFontWeight(*this, weight);
1393 }
1394
1395 bool Controller::IsInputFontWeightDefined() const
1396 {
1397   return InputFontHandler::IsInputFontWeightDefined(*this);
1398 }
1399
1400 FontWeight Controller::GetInputFontWeight() const
1401 {
1402   return InputFontHandler::GetInputFontWeight(*this);
1403 }
1404
1405 void Controller::SetInputFontWidth( FontWidth width )
1406 {
1407   InputFontHandler::SetInputFontWidth(*this, width);
1408 }
1409
1410 bool Controller::IsInputFontWidthDefined() const
1411 {
1412   return InputFontHandler::IsInputFontWidthDefined(*this);
1413 }
1414
1415 FontWidth Controller::GetInputFontWidth() const
1416 {
1417   return InputFontHandler::GetInputFontWidth(*this);
1418 }
1419
1420 void Controller::SetInputFontSlant( FontSlant slant )
1421 {
1422   InputFontHandler::SetInputFontSlant(*this, slant);
1423 }
1424
1425 bool Controller::IsInputFontSlantDefined() const
1426 {
1427   return InputFontHandler::IsInputFontSlantDefined(*this);
1428 }
1429
1430 FontSlant Controller::GetInputFontSlant() const
1431 {
1432   return InputFontHandler::GetInputFontSlant(*this);
1433 }
1434
1435 void Controller::SetInputFontPointSize( float size )
1436 {
1437   InputFontHandler::SetInputFontPointSize(*this, size);
1438 }
1439
1440 float Controller::GetInputFontPointSize() const
1441 {
1442   return InputFontHandler::GetInputFontPointSize(*this);
1443 }
1444
1445 void Controller::SetInputLineSpacing( float lineSpacing )
1446 {
1447   if( NULL != mImpl->mEventData )
1448   {
1449     mImpl->mEventData->mInputStyle.lineSpacing = lineSpacing;
1450     mImpl->mEventData->mInputStyle.isLineSpacingDefined = true;
1451   }
1452 }
1453
1454 float Controller::GetInputLineSpacing() const
1455 {
1456   if( NULL != mImpl->mEventData )
1457   {
1458     return mImpl->mEventData->mInputStyle.lineSpacing;
1459   }
1460
1461   return 0.f;
1462 }
1463
1464 void Controller::SetInputShadowProperties( const std::string& shadowProperties )
1465 {
1466   if( NULL != mImpl->mEventData )
1467   {
1468     mImpl->mEventData->mInputStyle.shadowProperties = shadowProperties;
1469   }
1470 }
1471
1472 const std::string& Controller::GetInputShadowProperties() const
1473 {
1474   if( NULL != mImpl->mEventData )
1475   {
1476     return mImpl->mEventData->mInputStyle.shadowProperties;
1477   }
1478
1479   return EMPTY_STRING;
1480 }
1481
1482 void Controller::SetInputUnderlineProperties( const std::string& underlineProperties )
1483 {
1484   if( NULL != mImpl->mEventData )
1485   {
1486     mImpl->mEventData->mInputStyle.underlineProperties = underlineProperties;
1487   }
1488 }
1489
1490 const std::string& Controller::GetInputUnderlineProperties() const
1491 {
1492   if( NULL != mImpl->mEventData )
1493   {
1494     return mImpl->mEventData->mInputStyle.underlineProperties;
1495   }
1496
1497   return EMPTY_STRING;
1498 }
1499
1500 void Controller::SetInputEmbossProperties( const std::string& embossProperties )
1501 {
1502   if( NULL != mImpl->mEventData )
1503   {
1504     mImpl->mEventData->mInputStyle.embossProperties = embossProperties;
1505   }
1506 }
1507
1508 const std::string& Controller::GetInputEmbossProperties() const
1509 {
1510   if( NULL != mImpl->mEventData )
1511   {
1512     return mImpl->mEventData->mInputStyle.embossProperties;
1513   }
1514
1515   return GetDefaultEmbossProperties();
1516 }
1517
1518 void Controller::SetInputOutlineProperties( const std::string& outlineProperties )
1519 {
1520   if( NULL != mImpl->mEventData )
1521   {
1522     mImpl->mEventData->mInputStyle.outlineProperties = outlineProperties;
1523   }
1524 }
1525
1526 const std::string& Controller::GetInputOutlineProperties() const
1527 {
1528   if( NULL != mImpl->mEventData )
1529   {
1530     return mImpl->mEventData->mInputStyle.outlineProperties;
1531   }
1532
1533   return GetDefaultOutlineProperties();
1534 }
1535
1536 void Controller::SetInputModePassword( bool passwordInput )
1537 {
1538   if( NULL != mImpl->mEventData )
1539   {
1540     mImpl->mEventData->mPasswordInput = passwordInput;
1541   }
1542 }
1543
1544 bool Controller::IsInputModePassword()
1545 {
1546   if( NULL != mImpl->mEventData )
1547   {
1548     return mImpl->mEventData->mPasswordInput;
1549   }
1550   return false;
1551 }
1552
1553 void Controller::SetNoTextDoubleTapAction( NoTextTap::Action action )
1554 {
1555   if( NULL != mImpl->mEventData )
1556   {
1557     mImpl->mEventData->mDoubleTapAction = action;
1558   }
1559 }
1560
1561 Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
1562 {
1563   NoTextTap::Action action = NoTextTap::NO_ACTION;
1564
1565   if( NULL != mImpl->mEventData )
1566   {
1567     action = mImpl->mEventData->mDoubleTapAction;
1568   }
1569
1570   return action;
1571 }
1572
1573 void Controller::SetNoTextLongPressAction( NoTextTap::Action action )
1574 {
1575   if( NULL != mImpl->mEventData )
1576   {
1577     mImpl->mEventData->mLongPressAction = action;
1578   }
1579 }
1580
1581 Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
1582 {
1583   NoTextTap::Action action = NoTextTap::NO_ACTION;
1584
1585   if( NULL != mImpl->mEventData )
1586   {
1587     action = mImpl->mEventData->mLongPressAction;
1588   }
1589
1590   return action;
1591 }
1592
1593 bool Controller::IsUnderlineSetByString()
1594 {
1595   return mImpl->mUnderlineSetByString;
1596 }
1597
1598 void Controller::UnderlineSetByString( bool setByString )
1599 {
1600   mImpl->mUnderlineSetByString = setByString;
1601 }
1602
1603 bool Controller::IsShadowSetByString()
1604 {
1605   return mImpl->mShadowSetByString;
1606 }
1607
1608 void Controller::ShadowSetByString( bool setByString )
1609 {
1610   mImpl->mShadowSetByString = setByString;
1611 }
1612
1613 bool Controller::IsOutlineSetByString()
1614 {
1615   return mImpl->mOutlineSetByString;
1616 }
1617
1618 void Controller::OutlineSetByString( bool setByString )
1619 {
1620   mImpl->mOutlineSetByString = setByString;
1621 }
1622
1623 bool Controller::IsFontStyleSetByString()
1624 {
1625   return mImpl->mFontStyleSetByString;
1626 }
1627
1628 void Controller::FontStyleSetByString( bool setByString )
1629 {
1630   mImpl->mFontStyleSetByString = setByString;
1631 }
1632
1633 // public : Queries & retrieves.
1634
1635 Layout::Engine& Controller::GetLayoutEngine()
1636 {
1637   return mImpl->mLayoutEngine;
1638 }
1639
1640 View& Controller::GetView()
1641 {
1642   return mImpl->mView;
1643 }
1644
1645 Vector3 Controller::GetNaturalSize()
1646 {
1647   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::GetNaturalSize\n" );
1648   Vector3 naturalSize;
1649
1650   // Make sure the model is up-to-date before layouting
1651   ProcessModifyEvents();
1652
1653   if( mImpl->mRecalculateNaturalSize )
1654   {
1655     // Operations that can be done only once until the text changes.
1656     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
1657                                                                            GET_SCRIPTS       |
1658                                                                            VALIDATE_FONTS    |
1659                                                                            GET_LINE_BREAKS   |
1660                                                                            BIDI_INFO         |
1661                                                                            SHAPE_TEXT        |
1662                                                                            GET_GLYPH_METRICS );
1663
1664     // Set the update info to relayout the whole text.
1665     mImpl->mTextUpdateInfo.mParagraphCharacterIndex = 0u;
1666     mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
1667
1668     // Make sure the model is up-to-date before layouting
1669     mImpl->UpdateModel( onlyOnceOperations );
1670
1671     // Layout the text for the new width.
1672     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | LAYOUT | REORDER );
1673
1674     // Store the actual control's size to restore later.
1675     const Size actualControlSize = mImpl->mModel->mVisualModel->mControlSize;
1676
1677     DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ),
1678                 static_cast<OperationsMask>( onlyOnceOperations |
1679                                              LAYOUT | REORDER ),
1680                 naturalSize.GetVectorXY() );
1681
1682     // Do not do again the only once operations.
1683     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
1684
1685     // Do the size related operations again.
1686     const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
1687                                                                         ALIGN  |
1688                                                                         REORDER );
1689     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
1690
1691     // Stores the natural size to avoid recalculate it again
1692     // unless the text/style changes.
1693     mImpl->mModel->mVisualModel->SetNaturalSize( naturalSize.GetVectorXY() );
1694
1695     mImpl->mRecalculateNaturalSize = false;
1696
1697     // Clear the update info. This info will be set the next time the text is updated.
1698     mImpl->mTextUpdateInfo.Clear();
1699     mImpl->mTextUpdateInfo.mClearAll = true;
1700
1701     // Restore the actual control's size.
1702     mImpl->mModel->mVisualModel->mControlSize = actualControlSize;
1703
1704     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize calculated %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z );
1705   }
1706   else
1707   {
1708     naturalSize = mImpl->mModel->mVisualModel->GetNaturalSize();
1709
1710     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize cached %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z );
1711   }
1712
1713   naturalSize.x = ConvertToEven( naturalSize.x );
1714   naturalSize.y = ConvertToEven( naturalSize.y );
1715
1716   return naturalSize;
1717 }
1718
1719 bool Controller::CheckForTextFit( float pointSize, Size& layoutSize )
1720 {
1721   Size textSize;
1722   mImpl->mFontDefaults->mFitPointSize = pointSize;
1723   mImpl->mFontDefaults->sizeDefined = true;
1724   ClearFontData();
1725
1726   // Operations that can be done only once until the text changes.
1727   const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32 |
1728                                                                               GET_SCRIPTS |
1729                                                                            VALIDATE_FONTS |
1730                                                                           GET_LINE_BREAKS |
1731                                                                                 BIDI_INFO |
1732                                                                                 SHAPE_TEXT|
1733                                                                          GET_GLYPH_METRICS );
1734
1735   mImpl->mTextUpdateInfo.mParagraphCharacterIndex = 0u;
1736   mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
1737
1738   // Make sure the model is up-to-date before layouting
1739   mImpl->UpdateModel( onlyOnceOperations );
1740
1741   DoRelayout( Size( layoutSize.width, MAX_FLOAT ),
1742               static_cast<OperationsMask>( onlyOnceOperations | LAYOUT),
1743               textSize);
1744
1745   // Clear the update info. This info will be set the next time the text is updated.
1746   mImpl->mTextUpdateInfo.Clear();
1747   mImpl->mTextUpdateInfo.mClearAll = true;
1748
1749   if( textSize.width > layoutSize.width || textSize.height > layoutSize.height )
1750   {
1751     return false;
1752   }
1753   return true;
1754 }
1755
1756 void Controller::FitPointSizeforLayout( Size layoutSize )
1757 {
1758   const OperationsMask operations  = mImpl->mOperationsPending;
1759   if( NO_OPERATION != ( UPDATE_LAYOUT_SIZE & operations ) || mImpl->mTextFitContentSize != layoutSize )
1760   {
1761     bool actualellipsis = mImpl->mModel->mElideEnabled;
1762     float minPointSize = mImpl->mTextFitMinSize;
1763     float maxPointSize = mImpl->mTextFitMaxSize;
1764     float pointInterval = mImpl->mTextFitStepSize;
1765
1766     mImpl->mModel->mElideEnabled = false;
1767     Vector<float> pointSizeArray;
1768
1769     // check zero value
1770     if( pointInterval < 1.f )
1771     {
1772       mImpl->mTextFitStepSize = pointInterval = 1.0f;
1773     }
1774
1775     pointSizeArray.Reserve( static_cast< unsigned int >( ceil( ( maxPointSize - minPointSize ) / pointInterval ) ) );
1776
1777     for( float i = minPointSize; i < maxPointSize; i += pointInterval )
1778     {
1779       pointSizeArray.PushBack( i );
1780     }
1781
1782     pointSizeArray.PushBack( maxPointSize );
1783
1784     int bestSizeIndex = 0;
1785     int min = bestSizeIndex + 1;
1786     int max = pointSizeArray.Size() - 1;
1787     while( min <= max )
1788     {
1789       int destI = ( min + max ) / 2;
1790
1791       if( CheckForTextFit( pointSizeArray[destI], layoutSize ) )
1792       {
1793         bestSizeIndex = min;
1794         min = destI + 1;
1795       }
1796       else
1797       {
1798         max = destI - 1;
1799         bestSizeIndex = max;
1800       }
1801     }
1802
1803     mImpl->mModel->mElideEnabled = actualellipsis;
1804     mImpl->mFontDefaults->mFitPointSize = pointSizeArray[bestSizeIndex];
1805     mImpl->mFontDefaults->sizeDefined = true;
1806     ClearFontData();
1807   }
1808 }
1809
1810 float Controller::GetHeightForWidth( float width )
1811 {
1812   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::GetHeightForWidth %p width %f\n", this, width );
1813   // Make sure the model is up-to-date before layouting
1814   ProcessModifyEvents();
1815
1816   Size layoutSize;
1817   if( fabsf( width - mImpl->mModel->mVisualModel->mControlSize.width ) > Math::MACHINE_EPSILON_1000 ||
1818                                                          mImpl->mTextUpdateInfo.mFullRelayoutNeeded ||
1819                                                          mImpl->mTextUpdateInfo.mClearAll            )
1820   {
1821     // Operations that can be done only once until the text changes.
1822     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
1823                                                                            GET_SCRIPTS       |
1824                                                                            VALIDATE_FONTS    |
1825                                                                            GET_LINE_BREAKS   |
1826                                                                            BIDI_INFO         |
1827                                                                            SHAPE_TEXT        |
1828                                                                            GET_GLYPH_METRICS );
1829
1830     // Set the update info to relayout the whole text.
1831     mImpl->mTextUpdateInfo.mParagraphCharacterIndex = 0u;
1832     mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
1833
1834     // Make sure the model is up-to-date before layouting
1835     mImpl->UpdateModel( onlyOnceOperations );
1836
1837
1838     // Layout the text for the new width.
1839     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | LAYOUT );
1840
1841     // Store the actual control's width.
1842     const float actualControlWidth = mImpl->mModel->mVisualModel->mControlSize.width;
1843
1844     DoRelayout( Size( width, MAX_FLOAT ),
1845                 static_cast<OperationsMask>( onlyOnceOperations |
1846                                              LAYOUT ),
1847                 layoutSize );
1848
1849     // Do not do again the only once operations.
1850     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
1851
1852     // Do the size related operations again.
1853     const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
1854                                                                         ALIGN  |
1855                                                                         REORDER );
1856
1857     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
1858
1859     // Clear the update info. This info will be set the next time the text is updated.
1860     mImpl->mTextUpdateInfo.Clear();
1861     mImpl->mTextUpdateInfo.mClearAll = true;
1862
1863     // Restore the actual control's width.
1864     mImpl->mModel->mVisualModel->mControlSize.width = actualControlWidth;
1865
1866     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth calculated %f\n", layoutSize.height );
1867   }
1868   else
1869   {
1870     layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize();
1871     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth cached %f\n", layoutSize.height );
1872   }
1873
1874   return layoutSize.height;
1875 }
1876
1877 int Controller::GetLineCount( float width )
1878 {
1879   GetHeightForWidth( width );
1880   int numberofLines = mImpl->mModel->GetNumberOfLines();
1881   return numberofLines;
1882 }
1883
1884 const ModelInterface* const Controller::GetTextModel() const
1885 {
1886   return mImpl->mModel.Get();
1887 }
1888
1889 float Controller::GetScrollAmountByUserInput()
1890 {
1891   float scrollAmount = 0.0f;
1892
1893   if (NULL != mImpl->mEventData && mImpl->mEventData->mCheckScrollAmount)
1894   {
1895     scrollAmount = mImpl->mModel->mScrollPosition.y -  mImpl->mModel->mScrollPositionLast.y;
1896     mImpl->mEventData->mCheckScrollAmount = false;
1897   }
1898   return scrollAmount;
1899 }
1900
1901 bool Controller::GetTextScrollInfo( float& scrollPosition, float& controlHeight, float& layoutHeight )
1902 {
1903   const Vector2& layout = mImpl->mModel->mVisualModel->GetLayoutSize();
1904   bool isScrolled;
1905
1906   controlHeight = mImpl->mModel->mVisualModel->mControlSize.height;
1907   layoutHeight = layout.height;
1908   scrollPosition = mImpl->mModel->mScrollPosition.y;
1909   isScrolled = !Equals( mImpl->mModel->mScrollPosition.y, mImpl->mModel->mScrollPositionLast.y, Math::MACHINE_EPSILON_1 );
1910   return isScrolled;
1911 }
1912
1913 void Controller::SetHiddenInputOption(const Property::Map& options )
1914 {
1915   if( NULL == mImpl->mHiddenInput )
1916   {
1917     mImpl->mHiddenInput = new HiddenText( this );
1918   }
1919   mImpl->mHiddenInput->SetProperties(options);
1920 }
1921
1922 void Controller::GetHiddenInputOption(Property::Map& options )
1923 {
1924   if( NULL != mImpl->mHiddenInput )
1925   {
1926     mImpl->mHiddenInput->GetProperties(options);
1927   }
1928 }
1929
1930 void Controller::SetPlaceholderProperty( const Property::Map& map )
1931 {
1932   PlaceholderHandler::SetPlaceholderProperty(*this, map);
1933 }
1934
1935 void Controller::GetPlaceholderProperty( Property::Map& map )
1936 {
1937   PlaceholderHandler::GetPlaceholderProperty(*this, map);
1938 }
1939
1940 Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
1941 {
1942   // Make sure the model is up-to-date before layouting
1943   ProcessModifyEvents();
1944
1945   if ( mImpl->mUpdateTextDirection )
1946   {
1947     // Operations that can be done only once until the text changes.
1948     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
1949                                                                            GET_SCRIPTS       |
1950                                                                            VALIDATE_FONTS    |
1951                                                                            GET_LINE_BREAKS   |
1952                                                                            BIDI_INFO         |
1953                                                                            SHAPE_TEXT        |
1954                                                                            GET_GLYPH_METRICS );
1955
1956     // Set the update info to relayout the whole text.
1957     mImpl->mTextUpdateInfo.mParagraphCharacterIndex = 0u;
1958     mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
1959
1960     // Make sure the model is up-to-date before layouting
1961     mImpl->UpdateModel( onlyOnceOperations );
1962
1963     Vector3 naturalSize;
1964     DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ),
1965                 static_cast<OperationsMask>( onlyOnceOperations |
1966                                              LAYOUT | REORDER | UPDATE_DIRECTION ),
1967                 naturalSize.GetVectorXY() );
1968
1969     // Do not do again the only once operations.
1970     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
1971
1972     // Clear the update info. This info will be set the next time the text is updated.
1973     mImpl->mTextUpdateInfo.Clear();
1974
1975     // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT.
1976     mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
1977
1978     mImpl->mUpdateTextDirection = false;
1979   }
1980
1981   return mImpl->mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT;
1982 }
1983
1984 Toolkit::DevelText::VerticalLineAlignment::Type Controller::GetVerticalLineAlignment() const
1985 {
1986   return mImpl->mModel->GetVerticalLineAlignment();
1987 }
1988
1989 void Controller::SetVerticalLineAlignment( Toolkit::DevelText::VerticalLineAlignment::Type alignment )
1990 {
1991   mImpl->mModel->mVerticalLineAlignment = alignment;
1992 }
1993
1994 // public : Relayout.
1995
1996 Controller::UpdateTextType Controller::Relayout( const Size& size, Dali::LayoutDirection::Type layoutDirection )
1997 {
1998   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f, autoScroll[%s]\n", this, size.width, size.height, mImpl->mIsAutoScrollEnabled ?"true":"false"  );
1999
2000   UpdateTextType updateTextType = NONE_UPDATED;
2001
2002   if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
2003   {
2004     if( 0u != mImpl->mModel->mVisualModel->mGlyphPositions.Count() )
2005     {
2006       mImpl->mModel->mVisualModel->mGlyphPositions.Clear();
2007       updateTextType = MODEL_UPDATED;
2008     }
2009
2010     // Clear the update info. This info will be set the next time the text is updated.
2011     mImpl->mTextUpdateInfo.Clear();
2012
2013     // Not worth to relayout if width or height is equal to zero.
2014     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::Relayout (skipped)\n" );
2015
2016     return updateTextType;
2017   }
2018
2019   // Whether a new size has been set.
2020   const bool newSize = ( size != mImpl->mModel->mVisualModel->mControlSize );
2021
2022   if( newSize )
2023   {
2024     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "new size (previous size %f,%f)\n", mImpl->mModel->mVisualModel->mControlSize.width, mImpl->mModel->mVisualModel->mControlSize.height );
2025
2026     if( ( 0 == mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd ) &&
2027         ( 0 == mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters ) &&
2028         ( ( mImpl->mModel->mVisualModel->mControlSize.width < Math::MACHINE_EPSILON_1000 ) || ( mImpl->mModel->mVisualModel->mControlSize.height < Math::MACHINE_EPSILON_1000 ) ) )
2029     {
2030       mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
2031     }
2032
2033     // Layout operations that need to be done if the size changes.
2034     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
2035                                                              LAYOUT                    |
2036                                                              ALIGN                     |
2037                                                              UPDATE_LAYOUT_SIZE        |
2038                                                              REORDER );
2039     // Set the update info to relayout the whole text.
2040     mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
2041     mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
2042
2043     // Store the size used to layout the text.
2044     mImpl->mModel->mVisualModel->mControlSize = size;
2045   }
2046
2047   // Whether there are modify events.
2048   if( 0u != mImpl->mModifyEvents.Count() )
2049   {
2050     // Style operations that need to be done if the text is modified.
2051     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
2052                                                              COLOR );
2053   }
2054
2055   // Set the update info to elide the text.
2056   if( mImpl->mModel->mElideEnabled ||
2057       ( ( NULL != mImpl->mEventData ) && mImpl->mEventData->mIsPlaceholderElideEnabled ) )
2058   {
2059     // Update Text layout for applying elided
2060     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
2061                                                              ALIGN                     |
2062                                                              LAYOUT                    |
2063                                                              UPDATE_LAYOUT_SIZE        |
2064                                                              REORDER );
2065     mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
2066     mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
2067   }
2068
2069   if( mImpl->mModel->mMatchSystemLanguageDirection  && mImpl->mLayoutDirection != layoutDirection )
2070   {
2071     // Clear the update info. This info will be set the next time the text is updated.
2072     mImpl->mTextUpdateInfo.mClearAll = true;
2073     // Apply modifications to the model
2074     // Shape the text again is needed because characters like '()[]{}' have to be mirrored and the glyphs generated again.
2075     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
2076                                                              GET_GLYPH_METRICS         |
2077                                                              SHAPE_TEXT                |
2078                                                              UPDATE_DIRECTION          |
2079                                                              LAYOUT                    |
2080                                                              BIDI_INFO                 |
2081                                                              REORDER );
2082     mImpl->mLayoutDirection = layoutDirection;
2083   }
2084
2085   // Make sure the model is up-to-date before layouting.
2086   ProcessModifyEvents();
2087   bool updated = mImpl->UpdateModel( mImpl->mOperationsPending );
2088
2089   // Layout the text.
2090   Size layoutSize;
2091   updated = DoRelayout( size,
2092                         mImpl->mOperationsPending,
2093                         layoutSize ) || updated;
2094
2095
2096   if( updated )
2097   {
2098     updateTextType = MODEL_UPDATED;
2099   }
2100
2101   // Do not re-do any operation until something changes.
2102   mImpl->mOperationsPending = NO_OPERATION;
2103   mImpl->mModel->mScrollPositionLast = mImpl->mModel->mScrollPosition;
2104
2105   // Whether the text control is editable
2106   const bool isEditable = NULL != mImpl->mEventData;
2107
2108   // Keep the current offset as it will be used to update the decorator's positions (if the size changes).
2109   Vector2 offset;
2110   if( newSize && isEditable )
2111   {
2112     offset = mImpl->mModel->mScrollPosition;
2113   }
2114
2115   if( !isEditable || !IsMultiLineEnabled() )
2116   {
2117     // After doing the text layout, the vertical offset to place the actor in the desired position can be calculated.
2118     CalculateVerticalOffset( size );
2119   }
2120
2121   if( isEditable )
2122   {
2123     if( newSize )
2124     {
2125       // If there is a new size, the scroll position needs to be clamped.
2126       mImpl->ClampHorizontalScroll( layoutSize );
2127
2128       // Update the decorator's positions is needed if there is a new size.
2129       mImpl->mEventData->mDecorator->UpdatePositions( mImpl->mModel->mScrollPosition - offset );
2130     }
2131
2132     // Move the cursor, grab handle etc.
2133     if( mImpl->ProcessInputEvents() )
2134     {
2135       updateTextType = static_cast<UpdateTextType>( updateTextType | DECORATOR_UPDATED );
2136     }
2137   }
2138
2139   // Clear the update info. This info will be set the next time the text is updated.
2140   mImpl->mTextUpdateInfo.Clear();
2141   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::Relayout\n" );
2142
2143   return updateTextType;
2144 }
2145
2146 void Controller::RequestRelayout()
2147 {
2148   mImpl->RequestRelayout();
2149 }
2150
2151 // public : Input style change signals.
2152
2153 bool Controller::IsInputStyleChangedSignalsQueueEmpty()
2154 {
2155   return ( NULL == mImpl->mEventData ) || ( 0u == mImpl->mEventData->mInputStyleChangedQueue.Count() );
2156 }
2157
2158 void Controller::ProcessInputStyleChangedSignals()
2159 {
2160   if( NULL == mImpl->mEventData )
2161   {
2162     // Nothing to do.
2163     return;
2164   }
2165
2166   for( Vector<InputStyle::Mask>::ConstIterator it = mImpl->mEventData->mInputStyleChangedQueue.Begin(),
2167          endIt = mImpl->mEventData->mInputStyleChangedQueue.End();
2168        it != endIt;
2169        ++it )
2170   {
2171     const InputStyle::Mask mask = *it;
2172
2173     if( NULL != mImpl->mEditableControlInterface )
2174     {
2175       // Emit the input style changed signal.
2176       mImpl->mEditableControlInterface->InputStyleChanged( mask );
2177     }
2178   }
2179
2180   mImpl->mEventData->mInputStyleChangedQueue.Clear();
2181 }
2182
2183 // public : Text-input Event Queuing.
2184
2185 void Controller::KeyboardFocusGainEvent()
2186 {
2187   EventHandler::KeyboardFocusGainEvent(*this);
2188 }
2189
2190 void Controller::KeyboardFocusLostEvent()
2191 {
2192   EventHandler::KeyboardFocusLostEvent(*this);
2193 }
2194
2195 bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
2196 {
2197   return EventHandler::KeyEvent(*this, keyEvent);
2198 }
2199
2200 void Controller::TapEvent( unsigned int tapCount, float x, float y )
2201 {
2202   EventHandler::TapEvent(*this, tapCount, x, y);
2203 }
2204
2205 void Controller::PanEvent( GestureState state, const Vector2& displacement )
2206 {
2207   EventHandler::PanEvent(*this, state, displacement);
2208 }
2209
2210 void Controller::LongPressEvent( GestureState state, float x, float y )
2211 {
2212   EventHandler::LongPressEvent(*this, state, x, y);
2213 }
2214
2215 void Controller::SelectEvent( float x, float y, SelectionType selectType )
2216 {
2217   EventHandler::SelectEvent(*this, x, y, selectType);
2218 }
2219
2220 void Controller::SetTextSelectionRange(const uint32_t *start, const uint32_t *end)
2221 {
2222   if( mImpl->mEventData )
2223   {
2224     mImpl->mEventData->mCheckScrollAmount = true;
2225     mImpl->mEventData->mIsLeftHandleSelected = true;
2226     mImpl->mEventData->mIsRightHandleSelected = true;
2227     mImpl->SetTextSelectionRange(start, end);
2228     mImpl->RequestRelayout();
2229     KeyboardFocusGainEvent();
2230   }
2231 }
2232
2233 Uint32Pair Controller::GetTextSelectionRange() const
2234 {
2235   return mImpl->GetTextSelectionRange();
2236 }
2237
2238 CharacterIndex Controller::GetPrimaryCursorPosition() const
2239 {
2240   return mImpl->GetPrimaryCursorPosition();
2241 }
2242
2243 bool Controller::SetPrimaryCursorPosition( CharacterIndex index )
2244 {
2245   if( mImpl->mEventData )
2246   {
2247     mImpl->mEventData->mCheckScrollAmount = true;
2248     mImpl->mEventData->mIsLeftHandleSelected = true;
2249     mImpl->mEventData->mIsRightHandleSelected = true;
2250     mImpl->mEventData->mCheckScrollAmount = true;
2251     if( mImpl->SetPrimaryCursorPosition(index) )
2252     {
2253       KeyboardFocusGainEvent();
2254       return true;
2255     }
2256   }
2257   return false;
2258 }
2259
2260 void Controller::SelectWholeText()
2261 {
2262   SelectEvent( 0.f, 0.f, SelectionType::ALL );
2263 }
2264
2265 void Controller::SelectNone()
2266 {
2267   SelectEvent( 0.f, 0.f, SelectionType::NONE );
2268 }
2269
2270 string Controller::GetSelectedText() const
2271 {
2272   string text;
2273   if( EventData::SELECTING == mImpl->mEventData->mState )
2274   {
2275     mImpl->RetrieveSelection( text, false );
2276   }
2277   return text;
2278 }
2279
2280 InputMethodContext::CallbackData Controller::OnInputMethodContextEvent( InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent )
2281 {
2282   return EventHandler::OnInputMethodContextEvent(*this, inputMethodContext, inputMethodContextEvent);
2283 }
2284
2285 void Controller::PasteClipboardItemEvent()
2286 {
2287   EventHandler::PasteClipboardItemEvent(*this);
2288 }
2289
2290 // protected : Inherit from Text::Decorator::ControllerInterface.
2291
2292 void Controller::GetTargetSize( Vector2& targetSize )
2293 {
2294   targetSize = mImpl->mModel->mVisualModel->mControlSize;
2295 }
2296
2297 void Controller::AddDecoration( Actor& actor, bool needsClipping )
2298 {
2299   if( NULL != mImpl->mEditableControlInterface )
2300   {
2301     mImpl->mEditableControlInterface->AddDecoration( actor, needsClipping );
2302   }
2303 }
2304
2305 bool Controller::IsEditable() const
2306 {
2307   return mImpl->IsEditable();
2308 }
2309
2310 void Controller::SetEditable( bool editable )
2311 {
2312   mImpl->SetEditable( editable );
2313   if(mImpl->mEventData && mImpl->mEventData->mDecorator)
2314   {
2315     mImpl->mEventData->mDecorator->SetEditable( editable );
2316   }
2317 }
2318
2319 void Controller::ScrollBy( Vector2 scroll )
2320 {
2321   if( mImpl->mEventData && (fabs(scroll.x) > Math::MACHINE_EPSILON_0 || fabs(scroll.y) > Math::MACHINE_EPSILON_0))
2322   {
2323       const Vector2& layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize();
2324       const Vector2 currentScroll = mImpl->mModel->mScrollPosition;
2325
2326       scroll.x = -scroll.x;
2327       scroll.y = -scroll.y;
2328
2329       if( fabs(scroll.x) > Math::MACHINE_EPSILON_0 )
2330       {
2331         mImpl->mModel->mScrollPosition.x += scroll.x;
2332         mImpl->ClampHorizontalScroll( layoutSize );
2333       }
2334
2335       if( fabs(scroll.y) > Math::MACHINE_EPSILON_0 )
2336       {
2337         mImpl->mModel->mScrollPosition.y += scroll.y;
2338         mImpl->ClampVerticalScroll( layoutSize );
2339       }
2340
2341       if (mImpl->mModel->mScrollPosition != currentScroll)
2342       {
2343         mImpl->mEventData->mDecorator->UpdatePositions( mImpl->mModel->mScrollPosition - currentScroll );
2344         mImpl->RequestRelayout();
2345       }
2346   }
2347 }
2348
2349 float Controller::GetHorizontalScrollPosition()
2350 {
2351   if( mImpl->mEventData )
2352   {
2353     //scroll values are negative internally so we convert them to positive numbers
2354     return -mImpl->mModel->mScrollPosition.x;
2355   }
2356   return 0;
2357 }
2358
2359 float Controller::GetVerticalScrollPosition()
2360 {
2361   if( mImpl->mEventData )
2362   {
2363     //scroll values are negative internally so we convert them to positive numbers
2364     return -mImpl->mModel->mScrollPosition.y;
2365   }
2366   return 0;
2367 }
2368
2369 void Controller::DecorationEvent( HandleType handleType, HandleState state, float x, float y )
2370 {
2371   EventHandler::DecorationEvent(*this, handleType, state, x, y);
2372 }
2373
2374 // protected : Inherit from TextSelectionPopup::TextPopupButtonCallbackInterface.
2375
2376 void Controller::TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::Buttons button )
2377 {
2378   EventHandler::TextPopupButtonTouched(*this, button);
2379 }
2380
2381 void Controller::DisplayTimeExpired()
2382 {
2383   mImpl->mEventData->mUpdateCursorPosition = true;
2384   // Apply modifications to the model
2385   mImpl->mOperationsPending = ALL_OPERATIONS;
2386
2387   mImpl->RequestRelayout();
2388 }
2389
2390 // private : Update.
2391
2392 void Controller::InsertText( const std::string& text, Controller::InsertType type )
2393 {
2394   bool removedPrevious = false;
2395   bool removedSelected = false;
2396   bool maxLengthReached = false;
2397
2398   DALI_ASSERT_DEBUG( NULL != mImpl->mEventData && "Unexpected InsertText" )
2399
2400   if( NULL == mImpl->mEventData )
2401   {
2402     return;
2403   }
2404
2405   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::InsertText %p %s (%s) mPrimaryCursorPosition %d mPreEditFlag %d mPreEditStartPosition %d mPreEditLength %d\n",
2406                  this, text.c_str(), (COMMIT == type ? "COMMIT" : "PRE_EDIT"),
2407                  mImpl->mEventData->mPrimaryCursorPosition, mImpl->mEventData->mPreEditFlag, mImpl->mEventData->mPreEditStartPosition, mImpl->mEventData->mPreEditLength );
2408
2409   // TODO: At the moment the underline runs are only for pre-edit.
2410   mImpl->mModel->mVisualModel->mUnderlineRuns.Clear();
2411
2412   // Remove the previous InputMethodContext pre-edit.
2413   if( mImpl->mEventData->mPreEditFlag && ( 0u != mImpl->mEventData->mPreEditLength ) )
2414   {
2415     removedPrevious = RemoveText( -static_cast<int>( mImpl->mEventData->mPrimaryCursorPosition - mImpl->mEventData->mPreEditStartPosition ),
2416                                   mImpl->mEventData->mPreEditLength,
2417                                   DONT_UPDATE_INPUT_STYLE );
2418
2419     mImpl->mEventData->mPrimaryCursorPosition = mImpl->mEventData->mPreEditStartPosition;
2420     mImpl->mEventData->mPreEditLength = 0u;
2421   }
2422   else
2423   {
2424     // Remove the previous Selection.
2425     removedSelected = RemoveSelectedText();
2426
2427   }
2428
2429   Vector<Character> utf32Characters;
2430   Length characterCount = 0u;
2431
2432   if( !text.empty() )
2433   {
2434     //  Convert text into UTF-32
2435     utf32Characters.Resize( text.size() );
2436
2437     // This is a bit horrible but std::string returns a (signed) char*
2438     const uint8_t* utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
2439
2440     // Transform a text array encoded in utf8 into an array encoded in utf32.
2441     // It returns the actual number of characters.
2442     characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() );
2443     utf32Characters.Resize( characterCount );
2444
2445     DALI_ASSERT_DEBUG( text.size() >= utf32Characters.Count() && "Invalid UTF32 conversion length" );
2446     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "UTF8 size %d, UTF32 size %d\n", text.size(), utf32Characters.Count() );
2447   }
2448
2449   if( 0u != utf32Characters.Count() ) // Check if Utf8ToUtf32 conversion succeeded
2450   {
2451     // The placeholder text is no longer needed
2452     if( mImpl->IsShowingPlaceholderText() )
2453     {
2454       ResetText();
2455     }
2456
2457     mImpl->ChangeState( EventData::EDITING );
2458
2459     // Handle the InputMethodContext (predicitive text) state changes
2460     if( COMMIT == type )
2461     {
2462       // InputMethodContext is no longer handling key-events
2463       mImpl->ClearPreEditFlag();
2464     }
2465     else // PRE_EDIT
2466     {
2467       if( !mImpl->mEventData->mPreEditFlag )
2468       {
2469         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Entered PreEdit state\n" );
2470
2471         // Record the start of the pre-edit text
2472         mImpl->mEventData->mPreEditStartPosition = mImpl->mEventData->mPrimaryCursorPosition;
2473       }
2474
2475       mImpl->mEventData->mPreEditLength = utf32Characters.Count();
2476       mImpl->mEventData->mPreEditFlag = true;
2477
2478       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "mPreEditStartPosition %d mPreEditLength %d\n", mImpl->mEventData->mPreEditStartPosition, mImpl->mEventData->mPreEditLength );
2479     }
2480
2481     const Length numberOfCharactersInModel = mImpl->mModel->mLogicalModel->mText.Count();
2482
2483     // Restrict new text to fit within Maximum characters setting.
2484     Length maxSizeOfNewText = std::min( ( mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel ), characterCount );
2485     maxLengthReached = ( characterCount > maxSizeOfNewText );
2486
2487     // The cursor position.
2488     CharacterIndex& cursorIndex = mImpl->mEventData->mPrimaryCursorPosition;
2489
2490     // Update the text's style.
2491
2492     // Updates the text style runs by adding characters.
2493     mImpl->mModel->mLogicalModel->UpdateTextStyleRuns( cursorIndex, maxSizeOfNewText );
2494
2495     // Get the character index from the cursor index.
2496     const CharacterIndex styleIndex = ( cursorIndex > 0u ) ? cursorIndex - 1u : 0u;
2497
2498     // Retrieve the text's style for the given index.
2499     InputStyle style;
2500     mImpl->RetrieveDefaultInputStyle( style );
2501     mImpl->mModel->mLogicalModel->RetrieveStyle( styleIndex, style );
2502
2503     // Whether to add a new text color run.
2504     const bool addColorRun = ( style.textColor != mImpl->mEventData->mInputStyle.textColor ) && !mImpl->mEventData->mInputStyle.isDefaultColor;
2505
2506     // Whether to add a new font run.
2507     const bool addFontNameRun = ( style.familyName != mImpl->mEventData->mInputStyle.familyName ) && mImpl->mEventData->mInputStyle.isFamilyDefined;
2508     const bool addFontWeightRun = ( style.weight != mImpl->mEventData->mInputStyle.weight ) && mImpl->mEventData->mInputStyle.isWeightDefined;
2509     const bool addFontWidthRun = ( style.width != mImpl->mEventData->mInputStyle.width ) && mImpl->mEventData->mInputStyle.isWidthDefined;
2510     const bool addFontSlantRun = ( style.slant != mImpl->mEventData->mInputStyle.slant ) && mImpl->mEventData->mInputStyle.isSlantDefined;
2511     const bool addFontSizeRun = ( style.size != mImpl->mEventData->mInputStyle.size ) && mImpl->mEventData->mInputStyle.isSizeDefined ;
2512
2513     // Add style runs.
2514     if( addColorRun )
2515     {
2516       const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
2517       mImpl->mModel->mLogicalModel->mColorRuns.Resize( numberOfRuns + 1u );
2518
2519       ColorRun& colorRun = *( mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns );
2520       colorRun.color = mImpl->mEventData->mInputStyle.textColor;
2521       colorRun.characterRun.characterIndex = cursorIndex;
2522       colorRun.characterRun.numberOfCharacters = maxSizeOfNewText;
2523     }
2524
2525     if( addFontNameRun   ||
2526         addFontWeightRun ||
2527         addFontWidthRun  ||
2528         addFontSlantRun  ||
2529         addFontSizeRun )
2530     {
2531       const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mFontDescriptionRuns.Count();
2532       mImpl->mModel->mLogicalModel->mFontDescriptionRuns.Resize( numberOfRuns + 1u );
2533
2534       FontDescriptionRun& fontDescriptionRun = *( mImpl->mModel->mLogicalModel->mFontDescriptionRuns.Begin() + numberOfRuns );
2535
2536       if( addFontNameRun )
2537       {
2538         fontDescriptionRun.familyLength = mImpl->mEventData->mInputStyle.familyName.size();
2539         fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength];
2540         memcpy( fontDescriptionRun.familyName, mImpl->mEventData->mInputStyle.familyName.c_str(), fontDescriptionRun.familyLength );
2541         fontDescriptionRun.familyDefined = true;
2542
2543         // The memory allocated for the font family name is freed when the font description is removed from the logical model.
2544       }
2545
2546       if( addFontWeightRun )
2547       {
2548         fontDescriptionRun.weight = mImpl->mEventData->mInputStyle.weight;
2549         fontDescriptionRun.weightDefined = true;
2550       }
2551
2552       if( addFontWidthRun )
2553       {
2554         fontDescriptionRun.width = mImpl->mEventData->mInputStyle.width;
2555         fontDescriptionRun.widthDefined = true;
2556       }
2557
2558       if( addFontSlantRun )
2559       {
2560         fontDescriptionRun.slant = mImpl->mEventData->mInputStyle.slant;
2561         fontDescriptionRun.slantDefined = true;
2562       }
2563
2564       if( addFontSizeRun )
2565       {
2566         fontDescriptionRun.size = static_cast<PointSize26Dot6>( mImpl->mEventData->mInputStyle.size * mImpl->mFontSizeScale * 64.f );
2567         fontDescriptionRun.sizeDefined = true;
2568       }
2569
2570       fontDescriptionRun.characterRun.characterIndex = cursorIndex;
2571       fontDescriptionRun.characterRun.numberOfCharacters = maxSizeOfNewText;
2572     }
2573
2574     // Insert at current cursor position.
2575     Vector<Character>& modifyText = mImpl->mModel->mLogicalModel->mText;
2576
2577     auto pos = modifyText.End();
2578     if( cursorIndex < numberOfCharactersInModel )
2579     {
2580       pos = modifyText.Begin() + cursorIndex;
2581     }
2582     unsigned int realPos = pos - modifyText.Begin();
2583     modifyText.Insert( pos, utf32Characters.Begin(), utf32Characters.Begin() + maxSizeOfNewText );
2584
2585     if( NULL != mImpl->mEditableControlInterface )
2586     {
2587       mImpl->mEditableControlInterface->TextInserted( realPos, maxSizeOfNewText, text );
2588     }
2589
2590     // Mark the first paragraph to be updated.
2591     if( Layout::Engine::SINGLE_LINE_BOX == mImpl->mLayoutEngine.GetLayout() )
2592     {
2593       mImpl->mTextUpdateInfo.mCharacterIndex = 0;
2594       mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
2595       mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = numberOfCharactersInModel + maxSizeOfNewText;
2596       mImpl->mTextUpdateInfo.mClearAll = true;
2597     }
2598     else
2599     {
2600       mImpl->mTextUpdateInfo.mCharacterIndex = std::min( cursorIndex, mImpl->mTextUpdateInfo.mCharacterIndex );
2601       mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd += maxSizeOfNewText;
2602     }
2603
2604     // Update the cursor index.
2605     cursorIndex += maxSizeOfNewText;
2606
2607     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 );
2608   }
2609
2610   if( ( 0u == mImpl->mModel->mLogicalModel->mText.Count() ) &&
2611       mImpl->IsPlaceholderAvailable() )
2612   {
2613     // Show place-holder if empty after removing the pre-edit text
2614     ShowPlaceholderText();
2615     mImpl->mEventData->mUpdateCursorPosition = true;
2616     mImpl->ClearPreEditFlag();
2617   }
2618   else if( removedPrevious ||
2619            removedSelected ||
2620            ( 0 != utf32Characters.Count() ) )
2621   {
2622     // Queue an inserted event
2623     mImpl->QueueModifyEvent( ModifyEvent::TEXT_INSERTED );
2624
2625     mImpl->mEventData->mUpdateCursorPosition = true;
2626     if( removedSelected )
2627     {
2628       mImpl->mEventData->mScrollAfterDelete = true;
2629     }
2630     else
2631     {
2632       mImpl->mEventData->mScrollAfterUpdatePosition = true;
2633     }
2634   }
2635
2636   if( maxLengthReached )
2637   {
2638     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "MaxLengthReached (%d)\n", mImpl->mModel->mLogicalModel->mText.Count() );
2639
2640     mImpl->ResetInputMethodContext();
2641
2642     if( NULL != mImpl->mEditableControlInterface )
2643     {
2644       // Do this last since it provides callbacks into application code
2645       mImpl->mEditableControlInterface->MaxLengthReached();
2646     }
2647   }
2648 }
2649
2650 void Controller::PasteText( const std::string& stringToPaste )
2651 {
2652   InsertText( stringToPaste, Text::Controller::COMMIT );
2653   mImpl->ChangeState( EventData::EDITING );
2654   mImpl->RequestRelayout();
2655
2656   if( NULL != mImpl->mEditableControlInterface )
2657   {
2658     // Do this last since it provides callbacks into application code
2659     mImpl->mEditableControlInterface->TextChanged();
2660   }
2661 }
2662
2663 bool Controller::RemoveText( int cursorOffset,
2664                              int numberOfCharacters,
2665                              UpdateInputStyleType type )
2666 {
2667   bool removed = false;
2668
2669   if( NULL == mImpl->mEventData )
2670   {
2671     return removed;
2672   }
2673
2674   DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::RemoveText %p mText.Count() %d cursor %d cursorOffset %d numberOfCharacters %d\n",
2675                  this, mImpl->mModel->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition, cursorOffset, numberOfCharacters );
2676
2677   if( !mImpl->IsShowingPlaceholderText() )
2678   {
2679     // Delete at current cursor position
2680     Vector<Character>& currentText = mImpl->mModel->mLogicalModel->mText;
2681     CharacterIndex& oldCursorIndex = mImpl->mEventData->mPrimaryCursorPosition;
2682
2683     CharacterIndex cursorIndex = 0;
2684
2685     // Validate the cursor position & number of characters
2686     if( ( static_cast< int >( mImpl->mEventData->mPrimaryCursorPosition ) + cursorOffset ) >= 0 )
2687     {
2688       cursorIndex = mImpl->mEventData->mPrimaryCursorPosition + cursorOffset;
2689     }
2690
2691     if( ( cursorIndex + numberOfCharacters ) > currentText.Count() )
2692     {
2693       numberOfCharacters = currentText.Count() - cursorIndex;
2694     }
2695
2696     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.
2697         ( ( cursorIndex + numberOfCharacters ) <= mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters ) )
2698     {
2699       // Mark the paragraphs to be updated.
2700       if( Layout::Engine::SINGLE_LINE_BOX == mImpl->mLayoutEngine.GetLayout() )
2701       {
2702         mImpl->mTextUpdateInfo.mCharacterIndex = 0;
2703         mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
2704         mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters - numberOfCharacters;
2705         mImpl->mTextUpdateInfo.mClearAll = true;
2706       }
2707       else
2708       {
2709         mImpl->mTextUpdateInfo.mCharacterIndex = std::min( cursorIndex, mImpl->mTextUpdateInfo.mCharacterIndex );
2710         mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove += numberOfCharacters;
2711       }
2712
2713       // Update the input style and remove the text's style before removing the text.
2714
2715       if( UPDATE_INPUT_STYLE == type )
2716       {
2717         // Keep a copy of the current input style.
2718         InputStyle currentInputStyle;
2719         currentInputStyle.Copy( mImpl->mEventData->mInputStyle );
2720
2721         // Set first the default input style.
2722         mImpl->RetrieveDefaultInputStyle( mImpl->mEventData->mInputStyle );
2723
2724         // Update the input style.
2725         mImpl->mModel->mLogicalModel->RetrieveStyle( cursorIndex, mImpl->mEventData->mInputStyle );
2726
2727         // Compare if the input style has changed.
2728         const bool hasInputStyleChanged = !currentInputStyle.Equal( mImpl->mEventData->mInputStyle );
2729
2730         if( hasInputStyleChanged )
2731         {
2732           const InputStyle::Mask styleChangedMask = currentInputStyle.GetInputStyleChangeMask( mImpl->mEventData->mInputStyle );
2733           // Queue the input style changed signal.
2734           mImpl->mEventData->mInputStyleChangedQueue.PushBack( styleChangedMask );
2735         }
2736       }
2737
2738       // If the number of current text and the number of characters to be deleted are same,
2739       // it means all texts should be removed and all Preedit variables should be initialized.
2740       if( ( currentText.Count() - numberOfCharacters == 0 ) && ( cursorIndex == 0 ) )
2741       {
2742         mImpl->ClearPreEditFlag();
2743         mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = 0;
2744       }
2745
2746       // Updates the text style runs by removing characters. Runs with no characters are removed.
2747       mImpl->mModel->mLogicalModel->UpdateTextStyleRuns( cursorIndex, -numberOfCharacters );
2748
2749       // Remove the characters.
2750       Vector<Character>::Iterator first = currentText.Begin() + cursorIndex;
2751       Vector<Character>::Iterator last  = first + numberOfCharacters;
2752
2753       if( NULL != mImpl->mEditableControlInterface )
2754       {
2755         std::string utf8;
2756         Utf32ToUtf8( first, numberOfCharacters, utf8 );
2757         mImpl->mEditableControlInterface->TextDeleted( cursorIndex, numberOfCharacters, utf8 );
2758       }
2759
2760       currentText.Erase( first, last );
2761
2762       // Cursor position retreat
2763       oldCursorIndex = cursorIndex;
2764
2765       mImpl->mEventData->mScrollAfterDelete = true;
2766
2767       if( EventData::INACTIVE == mImpl->mEventData->mState )
2768       {
2769         mImpl->ChangeState( EventData::EDITING );
2770       }
2771
2772       DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::RemoveText %p removed %d\n", this, numberOfCharacters );
2773       removed = true;
2774     }
2775   }
2776
2777   return removed;
2778 }
2779
2780 bool Controller::RemoveSelectedText()
2781 {
2782   bool textRemoved( false );
2783
2784   if( EventData::SELECTING == mImpl->mEventData->mState )
2785   {
2786     std::string removedString;
2787     mImpl->RetrieveSelection( removedString, true );
2788
2789     if( !removedString.empty() )
2790     {
2791       textRemoved = true;
2792       mImpl->ChangeState( EventData::EDITING );
2793     }
2794   }
2795
2796   return textRemoved;
2797 }
2798
2799 // private : Relayout.
2800
2801 bool Controller::DoRelayout( const Size& size,
2802                              OperationsMask operationsRequired,
2803                              Size& layoutSize )
2804 {
2805   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::DoRelayout %p size %f,%f\n", this, size.width, size.height );
2806   bool viewUpdated( false );
2807
2808   // Calculate the operations to be done.
2809   const OperationsMask operations = static_cast<OperationsMask>( mImpl->mOperationsPending & operationsRequired );
2810
2811   const CharacterIndex startIndex = mImpl->mTextUpdateInfo.mParagraphCharacterIndex;
2812   const Length requestedNumberOfCharacters = mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters;
2813
2814   // Get the current layout size.
2815   layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize();
2816
2817   if( NO_OPERATION != ( LAYOUT & operations ) )
2818   {
2819     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::DoRelayout LAYOUT & operations\n");
2820
2821     // Some vectors with data needed to layout and reorder may be void
2822     // after the first time the text has been laid out.
2823     // Fill the vectors again.
2824
2825     // Calculate the number of glyphs to layout.
2826     const Vector<GlyphIndex>& charactersToGlyph = mImpl->mModel->mVisualModel->mCharactersToGlyph;
2827     const Vector<Length>& glyphsPerCharacter = mImpl->mModel->mVisualModel->mGlyphsPerCharacter;
2828     const GlyphIndex* const charactersToGlyphBuffer = charactersToGlyph.Begin();
2829     const Length* const glyphsPerCharacterBuffer = glyphsPerCharacter.Begin();
2830
2831     const CharacterIndex lastIndex = startIndex + ( ( requestedNumberOfCharacters > 0u ) ? requestedNumberOfCharacters - 1u : 0u );
2832     const GlyphIndex startGlyphIndex = mImpl->mTextUpdateInfo.mStartGlyphIndex;
2833
2834     // Make sure the index is not out of bound
2835     if ( charactersToGlyph.Count() != glyphsPerCharacter.Count() ||
2836          requestedNumberOfCharacters > charactersToGlyph.Count() ||
2837          ( lastIndex > charactersToGlyph.Count() && charactersToGlyph.Count() > 0u ) )
2838     {
2839       std::string currentText;
2840       GetText( currentText );
2841
2842       DALI_LOG_ERROR( "Controller::DoRelayout: Attempting to access invalid buffer\n" );
2843       DALI_LOG_ERROR( "Current text is: %s\n", currentText.c_str() );
2844       DALI_LOG_ERROR( "startIndex: %u, lastIndex: %u, requestedNumberOfCharacters: %u, charactersToGlyph.Count = %lu, glyphsPerCharacter.Count = %lu\n", startIndex, lastIndex, requestedNumberOfCharacters, charactersToGlyph.Count(), glyphsPerCharacter.Count());
2845
2846       return false;
2847     }
2848
2849     const Length numberOfGlyphs = ( requestedNumberOfCharacters > 0u ) ? *( charactersToGlyphBuffer + lastIndex ) + *( glyphsPerCharacterBuffer + lastIndex ) - startGlyphIndex : 0u;
2850     const Length totalNumberOfGlyphs = mImpl->mModel->mVisualModel->mGlyphs.Count();
2851
2852     if( 0u == totalNumberOfGlyphs )
2853     {
2854       if( NO_OPERATION != ( UPDATE_LAYOUT_SIZE & operations ) )
2855       {
2856         mImpl->mModel->mVisualModel->SetLayoutSize( Size::ZERO );
2857       }
2858
2859       // Nothing else to do if there is no glyphs.
2860       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::DoRelayout no glyphs, view updated true\n" );
2861       return true;
2862     }
2863
2864     // Set the layout parameters.
2865     Layout::Parameters layoutParameters( size,
2866                                          mImpl->mModel);
2867
2868     // Resize the vector of positions to have the same size than the vector of glyphs.
2869     Vector<Vector2>& glyphPositions = mImpl->mModel->mVisualModel->mGlyphPositions;
2870     glyphPositions.Resize( totalNumberOfGlyphs );
2871
2872     // Whether the last character is a new paragraph character.
2873     const Character* const textBuffer = mImpl->mModel->mLogicalModel->mText.Begin();
2874     mImpl->mTextUpdateInfo.mIsLastCharacterNewParagraph =  TextAbstraction::IsNewParagraph( *( textBuffer + ( mImpl->mModel->mLogicalModel->mText.Count() - 1u ) ) );
2875     layoutParameters.isLastNewParagraph = mImpl->mTextUpdateInfo.mIsLastCharacterNewParagraph;
2876
2877     // The initial glyph and the number of glyphs to layout.
2878     layoutParameters.startGlyphIndex = startGlyphIndex;
2879     layoutParameters.numberOfGlyphs = numberOfGlyphs;
2880     layoutParameters.startLineIndex = mImpl->mTextUpdateInfo.mStartLineIndex;
2881     layoutParameters.estimatedNumberOfLines = mImpl->mTextUpdateInfo.mEstimatedNumberOfLines;
2882
2883     // Update the ellipsis
2884     bool elideTextEnabled = mImpl->mModel->mElideEnabled;
2885
2886     if( NULL != mImpl->mEventData )
2887     {
2888       if( mImpl->mEventData->mPlaceholderEllipsisFlag && mImpl->IsShowingPlaceholderText() )
2889       {
2890         elideTextEnabled = mImpl->mEventData->mIsPlaceholderElideEnabled;
2891       }
2892       else if( EventData::INACTIVE != mImpl->mEventData->mState )
2893       {
2894         // Disable ellipsis when editing
2895         elideTextEnabled = false;
2896       }
2897
2898       // Reset the scroll position in inactive state
2899       if( elideTextEnabled && ( mImpl->mEventData->mState == EventData::INACTIVE ) )
2900       {
2901         ResetScrollPosition();
2902       }
2903     }
2904
2905     // Update the visual model.
2906     bool isAutoScrollEnabled = mImpl->mIsAutoScrollEnabled;
2907     Size newLayoutSize;
2908     viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters,
2909                                                    newLayoutSize,
2910                                                    elideTextEnabled,
2911                                                    isAutoScrollEnabled );
2912     mImpl->mIsAutoScrollEnabled = isAutoScrollEnabled;
2913
2914     viewUpdated = viewUpdated || ( newLayoutSize != layoutSize );
2915
2916     if( viewUpdated )
2917     {
2918       layoutSize = newLayoutSize;
2919
2920       if( NO_OPERATION != ( UPDATE_DIRECTION & operations ) )
2921       {
2922         mImpl->mIsTextDirectionRTL = false;
2923       }
2924
2925       if ( ( NO_OPERATION != ( UPDATE_DIRECTION & operations ) ) && !mImpl->mModel->mVisualModel->mLines.Empty() )
2926       {
2927         mImpl->mIsTextDirectionRTL = mImpl->mModel->mVisualModel->mLines[0u].direction;
2928       }
2929
2930       // Sets the layout size.
2931       if( NO_OPERATION != ( UPDATE_LAYOUT_SIZE & operations ) )
2932       {
2933         mImpl->mModel->mVisualModel->SetLayoutSize( layoutSize );
2934       }
2935     } // view updated
2936   }
2937
2938   if( NO_OPERATION != ( ALIGN & operations ) )
2939   {
2940     // The laid-out lines.
2941     Vector<LineRun>& lines = mImpl->mModel->mVisualModel->mLines;
2942
2943     CharacterIndex alignStartIndex = startIndex;
2944     Length alignRequestedNumberOfCharacters = requestedNumberOfCharacters;
2945
2946     // the whole text needs to be full aligned.
2947     // If you do not do a full aligned, only the last line of the multiline input is aligned.
2948     if(  mImpl->mEventData && mImpl->mEventData->mUpdateAlignment )
2949     {
2950       alignStartIndex = 0u;
2951       alignRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
2952       mImpl->mEventData->mUpdateAlignment = false;
2953     }
2954
2955     // Need to align with the control's size as the text may contain lines
2956     // starting either with left to right text or right to left.
2957     mImpl->mLayoutEngine.Align( size,
2958                                 alignStartIndex,
2959                                 alignRequestedNumberOfCharacters,
2960                                 mImpl->mModel->mHorizontalAlignment,
2961                                 lines,
2962                                 mImpl->mModel->mAlignmentOffset,
2963                                 mImpl->mLayoutDirection,
2964                                 mImpl->mModel->mMatchSystemLanguageDirection );
2965
2966     viewUpdated = true;
2967   }
2968 #if defined(DEBUG_ENABLED)
2969   std::string currentText;
2970   GetText( currentText );
2971   DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::DoRelayout [%p] mImpl->mIsTextDirectionRTL[%s] [%s]\n", this, (mImpl->mIsTextDirectionRTL)?"true":"false",  currentText.c_str() );
2972 #endif
2973   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::DoRelayout, view updated %s\n", ( viewUpdated ? "true" : "false" ) );
2974   return viewUpdated;
2975 }
2976
2977 void Controller::CalculateVerticalOffset( const Size& controlSize )
2978 {
2979   Size layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize();
2980
2981   if( fabsf( layoutSize.height ) < Math::MACHINE_EPSILON_1000 )
2982   {
2983     // Get the line height of the default font.
2984     layoutSize.height = mImpl->GetDefaultFontLineHeight();
2985   }
2986
2987   switch( mImpl->mModel->mVerticalAlignment )
2988   {
2989     case VerticalAlignment::TOP:
2990     {
2991       mImpl->mModel->mScrollPosition.y = 0.f;
2992       break;
2993     }
2994     case VerticalAlignment::CENTER:
2995     {
2996       mImpl->mModel->mScrollPosition.y = floorf( 0.5f * ( controlSize.height - layoutSize.height ) ); // try to avoid pixel alignment.
2997       break;
2998     }
2999     case VerticalAlignment::BOTTOM:
3000     {
3001       mImpl->mModel->mScrollPosition.y = controlSize.height - layoutSize.height;
3002       break;
3003     }
3004   }
3005 }
3006
3007 // private : Events.
3008
3009 void Controller::ProcessModifyEvents()
3010 {
3011   EventHandler::ProcessModifyEvents(*this);
3012 }
3013
3014 void Controller::TextReplacedEvent()
3015 {
3016   EventHandler::TextReplacedEvent(*this);
3017 }
3018
3019 void Controller::TextInsertedEvent()
3020 {
3021   EventHandler::TextInsertedEvent(*this);
3022 }
3023
3024 void Controller::TextDeletedEvent()
3025 {
3026   EventHandler::TextDeletedEvent(*this);
3027 }
3028
3029 bool Controller::DeleteEvent( int keyCode )
3030 {
3031   return EventHandler::DeleteEvent(*this, keyCode);
3032 }
3033
3034 // private : Helpers.
3035
3036 void Controller::ResetText()
3037 {
3038   // Reset buffers.
3039   mImpl->mModel->mLogicalModel->mText.Clear();
3040
3041   // Reset the embedded images buffer.
3042   mImpl->mModel->mLogicalModel->ClearEmbeddedImages();
3043
3044   // We have cleared everything including the placeholder-text
3045   mImpl->PlaceholderCleared();
3046
3047   mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
3048   mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
3049   mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = 0u;
3050
3051   // Clear any previous text.
3052   mImpl->mTextUpdateInfo.mClearAll = true;
3053
3054   // The natural size needs to be re-calculated.
3055   mImpl->mRecalculateNaturalSize = true;
3056
3057   // The text direction needs to be updated.
3058   mImpl->mUpdateTextDirection = true;
3059
3060   // Apply modifications to the model
3061   mImpl->mOperationsPending = ALL_OPERATIONS;
3062 }
3063
3064 void Controller::ShowPlaceholderText()
3065 {
3066   if( mImpl->IsPlaceholderAvailable() )
3067   {
3068     DALI_ASSERT_DEBUG( mImpl->mEventData && "No placeholder text available" );
3069
3070     if( NULL == mImpl->mEventData )
3071     {
3072       return;
3073     }
3074
3075     mImpl->mEventData->mIsShowingPlaceholderText = true;
3076
3077     // Disable handles when showing place-holder text
3078     mImpl->mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
3079     mImpl->mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
3080     mImpl->mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
3081
3082     const char* text( NULL );
3083     size_t size( 0 );
3084
3085     // TODO - Switch Placeholder text when changing state
3086     if( ( EventData::INACTIVE != mImpl->mEventData->mState ) &&
3087         ( 0u != mImpl->mEventData->mPlaceholderTextActive.c_str() ) )
3088     {
3089       text = mImpl->mEventData->mPlaceholderTextActive.c_str();
3090       size = mImpl->mEventData->mPlaceholderTextActive.size();
3091     }
3092     else
3093     {
3094       text = mImpl->mEventData->mPlaceholderTextInactive.c_str();
3095       size = mImpl->mEventData->mPlaceholderTextInactive.size();
3096     }
3097
3098     mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
3099     mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
3100
3101     // Reset model for showing placeholder.
3102     mImpl->mModel->mLogicalModel->mText.Clear();
3103     mImpl->mModel->mVisualModel->SetTextColor( mImpl->mEventData->mPlaceholderTextColor );
3104
3105     // Convert text into UTF-32
3106     Vector<Character>& utf32Characters = mImpl->mModel->mLogicalModel->mText;
3107     utf32Characters.Resize( size );
3108
3109     // This is a bit horrible but std::string returns a (signed) char*
3110     const uint8_t* utf8 = reinterpret_cast<const uint8_t*>( text );
3111
3112     // Transform a text array encoded in utf8 into an array encoded in utf32.
3113     // It returns the actual number of characters.
3114     const Length characterCount = Utf8ToUtf32( utf8, size, utf32Characters.Begin() );
3115     utf32Characters.Resize( characterCount );
3116
3117     // The characters to be added.
3118     mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = characterCount;
3119
3120     // Reset the cursor position
3121     mImpl->mEventData->mPrimaryCursorPosition = 0;
3122
3123     // The natural size needs to be re-calculated.
3124     mImpl->mRecalculateNaturalSize = true;
3125
3126     // The text direction needs to be updated.
3127     mImpl->mUpdateTextDirection = true;
3128
3129     // Apply modifications to the model
3130     mImpl->mOperationsPending = ALL_OPERATIONS;
3131
3132     // Update the rest of the model during size negotiation
3133     mImpl->QueueModifyEvent( ModifyEvent::TEXT_REPLACED );
3134   }
3135 }
3136
3137 void Controller::ClearFontData()
3138 {
3139   if( mImpl->mFontDefaults )
3140   {
3141     mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
3142   }
3143
3144   // Set flags to update the model.
3145   mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
3146   mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
3147   mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
3148
3149   mImpl->mTextUpdateInfo.mClearAll = true;
3150   mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
3151   mImpl->mRecalculateNaturalSize = true;
3152
3153   mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
3154                                                            VALIDATE_FONTS            |
3155                                                            SHAPE_TEXT                |
3156                                                            BIDI_INFO                 |
3157                                                            GET_GLYPH_METRICS         |
3158                                                            LAYOUT                    |
3159                                                            UPDATE_LAYOUT_SIZE        |
3160                                                            REORDER                   |
3161                                                            ALIGN );
3162 }
3163
3164 void Controller::ClearStyleData()
3165 {
3166   mImpl->mModel->mLogicalModel->mColorRuns.Clear();
3167   mImpl->mModel->mLogicalModel->ClearFontDescriptionRuns();
3168 }
3169
3170 void Controller::ResetCursorPosition( CharacterIndex cursorIndex )
3171 {
3172   // Reset the cursor position
3173   if( NULL != mImpl->mEventData )
3174   {
3175     mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
3176
3177     // Update the cursor if it's in editing mode.
3178     if( EventData::IsEditingState( mImpl->mEventData->mState )  )
3179     {
3180       mImpl->mEventData->mUpdateCursorPosition = true;
3181     }
3182   }
3183 }
3184
3185 CharacterIndex Controller::GetCursorPosition()
3186 {
3187   if( !mImpl->mEventData )
3188     return 0;
3189
3190   return mImpl->mEventData->mPrimaryCursorPosition;
3191 }
3192
3193 void Controller::ResetScrollPosition()
3194 {
3195   if( NULL != mImpl->mEventData )
3196   {
3197     // Reset the scroll position.
3198     mImpl->mModel->mScrollPosition = Vector2::ZERO;
3199     mImpl->mEventData->mScrollAfterUpdatePosition = true;
3200   }
3201 }
3202
3203 void Controller::SetControlInterface( ControlInterface* controlInterface )
3204 {
3205   mImpl->mControlInterface = controlInterface;
3206 }
3207
3208 bool Controller::ShouldClearFocusOnEscape() const
3209 {
3210   return mImpl->mShouldClearFocusOnEscape;
3211 }
3212
3213 Actor Controller::CreateBackgroundActor()
3214 {
3215   return mImpl->CreateBackgroundActor();
3216 }
3217
3218 // private : Private contructors & copy operator.
3219
3220 Controller::Controller()
3221 : Controller(nullptr, nullptr, nullptr)
3222 {
3223 }
3224
3225 Controller::Controller( ControlInterface* controlInterface )
3226 :Controller( controlInterface, nullptr, nullptr)
3227 {
3228 }
3229
3230 Controller::Controller( ControlInterface* controlInterface,
3231                         EditableControlInterface* editableControlInterface,
3232                         SelectableControlInterface* selectableControlInterface )
3233 : mImpl(new Controller::Impl(controlInterface, editableControlInterface, selectableControlInterface))
3234 {
3235 }
3236
3237 // The copy constructor and operator are left unimplemented.
3238
3239 // protected : Destructor.
3240
3241 Controller::~Controller()
3242 {
3243   delete mImpl;
3244 }
3245
3246 } // namespace Text
3247
3248 } // namespace Toolkit
3249
3250 } // namespace Dali