TextInput Popup scrolling fixed after GUI changes. GUI settings changed.
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / controls / text-input / text-input-popup-impl.cpp
index 3fbe619..14f998f 100644 (file)
@@ -32,12 +32,8 @@ namespace
 {
 const Vector2 DEFAULT_POPUP_INDICATOR_OFFSET(0.0f, 60.0f);
 
-
-// TODO: This should be based on the content for example:
 // 1. For selection: should be above top of highlighted selection, or below bottom of highlighted selection + end handle.
 // 2. For cursor: should be above top of cursor, or below bottom of cursor + grab handle.
-const std::string POPUP_ALTERNATIVE_OFFSET("popup-alternative-offset");       ///< Alternative offset property for confinenment constraint.
-const std::string POPUP_REQUESTED_POSITION("popup-requested-position");       ///< Position the Popup was requested to be, for confinenment constraint.
 
 /**
  * Image resource paths
@@ -45,9 +41,14 @@ const std::string POPUP_REQUESTED_POSITION("popup-requested-position");       //
 const std::string POPUP_BACKGROUND( DALI_IMAGE_DIR "popup_bubble_bg.#.png" );
 const std::string POPUP_BACKGROUND_EFFECT( DALI_IMAGE_DIR "popup_bubble_bg_ef.#.png" );
 const std::string POPUP_BACKGROUND_LINE( DALI_IMAGE_DIR "popup_bubble_bg_line.#.png" );
+
 const std::string POPUP_TAIL_BOTTOM( DALI_IMAGE_DIR "popup_bubble_tail_bottom.png" );
 const std::string POPUP_TAIL_BOTTOM_EFFECT( DALI_IMAGE_DIR "popup_bubble_tail_bottom_ef.png" );
 const std::string POPUP_TAIL_BOTTOM_LINE( DALI_IMAGE_DIR "popup_bubble_tail_bottom_line.png" );
+const std::string POPUP_TAIL_TOP( DALI_IMAGE_DIR "popup_bubble_tail_top.png" );
+const std::string POPUP_TAIL_TOP_EFFECT( DALI_IMAGE_DIR "popup_bubble_tail_top_ef.png" );
+const std::string POPUP_TAIL_TOP_LINE( DALI_IMAGE_DIR "popup_bubble_tail_top_line.png" );
+
 const std::string OPTION_ICON_CLIPBOARD( DALI_IMAGE_DIR "copy_paste_icon_clipboard.png" );
 const std::string OPTION_ICON_COPY( DALI_IMAGE_DIR "copy_paste_icon_copy.png" );
 const std::string OPTION_ICON_CUT( DALI_IMAGE_DIR "copy_paste_icon_cut.png" );
@@ -58,15 +59,16 @@ const std::string OPTION_ICON_SELECT_ALL( DALI_IMAGE_DIR "copy_paste_icon_select
 /**
  * Constant values for building the GUI
  */
-const Vector4 POPUP_BORDER( 14.0f, 14.0f, 14.0f, 14.0f );  ///< The margin of the popup.
+const Vector4 POPUP_MARGIN( 14.0f, 14.0f, 14.0f, 14.0f );  ///< Margin around the popup visible background Image.
+const Vector4 POPUP_BORDER( 2.0f, 2.0f, 2.0f, 2.0f );  ///< The Border of the popup.
 const Vector2 POPUP_MIN_SIZE( 0.0f, 126.0f );  ///< The minimum size of the popup.
 const Vector2 POPUP_MAX_SIZE( 720.0f, 126.0f );  ///< The maximum size of the popup.
 const float POPUP_TAIL_Y_OFFSET( -2.25f );  ///< The y offset of the tail.
 const Vector2 POPUP_TAIL_SIZE( 36.0f, 36.0f );  ///< The size of the tail.
 const Vector2 POPUP_DIVIDER_SIZE( 1.0f, 126.0f );  ///< The size of the divider.
 
-const Vector4 OPTION_MARGIN( 0.0f, 0.0f, 24.0f, 19.0f );  ///< The margin of the icon. the order is left, right, top and bottom
-const Vector2 OPTION_MAX_SIZE( 360.0f, 126.0f );  ///< The maximum size of the option.
+const Vector4 OPTION_PADDING( 16.0f, 16.0f, 24.0f, 19.0f );  ///< The padding within the option to position icon and text away from the border. The order is left, right, top and bottom
+const Vector2 OPTION_MAX_SIZE( 220.0f, 126.0f );  ///< The maximum size of the option.
 const Vector2 OPTION_MIN_SIZE( 128.0f, 126.0f );  ///< The minimum size of the option.
 const Vector2 OPTION_ICON_SIZE( 45.0f, 45.0f );  ///< The size of the icon.
 const Vector2 OPTION_TEXT_MIN_SIZE( 128.0f, 30.0f );  ///< The minimum size of the text.
@@ -86,130 +88,6 @@ const Vector4 DEFAULT_OPTION_ICON_PRESSED( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
 const Vector4 DEFAULT_OPTION_TEXT( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
 const Vector4 DEFAULT_OPTION_TEXT_PRESSED( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
 
-
-/**
- * Confine Actor to boundaries of reference actor (e.g. Parent)
- * Actor bounds (top-left position + size) are confined to reference Actor's
- * bounds.
- */
-struct ConfinementConstraint
-{
-  /**
-   * Confinement constraint constructor.
-   * @param[in] topLeftMargin (optional) Top-Left margins (defaults to 0.0f, 0.0f)
-   * @param[in] bottomRightMargin (optional) Bottom-Right margins (defaults to 0.0f, 0.0f)
-   * @paran[in[ flipHorizontal (optional) whether to flip Actor to other side if near edge
-   * @param[in] flipVertical (optional) whether to flip Actor to the other side if near edge
-   * @param[in] boundingRect Rectangle to bound Popup to.
-   *
-   */
-  ConfinementConstraint(Vector2 topLeftMargin = Vector2::ZERO, Vector2 bottomRightMargin = Vector2::ZERO, bool flipHorizontal = false, bool flipVertical = false, Rect<float> boundingRect = Rect<float>(0.0f, 0.0f, 0.0f, 0.0f) )
-  : mMinIndent(topLeftMargin),
-    mMaxIndent(bottomRightMargin),
-    mFlipHorizontal(flipHorizontal),
-    mFlipVertical(flipVertical),
-    mBoundingRect( boundingRect )
-  {
-  }
-
-  Vector3 operator()(const Vector3&    constPosition,
-                     const PropertyInput& sizeProperty,
-                     const PropertyInput& parentOriginProperty,
-                     const PropertyInput& anchorPointProperty,
-                     const PropertyInput& referenceSizeProperty,
-                     const PropertyInput& alternativeOffsetProperty,
-                     const PropertyInput& requestedPositionProperty )
-  {
-    const Vector3& size = sizeProperty.GetVector3();
-    const Vector3& origin = parentOriginProperty.GetVector3();
-    const Vector3& anchor = anchorPointProperty.GetVector3();
-    const Vector3& referenceSize = referenceSizeProperty.GetVector3();
-    const Vector2& alternativeOffset = alternativeOffsetProperty.GetVector2();
-    const Vector3& requestedPosition = requestedPositionProperty.GetVector3();
-
-    Vector3 newPosition( requestedPosition );
-
-    // Get actual position of Actor relative to parent's Top-Left.
-    Vector3 position(constPosition + origin * referenceSize);
-
-    // if top-left corner is outside of Top-Left bounds, then push back in screen.
-
-    Vector3 corner(position - size * anchor - mMinIndent);
-
-    if ( mFlipHorizontal )
-    {
-      if( corner.x < mBoundingRect.x )
-      {
-        // Snap Popup to left hand boundary so stays visible
-        corner.x = mBoundingRect.x - ( origin.x * referenceSize.x ) + ( size.x * anchor.x );
-        newPosition.x = corner.x;
-      }
-      else if ( ( corner.x + size.x ) > ( mBoundingRect.x + mBoundingRect.width ))
-      {
-        // Calculate offset from left boundary Popup must be placed at so it does not exceed right side boundary.
-        float requiredOffSetFromLeftBoundaryToFit = mBoundingRect.width - size.x;
-        corner.x = mBoundingRect.x + requiredOffSetFromLeftBoundaryToFit - ( origin.x * referenceSize.x ) + ( size.x * anchor.x );
-        newPosition.x = corner.x;
-       }
-    }
-
-    if(mFlipVertical && corner.y < 0.0f)
-    {
-      corner.y = 0.0f;
-      newPosition.y += size.height + alternativeOffset.height;
-    }
-
-    newPosition.y -= std::min(corner.y, 0.0f);
-
-    // if bottom-right corner is outside of Bottom-Right bounds, then push back in screen.
-    corner += size - referenceSize + mMinIndent + mMaxIndent;
-
-    if(mFlipVertical && corner.y > 0.0f)
-    {
-      corner.y = 0.0f;
-      newPosition.y -= size.height + alternativeOffset.height;
-    }
-
-    return newPosition;
-  }
-
-  Vector3 mMinIndent;                                   ///< Top-Left Margin
-  Vector3 mMaxIndent;                                   ///< Bottom-Right Margin.
-  bool mFlipHorizontal;                                 ///< Whether to flip actor's position if exceeds horizontal screen bounds
-  bool mFlipVertical;                                   ///< Whether to flip actor's position if exceeds vertical screen bounds
-  Rect<float> mBoundingRect;                            ///< Bounding Rect Popup must stay within
-};
-
-/**
- * Confine actor to the x axis boundaries of reference actor (e.g. Parent)
- */
-struct ParentXAxisConstraint
-{
-  /**
-   * Confinement constraint constructor.
-   */
-  ParentXAxisConstraint( float handlesMidPoint = 0.0f )
-  : mHandlesMidPoint( handlesMidPoint )
-  {
-  }
-
-  float operator()(  const float          constXPosition,
-                     const PropertyInput& localSizeWidthProperty,
-                     const PropertyInput& parentWidthProperty,
-                     const PropertyInput& anchorPointXProperty )
-  {
-    const float localSizeProperty = localSizeWidthProperty.GetFloat();
-    const float size = parentWidthProperty.GetFloat();
-
-    float newPosition = std::max( mHandlesMidPoint, -size/2 + localSizeProperty );
-    newPosition = std::min( newPosition, size/2 - localSizeProperty );
-    return newPosition;
-  }
-
-  float mHandlesMidPoint;
-};
-
-
 } // unnamed namespace
 
 namespace Dali
@@ -234,9 +112,11 @@ const char* const TextInputPopup::OPTION_CLIPBOARD("option-clipboard");
 
 TextInputPopup::TextInputPopup()
 : mState(StateHidden),
-  mRoot(Layer::New()),
+  mRoot( Layer::New() ),
+  mButtons(),
+  mVisiblePopUpSize(),
   mPopupTailXPosition( 0.0f ),
-  mContentSize( POPUP_MIN_SIZE ),
+  mContentSize(),
   mBackgroundColor( DEFAULT_POPUP_BACKGROUND ),
   mBackgroundPressedColor( DEFAULT_POPUP_BACKGROUND_PRESSED ),
   mLineColor( DEFAULT_POPUP_LINE_COLOR ),
@@ -254,51 +134,40 @@ TextInputPopup::TextInputPopup()
   mHideFinishedSignal(),
   mShowFinishedSignal()
 {
-  mAlternativeOffsetProperty = mRoot.RegisterProperty( POPUP_ALTERNATIVE_OFFSET, Vector2::ZERO );
-  mRequestionPositionProperty = mRoot.RegisterProperty( POPUP_REQUESTED_POSITION, Vector3::ZERO );
-  mRoot.SetParentOrigin( ParentOrigin::CENTER );
+  mRoot.SetParentOrigin( ParentOrigin::TOP_LEFT );
   mRoot.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
-  // constrain popup to size of parent.
 }
 
-void TextInputPopup::AddToStage()
+void TextInputPopup::AddToParent( Actor parent )
 {
-  // TODO: Confinement constraint borders should be defined by the application.
-  // It should also not use the stage directly, instead it should add to parent container.
-  Stage::GetCurrent().Add(mRoot);
+  Actor existingParent = mRoot.GetParent();
 
-  ApplyConfinementConstraint();
+  if ( !existingParent )
+  {
+    parent.Add( mRoot );
+  }
 }
 
-void TextInputPopup::ApplyConfinementConstraint()
+void TextInputPopup::RemoveFromParent()
 {
-  mRoot.RemoveConstraints();
-  Constraint constraint = Constraint::New<Vector3>( Actor::POSITION,
-                                                    LocalSource( Actor::SIZE ),
-                                                    LocalSource( Actor::PARENT_ORIGIN ),
-                                                    LocalSource( Actor::ANCHOR_POINT ),
-                                                    ParentSource( Actor::SIZE ),
-                                                    LocalSource( mAlternativeOffsetProperty ),
-                                                    LocalSource( mRequestionPositionProperty),
-                                                    ConfinementConstraint( DEFAULT_POPUP_INDICATOR_OFFSET,
-                                                                           Vector2::ZERO,
-                                                                           true,
-                                                                           true, mBoundingRect ) );
-  mRoot.ApplyConstraint(constraint);
+  Actor parent = mRoot.GetParent();
+
+  if ( parent )
+  {
+    parent.Remove( mRoot );
+  }
 }
 
-void TextInputPopup::ApplyTailConstraint()
+void TextInputPopup::CreateLayer( const Vector2& size )
 {
-  mTail.RemoveConstraints();
-  Constraint constraint = Constraint::New<float>( Actor::POSITION_X,
-                                                  LocalSource( Actor::SIZE_WIDTH ),
-                                                  ParentSource( Actor::SIZE_WIDTH ),
-                                                  LocalSource( Actor::PARENT_ORIGIN_X ),
-                                                  ParentXAxisConstraint( mPopupTailXPosition ));
-  mTail.ApplyConstraint( constraint );
+  mLayer = Layer::New();
+  mLayer.SetParentOrigin(ParentOrigin::CENTER);
+  mLayer.SetAnchorPoint(AnchorPoint::CENTER);
+  mLayer.SetSize( size ); // matches stencil size
+  mLayer.SetName("popup-mLayer");
 }
 
-void TextInputPopup::CreateStencil( const Vector2& size)
+void TextInputPopup::CreateStencil( const Vector2& size )
 {
   mStencil = CreateSolidColorActor( Color::BLUE );
   mStencil.SetParentOrigin( ParentOrigin::CENTER );
@@ -311,28 +180,27 @@ void TextInputPopup::CreateStencil( const Vector2& size)
 
 void TextInputPopup::OnScrollStarted( const Vector3& position )
 {
-  mBackground.SetSensitive( false );
+  mButtons.SetSensitive( false );
 }
 
 void TextInputPopup::OnScrollCompleted( const Vector3& position )
 {
-  mBackground.SetSensitive( true );
+  mButtons.SetSensitive( true );
 }
 
 void TextInputPopup::CreateScrollView()
 {
   mScrollView = Toolkit::ScrollView::New();
   mScrollView.SetName("popup-scroll-view");
-  mScrollView.SetAnchorPoint( AnchorPoint::TOP_LEFT );
-  mScrollView.SetParentOrigin( ParentOrigin::TOP_LEFT );
-  mScrollView.SetPosition( POPUP_BORDER.x, POPUP_BORDER.y );
+  mScrollView.SetAnchorPoint( AnchorPoint::CENTER );
+  mScrollView.SetParentOrigin( ParentOrigin::CENTER );
   mScrollView.SetScrollingDirection( PanGestureDetector::DIRECTION_HORIZONTAL, Degree( 40.0f ) );
   mScrollView.SetAxisAutoLock( true );
   mScrollView.ScrollStartedSignal().Connect( this, &TextInputPopup::OnScrollStarted );
   mScrollView.ScrollCompletedSignal().Connect( this, &TextInputPopup::OnScrollCompleted );
 }
 
-void TextInputPopup::UpdateScrollViewProperty( const Vector2& visibleSize )
+void TextInputPopup::UpdateScrollViewRulerAndSize( const Vector2& visibleSize )
 {
   mScrollView.SetSize( visibleSize.x, visibleSize.y );
 
@@ -344,10 +212,6 @@ void TextInputPopup::UpdateScrollViewProperty( const Vector2& visibleSize )
   mScrollView.SetRulerY(rulerY);
 }
 
-void TextInputPopup::RemoveFromStage()
-{
-  Stage::GetCurrent().Remove( mRoot );
-}
 
 void TextInputPopup::Clear()
 {
@@ -356,13 +220,10 @@ void TextInputPopup::Clear()
     UnparentAndReset( mTail );
     UnparentAndReset( mStencil );
     UnparentAndReset( mBackground );
+    UnparentAndReset( mButtons );
     UnparentAndReset( mScrollView );
-    mButtonContainer.clear();
     mDividerContainer.clear();
-
-    RemoveFromStage();
-    mRoot.RemoveConstraints();
-
+    RemoveFromParent();
     mState = StateHidden;
   }
 }
@@ -374,7 +235,7 @@ ImageActor TextInputPopup::CreateOptionIcon( Image iconImage, const Vector4& col
   icon.SetParentOrigin( ParentOrigin::TOP_CENTER );
   icon.SetAnchorPoint( AnchorPoint::TOP_CENTER );
   icon.SetColor( color );
-  icon.SetY( OPTION_MARGIN.z );
+  icon.SetY( OPTION_PADDING.z - POPUP_BORDER.y );
   return icon;
 }
 
@@ -391,11 +252,15 @@ Toolkit::TextView TextInputPopup::CreateOptionCaption( const std::string& captio
 
   Toolkit::TextView textView = Toolkit::TextView::New( styledCaption );
   textView.SetSizePolicy( Toolkit::Control::Fixed, Toolkit::Control::Fixed );
-  textView.SetWidthExceedPolicy( Toolkit::TextView::ShrinkToFit );
-  textView.SetHeightExceedPolicy( Toolkit::TextView::ShrinkToFit );
+  textView.SetWidthExceedPolicy( Toolkit::TextView::EllipsizeEnd );
+  textView.SetHeightExceedPolicy( Toolkit::TextView::EllipsizeEnd );
   textView.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
   textView.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
-  textView.SetY( -OPTION_MARGIN.w );
+  textView.SetY( -OPTION_PADDING.w + POPUP_BORDER.w );
+
+  MarkupProcessor::StyledTextArray styledCaptionEllipsize;
+  MarkupProcessor::SetTextStyle( Text("..."), styledCaptionEllipsize, style );
+  textView.SetEllipsizeText( styledCaptionEllipsize );
 
   const float textWidth = textView.GetWidthForHeight( OPTION_TEXT_MIN_SIZE.y );
   textView.SetSize( textWidth, OPTION_TEXT_MIN_SIZE.y );
@@ -413,7 +278,6 @@ void TextInputPopup::CreateBackground()
     mBackground.SetAnchorPoint( AnchorPoint::CENTER );
     mBackground.SetParentOrigin( ParentOrigin::CENTER );
     mBackground.SetName( "text-input-popup-background" );
-    mBackground.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
     mBackground.SetColor( mBackgroundColor );
 
     Image bgEffectImg = Image::New( POPUP_BACKGROUND_EFFECT );
@@ -436,7 +300,6 @@ void TextInputPopup::CreateBackground()
     mBackgroundEffect.Add( mBackgroundLine );
 
     Hide(false);
-    AddToStage();
   }
 }
 
@@ -475,17 +338,17 @@ void TextInputPopup::CreateTail()
 
 ImageActor TextInputPopup::CreateDivider()
 {
-    ImageActor divider = Toolkit::CreateSolidColorActor( mLineColor );
-    divider.SetParentOrigin( ParentOrigin::TOP_LEFT );
-    divider.SetAnchorPoint( AnchorPoint::TOP_LEFT );
-    divider.SetSize( POPUP_DIVIDER_SIZE );
-    divider.SetPosition( mContentSize.width - POPUP_DIVIDER_SIZE.width, 0.0f );
+  ImageActor divider = Toolkit::CreateSolidColorActor( mLineColor );
+  divider.SetParentOrigin( ParentOrigin::TOP_LEFT );
+  divider.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  divider.SetSize( POPUP_DIVIDER_SIZE.width , mContentSize.height );
+  divider.SetPosition( mContentSize.width - POPUP_DIVIDER_SIZE.width, 0.0f );
 
-    // Keep track of all the dividers. As their height's need to be updated to the max. of all
-    // buttons currently added.
-    mDividerContainer.push_back( divider );
+  // Keep track of all the dividers. As their height's need to be updated to the max of all
+  // buttons currently added.
+  mDividerContainer.push_back( divider );
 
-    return divider;
+  return divider;
 }
 
 ImageActor TextInputPopup::CreatePressedBackground( const Vector2& requiredSize )
@@ -583,13 +446,18 @@ void TextInputPopup::CreateOrderedListOfOptions()
       }
     }
 
