Support Shift+Left/Right keys for text selection and Ctrl+C/V/X for text copy/paste/cut
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller.cpp
old mode 100644 (file)
new mode 100755 (executable)
index b2fec63..1c15e22
 #include <dali/integration-api/debug.h>
 #include <dali/devel-api/adaptor-framework/clipboard-event-notifier.h>
 #include <dali/devel-api/text-abstraction/font-client.h>
+#include <dali/devel-api/adaptor-framework/key-devel.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/text-controls/placeholder-properties.h>
 #include <dali-toolkit/internal/text/bidirectional-support.h>
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
@@ -47,12 +49,18 @@ const float MAX_FLOAT = std::numeric_limits<float>::max();
 
 const std::string EMPTY_STRING("");
 
-const char * const PLACEHOLDER_TEXT = "placeholderText";
-const char * const PLACEHOLDER_COLOR = "placeholderColor";
-const char * const PLACEHOLDER_FONT_FAMILY = "placeholderFontFamily";
-const char * const PLACEHOLDER_FONT_STYLE = "placeholderFontStyle";
-const char * const PLACEHOLDER_POINT_SIZE = "placeholderPointSize";
-const char * const PLACEHOLDER_PIXEL_SIZE = "placeholderPixelSize";
+const std::string KEY_C_NAME = "c";
+const std::string KEY_V_NAME = "v";
+const std::string KEY_X_NAME = "x";
+
+const char * const PLACEHOLDER_TEXT = "text";
+const char * const PLACEHOLDER_TEXT_FOCUSED = "textFocused";
+const char * const PLACEHOLDER_COLOR = "color";
+const char * const PLACEHOLDER_FONT_FAMILY = "fontFamily";
+const char * const PLACEHOLDER_FONT_STYLE = "fontStyle";
+const char * const PLACEHOLDER_POINT_SIZE = "pointSize";
+const char * const PLACEHOLDER_PIXEL_SIZE = "pixelSize";
+const char * const PLACEHOLDER_ELLIPSIS = "ellipsis";
 
 float ConvertToEven( float value )
 {
@@ -343,6 +351,7 @@ void Controller::SetMultiLineEnabled( bool enable )
                                                                           ALIGN              |
                                                                           REORDER );
 
+    mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | layoutOperations );
 
     mImpl->RequestRelayout();
@@ -354,7 +363,7 @@ bool Controller::IsMultiLineEnabled() const
   return Layout::Engine::MULTI_LINE_BOX == mImpl->mLayoutEngine.GetLayout();
 }
 
-void Controller::SetHorizontalAlignment( Layout::HorizontalAlignment alignment )
+void Controller::SetHorizontalAlignment( Text::HorizontalAlignment::Type alignment )
 {
   if( alignment != mImpl->mModel->mHorizontalAlignment )
   {
@@ -368,12 +377,12 @@ void Controller::SetHorizontalAlignment( Layout::HorizontalAlignment alignment )
   }
 }
 
-Layout::HorizontalAlignment Controller::GetHorizontalAlignment() const
+Text::HorizontalAlignment::Type Controller::GetHorizontalAlignment() const
 {
   return mImpl->mModel->mHorizontalAlignment;
 }
 
-void Controller::SetVerticalAlignment( Layout::VerticalAlignment alignment )
+void Controller::SetVerticalAlignment( VerticalAlignment::Type alignment )
 {
   if( alignment != mImpl->mModel->mVerticalAlignment )
   {
@@ -386,11 +395,39 @@ void Controller::SetVerticalAlignment( Layout::VerticalAlignment alignment )
   }
 }
 
-Layout::VerticalAlignment Controller::GetVerticalAlignment() const
+VerticalAlignment::Type Controller::GetVerticalAlignment() const
 {
   return mImpl->mModel->mVerticalAlignment;
 }
 
+void Controller::SetLineWrapMode( Text::LineWrap::Mode lineWrapMode )
+{
+  if( lineWrapMode != mImpl->mModel->mLineWrapMode )
+  {
+    // Set the text wrap mode.
+    mImpl->mModel->mLineWrapMode = lineWrapMode;
+
+
+    // Update Text layout for applying wrap mode
+    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
+                                                             ALIGN                     |
+                                                             LAYOUT                    |
+                                                             UPDATE_LAYOUT_SIZE        |
+                                                             REORDER                   );
+    mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
+    mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
+    mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
+
+    // Request relayout
+    mImpl->RequestRelayout();
+  }
+}
+
+Text::LineWrap::Mode Controller::GetLineWrapMode() const
+{
+  return mImpl->mModel->mLineWrapMode;
+}
+
 void Controller::SetTextElideEnabled( bool enabled )
 {
   mImpl->mModel->mElideEnabled = enabled;
@@ -401,6 +438,24 @@ bool Controller::IsTextElideEnabled() const
   return mImpl->mModel->mElideEnabled;
 }
 
