TextInput Decorator class and stubbed decoration classes
authorAgnelo Vaz <agnelo.vaz@samsung.com>
Thu, 24 Apr 2014 20:27:25 +0000 (21:27 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Thu, 15 May 2014 11:54:38 +0000 (12:54 +0100)
Problem:TextInput is a huge class with many responsibilities, it's hard to maintain and decorations can not be re-used.
Solution: Spilt into multiple classes. In this patch the Decorator initiates creation of decorations and positions them.
Stubbed Decoration classes provided for build purposes.

Change-Id: Ib880849dbc80cb1b6510a06401f5a6bfccfa55e8
Signed-off-by: Agnelo Vaz <agnelo.vaz@samsung.com>
base/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.cpp [new file with mode: 0644]
base/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.h [new file with mode: 0644]
base/dali-toolkit/internal/controls/text-input/text-input-handles-impl.h [new file with mode: 0644]
base/dali-toolkit/internal/controls/text-input/text-input-popup-new-impl.h [new file with mode: 0644]
base/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.h [new file with mode: 0644]
base/dali-toolkit/internal/controls/text-input/text-input-text-style-impl.h [new file with mode: 0644]
base/dali-toolkit/internal/controls/text-input/textview-character-positions-impl.h [new file with mode: 0644]
base/dali-toolkit/internal/file.list

diff --git a/base/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.cpp b/base/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.cpp
new file mode 100644 (file)
index 0000000..1e034a3
--- /dev/null
@@ -0,0 +1,1221 @@
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/text-input/text-input-decorator-impl.h>
+
+#include <dali-toolkit/internal/controls/text-input/text-input-handles-impl.h>
+
+using namespace Dali;
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+  Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TEXT_INPUT_DECORATOR");
+#endif
+
+  const Vector3 DEFAULT_SELECTION_HANDLE_SIZE( 51.0f, 79.0f, 0.0f );
+  const float TOP_HANDLE_TOP_OFFSET(-1.5f);                                   // Offset between top handle and cutCopyPaste pop-up
+  const float BOTTOM_HANDLE_BOTTOM_OFFSET(1.5f);                              // Offset between bottom handle and cutCopyPaste pop-up
+  const float UI_Z_OFFSET( 0.2f );                                            // Text Selection Handles/Cursor z-offset.
+  const Vector3 UI_OFFSET(0.0f, 0.0f, UI_Z_OFFSET);                           // Text Selection Handles/Cursor offset.
+  const char* DEFAULT_CURSOR( DALI_IMAGE_DIR "cursor.png" );
+  const Vector4 DEFAULT_CURSOR_IMAGE_9_BORDER( 2.0f, 2.0f, 2.0f, 2.0f );
+  const std::size_t CURSOR_BLINK_INTERVAL = 500;                              // Cursor blink interval
+  const float CURSOR_THICKNESS(6.0f);
+  const Degree CURSOR_ANGLE_OFFSET(2.0f);                                     // Offset from the angle
+
+  const unsigned int SCROLL_TICK_INTERVAL = 50u;
+  const float SCROLL_THRESHOLD = 10.f;
+  const float SCROLL_SPEED = 15.f;
+
+  /**
+   * Whether the given position plus the cursor size offset is inside the given boundary.
+   *
+   * @param[in] position The given position.
+   * @param[in] cursorSize The cursor size.
+   * @param[in] controlSize The given boundary.
+   * @param[in] threshold imaginary indent around boundary that will trigger the position to be outside of control.
+   *
+   * @return whether the given position is inside the given boundary.
+   */
+  bool IsPositionWithinControl( const Vector3& position, const Size& cursorSize, const Vector3& controlSize, const Vector2 threshold = Vector2::ZERO )
+  {
+    return ( position.x >= -Math::MACHINE_EPSILON_1000 + threshold.x ) &&
+           ( position.x <= controlSize.width - threshold.x + Math::MACHINE_EPSILON_1000 ) &&
+           ( position.y - cursorSize.height >= -Math::MACHINE_EPSILON_1000 + threshold.y ) &&
+           ( position.y <= controlSize.height + Math::MACHINE_EPSILON_1000 - threshold.y);
+  }
+}
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+Decorator::Decorator( TextViewCharacterPositioning& textViewManager, TextInputTextStyle& textStyle ):
+  mTextViewCharacterPositioning( textViewManager ),
+  mTextStyle( textStyle ),
+  mCursorPosition( 0 ),
+  mTextHighlight( textViewManager ),
+  mCursorBlinkStatus( true ),
+  mCursorVisibility( true ),
+  mGrabHandleEnabled( true )
+{
+}
+
+Decorator::~Decorator()
+{
+}
+
+/**
+ * Bounding Box
+ */
+void Decorator::SetBoundingBox( const Rect<float>& boundingRectangle )
+{
+  // Convert to world coordinates and store as a Vector4 to be compatible with Property Notifications.
+  Vector2 stageSize = Dali::Stage::GetCurrent().GetSize();
+
+  const float originX = boundingRectangle.x - 0.5f * stageSize.width;
+  const float originY = boundingRectangle.y - 0.5f * stageSize.height;
+
+  const Vector4 boundary( originX,
+                          originY,
+                          originX + boundingRectangle.width,
+                          originY + boundingRectangle.height );
+
+  mBoundingRectangleWorldCoordinates = boundary;
+}
+
+Vector4 Decorator::GetBoundingBox() const
+{
+  return mBoundingRectangleWorldCoordinates;
+}
+
+/**
+ * Selection Handles
+ */
+void Decorator::OnHandlePan(Actor actor, PanGesture gesture)
+{
+  Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne();
+  Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo();
+
+  switch (gesture.state)
+  {
+    case Gesture::Started:
+    // fall through so code not duplicated
+    case Gesture::Continuing:
+    {
+      if ( actor.GetParent() == mTextInputHandles.GetSelectionHandleOne() )
+      {
+        MoveSelectionHandle( selectionHandleOne, mSelectionHandleOneActualPosition, mSelectionHandleOnePosition, gesture.displacement );
+        HidePopUp();
+      }
+      else if ( actor.GetParent() == mTextInputHandles.GetSelectionHandleTwo() )
+      {
+        MoveSelectionHandle( selectionHandleTwo, mSelectionHandleTwoActualPosition, mSelectionHandleTwoPosition, gesture.displacement );
+        HidePopUp();
+      }
+      else if ( actor.GetParent() == mTextInputHandles.GetGrabHandle() )
+      {
+        SetCursorVisibility( true );
+        ShowGrabHandle( mGrabHandleVisibility && mIsGrabHandleInScrollArea );
+        MoveGrabHandle( gesture.displacement );
+        HidePopUp(); // Do not show popup while handle is moving
+      }
+    }
+    break;
+
+    case Gesture::Finished:
+    {
+      // Revert back to non-pressed selection handle images
+      if ( actor.GetParent() == mTextInputHandles.GetSelectionHandleOne() )
+      {
+        mSelectionHandleOneActualPosition = MoveSelectionHandle( selectionHandleOne, mSelectionHandleOneActualPosition, mSelectionHandleOnePosition, gesture.displacement );
+        ShowPopupCutCopyPaste();
+        ShowPopUp();
+      }
+      else if ( actor.GetParent() == mTextInputHandles.GetSelectionHandleTwo() )
+      {
+        mSelectionHandleTwoActualPosition = MoveSelectionHandle( selectionHandleTwo, mSelectionHandleTwoActualPosition, mSelectionHandleTwoPosition, gesture.displacement );
+        ShowPopupCutCopyPaste();
+        ShowPopUp();
+      }
+      else if ( actor.GetParent() == mTextInputHandles.GetGrabHandle() )
+      {
+        MoveGrabHandle( gesture.displacement );
+        SetCursorVisibility( true );
+        ShowPopupCutCopyPaste();
+        ShowPopUp();
+      }
+    }
+    break;
+    default:
+      break;
+  }
+}
+
+void Decorator::CreateSelectionHandles( Actor targetParent )
+{
+  if ( !mPanGestureDetector )
+  {
+    mPanGestureDetector = PanGestureDetector::New();
+    mPanGestureDetector.DetectedSignal().Connect(this, &Decorator::OnHandlePan);
+  }
+
+  if ( !mTextInputHandles.GetSelectionHandleOne() )
+  {
+    mTextInputHandles.CreateSelectionHandles();
+
+    mTextInputHandles.AttachSelectionHandlesToGivenPanGesture( mPanGestureDetector );
+
+    targetParent.Add( mTextInputHandles.GetSelectionHandleOne() );
+    targetParent.Add( mTextInputHandles.GetSelectionHandleTwo() );
+
+    SetUpHandlePropertyNotifications();
+  }
+}
+
+void Decorator::RemoveSelectionHandles()
+{
+  mTextInputHandles.DestorySelectionHandles();
+}
+
+Vector3 Decorator::GetSelectionHandleSize()
+{
+  return DEFAULT_SELECTION_HANDLE_SIZE;
+}
+
+std::size_t Decorator::GetHandleOnePosition() const
+{
+  return mSelectionHandleOnePosition;
+}
+
+std::size_t Decorator::GetHandleTwoPosition() const
+{
+  return mSelectionHandleTwoPosition;
+}
+
+Vector3 Decorator::PositionSelectionHandle( Actor selectionHandle, std::size_t position )
+{
+  bool direction(false);
+  Vector3 alternatePosition;
+  bool alternatePositionValid(false);
+
+  Vector3 actualPositionOfSelectionHandle = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( position, direction, alternatePosition,alternatePositionValid );
+
+  return PositionSelectionHandle( selectionHandle, actualPositionOfSelectionHandle, position );
+
+}
+
+Vector3 Decorator::PositionSelectionHandle( Actor selectionHandle, Vector3& actualPosition, std::size_t position )
+{
+  const Vector3 DEFAULT_HANDLE_OFFSET(0.0f, -5.0f, 0.0f);
+
+  selectionHandle.SetPosition( actualPosition += DEFAULT_HANDLE_OFFSET );
+
+  if( mTextViewCharacterPositioning.IsScrollEnabled() )
+  {
+    const Vector3 controlSize = mTextViewCharacterPositioning.GetTextView().GetCurrentSize();
+    const Size cursorSize( GetCursorSizeAt( position ) );
+    bool handleVisible = IsPositionWithinControl( actualPosition, Vector2(DEFAULT_HANDLE_OFFSET.width, DEFAULT_HANDLE_OFFSET.height), controlSize );
+
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::PositionSelectionHandle controlSize[%f,%f] cursorSize[%f,%f] actualPos[%f,%f] visible[%s] \n",
+              controlSize.x, controlSize.y, cursorSize.x, cursorSize.y, actualPosition.x, actualPosition.y, ( handleVisible )?"true":"false" );
+
+    selectionHandle.SetVisible( handleVisible );
+  }
+  return actualPosition;
+}
+
+void Decorator::SetSelectionHandlesVisibility(bool visible )
+{
+  mTextInputHandles.SetSelectionHandleOneVisibility( visible );
+  mTextInputHandles.SetSelectionHandleTwoVisibility( visible );
+}
+
+bool Decorator::OnHandleReleased()
+{
+  ShowPopUp();
+  return false;
+}
+
+void Decorator::PositionSelectionHandles( std::size_t start, std::size_t end )
+{
+  mSelectionHandleOnePosition = start;
+  mSelectionHandleTwoPosition = end;
+
+  mTextViewCharacterPositioning.UpdateTextLayoutInfo();
+
+  mSelectionHandleOneActualPosition = PositionSelectionHandle( mTextInputHandles.GetSelectionHandleOne(), mSelectionHandleOnePosition );
+  mSelectionHandleTwoActualPosition = PositionSelectionHandle( mTextInputHandles.GetSelectionHandleTwo(), mSelectionHandleTwoPosition );
+
+  mTextInputHandles.ReleasedSignal().Connect( this, &Decorator::OnHandleReleased );
+}
+
+Vector3 Decorator::MoveSelectionHandle( Actor selectionHandle,
+                                                          Vector3& actualSelectionHandlePosition,
+                                                          std::size_t& currentSelectionHandlePosition,
+                                                          const Vector2& displacement )
+{
+  Vector3 actualHandlePosition;
+  actualSelectionHandlePosition.x += displacement.x * selectionHandle.GetCurrentScale().x;
+  actualSelectionHandlePosition.y += displacement.y * selectionHandle.GetCurrentScale().y;;
+
+  // Selection handles should jump to the nearest character
+  std::size_t newHandlePosition = 0;
+  newHandlePosition = mTextViewCharacterPositioning.ReturnClosestIndex( actualSelectionHandlePosition.GetVectorXY() );
+
+  bool direction(false);
+  Vector3 alternatePosition;
+  bool alternatePositionValid(false);
+  actualHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newHandlePosition,direction, alternatePosition, alternatePositionValid  );
+
+  bool handleVisible = true;
+
+  Vector2 min, max;
+  if( mTextViewCharacterPositioning.IsScrollEnabled() )
+  {
+    const Vector3 controlSize = mTextViewCharacterPositioning.GetTextView().GetCurrentSize();
+    const Size cursorSize( GetCursorSizeAt( newHandlePosition ) );
+
+    handleVisible = IsPositionWithinControl( actualHandlePosition,
+                                             cursorSize,
+                                             controlSize );
+
+    if( handleVisible )
+    {
+      StopScrollTimer();
+      mCurrentHandlePosition = actualHandlePosition;
+      mScrollDisplacement = Vector2::ZERO;
+    }
+    else
+    {
+
+      if( ( actualHandlePosition.x < SCROLL_THRESHOLD ) && ( displacement.x <= 0.f ) )
+      {
+        mScrollDisplacement.x = -SCROLL_SPEED;
+      }
+      else if( ( actualHandlePosition.x > controlSize.width - SCROLL_THRESHOLD ) && ( displacement.x >= 0.f ) )
+      {
+        mScrollDisplacement.x = SCROLL_SPEED;
+      }
+      if( ( actualHandlePosition.y < SCROLL_THRESHOLD ) && ( displacement.y <= 0.f ) )
+      {
+        mScrollDisplacement.y = -SCROLL_SPEED;
+      }
+      else if( ( actualHandlePosition.y > controlSize.height - SCROLL_THRESHOLD ) && ( displacement.y >= 0.f ) )
+      {
+        mScrollDisplacement.y = SCROLL_SPEED;
+      }
+      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::MoveSelectionHandle Handle not visible scroll displacement [%f]\n", mScrollDisplacement.x);
+
+      StartScrollTimer();
+   }
+  }
+
+  if ( handleVisible &&                                          // Ensure the handle is visible.
+     ( newHandlePosition != currentSelectionHandlePosition ) &&  // Ensure the handle has moved.
+     ( newHandlePosition != mSelectionHandleTwoPosition ) &&     // Ensure new handle position not the same position as an existing handle.
+     ( newHandlePosition != mSelectionHandleOnePosition ) )
+  {
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::MoveSelectionHandle Handle visible and moved]\n");
+
+    currentSelectionHandlePosition = newHandlePosition;
+
+    PositionSelectionHandle( selectionHandle, actualHandlePosition, newHandlePosition );
+
+    ShowUpdatedHighlight();
+
+    // Set Active Style to that of first character in selection
+    std::size_t firstHandleInSelection = std::min( mSelectionHandleOnePosition, mSelectionHandleTwoPosition );
+
+    const TextStyle inputStyle = mTextViewCharacterPositioning.GetStyleAt( firstHandleInSelection );
+    mTextStyle.SetInputStyle( inputStyle );
+  }
+  return actualHandlePosition; // Returns Handle position passed in if new value not assigned.
+}
+
+/**
+ * GrabHandle
+ */
+void Decorator::PositionGrabHandle( std::size_t positionInText )
+{
+  bool direction(false);
+  Vector3 alternatePosition;
+  bool alternatePositionValid(false);
+
+  mGrabHandlePosition = positionInText;
+
+  mTextViewCharacterPositioning.UpdateTextLayoutInfo();
+  mActualGrabHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( positionInText, direction, alternatePosition,alternatePositionValid );
+
+  mTextInputHandles.GetGrabHandle().SetPosition( mActualGrabHandlePosition );
+}
+
+void Decorator::MoveGrabHandle( const Vector2& displacement /*, std::size_t currentHandlePosition */)
+{
+  mActualGrabHandlePosition.x += displacement.x;
+  mActualGrabHandlePosition.y += displacement.y;
+
+  // Grab handle should jump to the nearest character and take cursor with it
+  std::size_t newHandlePosition = mTextViewCharacterPositioning.ReturnClosestIndex( mActualGrabHandlePosition.GetVectorXY() );
+
+  Vector3 actualHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newHandlePosition );
+
+  bool handleVisible = true;
+
+  if( mTextViewCharacterPositioning.IsScrollEnabled() )
+  {
+    const Vector3 controlSize = mTextViewCharacterPositioning.GetTextView().GetCurrentSize();
+    const Size cursorSize( GetCursorSizeAt( newHandlePosition ) );
+    // Scrolls the text if the handle is not in a visible position
+    handleVisible = IsPositionWithinControl( actualHandlePosition,
+                                                cursorSize,
+                                                controlSize );
+
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::MoveGrabHandle handleVisible[%s]\n", ( handleVisible )?"true":"false");
+
+    if( handleVisible )
+    {
+      StopScrollTimer();
+      mCurrentHandlePosition = actualHandlePosition;
+      mScrollDisplacement = Vector2::ZERO;
+    }
+    else
+    {
+      if( ( actualHandlePosition.x < SCROLL_THRESHOLD ) && ( displacement.x <= 0.f ) )
+      {
+        mScrollDisplacement.x = -SCROLL_SPEED;
+      }
+      else if( ( actualHandlePosition.x > controlSize.width - SCROLL_THRESHOLD ) && ( displacement.x >= 0.f ) )
+      {
+        mScrollDisplacement.x = SCROLL_SPEED;
+      }
+      if( ( actualHandlePosition.y < SCROLL_THRESHOLD ) && ( displacement.y <= 0.f ) )
+      {
+        mScrollDisplacement.y = -SCROLL_SPEED;
+      }
+      else if( ( actualHandlePosition.y > controlSize.height - SCROLL_THRESHOLD ) && ( displacement.y >= 0.f ) )
+      {
+        mScrollDisplacement.y = SCROLL_SPEED;
+      }
+      StartScrollTimer();
+    }
+  }
+
+    if( ( newHandlePosition != mGrabHandlePosition ) &&                           // Only redraw cursor and do updates if position changed
+        ( handleVisible ) )// and the new position is visible (if scroll is not enabled, it's always true).
+    {
+      mActualGrabHandlePosition = actualHandlePosition;
+      mTextInputHandles.GetGrabHandle().SetPosition( mActualGrabHandlePosition );
+
+      //PositionGrabHandle( newHandlePosition );
+      mGrabHandlePosition = newHandlePosition;
+      SetCurrentCursorPosition( mGrabHandlePosition );
+      DrawCursor( mGrabHandlePosition );
+
+      const std::size_t cursorPosition = GetCurrentCursorPosition();
+
+      // Let keyboard know the new cursor position so can 're-capture' for prediction.
+      mCursorRePositionedSignal.Emit();
+
+      // Set Input Style to that of cursor position
+      if ( !mTextViewCharacterPositioning.IsStyledTextEmpty()  && ( cursorPosition > 0 ) )
+      {
+        DALI_ASSERT_DEBUG( ( 0 <= cursorPosition-1 ) && ( cursorPosition-1 < mTextViewCharacterPositioning.StyledTextSize() ) );
+        const TextStyle inputStyle = mTextViewCharacterPositioning.GetStyleAt( cursorPosition-1 );
+        mTextStyle.SetInputStyle( inputStyle );
+      }
+    }
+}
+
+void Decorator::ShowGrabHandle( bool visible )
+{
+  mGrabHandleVisibility = visible;
+  mTextInputHandles.SetGrabHandleVisibility( visible );
+}
+
+void Decorator::CreateGrabHandle( Actor targetParent )
+{
+  if ( !mPanGestureDetector )
+  {
+    mPanGestureDetector = PanGestureDetector::New();
+    mPanGestureDetector.DetectedSignal().Connect(this, &Decorator::OnHandlePan);
+  }
+
+  if ( !mTextInputHandles.GetGrabHandle() )
+  {
+    mTextInputHandles.CreateGrabHandle();
+    mTextInputHandles.AttachGrabHandleToGivenPanGesture( mPanGestureDetector );
+    targetParent.Add( mTextInputHandles.GetGrabHandle() );
+  }
+}
+
+void Decorator::SetGrabHandleImage( Image image )
+{
+  mTextInputHandles.SetGrabHandleImage( image );
+}
+
+void Decorator::EnableGrabHandle( bool toggle)
+{
+  // enables grab handle with will in turn de-activate magnifier
+  mGrabHandleEnabled = toggle;
+}
+
+bool Decorator::IsGrabHandleEnabled()
+{
+  // if false then magnifier will be shown instead.
+  return mGrabHandleEnabled;
+}
+
+/**
+ * Cursor
+ */
+std::size_t Decorator::GetCurrentCursorPosition() const
+{
+  return mCursorPosition;
+}
+
+void Decorator::SetCurrentCursorPosition( std::size_t newCursorPosition )
+{
+  mCursorPosition = newCursorPosition;
+}
+
+void Decorator::SetCursorVisibility( bool visible )
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::SetCursorVisibility[%s]\n", ( visible )?"true":"false");
+
+  mCursorVisibility = visible;
+  mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea );
+  mCursorRTL.SetVisible( mCursorVisibility && mCursorRTLEnabled );
+}
+
+void Decorator::DrawCursor(const std::size_t nthChar)
+{
+  std::size_t cursorPosition = GetCurrentCursorPosition();
+
+  // Get height of cursor and set its size
+  Size size( CURSOR_THICKNESS, 0.0f );
+  if ( !mTextViewCharacterPositioning.IsTextEmpty() )
+  {
+    Vector2 min, max; // out parameters for GetRowRectFromCharacterPosition
+    size.height = mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( mTextViewCharacterPositioning.GetVisualPosition( cursorPosition ), min, max  ).height;
+  }
+  else
+  {
+    // Measure Font so know how big text will be if no initial text to measure.
+    size.height = mTextViewCharacterPositioning.GetLineHeight( nthChar );
+  }
+
+  mCursor.SetSize(size);
+
+  // If the character is italic then the cursor also tilts.
+  if ( !mTextViewCharacterPositioning.IsStyledTextEmpty()  && ( cursorPosition > 0 ) )
+  {
+    DALI_ASSERT_DEBUG( ( 0 <= cursorPosition-1 ) && ( cursorPosition-1 < mTextViewCharacterPositioning.StyledTextSize() ) );
+    const TextStyle styleAtCursor = mTextViewCharacterPositioning.GetStyleAt( cursorPosition-1 );
+    mCursor.SetRotation( styleAtCursor.GetItalics() ? Degree( styleAtCursor.GetItalicsAngle() - CURSOR_ANGLE_OFFSET ) : Degree( 0.f ), Vector3::ZAXIS );
+  }
+
+  DALI_ASSERT_DEBUG( cursorPosition <= mTextViewCharacterPositioning.GetNumberOfCharactersInText() );
+  if ( ( cursorPosition <= mTextViewCharacterPositioning.GetNumberOfCharactersInText() ) )
+  {
+    Vector3 altPosition;    // Alternate (i.e. opposite direction) cursor position.
+    bool altPositionValid( false );  // Alternate cursor validity flag.
+    bool directionRTL( false );      // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently)
+    Vector3 position = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( cursorPosition, directionRTL, altPosition, altPositionValid );
+
+    SetAltCursorEnabled( altPositionValid );
+
+    if(!altPositionValid)
+    {
+      mCursor.SetPosition( position + UI_OFFSET );
+    }
+    else
+    {
+      size.height *= 0.5f;
+      mCursor.SetSize(size);
+      mCursor.SetPosition( position + UI_OFFSET - Vector3(0.0f, directionRTL ? 0.0f : size.height, 0.0f) );
+      Vector2 min, max; // out parameters for GetRowRectFromCharacterPosition
+      Size rowSize = mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( mTextViewCharacterPositioning.GetVisualPosition( cursorPosition ), min, max );
+      size.height = rowSize.height * 0.5f;
+      mCursorRTL.SetSize(size);
+      mCursorRTL.SetPosition( altPosition + UI_OFFSET - Vector3(0.0f, directionRTL ? size.height : 0.0f, 0.0f) );
+    }
+
+    if( mTextViewCharacterPositioning.IsScrollEnabled() )
+    {
+      // Whether cursor and grab handle are inside the boundaries of the text-input when text scroll is enabled.
+      const Vector3& controlSize = mTextViewCharacterPositioning.GetTextView().GetCurrentSize();
+      mIsCursorInScrollArea = mIsGrabHandleInScrollArea = IsPositionWithinControl( position, size, controlSize );
+    }
+  }
+}
+
+void Decorator::SetAltCursorEnabled( bool enabled )
+{
+  mCursorRTLEnabled = enabled;
+  mCursorRTL.SetVisible( mCursorVisibility && mCursorRTLEnabled );
+}
+
+void Decorator::SetCursorImage(Dali::Image image, const Vector4& border )
+{
+  DALI_ASSERT_DEBUG ( image && "Create cursor image invalid")
+
+  if ( image )
+  {
+    mCursor.SetImage( image );
+    mCursor.SetNinePatchBorder( border );
+  }
+}
+
+void Decorator::SetRTLCursorImage( Image image, const Vector4& border )
+{
+  DALI_ASSERT_DEBUG ( image && "Create cursor image invalid")
+
+  if ( image )
+  {
+    mCursorRTL.SetImage( image );
+    mCursorRTL.SetNinePatchBorder(  border );
+  }
+}
+
+ImageActor Decorator::CreateCursor( Image cursorImage, const Vector4& border, const std::string& cursorName )
+{
+  ImageActor cursor;
+
+  if ( cursorImage )
+  {
+    cursor = ImageActor::New( cursorImage );
+  }
+  else
+  {
+    cursor = ImageActor::New( Image::New( DEFAULT_CURSOR ) );
+  }
+
+  cursor.SetStyle(ImageActor::STYLE_NINE_PATCH);
+  cursor.SetNinePatchBorder( border );
+  cursor.SetAnchorPoint(AnchorPoint::BOTTOM_CENTER);
+  cursor.SetVisible(false);
+  cursor.SetName( cursorName );
+  return cursor;
+}
+
+void Decorator::CreateCursors( Actor targetParent )
+{
+  Image mCursorImage = Image::New( DEFAULT_CURSOR );
+  mCursor = CreateCursor (mCursorImage, DEFAULT_CURSOR_IMAGE_9_BORDER , "mainCursor");
+  mCursorRTL = CreateCursor ( mCursorImage, DEFAULT_CURSOR_IMAGE_9_BORDER, "rtlCursor");
+  targetParent.Add( mCursor );
+  targetParent.Add( mCursorRTL );
+}
+
+Size Decorator::GetCursorSizeAt( std::size_t positionWithinTextToGetCursorSize )
+{
+  std::size_t visualPosition = mTextViewCharacterPositioning.GetVisualPosition( positionWithinTextToGetCursorSize );
+
+  Vector2 min, max;
+
+  const Size cursorSize( CURSOR_THICKNESS,
+      mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( visualPosition, min, max ).height );
+
+  return cursorSize;
+}
+
+void Decorator::StartCursorBlinkTimer()
+{
+  if ( !mCursorBlinkTimer )
+  {
+    mCursorBlinkTimer = Timer::New( CURSOR_BLINK_INTERVAL );
+    mCursorBlinkTimer.TickSignal().Connect( this, &Decorator::OnCursorBlinkTimerTick );
+  }
+
+  if ( !mCursorBlinkTimer.IsRunning() )
+  {
+    mCursorBlinkTimer.Start();
+  }
+}
+
+void Decorator::StopCursorBlinkTimer()
+{
+  if ( mCursorBlinkTimer )
+  {
+    mCursorBlinkTimer.Stop();
+  }
+}
+
+bool Decorator::OnCursorBlinkTimerTick()
+{
+  // Cursor blinking
+  mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea && mCursorBlinkStatus );
+  if ( mCursorRTLEnabled )
+  {
+    mCursorRTL.SetVisible( mCursorVisibility && mIsCursorInScrollArea && mCursorBlinkStatus );
+  }
+  mCursorBlinkStatus = !mCursorBlinkStatus;
+
+  return true;
+}
+
+/**
+ * Highlight
+ */
+void Decorator::ShowUpdatedHighlight()
+{
+  Toolkit::TextView::TextLayoutInfo textLayoutInfo = mTextViewCharacterPositioning.GetLayoutInfo();
+  TextHighlight::HighlightInfo highlightInfo = mTextHighlight.CalculateHighlightInfo( mSelectionHandleOnePosition, mSelectionHandleTwoPosition, textLayoutInfo );
+
+  // Clamp highlightInfo so they don't exceed the boundary of the control.
+  const Vector3& controlSize = mTextViewCharacterPositioning.GetTextView().GetCurrentSize();
+  highlightInfo.Clamp2D( Vector2::ZERO, Vector2(controlSize.x, controlSize.y) );
+
+  mTextHighlight.UpdateHighlight( highlightInfo );
+}
+
+void Decorator::CreateHighlight( Actor parent )
+{
+  DALI_ASSERT_DEBUG( parent && "Highlight target parent does not exist" );
+
+  if ( !mHighlightMeshActor )
+  {
+    mHighlightMeshActor = MeshActor::New( mTextHighlight.CreateHighLightMesh() );
+    mHighlightMeshActor.SetName( "HighlightMeshActor" );
+    mHighlightMeshActor.SetInheritShaderEffect( false );
+    mHighlightMeshActor.SetAffectedByLighting(false);
+    parent.Add( mHighlightMeshActor );
+  }
+}
+
+void Decorator::RemoveHighlight()
+{
+  if ( mHighlightMeshActor )
+  {
+    mHighlightMeshActor.Unparent();
+    mHighlightMeshActor.Reset();
+    // NOTE: We cannot dereference mHighlightMesh, due to a how the scene-graph MeshRenderer uses the Mesh data.
+  }
+}
+
+void Decorator::HighlightVisibility( bool visiblility )
+{
+  if ( mHighlightMeshActor )
+  {
+    mHighlightMeshActor.SetVisible( visiblility );
+  }
+}
+
+/**
+ *  Callbacks connected to be Property notifications for Boundary checking.
+ */
+// Note If PropertyNotification signal definition included Actor we would not need to duplicate functions.
+void Decorator::OnHandleOneLeavesBoundary( PropertyNotification& source)
+{
+  mTextInputHandles.GetSelectionHandleOne().SetOpacity(0.0f);
+}
+
+void Decorator::OnHandleOneWithinBoundary(PropertyNotification& source)
+{
+  mTextInputHandles.GetSelectionHandleOne().SetOpacity(1.0f);
+}
+
+void Decorator::OnHandleTwoLeavesBoundary( PropertyNotification& source)
+{
+  mTextInputHandles.GetSelectionHandleTwo().SetOpacity(0.0f);
+}
+
+void Decorator::OnHandleTwoWithinBoundary(PropertyNotification& source)
+{
+  mTextInputHandles.GetSelectionHandleTwo().SetOpacity(1.0f);
+}
+
+void Decorator::OnLeftBoundaryExceeded(PropertyNotification& source)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::General, "TextInputDecorationLayouter::OnLeftBoundaryExceeded\n");
+  Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne();
+  selectionHandleOne.SetScale( -1.0f, 1.0f, 1.0f );
+  selectionHandleOne.SetAnchorPoint( AnchorPoint::TOP_LEFT);
+}
+
+void Decorator::OnReturnToLeftBoundary(PropertyNotification& source)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::General, "TextInputDecorationLayouter::OnReturnToLeftBoundary\n");
+  Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne();
+  selectionHandleOne.SetScale( 1.0f, 1.0f, 1.0f );
+  selectionHandleOne.SetAnchorPoint( AnchorPoint::TOP_RIGHT);
+}
+
+void Decorator::OnRightBoundaryExceeded(PropertyNotification& source)
+{
+  Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo();
+  selectionHandleTwo.SetScale( -1.0f, 1.0f, 1.0f );
+  selectionHandleTwo.SetAnchorPoint( AnchorPoint::TOP_RIGHT);
+}
+
+void Decorator::OnReturnToRightBoundary(PropertyNotification& source)
+{
+  Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo();
+  selectionHandleTwo.SetScale( 1.0f, 1.0f, 1.0f );
+  selectionHandleTwo.SetAnchorPoint( AnchorPoint::TOP_LEFT);
+}
+
+void Decorator::SetUpHandlePropertyNotifications()
+{
+  /* Property notifications for handles exceeding the boundary and returning back within boundary */
+
+  Vector3 handlesize = GetSelectionHandleSize();
+
+  Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne();
+  Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo();
+
+  // Exceeding horizontal boundary
+  PropertyNotification leftNotification = selectionHandleOne.AddPropertyNotification( Actor::WORLD_POSITION_X, LessThanCondition( mBoundingRectangleWorldCoordinates.x + handlesize.x) );
+  leftNotification.NotifySignal().Connect( this, &Decorator::OnLeftBoundaryExceeded );
+
+  PropertyNotification rightNotification = selectionHandleTwo.AddPropertyNotification( Actor::WORLD_POSITION_X, GreaterThanCondition( mBoundingRectangleWorldCoordinates.z - handlesize.x ) );
+  rightNotification.NotifySignal().Connect( this, &Decorator::OnRightBoundaryExceeded );
+
+  // Within horizontal boundary
+  PropertyNotification leftLeaveNotification = selectionHandleOne.AddPropertyNotification( Actor::WORLD_POSITION_X, GreaterThanCondition( mBoundingRectangleWorldCoordinates.x + 2*handlesize.x ) );
+  leftLeaveNotification.NotifySignal().Connect( this, &Decorator::OnReturnToLeftBoundary );
+
+  PropertyNotification rightLeaveNotification = selectionHandleTwo.AddPropertyNotification( Actor::WORLD_POSITION_X, LessThanCondition( mBoundingRectangleWorldCoordinates.z - 2*handlesize.x ) );
+  rightLeaveNotification.NotifySignal().Connect( this, &Decorator::OnReturnToRightBoundary );
+
+  // Exceeding vertical boundary
+  PropertyNotification verticalExceedNotificationOne = selectionHandleOne.AddPropertyNotification( Actor::WORLD_POSITION_Y,
+                                                       OutsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y,
+                                                                         mBoundingRectangleWorldCoordinates.w - handlesize.y ) );
+  verticalExceedNotificationOne.NotifySignal().Connect( this, &Decorator::OnHandleOneLeavesBoundary );
+
+  PropertyNotification verticalExceedNotificationTwo = selectionHandleTwo.AddPropertyNotification( Actor::WORLD_POSITION_Y,
+                                                       OutsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y,
+                                                                         mBoundingRectangleWorldCoordinates.w - handlesize.y ) );
+  verticalExceedNotificationTwo.NotifySignal().Connect( this, &Decorator::OnHandleTwoLeavesBoundary );
+
+  // Within vertical boundary
+  PropertyNotification verticalWithinNotificationOne = selectionHandleOne.AddPropertyNotification( Actor::WORLD_POSITION_Y,
+                                                       InsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y,
+                                                                        mBoundingRectangleWorldCoordinates.w - handlesize.y ) );
+  verticalWithinNotificationOne.NotifySignal().Connect( this, &Decorator::OnHandleOneWithinBoundary );
+
+  PropertyNotification verticalWithinNotificationTwo = selectionHandleTwo.AddPropertyNotification( Actor::WORLD_POSITION_Y,
+                                                       InsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y,
+                                                                        mBoundingRectangleWorldCoordinates.w - handlesize.y ) );
+  verticalWithinNotificationTwo.NotifySignal().Connect( this, &Decorator::OnHandleTwoWithinBoundary );
+}
+
+/**
+ * PopUp
+ */
+Vector3 Decorator::PositionOfPopUpRelativeToSelectionHandles()
+{
+  Vector3 position;
+  Vector2 min, max;
+  Vector3 topHandle;
+  Size rowSize;
+
+  // When text is selected, show popup above top handle (and text), or below bottom handle.
+
+  // topHandle: referring to the top most point of the handle or the top line of selection.
+  if ( mSelectionHandleTwoActualPosition.y > mSelectionHandleOneActualPosition.y )
+  {
+    topHandle = mSelectionHandleOneActualPosition;
+    rowSize= mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( mSelectionHandleOnePosition, min, max );
+  }
+  else
+  {
+    topHandle = mSelectionHandleTwoActualPosition;
+    rowSize = mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( mSelectionHandleTwoPosition, min, max );
+  }
+  topHandle.y += TOP_HANDLE_TOP_OFFSET - rowSize.height;
+  position = Vector3(topHandle.x, topHandle.y, 0.0f);
+
+  return position;
+}
+
+Vector3 Decorator::AlternatePopUpPositionRelativeToSelectionHandles()
+{
+  // alternativePosition: referring to the bottom most point of the handle or the bottom line of selection.
+  Vector3 alternativePosition;
+  alternativePosition.y = std::max ( mSelectionHandleTwoActualPosition.y , mSelectionHandleOneActualPosition.y );
+  alternativePosition.y += GetSelectionHandleSize().y + mPopUpPanel.GetSize().y + BOTTOM_HANDLE_BOTTOM_OFFSET;
+
+  return alternativePosition;
+}
+
+Vector3 Decorator::PositionOfPopUpRelativeToCursor()
+{
+  // When no text is selected, show PopUp at position of cursor
+  Vector3 position;
+  Vector2 min, max;
+  std::size_t cursorPosition = GetCurrentCursorPosition();
+  position = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( cursorPosition );
+  const Size rowSize = mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( cursorPosition, min, max );
+  position.y -= rowSize.height;
+
+  return position;
+}
+
+Vector3 Decorator::AlternatePopUpPositionRelativeToCursor()
+{
+  std::size_t cursorPosition = GetCurrentCursorPosition();
+  Vector3 alternativePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( cursorPosition );
+
+  if (  mTextInputHandles.GetGrabHandle() )
+  {
+    // If grab handle enabled then position pop-up below the grab handle.
+    alternativePosition.y +=  mTextInputHandles.GetGrabHandle().GetCurrentSize().height  + mPopUpPanel.GetSize().y + BOTTOM_HANDLE_BOTTOM_OFFSET ;
+  }
+  else
+  {
+    alternativePosition.y += mPopUpPanel.GetSize().y;
+  }
+
+  return alternativePosition;
+
+}
+
+Vector3 Decorator::PositionOfPopUpRelativeToGrabHandle()
+{
+   return Vector3::ZERO;
+}
+
+void Decorator::ShowPopUp()
+{
+  Vector3 position;
+  Vector3 alternativePosition;
+  Size rowSize;
+
+  DALI_ASSERT_DEBUG( mPopUpTarget && "PopUp Target Actor does not exist" );
+
+  if( mHighlightMeshActor ) // Text Selection mode
+  {
+    position = PositionOfPopUpRelativeToSelectionHandles();
+  }
+  else // Not in Text Selection mode so position relative to cursor.
+  {
+    position = PositionOfPopUpRelativeToCursor();
+  }
+
+  // reposition popup above the desired cursor position.
+  mPopUpPanel.Show( mPopUpTarget, true );
+  mPopUpPanel.Self().SetPosition( position );
+  mPopUpPanel.PressedSignal().Connect( this, &Decorator::OnPopupButtonPressed );
+
+  SetUpPopUpPositionNotifications();
+  mPopUpPanel.ApplyConfinementConstraint( mBoundingRectangleWorldCoordinates );
+}
+
+void Decorator::ShowPopUp( Actor target )
+{
+  mPopUpTarget = target;
+  ShowPopupCutCopyPaste();
+}
+
+void Decorator::ShowPopupCutCopyPaste()
+{
+  bool isAllTextSelectedAlready = ( mTextViewCharacterPositioning.StyledTextSize() == GetSelectedText().size() );
+  bool isTextEmpty = mTextViewCharacterPositioning.IsStyledTextEmpty() ;
+  bool isSubsetOfTextAlreadySelected = ( !isAllTextSelectedAlready ) && mHighlightMeshActor;
+
+  Clipboard clipboard = Clipboard::Get();
+  bool hasClipboardGotContent = clipboard.NumberOfItems();
+
+  mPopUpPanel.CreateCutCopyPastePopUp( isAllTextSelectedAlready, isTextEmpty, hasClipboardGotContent, isSubsetOfTextAlreadySelected );
+  ShowPopUp();
+}
+
+void Decorator::HidePopUp( bool animate, bool signalFinished )
+{
+  if ( ( mPopUpPanel.GetState() == TextInputPopupNew::StateShowing ) || ( mPopUpPanel.GetState() == TextInputPopupNew::StateShown )  )
+  {
+    mPopUpPanel.Hide( animate );
+  }
+}
+
+void Decorator::AddPopupOption(const std::string& name, const std::string& caption, const Image icon, bool finalOption)
+{
+  mPopUpPanel.AddButton(name, caption, icon, finalOption);
+}
+
+void Decorator::ClearPopup()
+{
+  mPopUpPanel.Clear();
+}
+
+void Decorator::PopUpLeavesVerticalBoundary( PropertyNotification& source)
+{
+  Vector3 position, alternativePosition;
+
+  if( mHighlightMeshActor ) // Text Selection mode
+  {
+    alternativePosition = AlternatePopUpPositionRelativeToSelectionHandles();
+  }
+  else // Not in Text Selection mode
+  {
+    alternativePosition = AlternatePopUpPositionRelativeToCursor();
+    // if can't be positioned above, then position below row.
+  }
+  // reposition popup above the desired cursor position.
+  mPopUpPanel.Self().SetPosition( alternativePosition );
+}
+
+void Decorator::SetUpPopUpPositionNotifications( )
+{
+  // Note Property notifications ignore any set anchor point so conditions must allow for this.  Default is Top Left.
+
+  // Exceeding vertical boundary
+  PropertyNotification verticalExceedNotificationOne = mPopUpPanel.Self().AddPropertyNotification( Actor::WORLD_POSITION_Y,
+                                                       OutsideCondition( mBoundingRectangleWorldCoordinates.y + mPopUpPanel.GetSize().y/2,
+                                                                         mBoundingRectangleWorldCoordinates.w - mPopUpPanel.GetSize().y/2 ) );
+  verticalExceedNotificationOne.NotifySignal().Connect( this, &Decorator::PopUpLeavesVerticalBoundary );
+}
+
+bool Decorator::OnPopupButtonPressed( Toolkit::Button button )
+{
+  mPopUpButtonPressedSignal.Emit( button );
+  return false;
+}
+
+Decorator::PressedSignal& Decorator::PopUpButtonPressedSignal()
+{
+  return mPopUpButtonPressedSignal;
+}
+
+Decorator::CursorPositionedSignal& Decorator::CursorRePositionedSignal()
+{
+  return mCursorRePositionedSignal;
+}
+
+/**
+ *  Decoration Positioning during Scrolling
+ */
+void Decorator::TextViewScrolled( Toolkit::TextView textView, Vector2 scrollPosition )
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::TextViewScrolled\n");
+
+  const Vector3& controlSize = mTextViewCharacterPositioning.GetTextView().GetCurrentSize(); // todo Could store size and only update in Control Size change.
+  Size cursorSize( CURSOR_THICKNESS, 0.f );
+
+  // Updates the cursor and grab handle position and visibility.
+  if( mTextInputHandles.GetGrabHandle() || mCursor )
+  {
+    Vector2 min, max;
+    size_t cursorTextPosition = GetCurrentCursorPosition();
+    cursorSize.height  = mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( cursorTextPosition, min, max ).height;
+
+    const Vector3 cursorPosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( cursorTextPosition );
+
+    bool mIsCursorInScrollArea = IsPositionWithinControl( cursorPosition, cursorSize, controlSize );
+    bool mIsGrabHandleInScrollArea = mIsCursorInScrollArea;
+
+    Vector2 actualGrabHandlePosition = cursorPosition.GetVectorXY();
+
+    if( mTextInputHandles.GetGrabHandle() )
+    {
+      ShowGrabHandle( mGrabHandleVisibility && mIsGrabHandleInScrollArea );
+      PositionGrabHandle( cursorTextPosition );
+    }
+
+    if( mCursor )
+    {
+      mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea );
+      DrawCursor( cursorTextPosition );
+      mCursor.SetPosition( Vector3(actualGrabHandlePosition) + UI_OFFSET );
+    }
+  }
+
+  Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne();
+  Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo();
+
+  // Updates the selection handles and highlighted text position and visibility.
+  if( mTextInputHandles.GetSelectionHandleOne() && mTextInputHandles.GetSelectionHandleTwo() )
+  {
+    const Vector3 cursorPositionOne = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition );
+    const Vector3 cursorPositionTwo = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition );
+
+    Size cursorSize( GetCursorSizeAt( mSelectionHandleOnePosition ) );
+    const bool isSelectionHandleOneVisible = IsPositionWithinControl( cursorPositionOne, cursorSize, controlSize );
+
+    cursorSize =  GetCursorSizeAt( mSelectionHandleTwoPosition );
+    const bool isSelectionHandleTwoVisible = IsPositionWithinControl( cursorPositionTwo, cursorSize, controlSize );
+
+    mSelectionHandleOneActualPosition = cursorPositionOne.GetVectorXY();
+    mSelectionHandleTwoActualPosition = cursorPositionTwo.GetVectorXY();
+
+    selectionHandleOne.SetVisible( isSelectionHandleOneVisible );
+    selectionHandleTwo.SetVisible( isSelectionHandleTwoVisible );
+
+    PositionSelectionHandle( selectionHandleOne, mSelectionHandleOneActualPosition, mSelectionHandleOnePosition );
+    PositionSelectionHandle( selectionHandleTwo, mSelectionHandleTwoActualPosition, mSelectionHandleTwoPosition );
+
+    if( mHighlightMeshActor )
+    {
+      mHighlightMeshActor.SetVisible( true );
+      ShowUpdatedHighlight();
+    }
+  }
+}
+
+void Decorator::StartScrollTimer()
+{
+  if( !mScrollTimer )
+  {
+    mScrollTimer = Timer::New( SCROLL_TICK_INTERVAL );
+    mScrollTimer.TickSignal().Connect( this, &Decorator::OnScrollTimerTick );
+  }
+
+  if( !mScrollTimer.IsRunning() )
+  {
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::StartScrollTimer\n");
+    mScrollTimer.Start();
+  }
+}
+
+void Decorator::StopScrollTimer()
+{
+  if( mScrollTimer )
+  {
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::StopScrollTimer\n");
+
+    mScrollTimer.Stop();
+    mScrollTimer.Reset();
+  }
+}
+
+bool Decorator::OnScrollTimerTick()
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::OnScrollTimerTick\n");
+
+  if ( mGrabHandleVisibility && mTextInputHandles.GetGrabHandle() )
+  {
+    std::size_t newGrabHandlePosition = mTextViewCharacterPositioning.ReturnClosestIndex( mActualGrabHandlePosition.GetVectorXY() );
+    if ( mGrabHandlePosition != newGrabHandlePosition )
+    {
+      Vector2 scrollPosition = mTextViewCharacterPositioning.GetScrollPosition();
+      Vector2 scrollDelta = ( mActualGrabHandlePosition - mCurrentHandlePosition ).GetVectorXY();
+      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::OnScrollTimerTick scrollPosition(%f) scrollDelta(%f)\n", scrollPosition.x, scrollDelta.x);
+      scrollPosition += scrollDelta;
+      mTextViewCharacterPositioning.SetScrollPosition( scrollPosition );
+
+      // If scroll position goes too far TextView will trim it to fit.
+      if ( mTextViewCharacterPositioning.IsScrollPositionTrimmed() )
+      {
+        StopScrollTimer();
+      }
+
+      mActualGrabHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newGrabHandlePosition ).GetVectorXY();
+    }
+  }
+
+  Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne();
+  Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo();
+
+  if ( selectionHandleOne && selectionHandleTwo )
+  {
+    std::size_t newHandleOnePosition = mTextViewCharacterPositioning.ReturnClosestIndex( mSelectionHandleOneActualPosition.GetVectorXY() );
+
+    // todo duplicated code should be a function
+
+    if ( mSelectionHandleOnePosition != newHandleOnePosition )
+    {
+      const Vector3 actualPosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newHandleOnePosition );
+
+      Vector2 scrollDelta = ( actualPosition - mSelectionHandleOneActualPosition ).GetVectorXY();
+
+      Vector2 scrollPosition = mTextViewCharacterPositioning.GetScrollPosition();
+      scrollPosition += scrollDelta;
+      mTextViewCharacterPositioning.SetScrollPosition( scrollPosition );
+
+      if( mTextViewCharacterPositioning.IsScrollPositionTrimmed() )
+      {
+        StopScrollTimer();
+      }
+
+      mSelectionHandleOnePosition = newHandleOnePosition;
+      mSelectionHandleOneActualPosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition ).GetVectorXY();
+    }
+    else
+    {
+      mSelectionHandleOneActualPosition.x += mScrollDisplacement.x;
+      mSelectionHandleOneActualPosition.y += mScrollDisplacement.y;
+    }
+
+    std::size_t newHandleTwoPosition = mTextViewCharacterPositioning.ReturnClosestIndex( mSelectionHandleTwoActualPosition.GetVectorXY() );
+
+    if ( mSelectionHandleTwoPosition != newHandleTwoPosition )
+    {
+      const Vector3 actualPosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newHandleTwoPosition );
+
+      Vector2 scrollDelta = ( actualPosition - mSelectionHandleTwoActualPosition ).GetVectorXY();
+
+      Vector2 scrollPosition = mTextViewCharacterPositioning.GetScrollPosition();
+      scrollPosition += scrollDelta;
+      mTextViewCharacterPositioning.SetScrollPosition( scrollPosition );
+
+      if( mTextViewCharacterPositioning.IsScrollPositionTrimmed() )
+      {
+        StopScrollTimer();
+      }
+
+      mSelectionHandleTwoPosition = newHandleTwoPosition;
+      mCurrentHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition ).GetVectorXY();
+
+    }
+    else
+    {
+      mSelectionHandleTwoActualPosition.x += mScrollDisplacement.x;
+      mSelectionHandleTwoActualPosition.y += mScrollDisplacement.y;
+    }
+  }
+
+  return true;
+}
+
+/**
+ *  Text Selection
+ */
+MarkupProcessor::StyledTextArray Decorator::GetSelectedText()
+{
+  MarkupProcessor::StyledTextArray currentSelectedText;
+
+  if ( mHighlightMeshActor ) // Text Selected
+  {
+    MarkupProcessor::StyledTextArray::iterator it = mTextViewCharacterPositioning.GetStyledTextArray().begin() + std::min(mSelectionHandleOnePosition, mSelectionHandleTwoPosition);
+    MarkupProcessor::StyledTextArray::iterator end = mTextViewCharacterPositioning.GetStyledTextArray().begin() + std::max(mSelectionHandleOnePosition, mSelectionHandleTwoPosition);
+
+    for(; it != end; ++it)
+    {
+      MarkupProcessor::StyledText& styledText( *it );
+      currentSelectedText.push_back( styledText );
+    }
+  }
+  return currentSelectedText;
+}
+
+} // Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
diff --git a/base/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.h b/base/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.h
new file mode 100644 (file)
index 0000000..087cde3
--- /dev/null
@@ -0,0 +1,635 @@
+#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_DECORATOR_H__
+#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_DECORATOR_H__
+
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <dali/dali.h>
+
+// INTERNAL INCLUDES
+
+#include <dali-toolkit/internal/controls/text-input/textview-character-positions-impl.h>
+#include <dali-toolkit/internal/controls/text-input/text-input-handles-impl.h>
+#include <dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.h>
+#include <dali-toolkit/internal/controls/text-input/text-input-popup-new-impl.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+class Decorator;
+
+typedef IntrusivePtr<Decorator> DecoratorPtr;
+
+/**
+ *  @brief Decorator Class
+ *
+ *  Decorations are Selection Handles, cursor, grab handle, magnifier the "cut copy paste" PopUp and Selection highlight.
+ *  The Decorator triggers creation of these decorations and positions them.
+ *  Decoration positions can be dependent on other decorations like the PopUp on the Selection handles.
+ *  The decorator maintains a Bounding Box which the decorations have to be positioned within, decorations can be flipped or hidden to obey this Bounding Box.
+ *  Scrolling of Text can effect positioning of decorations, the decorator repositions decorations in this case.
+ */
+
+class Decorator : public ConnectionTracker
+{
+
+public:
+
+  /**
+   * @brief Constructor
+   *
+   * @param[in] textviewManager TextViewManager to be used
+   */
+  Decorator( TextViewCharacterPositioning& textviewManager, TextInputTextStyle& textStyle);
+
+  /**
+   * @brief Default destructor
+   */
+  ~Decorator();
+
+  /**
+   * @brief Set the dimensions of the bounding rectangle for decorations to obey.
+   *
+   * @param[in] boundingRectangle
+   */
+  void SetBoundingBox( const Rect<float>& boundingRectangle );
+
+  /**
+   * @brief Get the bounding dimensions of the bounding box
+   *
+   * @return dimensions of the bounding box from world origin. (x, y, w, z )
+   *
+   *  -----------------
+   * |        ^        |
+   * |        |        |
+   * |        y        |
+   * |        |        |
+   * |        v        |
+   * |<--x--> o <--z-->|
+   * |        ^        |
+   * |        |        |
+   * |        w        |
+   * |        |        |
+   * |        v        |
+   *  -----------------
+   */
+  Vector4 GetBoundingBox() const;
+
+  /**
+   * @brief Callback when a handle is panned/moved, either selection handles or grab handle
+   *
+   * @param actor Handle of the selection or grab handle.
+   * @param gesture Data structure with the parameters of the gesture.
+   */
+  void OnHandlePan(Actor actor, PanGesture gesture);
+
+  // Selection Handles
+
+  /**
+   * @brief Create a left and right selection handle and parent both to the provided actor
+   * @param[in] parent actor in which the handles should be added to.
+   */
+  void CreateSelectionHandles( Actor parent );
+
+  /**
+   * @brief Remove selection handles from their parent
+   */
+  void RemoveSelectionHandles();
+
+  /**
+   * @brief Get size of Selection handles
+   *
+   * @return size of a selection handle
+   */
+  Vector3 GetSelectionHandleSize();
+
+  /**
+   * @brief Get position of Selection handle within text
+   *
+   * @return character position of a selection handle one
+   */
+  std::size_t GetHandleOnePosition() const;
+
+  /**
+   * @brief Get position of Selection handle within text
+   *
+   * @return character position of a selection handle two
+   */
+  std::size_t GetHandleTwoPosition() const;
+
+  /**
+   * @brief Position Selection a single handle at given positions within the text string.
+   *
+   * @param[in] selectionHandle handle to be positioned
+   * @param[in] position where to place handle
+   * @return Vector3 Position of handle as a coordinate.
+   */
+  Vector3 PositionSelectionHandle( Actor selectionHandle, std::size_t position );
+
+  /**
+   * @brief Position Selection a single handle at given coordinates
+   *
+   * @param[in] selectionHandle handle to be positioned
+   * @param[in] actualPosition coordinates to position handle
+   * @param[in] position where to place handle
+   * @return Vector3 Position of handle as a coordinate.
+   */
+  Vector3 PositionSelectionHandle( Actor selectionHandle, Vector3& actualPosition, std::size_t position );
+
+  /**
+   * @brief Make both selection handle visible or invisible
+   * @param[in] visible true to make visible, false to fine
+   */
+  void SetSelectionHandlesVisibility( bool visible );
+
+  /**
+   * @brief Callback for when a handle is released
+   * @return bool
+   */
+  bool OnHandleReleased();
+
+  /**
+   * @brief Position Selection handles at given positions within the text string.
+   *
+   * @param[in] start where to place first handle
+   * @param[in] end  where to place second handle
+   */
+  void PositionSelectionHandles( std::size_t start, std::size_t end );
+
+  /**
+   * @brief Move selection handle by the given displacement.
+   *
+   * @param[in] selectionHandle Actor to move
+   * @param[in] actualSelectionHandlePosition actual current position of the handle in x y z
+   * @param[in] currentSelectionHandlePosition current position along the string
+   * @param[in] displacement the x y displacement
+   */
+  Vector3 MoveSelectionHandle( Actor selectionHandle,
+                               Vector3& actualSelectionHandlePosition,
+                               std::size_t& currentSelectionHandlePosition,
+                               const Vector2& displacement );
+
+  /* Grab Handle */
+
+  /**
+   * @brief Position GrabHandlewith depending on the the character in the text it should be placed at
+   * @param[in] positonInText the character position within the text the handle should be at
+   */
+  void PositionGrabHandle( std::size_t positionInText );
+
+  /**
+   * @brief Move grab handle to the required position within the text
+   *
+   * @param[in] displacement Displacement of the grab handle in actor coordinates.
+   */
+  void MoveGrabHandle( const Vector2& displacement );
+
+  /**
+   * @brief Show or hide the GrabHandle is visibility is true
+   *
+   * @param[in] visible flag to show or not show the grab handle
+   */
+  void ShowGrabHandle( bool visible );
+
+  /**
+   * @brief Create the GrabHandle used to position cursor
+   * @param[in] targetParent the Actor to parent the GrabHandle
+   */
+  void CreateGrabHandle( Actor targetParent );
+
+  /**
+   * @brief Set the image to be used as the cursor grab hander
+   * @pre The text input actor has been initialised.
+   * @param[in] image The image to be used.
+   */
+  void SetGrabHandleImage( Image image );
+
+  /**
+   * @brief Toggle to enable the grab handle, used to position cursor when magnifier not being used.
+   * Default behaviour is to use the magnifier to position the cursor, enabling this prevents the magnifier from being shown.
+   * @param[in] toggle true to enable, false to disable grab handle
+   */
+  void EnableGrabHandle(bool toggle);
+
+  /**
+   * @brief Method to check if grab handle is enabled, if false then the magnifier will be used to position cursor.
+   * @return bool returns true is grab handle enabled.
+   */
+  bool IsGrabHandleEnabled();
+
+  /* Cursor */
+
+  /**
+   * @brief Get the current Cursor position
+   * @return current cursor position
+   */
+  std::size_t GetCurrentCursorPosition() const;
+
+  /**
+   * @brief Set the Cursor position
+   * @param[in] the position the cursor should be set to
+   */
+  void SetCurrentCursorPosition( std::size_t newCursorPosition );
+
+  /**
+   * @brief Set if the cursors are visible or not.
+   * @param[in] visible flag true for visible
+   */
+  void SetCursorVisibility( bool visible );
+
+  /**
+   * @brief Display cursor
+   * @param[in] nthChar position in text string to display cursor
+   */
+  void DrawCursor( const std::size_t nthChar = 0 );
+
+  /**
+   * Sets alternate cursor enable state
+   * @see SetCursorVisibility
+   * alternate cursor will only be visible if both SetCursorVisiblity
+   * and cursor enabled have been set to true.
+   */
+  void SetAltCursorEnabled( bool enabled );
+
+  /**
+   * @brief Set the image to be used for the regular left to right cursor
+   * @pre The text input actor has been initialised.
+   * @param[in] image The image to be used.
+   * @param[in] border The nine patch border for the image.
+   */
+  void SetCursorImage( Image image, const Vector4& border );
+
+  /**
+   * @brief Set the image to be used for the Right to Left cursor
+   * @pre The text input actor has been initialised.
+   * @param[in] image The image to be used.
+   * @param[in] border The nine patch border for the image.
+   */
+  void SetRTLCursorImage( Image image, const Vector4& border );
+
+  /**
+   * @brief Creates a cursor from the supplied image and nine patch border.
+   * @param[in] cursorImage the image to be used for the cursor.
+   * @param[in] border the nine patch border corresponding to the supplied image.
+   * @paran[in] cursorName actor name for cursor
+   * @return the image actor to be used as the cursor.
+   */
+  ImageActor CreateCursor( Image cursorImage, const Vector4& border,  const std::string& cursorName );
+
+  /**
+   * @brief Creates a regular and Right-To-Left cursor and parents them to give target Actor
+   * @param[in] targetParent target Actor
+   */
+  void CreateCursors( Actor targetParent );
+
+  /**
+   * @Brief Returns the cursor size at a given position in the text.
+   * @return Size the size of the cursor
+   */
+  Size GetCursorSizeAt( std::size_t positionWithinTextToGetCursorSize );
+
+  /**
+   * @brief  Start a timer to signal cursor to blink.
+   */
+  void StartCursorBlinkTimer();
+
+  /**
+   * @brief  Stop the timer signalling the cursor to blink.
+   */
+  void StopCursorBlinkTimer();
+
+  /**
+   * @brief Callback when handle timer ticks.
+   *
+   * Cursor should become visible/invisible to simulate blinking.
+   *
+   * @return True if the timer should be keep running.
+   */
+  bool OnCursorBlinkTimerTick();
+
+  /* Selection Highlight */
+
+  /**
+   * @brief Updates mesh data for selection highlight depending on handle positions and displays it.
+   */
+  void ShowUpdatedHighlight();
+
+  /**
+   * @brief Creates the Highlight used for selection
+   *
+   * @param[in] parent target actor in which the handles should be added to.
+   */
+  void CreateHighlight( Actor parent );
+
+  /**
+   * @brief Remove Highlight actor from it's parent
+   */
+  void RemoveHighlight();
+
+  /**
+   * @brief Set the visibility of the Highlight
+   *
+   * @param[in] visibility True to show and False to hide.
+   */
+  void HighlightVisibility( bool visiblility );
+
+  /* Boundary Property Notifications when handle exceed bounding box*/
+
+  /**
+   * @brief PropertyNotification Callback when left boundary exceeded so handle can be flipped.
+   *
+   * @param[in] source PropertyNotification
+   */
+  void OnLeftBoundaryExceeded( PropertyNotification& source );
+  /**
+   * @brief PropertyNotification Callback when within left boundary so handle can be flipped back.
+   *
+   * @param[in] source PropertyNotification
+   */
+  void OnReturnToLeftBoundary( PropertyNotification& source );
+  /**
+   * @brief PropertyNotification Callback when right boundary exceeded so handle can be flipped.
+   *
+   * @param[in] source PropertyNotification
+   */
+  void OnRightBoundaryExceeded( PropertyNotification& source );
+  /**
+   * @brief PropertyNotification Callback when within right boundary so handle can be flipped back.
+   *
+   * @param[in] source PropertyNotification
+   */
+  void OnReturnToRightBoundary( PropertyNotification& source );
+
+  /**
+   * @brief PropertyNotification Callbacks for hiding handle one when it exceeds boundary.
+   *
+   * @param[in] source PropertyNotification
+   */
+  void OnHandleOneLeavesBoundary( PropertyNotification& source );
+  /**
+   * @brief PropertyNotification Callbacks for showing hidden handle one when returns within boundary
+   *
+   * @param[in] source PropertyNotification
+   */
+  void OnHandleOneWithinBoundary( PropertyNotification& source );
+  /**
+   * @brief PropertyNotification Callbacks for hiding handle two it  when exceeds boundary.
+   *
+   * @param[in] source PropertyNotification
+   */
+  void OnHandleTwoLeavesBoundary( PropertyNotification& source );
+  /**
+   * @brief PropertyNotification Callbacks for showing hidden handle two when returns within boundary
+   *
+   * @param[in] source PropertyNotification
+   */
+  void OnHandleTwoWithinBoundary( PropertyNotification& source );
+
+  /**
+   * @brief Set up property notifications on the position of the handles to facilitate flipping and hiding when at screen boundary.
+   */
+  void SetUpHandlePropertyNotifications();
+
+  // Cut & Paste Pop-up
+
+  /**
+   * @brief Calculate positioning of PopUp relative to handles
+   * @return Actual position of PopUp
+   */
+  Vector3 PositionOfPopUpRelativeToSelectionHandles( );
+
+  /**
+   * @brief Calculate alternative position of PopUp relative to handles  when can it not be displayed in the default upper position.
+   * @return Actual position of PopUp
+   */
+  Vector3 AlternatePopUpPositionRelativeToSelectionHandles();
+
+  /**
+   * @brief Calculate positioning of PopUp relative to cursor
+   * @return Actual position of PopUp
+   */
+  Vector3 PositionOfPopUpRelativeToCursor();
+
+  /**
+   * @brief Calculate alternative position of PopUp relative to cursor when can not be displayed in normal upper position.
+   * @return Actual position of PopUp
+   */
+  Vector3 AlternatePopUpPositionRelativeToCursor();
+
+  /**
+   * @brief Calculate positioning of PopUp relative to GrabHandle
+   * @return Actual position of PopUp
+   */
+  Vector3 PositionOfPopUpRelativeToGrabHandle();
+
+ /**
+  * @brief Show the PopUp in the provided target
+  * @param[in] target target actor in which the PopUp should be added to.
+  */
+  void ShowPopUp( Actor target );
+
+  /**
+   * @brief Show PopUp in previously set Target.
+   * @pre Must have previously called ShopPopUp( Actor target ) otherwise PopUp will not be shown.
+   */
+  void ShowPopUp();
+
+  /**
+   * @brief Create and Show Cut Copy Paste PopUp
+   */
+  void ShowPopupCutCopyPaste();
+
+  /**
+   * @brief Hide PopUp
+   * @param[in] animate Animate or just hide instantly, default is true
+   * @param[in] signalFinished Signal when finished, default is true
+   */
+  void HidePopUp( bool animate=true, bool signalFinished=true );
+
+  /**
+   * @brief Adds a popup option.
+   * @brief Creates popup frame if not already created.
+   * @param[in] name The unique name for this option.
+   * @param[in] caption The caption (label) for this option
+   * @param[in] icon the image icon to be displayed for this option
+   * @param[in] finalOption Flag to indicate that this is the final option.
+   * (set to true on the last option you add)
+   */
+  void AddPopupOption(const std::string& name, const std::string& caption, const Image icon, bool finalOption = false);
+
+  /**
+   * @brief Removes popup, and its options.
+   */
+  void ClearPopup();
+
+  /**
+   * @brief PropertyNotification Callbacks for flipping PopUp when exceeds boundary.
+   * @param[in] source PropertyNotification
+   */
+  void PopUpLeavesVerticalBoundary( PropertyNotification& source );
+
+  /**
+   * @brief Setup position notifications when PopUp exceeds boundary
+   */
+  void SetUpPopUpPositionNotifications( );
+
+  /**
+   * @brief Callback for when a button is pressed in popup panel
+   * @param[in] button handle to the button pressed.
+   * @return bool consummation
+   */
+  bool OnPopupButtonPressed( Toolkit::Button button );
+
+  // Decoration positioning during scrolling
+
+  /**
+   * @brief Updates the position of the decorations when Text is scrolled.
+   *
+   * @param[in] textView Handle of the text-view.
+   * @param[in] scrollPosition The difference with the previous scroll position.
+   */
+  void TextViewScrolled( Toolkit::TextView textView, Vector2 scrollPosition );
+
+  /**
+   * @brief  Creates and starts a timer to scroll the text when handles are close to the edges of the text-input.
+   *
+   * It only starts the timer if it's already created.
+   */
+  void StartScrollTimer();
+
+  /**
+   * @brief  Stops the timer used to scroll the text.
+   */
+  void StopScrollTimer();
+
+  /**
+   * @brief Scroll Text according to handle position
+   * @param[in out] handlePosition handle position within character string
+   * @param[in] actual vector position of handle
+   * @return updated actual vector position of handle
+   */
+  Vector3 ScrollRelativeToHandle( std::size_t& handlePosition, Vector3& actualHandlePosition );
+
+  /**
+   * @brief Callback called by the timer used to scroll the text.
+   *
+   * It calculates and sets a new scroll position.
+   */
+  bool OnScrollTimerTick();
+
+  // Text Selection
+
+  /**
+   * @brief Function to get Text selected between the 2 selection handles.
+   * @return StyledTextArray an array of
+   */
+  MarkupProcessor::StyledTextArray GetSelectedText();
+
+private:
+
+  /**
+   * @brief Copy Constructor
+   * @param[in] decorator
+   * Undefined/Hidden.
+   */
+  Decorator(const Decorator& decorator);
+
+  /**
+   * @Assignment Constructor
+   * @param[in] rhs
+   * Undefined/Hidden.
+   */
+  Decorator& operator=(const Decorator& rhs);
+
+public:
+
+  typedef SignalV2< bool( Toolkit::Button ) > PressedSignal;
+  typedef SignalV2< void () > CursorPositionedSignal;
+  /**
+   * @brief Signal emitted when the button is touched.
+   * This is relayed from the PopUp class.  It enables the owner of the Decorator to act on the PopUp button press.
+   */
+  PressedSignal& PopUpButtonPressedSignal();
+
+  /**
+   * @brief Signal emitted when the cursor is repositioned
+   * @param[in] cursor the new cursor position
+   */
+  CursorPositionedSignal& CursorRePositionedSignal();
+
+private:
+
+  Vector4 mBoundingRectangleWorldCoordinates;
+
+  TextViewCharacterPositioning& mTextViewCharacterPositioning;
+
+  TextInputHandles mTextInputHandles;
+
+  TextInputTextStyle& mTextStyle;
+
+  Vector3 mSelectionHandleOneActualPosition;    // Actual x y position of handle
+  Vector3 mSelectionHandleTwoActualPosition;    // Actual x y position of handle
+  std::size_t mSelectionHandleOnePosition;      // Position of handle along the string of text
+  std::size_t mSelectionHandleTwoPosition;      // Position of handle along the string of text
+
+  TextInputPopupNew mPopUpPanel;                // PopUp used for Cut Cpoy and Paste
+  Actor mPopUpTarget;                           // Target Actor to parent PopUp
+
+  Vector3 mActualGrabHandlePosition;            // Actual position of grab handle, this might not be snapped to a character
+  std::size_t mGrabHandlePosition;              // Position of grab handle along the string of text
+  Vector3 mCurrentHandlePosition;
+
+  std::size_t mCursorPosition;                  // Current cursor position within the text string
+  ImageActor mCursor;                           // Cursor overlayed on Text to show where new text will be inserted
+  ImageActor mCursorRTL;                        // Right To Left Cursor overlayed on Text (where new RTL text would be inserted)
+  Animation mCursorAnimation;                   // Animation for cursor blinking.
+  Timer mCursorBlinkTimer;                      // Timer to signal cursor to blink
+
+  Vector2 mScrollDisplacement;                  // How much to scroll by
+  Timer mScrollTimer;                           // Timer to scroll text over a period of time not all in one update.
+
+  TextHighlight mTextHighlight;                 // Holds data required to construct the highlight
+  MeshActor mHighlightMeshActor;                // Mesh Actor to display highlight
+
+  PanGestureDetector mPanGestureDetector;
+
+  PressedSignal mPopUpButtonPressedSignal;           // Signal emitted when a button within the popup is pressed.
+  CursorPositionedSignal mCursorRePositionedSignal;  // Signal emitted when a button when cursor position is changed.
+
+  bool mCursorBlinkStatus:1;                    // \e true shows the cursor, \e false hides it.
+  bool mCursorVisibility:1;                     // Should cursor be visible
+  bool mCursorRTLEnabled:1;                     // Enable state of Alternate RTL Cursor (need to keep track of this as it's not always enabled)
+  bool mIsGrabHandleInScrollArea:1;             // Whether the grab handle is inside the boundaries of the text-input.
+  bool mIsCursorInScrollArea:1;                 // Whether the cursor is inside the boundaries of the text-input.
+  bool mGrabHandleVisibility:1;                 // Should grab handle be visible
+  bool mGrabHandleEnabled:1;                    // Flag to enable the grab handle instead of the default magnifier.
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_DECORATOR_H__
+
+
diff --git a/base/dali-toolkit/internal/controls/text-input/text-input-handles-impl.h b/base/dali-toolkit/internal/controls/text-input/text-input-handles-impl.h
new file mode 100644 (file)
index 0000000..3686466
--- /dev/null
@@ -0,0 +1,203 @@
+#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_HANDLES_H__
+#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_HANDLES_H__
+
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// INTERNAL INCLUDES
+#include <dali/dali.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+/**
+ * Class to create handles and alter their visualisation.
+ * Not responsible for positioning.
+ */
+
+class TextInputHandles : public ConnectionTracker
+{
+
+public:
+
+  typedef SignalV2< bool () > HandlesReleasedSignal;
+
+  /**
+   * Signal emitted when a handle is released
+   */
+  HandlesReleasedSignal& ReleasedSignal(){ return mReleasedSignal; };
+
+  /**
+   * Default constructor
+   */
+  TextInputHandles() {}
+
+  /**
+   * Destructor
+   */
+  ~TextInputHandles() {};
+
+  /**
+   * Create the selection handles
+   */
+  void CreateSelectionHandles(){};
+
+  /**
+   * Un-parents the Selection Handles and resets their Image Actors
+   */
+  void DestorySelectionHandles(){};
+
+  /**
+   * Set the Actor visibility on Selection Handle One
+   * @param[in] visibility visibility flag
+   */
+  void SetSelectionHandleOneVisibility( bool visibility ){};
+
+  /**
+   * Set the Actor visibility on Selection Handle Two
+   * @param[in] visibility visibility flag
+   */
+  void SetSelectionHandleTwoVisibility( bool visibility ){};
+
+  /**
+   * Attach the two selection handles to the pan gesture detector
+   * @param[in] panGestureDetector the PanGestureDetector to attach to
+   */
+  void AttachSelectionHandlesToGivenPanGesture(PanGestureDetector& panGestureDetector ){};
+
+  /**
+   * Attach the two selection handles to the tap gesture detector
+   * @param[in] tapGestureDetector the TapGestureDetector to attach to
+   */
+  void AttachSelectionHandlesToGivenTapDetector(TapGestureDetector& tapGestureDetector ){};
+
+  /**
+   * Attach the grab handle to the pan gesture detector
+   * @param[in] panGestureDetector the PanGestureDetector to attach to
+   */
+  void AttachGrabHandleToGivenPanGesture( PanGestureDetector& panGestureDetector ){};
+
+  /**
+   * Get Selection handle one
+   * @return selection handle actor
+   */
+  Actor GetSelectionHandleOne() { return Actor(); };
+
+  /**
+   * Get Selection handle two
+   * @return selection handle actor
+   */
+  Actor GetSelectionHandleTwo() { return Actor(); };
+
+  /**
+   * Get the grab handle
+   * @return grab handle Actor
+   */
+  Actor GetGrabHandle()  { return Actor(); };
+
+  /**
+   * Create the grab handle that positions the cursor
+   * @param[in] image the image to be used.
+   */
+  void CreateGrabHandle(){};
+
+  /**
+   * Removes and Resets GrabHandle
+   */
+  void DestoryGrabHandle(){};
+
+  /**
+   * Set the image to be used as the cursor grab hander
+   * @pre The text input actor has been initialised.
+   * @param[in] image The image to be used.
+   */
+  void SetGrabHandleImage( Dali::Image image ){};
+
+  /**
+   * Set the Actor visibility on the GrabHandle
+   * @param[in] visibility visibility flag
+   */
+  void SetGrabHandleVisibility( bool visibility ){};
+
+  /* Touch Event Callbacks */
+
+  /**
+   * Callback on selection handle touched.
+   * Sets the image depending if handle in pressed or normal state
+   * @param[in] actor touched
+   * @param[in] touch touch event, used to determine if down or up event
+   */
+  bool OnSelectionHandleTouched(Dali::Actor actor, const TouchEvent& touch){ return true; };
+
+private:
+
+  /**
+   * @brief Copy Constructor
+   * @param[in] handles
+   * Undefined/Hidden.
+   */
+  TextInputHandles(const TextInputHandles& handles);
+
+  /**
+   * @Assignment Constructor
+   * @param[in] rhs
+   * Undefined/Hidden.
+   */
+  TextInputHandles& operator=(const TextInputHandles& rhs);
+
+private:
+
+  ImageActor mSelectionHandleOne;                 // First selection handle used for selecting text to cut&paste
+  ImageActor mSelectionHandleTwo;                 // Second selection handle used for selecting text to cut&paste
+  Actor mHandleOneGrabArea;                       // Invisible actor that receives pans events for the selection handle.
+  Actor mHandleTwoGrabArea;                       // Invisible actor that receives pans events for the selection handle.
+
+  Image mSelectionHandleOneImage;                 // image used for selection handle one
+  Image mSelectionHandleOneImagePressed;          // image used for selection handle one pressed state
+  Image mSelectionHandleTwoImage;                 // image used for selection handle two
+  Image mSelectionHandleTwoImagePressed;          // image used for selection handle two pressed state
+
+  Vector3 mSelectionHandleOneOffset;              // Handle One's Offset
+  Vector3 mSelectionHandleTwoOffset;              // Handle Two's Offset
+  Vector3 mSelectionHandleOneCoordinatePosition;  // Actual x y z position of handle
+  Vector3 mSelectionHandleTwoCoordinatePosition;  // Actual x y z position of handle
+  std::size_t mSelectionHandleOneStringPosition;  // Position of handle along the string of text
+  std::size_t mSelectionHandleTwoStringPosition;  // Position of handle along the string of text
+
+  Image mGrabHandleImage;                         // Image to be used for grab handle
+  ImageActor mGrabHandle;                         // Handle used to move cursor for editing
+  Actor mGrabHandleGrabArea;                      // invisible actor that receives pans events for the grab handle.
+
+  HandlesReleasedSignal mReleasedSignal;          // Signal emitted when a handle is released
+
+  bool mIsSelectionHandleOneFlipped:1;            // Flag to know whether the handle one is flipped or not.
+  bool mIsSelectionHandleTwoFlipped:1;            // Flag to know whether the handle two is flipped or not.
+};
+
+
+} // namespace Internal
+
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_HANDLES_H__
diff --git a/base/dali-toolkit/internal/controls/text-input/text-input-popup-new-impl.h b/base/dali-toolkit/internal/controls/text-input/text-input-popup-new-impl.h
new file mode 100644 (file)
index 0000000..a3b5d4d
--- /dev/null
@@ -0,0 +1,274 @@
+#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_POPUP_NEW_H__
+#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_POPUP_NEW_H__
+
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// INTERNAL INCLUDES
+#include <dali/dali.h>
+
+#include <dali-toolkit/public-api/controls/text-view/text-view.h>
+#include <dali-toolkit/public-api/controls/buttons/button.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+/**
+ * @brief Class to create and Popup bar made up of buttons.
+ * It provides signals when a button is pressed.
+ * The Popup must be positioned by it's owner.
+ * The future plan is to reuse the Toolkit Popup control to house the buttons.
+ */
+
+class TextInputPopupNew : public ConnectionTracker
+{
+
+public:
+
+  enum State
+  {
+    StateHidden,
+    StateHiding,
+    StateShowing,
+    StateShown
+  };
+
+  // Signal names
+  static const char* const SIGNAL_PRESSED;
+  static const char* const SIGNAL_HIDE_FINISHED;
+  static const char* const SIGNAL_SHOW_FINISHED;
+
+  // Popup Button Pressed
+  typedef SignalV2< bool( Toolkit::Button ) > PopUpPressedSignal;
+
+  // Popup Hide Finished
+  typedef SignalV2< void( TextInputPopupNew& ) > PopUpHideFinishedSignal;
+
+  // Popup Show Finished
+  typedef SignalV2< void( TextInputPopupNew& ) > PopUpShowFinishedSignal;
+
+  /**
+   * Signal emitted when the button is touched.
+   */
+  PopUpPressedSignal& PressedSignal() { return mPressedSignal; }
+
+  /**
+   * Signal emitted when popup is completely hidden
+   * @note Only occurs after a Show() call with animation enabled.
+   */
+  PopUpHideFinishedSignal& HideFinishedSignal() {return mHideFinishedSignal;}
+
+  /**
+   * Signal emitted when popup is completely shown
+   * @note Only occurs after a Hide() call with animation enabled.
+   */
+  PopUpShowFinishedSignal& ShowFinishedSignal() {return mShowFinishedSignal;}
+
+public:
+
+  /**
+   * Default constructor
+   * Creates an empty popup base actor (no content i.e. invisible)
+   */
+  TextInputPopupNew(){};
+
+  /**
+   * Destructor
+   */
+  ~TextInputPopupNew(){};
+
+  /**
+   * @return The root actor of for this popup is returned.
+   */
+  Actor Self() { return mRootActor; };
+
+  /**
+   * Clears popup options (popup no longer exists)
+   */
+  void Clear(){};
+
+  /**
+   * Create the label
+   * @param[in] styledCaption The text to be displayed
+   * @return the newly created label
+   */
+  Toolkit::TextView CreateLabel( const MarkupProcessor::StyledTextArray& styledCaption ){return Toolkit::TextView();};
+
+  /**
+   * Create the label
+   * @param[in] iconImage the image to be used
+   * @return the newly created Image actor to be used as the icon
+   */
+  ImageActor CreateIcon( Image iconImage ) {return ImageActor();};
+
+  /**
+   * Creates and sets up the popup background
+   */
+  void CreatePopUpBackground(){};
+
+  /**
+   * Create divider if multiple options
+   */
+  void CreateDivider(){};
+
+  /**
+   * Create a background to be used when button pressed
+   * @param[in] requiredSize size Image actor should be
+   * @param[in] finalFlag flag to be set if option is the final one.
+   * @return Returns an Image Actor to be used a pressed background
+   */
+  ImageActor CreatePressedBackground( const Vector3 requiredSize, const bool finalFlag ){ return ImageActor(); };
+
+  /**
+   * Adds a popup option button.
+   * @note Creates popup frame if not already created.
+   * @param[in] name The unique name for this option.
+   * @param[in] caption The caption (label) for this option
+   * @param[in] iconImage Image to displayed with text.
+   * @param[in] finalOption Flag to indicate that this is the final option.
+   * (set to true on the last option you add)
+   */
+  void AddButton(const std::string& name, const std::string& caption, const Image iconImage, bool finalOption ){};
+
+  /**
+   * Hides the popup
+   * @param[in] animate (optional) whether to animate popup to hide state over time (i.e. tween).
+   */
+  void Hide(bool animate = true){};
+
+  /**
+   * Shows the popup
+   * @param[in] animate (optional) whether to animate popup to show state over time (i.e. tween).
+   * @param[in] target Actor to parent popup.
+   */
+  void Show( Actor target, bool animate = true ){};
+
+  /**
+   * @brief Get the calculated size of the PopUp
+   * This can not be set directly as is calculated depending on the content added.
+   *
+   * @return Vector3 size of PopUp.
+   */
+  Vector3 GetSize() const { return Vector3::ZERO;};
+
+  /**
+   * Returns the current state of the popup.
+   * @return The state of the popup see enum State
+   */
+  State GetState(void) const{ return StateHidden;};
+
+  /**
+   * Get the root actor which the buttons are added to.
+   * @return the root actor
+   */
+  Actor GetRootActor() const { return Actor(); };
+
+  /**
+   * @brief Creates the PopUp with the required buttons for the provided states.
+   * @param[in] isAllTextSelectedAlready Is all the text already selected
+   * @param[in] isTextEmpty Contains some text
+   * @param[in] hasClipboardGotContent  Something to paste from clipboard
+   * @param[in] isSubsetOfTextAlreadySelected  Some but not all text is selected
+   */
+  void CreateCutCopyPastePopUp( bool isAllTextSelectedAlready, bool isTextEmpty, bool hasClipboardGotContent, bool isSubsetOfTextAlreadySelected ){};
+
+  /**
+   * @brief Applies constraint to keep Popup in view within the desired area.
+   * @param[in] bounding box in which the PopUp must remain.
+   *
+   */
+  void ApplyConfinementConstraint( Vector4 boundingBox ){};
+
+private:
+
+  /**
+   * @brief Adds popup to the given parent
+   * @paran[in] parent target to add Popup to
+   */
+  void AddToParent( Actor parent ){};
+
+  /**
+   * Removes popup from Parent.
+   */
+  void RemoveFromStage(){};
+
+  /**
+   * Called when a button is pressed in the popup
+   * @param[in] button The button pressed.
+   */
+  bool OnButtonPressed( Toolkit::Button button ){return false;};
+
+  /**
+   * Invoked upon popup Hide animation completing.
+   * @note Only called for animating hide, not called for instantaneous (animate = false)
+   * @param[in] source The animation which completed.
+   */
+  void OnHideFinished(Animation& source){};
+
+  /**
+   * Invoked upon popup Show animation completing.
+   * @note Only called for animating show, not called for instantaneous (animate = false)
+   * @param[in] source The animation which completed.
+   */
+  void OnShowFinished(Animation& source);
+
+private:
+
+  /**
+   * @brief Copy Constructor
+   * @param[in] popup
+   * Undefined/Hidden.
+   */
+  TextInputPopupNew(const TextInputPopupNew& popup );
+
+  /**
+   * @Assignment Constructor
+   * @param[in] rhs
+   * Undefined/Hidden.
+   */
+  TextInputPopupNew& operator=(const TextInputPopupNew& rhs);
+
+private:
+
+  State mState;                                       // Popup State.
+  Actor mRootActor;                                   // The actor which all popup content is added to (i.e. panel and buttons)
+  Vector3 mPopupSize;                                 // Size of the PopUp determined by it's content and max/min size constraints.
+  ImageActor mBackground;                             // The background popup panel
+  ImageActor mTail;                                   // The tail for the popup
+  Vector3 mContentSize;                               // Size of Content (i.e. Buttons)
+  ActorContainer mButtonContainer;                    // List of buttons added to popup.
+  ActorContainer mDividerContainer;                   // List of dividers added to popup.
+  Animation mAnimation;                               // Popup Hide/Show animation.
+
+  PopUpPressedSignal mPressedSignal;                     // Signal emitted when a button within the popup is pressed.
+  PopUpHideFinishedSignal mHideFinishedSignal;           // Signal emitted when popup is completely hidden
+  PopUpShowFinishedSignal mShowFinishedSignal;           // Signal emitted when popup is completely shown
+
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_POPUP_NEW_H__
diff --git a/base/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.h b/base/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.h
new file mode 100644 (file)
index 0000000..ae95f7d
--- /dev/null
@@ -0,0 +1,179 @@
+#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_HIGHLIGHT_H__
+#define __DALI_TOOLKIT_INTERNAL_TEXT_HIGHLIGHT_H__
+
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// INTERNAL INCLUDES
+#include <dali/dali.h>
+#include <dali-toolkit/internal/controls/text-input/textview-character-positions-impl.h>
+
+#include <dali-toolkit/public-api/controls/text-view/text-view.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+/**
+ * @brief TextHighlight is a decoration which highlights selected text.
+ *
+ * The class creates a highlight mesh used to show selected text between handles.
+ * Not responsible for positioning.
+ */
+class TextHighlight
+{
+  /**
+   * structure to hold coordinates of each quad, which will make up the mesh.
+   */
+  struct QuadCoordinates
+  {
+    /**
+     * Default constructor
+     */
+    QuadCoordinates()
+    {
+    }
+
+    /**
+     * Constructor
+     * @param[in] x1 left co-ordinate
+     * @param[in] y1 top co-ordinate
+     * @param[in] x2 right co-ordinate
+     * @param[in] y2 bottom co-ordinate
+     */
+    QuadCoordinates(float x1, float y1, float x2, float y2)
+    : min(x1, y1),
+      max(x2, y2)
+    {
+    }
+
+    Vector2 min;                          ///< top-left (minimum) position of quad
+    Vector2 max;                          ///< bottom-right (maximum) position of quad
+  };
+
+  typedef std::vector<QuadCoordinates> QuadContainer;
+
+public:
+
+  /**
+   * structure for information required to build the highlight mesh
+   */
+  struct HighlightInfo
+  {
+    /**
+     * Adds a Quad (2D rectangular sub-selection)
+     * @param[in] x1 left co-ordinate
+     * @param[in] y1 top co-ordinate
+     * @param[in] x2 right co-ordinate
+     * @param[in] y2 bottom co-ordinate
+     */
+    void AddQuad( float x1, float y1, float x2, float y2 ){};
+
+    /**
+     * Clamps all quads to fit within a min -> max 2D boundary.
+     */
+    void Clamp2D(const Vector2& min, const Vector2& max){};
+
+    QuadContainer mQuadList;                                 ///< List of quads (sub-selections that form to create complete selection)
+  };
+
+  /**
+   * Constructor
+   * @param[in] textViewCharacterPositioning TextViewCharacterPositioning to be used for positioning information.
+   */
+  TextHighlight( TextViewCharacterPositioning& textViewCharacterPositioning ):mTextViewCharacterPositioning( textViewCharacterPositioning ){};
+
+  /**
+   * Destructor
+   */
+  ~TextHighlight(){};
+
+  /**
+   * Gets the table of the visual text positions which has a flag
+   * for each Character. The flag is either true (character selected)
+   * or false (character de-selected)
+   * @note startSelection can be greater or less than endSelection
+   *
+   * @param[in,out] selectedVisualText The vector to be resized and populated with the selected flags
+   * @param[in] startSelection The start selection point for the text
+   * @param[in] endSelection The end selection point for the text
+   * @param[in] endSelection The end selection point for the text
+   * @param[in] textLayoutInfo TextView character layout information
+   */
+  void GetVisualTextSelection(std::vector<bool>& selectedVisualText, std::size_t startSelection, std::size_t endSelection,
+                              Toolkit::TextView::TextLayoutInfo& textLayoutInfo){};
+
+  /**
+   * Iterates between selection handles and computes the info required to build the highlight mesh
+   * @param[in] handlePositionStart starting handle position
+   * @param[in] handlePositionEnd ending handle position
+   * @return textHighlight target TextHighlight
+   */
+  TextHighlight::HighlightInfo CalculateHighlightInfo( std::size_t handlePositionStart, std::size_t handlePositionEnd, Toolkit::TextView::TextLayoutInfo& textLayoutInfo )
+  { return HighlightInfo();};
+
+  /**
+   * Calculates new Mesh data so highlight moves with selection handles.
+   * @param[in] newHighlightInfo HighlightInfo calculated by CalculateHighlightInfo
+   */
+  void UpdateHighlight( TextHighlight::HighlightInfo& newHighlightInfo ){};
+
+  /**
+   * Creates the Mesh data needed by the Mesh Actor
+   */
+  Mesh CreateHighLightMesh(){return Mesh();};
+
+private:
+
+  /**
+   * @brief Copy Constructor
+   * @param[in] textHight
+   * Undefined/Hidden.
+   */
+  TextHighlight(const TextHighlight& textHight );
+
+  /**
+   * @Assignment Constructor
+   * @param[in] rhs
+   * Undefined/Hidden.
+   */
+  TextHighlight& operator=(const TextHighlight& rhs);
+
+private:
+
+  TextViewCharacterPositioning& mTextViewCharacterPositioning;
+
+  Mesh              mHighlightMesh;             ///< Mesh Data for highlight
+  MeshData          mMeshData;                  ///< Container to hold meshData for highlight
+  Material          mCustomMaterial;            ///< Custom material used for highlight
+  HighlightInfo     mNewHighlightInfo;          ///< Geometry info to create highlight.
+
+};
+
+
+} // namespace Internal
+
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_INTERNAL_TEXT_HIGHLIGHT_H__
diff --git a/base/dali-toolkit/internal/controls/text-input/text-input-text-style-impl.h b/base/dali-toolkit/internal/controls/text-input/text-input-text-style-impl.h
new file mode 100644 (file)
index 0000000..60815cb
--- /dev/null
@@ -0,0 +1,120 @@
+#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXT_STYLE_H__
+#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXT_STYLE_H__
+
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <dali/dali.h>
+
+// INTERNAL INCLUDES
+
+#include <dali-toolkit/internal/controls/text-input/textview-character-positions-impl.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+class TextInputTextStyle;
+
+typedef IntrusivePtr<TextInputTextStyle> TextInputTextStylePtr;
+
+/**
+ *  Stores the Input Text Style and provides functions to retrieve and manipulate it.
+ */
+
+class TextInputTextStyle : ConnectionTracker
+{
+
+public:
+
+  /**
+   * @brief Constructor
+   */
+  TextInputTextStyle(){};
+
+  /**
+   * @brief Destructor
+   */
+   ~TextInputTextStyle(){};
+
+  /**
+   * @brief Returns the current Input Style, this is the style that newly inputed text will inherit.
+   * @return TextStyle object representing new style.
+   */
+  TextStyle GetInputStyle() const{return mInputStyle;};
+
+  /**
+   * @brief Sets the Input style so newly inputed text will inherit this.
+   * @param[in] newStyle the style to now use for Input
+   * @return returns true if style changed.  False if new style is the same as current setting.
+   */
+  bool SetInputStyle( const TextStyle newStyle, const TextStyle::Mask mask = TextStyle::ALL ){return false;};
+
+  /**
+   * @brief Gets the Current Font used for newly inputed text
+   * @return the Font currently set for new text
+   */
+  Dali::Font GetInputFont() const{return Dali::Font();};
+
+  /**
+   * Signals
+   */
+
+  /* Input style changed signal.*/
+  typedef SignalV2< void( const TextStyle& style ) > StyleChangedSignalType;
+
+  /**
+   * @brief Signal emitted when style changes.
+   * @return The signal to connect to
+   */
+  StyleChangedSignalType& StyleChangedSignal();
+
+private:
+
+  /**
+   * @brief Copy Constructor
+   * @param[in] textStyle
+   * Undefined/Hidden.
+   */
+  TextInputTextStyle(const TextInputTextStyle& textStyle );
+
+  /**
+   * @Assignment Constructor
+   * @param[in] rhs
+   * Undefined/Hidden.
+   */
+  TextInputTextStyle& operator=(const TextInputTextStyle& rhs);
+
+private:
+
+  TextStyle mInputStyle;                               // Stores the current input style.
+  StyleChangedSignalType mStyleChangedSignal;          // Signal emitted when style changes.
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXT_STYLE_H__
+
+
diff --git a/base/dali-toolkit/internal/controls/text-input/textview-character-positions-impl.h b/base/dali-toolkit/internal/controls/text-input/textview-character-positions-impl.h
new file mode 100644 (file)
index 0000000..d905e22
--- /dev/null
@@ -0,0 +1,340 @@
+#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXTVIEW_CHARACTER_POSITIONS_H__
+#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXTVIEW_CHARACTER_POSITIONS_H__
+
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+///
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/text-input/text-input-text-style-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/dali.h>
+#include <dali-toolkit/public-api/controls/text-view/text-view.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+class TextInputTextStyle;
+
+/**
+ * Class which contains functions related to the TextView.
+ * Functions which are needed by various parts of the TextInput to determine the position of characters.
+ * Functions to Set the TextView so text justification, alignment and wrapping behaviour in the desired manner for text input.
+ * The functionality of this class may be divided in future.
+ */
+class TextViewCharacterPositioning
+{
+
+public:
+
+  /**
+   * @brief Constructor
+   *
+   * @param[in] displayedTextView TextView to be used with this class.
+   * @param[in] textStyle TextInputTextStyle to be used
+   */
+  TextViewCharacterPositioning( Toolkit::TextView displayedTextView, TextInputTextStyle& textStyle ):mTextStyle( textStyle ){};
+
+  /**
+   * Destructor
+   */
+  ~TextViewCharacterPositioning(){};
+
+  /**
+   * @brief Creates the TextView to be used within this class.
+   */
+  void CreateTextView(){};
+
+  /*
+   * @brief Get a handle to the current text view object
+   * If one does not exist then it's create.
+   * @return TextView
+   */
+  Toolkit::TextView GetTextView() const{return Toolkit::TextView();};
+
+  /**
+   * @brief Get the TextLayoutInfo from the TextView so know the updated positions of characters.
+   */
+  void UpdateTextLayoutInfo(){};
+
+
+  /**
+   *  @brief Get the TextLayoutInfo structure for the TextView
+   *  @return the TextLayoutInfo structure
+   */
+  const Toolkit::TextView::TextLayoutInfo& GetLayoutInfo() const{return mTextLayoutInfo;};
+
+
+  /**
+   * @brief Get the number of characters visually represented in the text
+   * @return the number of characters
+   */
+  std::size_t GetNumberOfCharactersInText() const{return 0;};
+
+  /**
+   * @brief Check if any text exists in TextView's character layout table
+   * @return bool true if empty
+   */
+  bool IsTextEmpty() const{return false;};
+
+  /**
+   * @brief Get the height of the line at the given cursor position
+   * @param[in] position
+   * @return float the height of the line
+   */
+  float GetLineHeight( std::size_t position ) const{return 0.0f;};
+
+  /**
+   * @brief Sets if the inputed text can exceed the text-input boundary.
+   * By default is enabled.
+   * @param[in] enable Whether the inputed text can exceed its boundary.
+   */
+  void SetTextExceedEnabled( bool enable ) {};
+
+  /**
+   * @brief Retrieves whether inputed text can exceed the text-input boundary.
+   * @return \e true if text inputed can exceed the boundary, otherwise \e false.
+   */
+  bool IsTextExceedEnabled() const{ return false;};
+
+  /**
+   * @brief From the given x and y vector the closest character position is returned
+   * @param[in] source the x and y position
+   * @return the position in the string of the character closest to the source.
+   */
+  std::size_t ReturnClosestIndex( const Vector2& source ){return 0;};
+
+  /**
+   * @brief If no text exists then this function uses the text alignment to position cursor.
+   * @param[in] cursorPosition
+   */
+  void GetActualPositionFromCharacterPositionWhenNoText( Vector3& cursorPosition ) const{};
+
+  /**
+   * @brief Function to position cursor when a word is wrapped to another line
+   * @param[in] characterPosition that actual position is required for
+   * @return the actual position of the cursor.
+   */
+  Vector3 PositionCursorAfterWordWrap( std::size_t characterPosition ) const{return Vector3::ZERO;};
+
+  /**
+   * @brief Returns the x-position of the current line justification
+   * (relative to left of text-view container)
+   * @return x position for line justification
+   */
+  float GetLineJustificationPosition() const{return 0.0f;};
+
+  /**
+   * @brief Retrieve the dimensions (and min-max) of this row of text that the character resides on.
+   * @param[in] characterPosition the position in the 'string' of characters.
+   * @param[out] min the top-left position of the rectangle representing this row
+   * @param[out] max the bottom-right position of the rectangle representing this row
+   * @return The size of the rectangle representing this row (max - min)
+   */
+  Size GetRowRectFromCharacterPosition(std::size_t characterPosition, Vector2& min, Vector2& max) const{return Vector2::ZERO;};
+
+  /**
+   * @brief Retrieve the character position of the first character on the row of text
+   * that this character resides on.
+   * @param[in] logicalPosition the position in the 'string' of characters.
+   * @return logical character position of start of row.
+   */
+  std::size_t GetRowStartFromCharacterPosition(std::size_t logicalPosition) const{return 0;};
+
+  /**
+   * @brief Gets the visual position of a logical position.
+   * @note This is preferred over directly accessing the Map, as it resolves visual
+   * positions outside of the character map range.
+   * @param[in] logicalPosition The logical position
+   * @return Visual position is returned.
+   */
+  std::size_t GetVisualPosition(std::size_t logicalPosition) const{return 0;};
+
+  /**
+   * @brief Return a vector which is the actual position for the given character position
+   * The character position is where a cursor would be position for that character.
+   * @param[in] characterPosition the logical (input) position in the 'string' of characters.
+   *
+   * @return Vector3 the actual x,y,z position
+   */
+  Vector3 GetActualPositionFromCharacterPosition(std::size_t characterPosition ) const{return Vector3::ZERO;};
+
+  /**
+   * @brief Return a vector which is the actual position for the given character position
+   * The character position is where a cursor would be positioned for that character to be inserted.
+   * An additional alternatePosition is also set in circumstances where the possible writing
+   * of characters would be in the opposite direction.
+   * e.g. "HelloشقشلاهؤEnglish"
+   *            |     |
+   *            *     +
+   * [*] - Primary actual position for cursor i.e. continuing writing LTR (English)
+   * [+] - Alternate actual position for cursor i.e. writing RTL (Arabic)
+   *
+   * @param[in] characterPosition the logical (input) position in the 'string' of characters.
+   * @param[out] directionRTL Whether the actual x,y,z position is after LTR (false) or RTL (true) text.
+   * @param[out] alternatePosition the actual x,y,z position of the cursor if user types
+   * in alternate direction to current flow of text.
+   * @param[out] alternatePositionValid whether this alternate position is valid.
+   * @return Vector3 the actual x,y,z position
+   */
+  Vector3 GetActualPositionFromCharacterPosition(std::size_t characterPosition, bool& directionRTL, Vector3& alternatePosition, bool& alternatePositionValid ) const{return Vector3::ZERO;};
+
+  /**
+   * @brief Get the currently displayed text.
+   * @return The currently displayed text.
+   */
+  std::string GetText() const{return std::string();};
+
+  /**
+   * @brief Get the text currently being displayed together with mark-up tags.
+   * @return string, the currently displayed string with mark-up.
+   */
+  std::string GetMarkupText() const{return std::string();};
+
+  /**
+   * @brief Sets whether markup processing should be carried out.
+   *
+   * @param[in] enable whether markup processing is carried out or not.
+   */
+  void SetMarkupProcessingEnabled( bool enable ){};
+
+  /**
+   * @brief Returns whether markup processing is enabled or not
+   *
+   * @return true is markup processing is enabled
+   */
+  bool IsMarkupProcessingEnabled() const{ return false;};
+
+  // Styled Text
+
+  /**
+   * @brief Check if styled text is empty
+   * @return bool returns true if styled text is empty
+   */
+  bool IsStyledTextEmpty() const{ return false;};
+
+  /**
+   * @brief The size of the style text
+   * @return std::size_t returns number of characters in styled text
+   */
+  std::size_t StyledTextSize() const{return 0;};
+
+  /**
+   * @brief Get the styled text array
+   * @return reference to MarkupProcessor::StyledTextArray
+   */
+  MarkupProcessor::StyledTextArray& GetStyledTextArray(){return mStyledText;};
+
+  /**
+   * @brief Get the style for the character at the given position
+   * @param[in] position of character style is required for
+   * @return a copy of the style structure for the character at the given position
+   */
+  TextStyle GetStyleAt( std::size_t position ) const{return TextStyle();};
+
+/**
+   * @briefApplies the given style to all text, selected or not selected.
+   * By default all style settings are applied but a bit mask could be used to modify only certain style settings.
+   * @param[in] style style to apply
+   * @param[in] mask mask style should be applied to
+   * @param[in] begin start position of range to apply style
+   * @param[in] end end position of range to apply style
+   */
+  void ApplyStyleToRange( const TextStyle& style, const TextStyle::Mask mask, const std::size_t begin, const std::size_t end ){};
+
+  // Snapshot
+  /**
+   * @copydoc TextView::SetSnapshotModeEnabled()
+   */
+  void SetSnapshotModeEnabled( bool enable ){};
+
+  /**
+   * @copydoc TextView::IsSnapshotModeEnabled()
+   */
+  bool IsSnapshotModeEnabled() const{ return false;};
+
+  // Scrolling
+  /**
+   * @copydoc TextView::SetScrollEnabled()
+   */
+  void SetScrollEnabled( bool enable ){};
+
+  /**
+   * @copydoc TextView::SetScrollPosition()
+   */
+  void SetScrollPosition( const Vector2& position ){};
+
+  /**
+   * @copydoc TextView::IsScrollEnabled()
+   */
+  bool IsScrollEnabled() const{ return false;};
+
+  /**
+   * @copydoc TextView::GetScrollPosition()
+   */
+  Vector2 GetScrollPosition() const{return Vector2::ZERO;};
+
+  /**
+   * @copydoc TextView::GetScrollPosition()
+   */
+  bool IsScrollPositionTrimmed() const{ return false;};
+
+private:
+
+  /**
+   * @brief Copy Constructor
+   * @param[in] characterPositioning
+   * Undefined.
+   */
+  TextViewCharacterPositioning(const TextViewCharacterPositioning& characterPositioning );
+
+  /**
+   * @Assignment Constructor
+   * @param[in] rhs
+   * Undefined.
+   */
+  TextViewCharacterPositioning& operator=(const TextViewCharacterPositioning& rhs);
+
+private:
+
+  Toolkit::TextView mDisplayedTextView;         // A text view object used to display the text.
+  TextInputTextStyle& mTextStyle;               // Holds the style object related to input style
+
+  MarkupProcessor::StyledTextArray mStyledText; // String currently displayed by TextView with style info.
+
+  Toolkit::TextView::TextLayoutInfo      mTextLayoutInfo; // It contains a table layout info per character sorted by the character's visual index (retrieved from TextView),
+                                                          // a reorder map that stores each character's visual (output) index according to its logical (input) index,
+                                                          // a reorder map that stores each character's logical (input) index according to its visual (output) index
+
+  bool mExceedEnabled:1; // flag set by user to determine if text can exceed the control's size
+  bool mMarkUpEnabled:1; // If Markup is being passed with the text
+};
+
+
+} // namespace Internal
+
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXTVIEW_CHARACTER_POSITIONS_H__
index 3f1a9f2..0c944aa 100644 (file)
@@ -35,6 +35,7 @@ toolkit_base_src_files = \
    $(toolkit_base_src_dir)/controls/scrollable/scroll-view/scroll-view-twist-effect-impl.cpp \
    $(toolkit_base_src_dir)/controls/scrollable/scroll-view/scroll-view-wobble-effect-impl.cpp \
    $(toolkit_base_src_dir)/controls/table-view/table-view-impl.cpp \
    $(toolkit_base_src_dir)/controls/scrollable/scroll-view/scroll-view-twist-effect-impl.cpp \
    $(toolkit_base_src_dir)/controls/scrollable/scroll-view/scroll-view-wobble-effect-impl.cpp \
    $(toolkit_base_src_dir)/controls/table-view/table-view-impl.cpp \
+   $(toolkit_base_src_dir)/controls/text-input/text-input-decorator-impl.cpp \
    $(toolkit_base_src_dir)/controls/text-input/text-input-impl.cpp \
    $(toolkit_base_src_dir)/controls/text-input/text-input-popup-impl.cpp \
    $(toolkit_base_src_dir)/controls/text-view/relayout-utilities.cpp   \
    $(toolkit_base_src_dir)/controls/text-input/text-input-impl.cpp \
    $(toolkit_base_src_dir)/controls/text-input/text-input-popup-impl.cpp \
    $(toolkit_base_src_dir)/controls/text-view/relayout-utilities.cpp   \