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