+void Controller::SetPlaceholderTextElideEnabled( bool enabled )
+{
+  mImpl->mEventData->mIsPlaceholderElideEnabled = enabled;
+  mImpl->mEventData->mPlaceholderEllipsisFlag = true;
+
+  // Update placeholder if there is no text
+  if( mImpl->IsShowingPlaceholderText() ||
+      ( 0u == mImpl->mModel->mLogicalModel->mText.Count() ) )
+  {
+    ShowPlaceholderText();
+  }
+}
+
+bool Controller::IsPlaceholderTextElideEnabled() const
+{
+  return mImpl->mEventData->mIsPlaceholderElideEnabled;
+}
+
 void Controller::SetSelectionEnabled( bool enabled )
 {
   mImpl->mEventData->mSelectionEnabled = enabled;
@@ -531,22 +586,6 @@ void Controller::GetText( std::string& text ) const
   }
 }
 
-void Controller::SetPlaceholderText( const std::string& text )
-{
-  if( NULL != mImpl->mEventData )
-  {
-    mImpl->mEventData->mPlaceholderText = text;
-
-    // Update placeholder if there is no text
-    if( mImpl->IsShowingPlaceholderText() ||
-        ( 0u == mImpl->mModel->mLogicalModel->mText.Count() ) )
-    {
-      ShowPlaceholderText();
-    }
-  }
-}
-
-// This is overloading function for PLACEHOLDER_TEXT_FOCUSED in text-field
 void Controller::SetPlaceholderText( PlaceholderType type, const std::string& text )
 {
   if( NULL != mImpl->mEventData )
@@ -569,15 +608,6 @@ void Controller::SetPlaceholderText( PlaceholderType type, const std::string& te
   }
 }
 
-void Controller::GetPlaceholderText( std::string& text ) const
-{
-  if( NULL != mImpl->mEventData )
-  {
-    text = mImpl->mEventData->mPlaceholderText;
-  }
-}
-
-// This is overloading function for PLACEHOLDER_TEXT_FOCUSED in text-field
 void Controller::GetPlaceholderText( PlaceholderType type, std::string& text ) const
 {
   if( NULL != mImpl->mEventData )
@@ -682,7 +712,12 @@ void Controller::SetDefaultFontWeight( FontWeight weight )
 
 bool Controller::IsDefaultFontWeightDefined() const
 {
-  return mImpl->mFontDefaults->weightDefined;
+  if( NULL != mImpl->mFontDefaults )
+  {
+    return mImpl->mFontDefaults->weightDefined;
+  }
+
+  return false;
 }
 
 FontWeight Controller::GetDefaultFontWeight() const
@@ -748,7 +783,12 @@ void Controller::SetDefaultFontWidth( FontWidth width )
 
 bool Controller::IsDefaultFontWidthDefined() const
 {
-  return mImpl->mFontDefaults->widthDefined;
+  if( NULL != mImpl->mFontDefaults )
+  {
+    return mImpl->mFontDefaults->widthDefined;
+  }
+
+  return false;
 }
 
 FontWidth Controller::GetDefaultFontWidth() const
@@ -814,7 +854,11 @@ void Controller::SetDefaultFontSlant( FontSlant slant )
 
 bool Controller::IsDefaultFontSlantDefined() const
 {
-  return mImpl->mFontDefaults->slantDefined;
+  if( NULL != mImpl->mFontDefaults )
+  {
+    return mImpl->mFontDefaults->slantDefined;
+  }
+  return false;
 }
 
 FontSlant Controller::GetDefaultFontSlant() const
@@ -1075,6 +1119,21 @@ const Vector4& Controller::GetShadowColor() const
   return mImpl->mModel->mVisualModel->GetShadowColor();
 }
 