-    if ( !match)
+    if ( !match )
     {
       mOrderListOfButtons.push_back( currentButton );
     }
   }
 }
 
+Vector2 TextInputPopup::GetConstrainedTextSize( const Vector2& textSize )
+{
+  return  Vector2( std::min( textSize.width, OPTION_MAX_SIZE.width - OPTION_PADDING.x - OPTION_PADDING.y ), textSize.height );
+}
+
 void TextInputPopup::AddOption(const std::string& name, const std::string& caption, const Image iconImage, bool finalOption)
 {
   // 1. Create container for text and icon when not pressed.
@@ -607,9 +475,16 @@ void TextInputPopup::AddOption(const std::string& name, const std::string& capti
 
   // 4. Calculate the size of option.
   const Vector2 textSize = Vector2( captionTextView.GetNaturalSize() );
-  const Vector2 optionSize( std::max( textSize.x, OPTION_ICON_SIZE.x ),
-                            OPTION_MARGIN.z + OPTION_ICON_SIZE.y + OPTION_GAP_ICON_TEXT + textSize.y + OPTION_MARGIN.w );
-  const Vector2 constrainedOptionSize = Min( Max( optionSize, OPTION_MIN_SIZE ), OPTION_MAX_SIZE );
+  captionTextView.SetSize( GetConstrainedTextSize( textSize ) );
+
+
+  const Vector2 optionSize( std::max( textSize.x, OPTION_ICON_SIZE.x ) +  OPTION_PADDING.x + OPTION_PADDING.z,
+                            OPTION_PADDING.z + OPTION_ICON_SIZE.y + OPTION_GAP_ICON_TEXT + textSize.y + OPTION_MAX_SIZE.y );
+
+
+  Vector2 constrainedOptionSize = Min( Max( optionSize, OPTION_MIN_SIZE ), OPTION_MAX_SIZE );
+
+  constrainedOptionSize.height = constrainedOptionSize.height - POPUP_BORDER.y - POPUP_BORDER.z;
 
   // 5. Create a option.
   Toolkit::PushButton option = Toolkit::PushButton::New();
@@ -619,25 +494,28 @@ void TextInputPopup::AddOption(const std::string& name, const std::string& capti
   option.SetSize( constrainedOptionSize );
   option.SetX( mContentSize.x );
   option.SetName( name );
+  option.SetAnimationTime( 0.0f );
   option.ClickedSignal().Connect( this, &TextInputPopup::OnButtonPressed );
-  mScrollView.Add( option );
+  mButtons.Add( option );
 
   // 6. Set the normal option image.
   option.SetButtonImage( optionContainer );
 
   // 7. Update the content size.
   mContentSize.x += constrainedOptionSize.x;
+  mContentSize.y = std::max ( constrainedOptionSize.y, mContentSize.y );
 
   // 8. Create the pressed container.
   Actor optionPressedContainer = Actor::New();
 
   // 9. Add option pressed background.
-  Vector2 optionPressedBackgroundSize( constrainedOptionSize.x - 1.0f, constrainedOptionSize.y - 2.0f );
+  Vector2 optionPressedBackgroundSize( constrainedOptionSize.x - POPUP_BORDER.x, mContentSize.y - POPUP_BORDER.y - POPUP_BORDER.w );
   ImageActor optionPressedBackground = CreatePressedBackground( optionPressedBackgroundSize );
   optionPressedContainer.Add( optionPressedBackground );
 
   // 10. Add pressed text
   Toolkit::TextView pressedCaptionTextView = CreateOptionCaption( caption, mTextPressedColor );
+  pressedCaptionTextView.SetSize( GetConstrainedTextSize( Vector2( pressedCaptionTextView.GetNaturalSize() ) ) );
   optionPressedBackground.Add( pressedCaptionTextView );
 
   // 11. Add pressed icon
@@ -651,7 +529,7 @@ void TextInputPopup::AddOption(const std::string& name, const std::string& capti
   if ( !finalOption )
   {
     ImageActor divider = CreateDivider();
-    mScrollView.Add( divider );
+    mButtons.Add( divider );
   }
 }
 
@@ -684,7 +562,7 @@ void TextInputPopup::Hide(bool animate)
   }
 }
 
-void TextInputPopup::Show(bool animate)
+void TextInputPopup::Show( Actor target, bool animate )
 {
   if( mRoot )
   {
@@ -696,6 +574,11 @@ void TextInputPopup::Show(bool animate)
       mAnimation.Reset();
     }
 
+    if ( target )
+    {
+      AddToParent( target );
+    }
+
     if(animate)
     {
       mAnimation = Animation::New( SHOW_POPUP_ANIMATION_DURATION );
@@ -715,12 +598,6 @@ void TextInputPopup::Show(bool animate)
   }
 }
 
-void TextInputPopup::SetAlternativeOffset(Vector2 offset)
-{
-  mRoot.SetProperty( mAlternativeOffsetProperty, offset );
-  ApplyConfinementConstraint();
-}
-
 TextInputPopup::State TextInputPopup::GetState(void) const
 {
   return mState;
@@ -908,19 +785,26 @@ unsigned int TextInputPopup::GetButtonPriorityPosition( TextInputPopup::Buttons
 
 void TextInputPopup::AddPopupOptions()
 {
-  mContentSize = POPUP_MIN_SIZE;
+  mContentSize = Vector2( POPUP_MIN_SIZE.width, ( POPUP_BORDER.y + POPUP_BORDER.z ) );
 
   // 1. Create the background.
   CreateBackground();
-  mRoot.Add(mBackground);
 
   // 2. Create the tail.
   CreateTail();
-  mBackground.Add( mTail );
 
-  // 3. Create the scroll view.
+  // 3. Create the scroll view and Actor to hold buttons.
   CreateScrollView();
-  mBackground.Add( mScrollView );
+
+  // Clear previous buttons
+  if ( mButtons )
+  {
+    UnparentAndReset( mButtons );
+  }
+
+  mButtons = Actor::New();
+  mButtons.SetParentOrigin( ParentOrigin::CENTER );
+  mButtons.SetAnchorPoint( AnchorPoint::CENTER );
 
   // 4. Create the options and add into the scroll view.
   for( std::vector<ButtonRequirement>::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it )
@@ -932,35 +816,61 @@ void TextInputPopup::AddPopupOptions()
     }
   }
 
-  // 5. Calcurate a lot of size to make the layout.
-  const Vector2 visibleContentSize  = Vector2( std::min( mContentSize.x, POPUP_MAX_SIZE.x - POPUP_BORDER.x - POPUP_BORDER.y ), mContentSize.y );
-  const Vector2 popupSize = Vector2( POPUP_BORDER.x + visibleContentSize.x + POPUP_BORDER.y,
-                                     POPUP_BORDER.z + visibleContentSize.y + POPUP_BORDER.w );
+  // 5. Calculate size of content and of popup including borders
+  const Vector2 popupSize = Vector2( std::min ( ( POPUP_BORDER.x + mContentSize.width + POPUP_BORDER.z ), POPUP_MAX_SIZE.width ) ,  POPUP_BORDER.y + mContentSize.height + POPUP_BORDER.w );
+
+  mVisiblePopUpSize = Vector3( popupSize.width - POPUP_BORDER.x - POPUP_BORDER.z , mContentSize.height, 1.0f);
+
+  mBackground.SetSize( popupSize.x + 28 - POPUP_BORDER.x - POPUP_BORDER.z, popupSize.y + 28 - POPUP_BORDER.y - POPUP_BORDER.w );
+  mButtons.SetSize( mVisiblePopUpSize.GetVectorXY() );
 
-  // 6. Set the scroll view ruller.
-  UpdateScrollViewProperty( visibleContentSize );
+  // 6. Set the scroll view ruler.
+  UpdateScrollViewRulerAndSize( mVisiblePopUpSize.GetVectorXY() );
 
-  // 8. Create stencil
-  const Vector2 stencilSize = Vector2( popupSize.x, popupSize.y + POPUP_TAIL_SIZE.x + POPUP_TAIL_Y_OFFSET );
+  // 7. Create stencil
+  const Vector2 stencilSize = Vector2( mVisiblePopUpSize.GetVectorXY() );
+
+  CreateLayer( stencilSize );
   CreateStencil( stencilSize );
-  mRoot.Add( mStencil );
 
-  // 7. Set the root size.
-  mRoot.SetSize( popupSize );   // Make Root Actor reflect the size of its content
+  mScrollView.Add ( mButtons );
+  mLayer.Add( mScrollView);
+  mLayer.Add( mStencil);
+  mRoot.Add( mTail );
+  mRoot.Add( mBackground );
+  mRoot.Add( mLayer );
 
+  // 8. Set the root size.
+  mRoot.SetSize( popupSize );   // Make Root Actor reflect the size of its content
 }
 
-void TextInputPopup::SetPopupBoundary( const Rect<float>& boundingRectangle )
+const Vector3& TextInputPopup::GetVisibileSize() const
 {
-  mBoundingRect =  boundingRectangle;
+  return mVisiblePopUpSize;
 }
 
-void TextInputPopup::SetTailPosition( const Vector3& position )
+void TextInputPopup::SetTailPosition( const Vector3& position, bool yAxisFlip )
 {
-  mRoot.SetProperty( mRequestionPositionProperty, position );
-  mPopupTailXPosition = position.x;
-  ApplyConfinementConstraint();
-  ApplyTailConstraint();
+  mPopupTailXPosition = std::max(  position.x, POPUP_TAIL_SIZE.width*0.5f - mVisiblePopUpSize.width*0.5f + POPUP_BORDER.x );
+
+  std::min( mPopupTailXPosition, mVisiblePopUpSize.width*0.5f - POPUP_BORDER.x - POPUP_TAIL_SIZE.width*0.5f );
+
+  mTail.SetX( mPopupTailXPosition );
+
+  if ( yAxisFlip )
+  {
+    Image tail = Image::New( POPUP_TAIL_TOP );
+    Image tailEffect = Image::New( POPUP_TAIL_TOP_EFFECT );
+    Image tailLine = Image::New( POPUP_TAIL_TOP_LINE );
+
+    mTail.SetImage( tail );
+    mTailEffect.SetImage( tailEffect );
+    mTailLine.SetImage( tailLine );
+
+    mTail.SetParentOrigin( ParentOrigin::TOP_CENTER );
+    mTail.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
+    mTail.SetY( POPUP_BORDER.y - POPUP_TAIL_Y_OFFSET );
+  }
 }
 
 bool TextInputPopup::OnButtonPressed( Toolkit::Button button )