+void Controller::SetShadowBlurRadius( const float& shadowBlurRadius )
+{
+  if ( fabsf( GetShadowBlurRadius() - shadowBlurRadius ) > Math::MACHINE_EPSILON_1 )
+  {
+    mImpl->mModel->mVisualModel->SetShadowBlurRadius( shadowBlurRadius );
+
+    mImpl->RequestRelayout();
+  }
+}
+
+const float& Controller::GetShadowBlurRadius() const
+{
+  return mImpl->mModel->mVisualModel->GetShadowBlurRadius();
+}
+
 void Controller::SetUnderlineColor( const Vector4& color )
 {
   mImpl->mModel->mVisualModel->SetUnderlineColor( color );
@@ -1111,6 +1170,30 @@ float Controller::GetUnderlineHeight() const
   return mImpl->mModel->mVisualModel->GetUnderlineHeight();
 }
 
+void Controller::SetOutlineColor( const Vector4& color )
+{
+  mImpl->mModel->mVisualModel->SetOutlineColor( color );
+
+  mImpl->RequestRelayout();
+}
+
+const Vector4& Controller::GetOutlineColor() const
+{
+  return mImpl->mModel->mVisualModel->GetOutlineColor();
+}
+
+void Controller::SetOutlineWidth( float width )
+{
+  mImpl->mModel->mVisualModel->SetOutlineWidth( width );
+
+  mImpl->RequestRelayout();
+}
+
+float Controller::GetOutlineWidth() const
+{
+  return mImpl->mModel->mVisualModel->GetOutlineWidth();
+}
+
 void Controller::SetDefaultEmbossProperties( const std::string& embossProperties )
 {
   if( NULL == mImpl->mEmbossDefaults )
@@ -1689,6 +1772,16 @@ void Controller::ShadowSetByString( bool setByString )
   mImpl->mShadowSetByString = setByString;
 }
 
+bool Controller::IsOutlineSetByString()
+{
+  return mImpl->mOutlineSetByString;
+}
+
+void Controller::OutlineSetByString( bool setByString )
+{
+  mImpl->mOutlineSetByString = setByString;
+}
+
 bool Controller::IsFontStyleSetByString()
 {
   return mImpl->mFontStyleSetByString;
@@ -1739,14 +1832,14 @@ Vector3 Controller::GetNaturalSize()
     mImpl->UpdateModel( onlyOnceOperations );
 
     // Layout the text for the new width.
-    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | LAYOUT );
+    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | LAYOUT | REORDER );
 
     // Store the actual control's size to restore later.
     const Size actualControlSize = mImpl->mModel->mVisualModel->mControlSize;
 
     DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ),
                 static_cast<OperationsMask>( onlyOnceOperations |
-                                             LAYOUT ),
+                                             LAYOUT | REORDER ),
                 naturalSize.GetVectorXY() );
 
     // Do not do again the only once operations.
@@ -1792,7 +1885,9 @@ float Controller::GetHeightForWidth( float width )
   ProcessModifyEvents();
 
   Size layoutSize;
-  if( fabsf( width - mImpl->mModel->mVisualModel->mControlSize.width ) > Math::MACHINE_EPSILON_1000 )
+  if( fabsf( width - mImpl->mModel->mVisualModel->mControlSize.width ) > Math::MACHINE_EPSILON_1000 ||
+                                                         mImpl->mTextUpdateInfo.mFullRelayoutNeeded ||
+                                                         mImpl->mTextUpdateInfo.mClearAll            )
   {
     // Operations that can be done only once until the text changes.
     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32  |
@@ -1913,13 +2008,19 @@ void Controller::SetPlaceholderProperty( const Property::Map& map )
     Property::Key& key = keyValue.first;
     Property::Value& value = keyValue.second;
 
-    if( key == PLACEHOLDER_TEXT )
+    if( key == Toolkit::Text::PlaceHolder::Property::TEXT  || key == PLACEHOLDER_TEXT )
+    {
+      std::string text = "";
+      value.Get( text );
+      SetPlaceholderText( Controller::PLACEHOLDER_TYPE_INACTIVE, text );
+    }
+    else if( key == Toolkit::Text::PlaceHolder::Property::TEXT_FOCUSED || key == PLACEHOLDER_TEXT_FOCUSED )
     {
       std::string text = "";
       value.Get( text );
-      SetPlaceholderText( text );
+      SetPlaceholderText( Controller::PLACEHOLDER_TYPE_ACTIVE, text );
     }
-    else if( key == PLACEHOLDER_COLOR )
+    else if( key == Toolkit::Text::PlaceHolder::Property::COLOR || key == PLACEHOLDER_COLOR )
     {
       Vector4 textColor;
       value.Get( textColor );
@@ -1928,17 +2029,17 @@ void Controller::SetPlaceholderProperty( const Property::Map& map )
         SetPlaceholderTextColor( textColor );
       }
     }
-    else if( key == PLACEHOLDER_FONT_FAMILY )
+    else if( key == Toolkit::Text::PlaceHolder::Property::FONT_FAMILY || key == PLACEHOLDER_FONT_FAMILY )
     {
       std::string fontFamily = "";
       value.Get( fontFamily );
       SetPlaceholderFontFamily( fontFamily );
     }
-    else if( key == PLACEHOLDER_FONT_STYLE )
+    else if( key == Toolkit::Text::PlaceHolder::Property::FONT_STYLE || key == PLACEHOLDER_FONT_STYLE )
     {
       SetFontStyleProperty( this, value, Text::FontStyle::PLACEHOLDER );
     }
-    else if( key == PLACEHOLDER_POINT_SIZE )
+    else if( key == Toolkit::Text::PlaceHolder::Property::POINT_SIZE || key == PLACEHOLDER_POINT_SIZE )
     {
       float pointSize;
       value.Get( pointSize );
@@ -1947,7 +2048,7 @@ void Controller::SetPlaceholderProperty( const Property::Map& map )
         SetPlaceholderTextFontSize( pointSize, Text::Controller::POINT_SIZE );
       }
     }
-    else if( key == PLACEHOLDER_PIXEL_SIZE )
+    else if( key == Toolkit::Text::PlaceHolder::Property::PIXEL_SIZE || key == PLACEHOLDER_PIXEL_SIZE )
     {
       float pixelSize;
       value.Get( pixelSize );
@@ -1956,6 +2057,12 @@ void Controller::SetPlaceholderProperty( const Property::Map& map )
         SetPlaceholderTextFontSize( pixelSize, Text::Controller::PIXEL_SIZE );
       }
     }
+    else if( key == Toolkit::Text::PlaceHolder::Property::ELLIPSIS || key == PLACEHOLDER_ELLIPSIS )
+    {
+      bool ellipsis;
+      value.Get( ellipsis );
+      SetPlaceholderTextElideEnabled( ellipsis );
+    }
   }
 }
 
@@ -1963,26 +2070,50 @@ void Controller::GetPlaceholderProperty( Property::Map& map )
 {
   if( NULL != mImpl->mEventData )
   {
-    map[ PLACEHOLDER_TEXT ] = mImpl->mEventData->mPlaceholderText;
-    map[ PLACEHOLDER_COLOR ] = mImpl->mEventData->mPlaceholderTextColor;
-    map[ PLACEHOLDER_FONT_FAMILY ] = GetPlaceholderFontFamily();
+    if( !mImpl->mEventData->mPlaceholderTextActive.empty() )
+    {
+      map[ Text::PlaceHolder::Property::TEXT_FOCUSED ] = mImpl->mEventData->mPlaceholderTextActive;
+    }
+    if( !mImpl->mEventData->mPlaceholderTextInactive.empty() )
+    {
+      map[ Text::PlaceHolder::Property::TEXT ] = mImpl->mEventData->mPlaceholderTextInactive;
+    }
+
+    map[ Text::PlaceHolder::Property::COLOR ] = mImpl->mEventData->mPlaceholderTextColor;
+    map[ Text::PlaceHolder::Property::FONT_FAMILY ] = GetPlaceholderFontFamily();
 
     Property::Value fontStyleMapGet;
     GetFontStyleProperty( this, fontStyleMapGet, Text::FontStyle::PLACEHOLDER );
-    map[ PLACEHOLDER_FONT_STYLE ] = fontStyleMapGet;
+    map[ Text::PlaceHolder::Property::FONT_STYLE ] = fontStyleMapGet;
 
     // Choose font size : POINT_SIZE or PIXEL_SIZE
     if( !mImpl->mEventData->mIsPlaceholderPixelSize )
     {
-      map[ PLACEHOLDER_POINT_SIZE ] = GetPlaceholderTextFontSize( Text::Controller::POINT_SIZE );
+      map[ Text::PlaceHolder::Property::POINT_SIZE ] = GetPlaceholderTextFontSize( Text::Controller::POINT_SIZE );
     }
     else
     {
-      map[ PLACEHOLDER_PIXEL_SIZE ] = GetPlaceholderTextFontSize( Text::Controller::PIXEL_SIZE );
+      map[ Text::PlaceHolder::Property::PIXEL_SIZE ] = GetPlaceholderTextFontSize( Text::Controller::PIXEL_SIZE );
+    }
+
+    if( mImpl->mEventData->mPlaceholderEllipsisFlag )
+    {
+      map[ Text::PlaceHolder::Property::ELLIPSIS ] = IsPlaceholderTextElideEnabled();
     }
   }
 }
 
+Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
+{
+  const LineRun* const firstline = mImpl->mModel->mVisualModel->mLines.Begin();
+  if ( firstline && firstline->direction )
+  {
+    return Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT;
+  }
+
+  return Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT;
+}
+
 // public : Relayout.
 
 Controller::UpdateTextType Controller::Relayout( const Size& size )
@@ -2037,6 +2168,20 @@ Controller::UpdateTextType Controller::Relayout( const Size& size )
                                                              COLOR );
   }
 
+  // Set the update info to elide the text.
+  if( mImpl->mModel->mElideEnabled ||
+      ( ( NULL != mImpl->mEventData ) && mImpl->mEventData->mIsPlaceholderElideEnabled ) )
+  {
+    // Update Text layout for applying elided
+    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
+                                                             ALIGN                     |
+                                                             LAYOUT                    |
+                                                             UPDATE_LAYOUT_SIZE        |
+                                                             REORDER );
+    mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
+    mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
+  }
+
   // Make sure the model is up-to-date before layouting.
   ProcessModifyEvents();
   bool updated = mImpl->UpdateModel( mImpl->mOperationsPending );
@@ -2192,6 +2337,7 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
   {
     int keyCode = keyEvent.keyCode;
     const std::string& keyString = keyEvent.keyPressed;
+    const std::string keyName = keyEvent.keyPressedName;
 
     const bool isNullKey = ( 0 == keyCode ) && ( keyString.empty() );
 
@@ -2200,14 +2346,12 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
     {
       // In some platforms arrive key events with no key code.
       // Do nothing.
+      return false;
     }
-    else if( Dali::DALI_KEY_ESCAPE == keyCode )
+    else if( Dali::DALI_KEY_ESCAPE == keyCode || Dali::DALI_KEY_BACK == keyCode  || Dali::DALI_KEY_SEARCH == keyCode )
     {
-      // Escape key is a special case which causes focus loss
-      KeyboardFocusLostEvent();
-
-      // Will request for relayout.
-      relayoutNeeded = true;
+      // Do nothing
+      return false;
     }
     else if( ( Dali::DALI_KEY_CURSOR_LEFT  == keyCode ) ||
              ( Dali::DALI_KEY_CURSOR_RIGHT == keyCode ) ||
@@ -2239,14 +2383,47 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
       mImpl->mEventData->mCheckScrollAmount = true;
       Event event( Event::CURSOR_KEY_EVENT );
       event.p1.mInt = keyCode;
+      event.p2.mBool = keyEvent.IsShiftModifier();
       mImpl->mEventData->mEventQueue.push_back( event );
 
       // Will request for relayout.
       relayoutNeeded = true;
     }
-    else if( Dali::DALI_KEY_BACKSPACE == keyCode )
+    else if ( Dali::DevelKey::DALI_KEY_CONTROL_LEFT == keyCode || Dali::DevelKey::DALI_KEY_CONTROL_RIGHT == keyCode )
     {
-      textChanged = BackspaceKeyEvent();
+      // Left or Right Control key event is received before Ctrl-C/V/X key event is received
+      // If not handle it here, any selected text will be deleted
+
+      // Do nothing
+      return false;
+    }
+    else if ( keyEvent.IsCtrlModifier() )
+    {
+      bool consumed = false;
+      if (keyName == KEY_C_NAME)
+      {
+        // Ctrl-C to copy the selected text
+        TextPopupButtonTouched( Toolkit::TextSelectionPopup::COPY );
+        consumed = true;
+      }
+      else if (keyName == KEY_V_NAME)
+      {
+        // Ctrl-V to paste the copied text
+        TextPopupButtonTouched( Toolkit::TextSelectionPopup::PASTE );
+        consumed = true;
+      }
+      else if (keyName == KEY_X_NAME)
+      {
+        // Ctrl-X to cut the selected text
+        TextPopupButtonTouched( Toolkit::TextSelectionPopup::CUT );
+        consumed = true;
+      }
+      return consumed;
+    }
+    else if( ( Dali::DALI_KEY_BACKSPACE == keyCode ) ||
+             ( Dali::DevelKey::DALI_KEY_DELETE == keyCode ) )
+    {
+      textChanged = DeleteEvent( keyCode );
 
       // Will request for relayout.
       relayoutNeeded = true;
@@ -2269,11 +2446,13 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
       // and a character is typed after the type of a upper case latin character.
 
       // Do nothing.
+      return false;
     }
     else if( ( Dali::DALI_KEY_VOLUME_UP == keyCode ) || ( Dali::DALI_KEY_VOLUME_DOWN == keyCode ) )
     {
       // This branch avoids calling the InsertText() method of the 'else' branch which can delete selected text.
       // Do nothing.
+      return false;
     }
     else
     {
@@ -3191,6 +3370,7 @@ bool Controller::DoRelayout( const Size& size,
     const Vector<CharacterIndex>& glyphsToCharactersMap = mImpl->mModel->mVisualModel->mGlyphsToCharacters;
     const Vector<Length>& charactersPerGlyph = mImpl->mModel->mVisualModel->mCharactersPerGlyph;
     const Character* const textBuffer = mImpl->mModel->mLogicalModel->mText.Begin();
+    float outlineWidth = mImpl->mModel->GetOutlineWidth();
 
     // Set the layout parameters.
     Layout::Parameters layoutParameters( size,
@@ -3204,7 +3384,9 @@ bool Controller::DoRelayout( const Size& size,
                                          charactersToGlyphBuffer,
                                          glyphsPerCharacterBuffer,
                                          totalNumberOfGlyphs,
-                                         mImpl->mModel->mHorizontalAlignment );
+                                         mImpl->mModel->mHorizontalAlignment,
+                                         mImpl->mModel->mLineWrapMode,
+                                         outlineWidth );
 
     // Resize the vector of positions to have the same size than the vector of glyphs.
     Vector<Vector2>& glyphPositions = mImpl->mModel->mVisualModel->mGlyphPositions;
@@ -3220,13 +3402,35 @@ bool Controller::DoRelayout( const Size& size,
     layoutParameters.startLineIndex = mImpl->mTextUpdateInfo.mStartLineIndex;
     layoutParameters.estimatedNumberOfLines = mImpl->mTextUpdateInfo.mEstimatedNumberOfLines;
 
+    // Update the ellipsis
+    bool elideTextEnabled = mImpl->mModel->mElideEnabled;
+
+    if( NULL != mImpl->mEventData )
+    {
+      if( mImpl->mEventData->mPlaceholderEllipsisFlag && mImpl->IsShowingPlaceholderText() )
+      {
+        elideTextEnabled = mImpl->mEventData->mIsPlaceholderElideEnabled;
+      }
+      else if( EventData::INACTIVE != mImpl->mEventData->mState )
+      {
+        // Disable ellipsis when editing
+        elideTextEnabled = false;
+      }
+
+      // Reset the scroll position in inactive state
+      if( elideTextEnabled && ( mImpl->mEventData->mState == EventData::INACTIVE ) )
+      {
+        ResetScrollPosition();
+      }
+    }
+
     // Update the visual model.
     Size newLayoutSize;
     viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters,
                                                    glyphPositions,
                                                    mImpl->mModel->mVisualModel->mLines,
                                                    newLayoutSize,
-                                                   mImpl->mModel->mElideEnabled );
+                                                   elideTextEnabled );
 
     viewUpdated = viewUpdated || ( newLayoutSize != layoutSize );
 
@@ -3325,17 +3529,17 @@ void Controller::CalculateVerticalOffset( const Size& controlSize )
 
   switch( mImpl->mModel->mVerticalAlignment )
   {
-    case Layout::VERTICAL_ALIGN_TOP:
+    case VerticalAlignment::TOP:
     {
       mImpl->mModel->mScrollPosition.y = 0.f;
       break;
     }
-    case Layout::VERTICAL_ALIGN_CENTER:
+    case VerticalAlignment::CENTER:
     {
       mImpl->mModel->mScrollPosition.y = floorf( 0.5f * ( controlSize.height - layoutSize.height ) ); // try to avoid pixel alignment.
       break;
     }
-    case Layout::VERTICAL_ALIGN_BOTTOM:
+    case VerticalAlignment::BOTTOM:
     {
       mImpl->mModel->mScrollPosition.y = controlSize.height - layoutSize.height;
       break;
@@ -3387,6 +3591,10 @@ void Controller::ProcessModifyEvents()
   {
     // When the text is being modified, delay cursor blinking
     mImpl->mEventData->mDecorator->DelayCursorBlink();
+
+    // Update selection position after modifying the text
+    mImpl->mEventData->mLeftSelectionPosition = mImpl->mEventData->mPrimaryCursorPosition;
+    mImpl->mEventData->mRightSelectionPosition = mImpl->mEventData->mPrimaryCursorPosition;
   }
 
   // Discard temporary text
@@ -3464,9 +3672,9 @@ void Controller::SelectEvent( float x, float y, bool selectAll )
   }
 }
 
-bool Controller::BackspaceKeyEvent()
+bool Controller::DeleteEvent( int keyCode )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::KeyEvent %p DALI_KEY_BACKSPACE\n", this );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::KeyEvent %p KeyCode : %d \n", this, keyCode );
 
   bool removed = false;
 
@@ -3482,13 +3690,20 @@ bool Controller::BackspaceKeyEvent()
   {
     removed = RemoveSelectedText();
   }
-  else if( mImpl->mEventData->mPrimaryCursorPosition > 0 )
+  else if( ( mImpl->mEventData->mPrimaryCursorPosition > 0 ) && ( keyCode == Dali::DALI_KEY_BACKSPACE) )
   {
     // Remove the character before the current cursor position
     removed = RemoveText( -1,
                           1,
                           UPDATE_INPUT_STYLE );
   }
+  else if( ( mImpl->mEventData->mPrimaryCursorPosition >= 0 ) && ( keyCode == Dali::DevelKey::DALI_KEY_DELETE ) )
+  {
+    // Remove the character after the current cursor position
+    removed = RemoveText( 0,
+                          1,
+                          UPDATE_INPUT_STYLE );
+  }
 
   if( removed )
   {
@@ -3553,27 +3768,17 @@ void Controller::ShowPlaceholderText()
     const char* text( NULL );
     size_t size( 0 );
 
-    if( !mImpl->mEventData->mPlaceholderTextActive.empty() || !mImpl->mEventData->mPlaceholderTextInactive.empty() )
+    // TODO - Switch Placeholder text when changing state
+    if( ( EventData::INACTIVE != mImpl->mEventData->mState ) &&
+        ( 0u != mImpl->mEventData->mPlaceholderTextActive.c_str() ) )
     {
-      if( ( EventData::INACTIVE != mImpl->mEventData->mState ) &&
-          ( 0u != mImpl->mEventData->mPlaceholderTextActive.c_str() ) )
-      {
-        text = mImpl->mEventData->mPlaceholderTextActive.c_str();
-        size = mImpl->mEventData->mPlaceholderTextActive.size();
-      }
-      else
-      {
-        text = mImpl->mEventData->mPlaceholderTextInactive.c_str();
-        size = mImpl->mEventData->mPlaceholderTextInactive.size();
-      }
+      text = mImpl->mEventData->mPlaceholderTextActive.c_str();
+      size = mImpl->mEventData->mPlaceholderTextActive.size();
     }
     else
     {
-      if( 0u != mImpl->mEventData->mPlaceholderText.c_str() )
-      {
-        text = mImpl->mEventData->mPlaceholderText.c_str();
-        size = mImpl->mEventData->mPlaceholderText.size();
-      }
+      text = mImpl->mEventData->mPlaceholderTextInactive.c_str();
+      size = mImpl->mEventData->mPlaceholderTextInactive.size();
     }
 
     mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
@@ -3669,6 +3874,16 @@ void Controller::ResetScrollPosition()
   }
 }
 
+void Controller::SetControlInterface( ControlInterface* controlInterface )
+{
+  mImpl->mControlInterface = controlInterface;
+}
+
+bool Controller::ShouldClearFocusOnEscape() const
+{
+  return mImpl->mShouldClearFocusOnEscape;
+}
+
 // private : Private contructors & copy operator.
 
 Controller::Controller()