From 138d00123ed6095e37951f7dc1c841c11a5adda3 Mon Sep 17 00:00:00 2001 From: Agnelo Vaz Date: Tue, 24 Jun 2014 15:54:59 +0100 Subject: [PATCH] TextInput Popup scrolling fixed after GUI changes. GUI settings changed. [problem] Scrolling would cause the buttons to leave the popup area. Change language to French to see issue [cause] Regression [solution] Popup sizes amended so buttons scroll again if do not fit. Popup max width reduced to look more like Tizen apps. Change-Id: Ibac5b243fd30a5c2f5bd58d0a4884676ae3aae5c Signed-off-by: Adeel Kazmi --- .../controls/text-input/text-input-impl.cpp | 3 - .../controls/text-input/text-input-popup-impl.cpp | 142 +++++++++++++-------- .../controls/text-input/text-input-popup-impl.h | 35 +++-- 3 files changed, 108 insertions(+), 72 deletions(-) diff --git a/base/dali-toolkit/internal/controls/text-input/text-input-impl.cpp b/base/dali-toolkit/internal/controls/text-input/text-input-impl.cpp index 2ec8170..b577b06 100644 --- a/base/dali-toolkit/internal/controls/text-input/text-input-impl.cpp +++ b/base/dali-toolkit/internal/controls/text-input/text-input-impl.cpp @@ -794,9 +794,6 @@ void TextInput::SetBoundingRectangle( const Rect& boundingRectangle ) originY + boundingRectangle.height ); mBoundingRectangleWorldCoordinates = boundary; - - // Set Boundary for Popup so it keeps the Pop-up within the area also. - mPopupPanel.SetPopupBoundary( boundingRectangle ); } const Rect TextInput::GetBoundingRectangle() const diff --git a/base/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp b/base/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp index 9951f88..14f998f 100644 --- a/base/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp +++ b/base/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp @@ -59,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. @@ -111,10 +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 ), @@ -156,6 +158,15 @@ void TextInputPopup::RemoveFromParent() } } +void TextInputPopup::CreateLayer( const Vector2& size ) +{ + 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 ) { mStencil = CreateSolidColorActor( Color::BLUE ); @@ -169,21 +180,20 @@ 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 ); @@ -210,10 +220,9 @@ void TextInputPopup::Clear() UnparentAndReset( mTail ); UnparentAndReset( mStencil ); UnparentAndReset( mBackground ); + UnparentAndReset( mButtons ); UnparentAndReset( mScrollView ); - mButtonContainer.clear(); mDividerContainer.clear(); - mRoot.RemoveConstraints(); RemoveFromParent(); mState = StateHidden; } @@ -226,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; } @@ -243,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 ); @@ -265,7 +278,6 @@ void TextInputPopup::CreateBackground() mBackground.SetAnchorPoint( AnchorPoint::CENTER ); mBackground.SetParentOrigin( ParentOrigin::CENTER ); mBackground.SetName( "text-input-popup-background" ); - mBackground.ApplyConstraint( Constraint::New( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) ); mBackground.SetColor( mBackgroundColor ); Image bgEffectImg = Image::New( POPUP_BACKGROUND_EFFECT ); @@ -288,7 +300,6 @@ void TextInputPopup::CreateBackground() mBackgroundEffect.Add( mBackgroundLine ); Hide(false); - GetRootActor().Add( mBackground ); } } @@ -330,7 +341,7 @@ ImageActor TextInputPopup::CreateDivider() ImageActor divider = Toolkit::CreateSolidColorActor( mLineColor ); divider.SetParentOrigin( ParentOrigin::TOP_LEFT ); divider.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - divider.SetSize( POPUP_DIVIDER_SIZE ); + 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 @@ -435,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. @@ -459,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(); @@ -473,24 +496,26 @@ void TextInputPopup::AddOption(const std::string& name, const std::string& capti 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 @@ -504,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 ); } } @@ -760,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::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it ) @@ -785,51 +817,59 @@ void TextInputPopup::AddPopupOptions() } // 5. Calculate size of content and of popup including borders - 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 ); - mVisiblePopUpSize = Vector3( popupSize.x, popupSize.y, 1.0f); + 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 ruler. - UpdateScrollViewRulerAndSize( visibleContentSize ); + UpdateScrollViewRulerAndSize( mVisiblePopUpSize.GetVectorXY() ); // 7. Create stencil - const Vector2 stencilSize = Vector2( popupSize.x, popupSize.y + POPUP_TAIL_SIZE.x + POPUP_TAIL_Y_OFFSET ); + const Vector2 stencilSize = Vector2( mVisiblePopUpSize.GetVectorXY() ); + + CreateLayer( stencilSize ); CreateStencil( stencilSize ); - mRoot.Add( mStencil ); + + 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& boundingRectangle ) -{ - mBoundingRect = boundingRectangle; -} - const Vector3& TextInputPopup::GetVisibileSize() const { return mVisiblePopUpSize; } - void TextInputPopup::SetTailPosition( const Vector3& position, bool yAxisFlip ) { - mPopupTailXPosition = position.x; - mTail.SetX( position.x ); + 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 ); - Image tailEffect = Image::New( POPUP_TAIL_TOP_EFFECT ); - mTailEffect.SetImage( tailEffect ); - - Image tailLine = Image::New( POPUP_TAIL_TOP_LINE ); - mTailLine.SetImage( tailLine ); } } diff --git a/base/dali-toolkit/internal/controls/text-input/text-input-popup-impl.h b/base/dali-toolkit/internal/controls/text-input/text-input-popup-impl.h index 759c104..4348ca8 100644 --- a/base/dali-toolkit/internal/controls/text-input/text-input-popup-impl.h +++ b/base/dali-toolkit/internal/controls/text-input/text-input-popup-impl.h @@ -162,6 +162,14 @@ public: void CreateOrderedListOfOptions(); /** + * Get the TextSize after constrained by the Popup margins. + * @param[in] textSize Natural size of text + * @return Vector2 constrained text size. + * + */ + Vector2 GetConstrainedTextSize( const Vector2& textSize ); + + /** * Adds a popup option. * @note Creates popup frame if not already created. * @param[in] name The unique name for this option. @@ -186,14 +194,6 @@ public: void Show( Actor target, bool animate = true ); /** - * Sets Alternative offset property. - * The alternative offset property is how much to move in the horizontal and vertical - * axes when the popup goes out of the screen on the left/right sides or top/bottom sides. - * @param[in] offset Vector holding the left/right offset (x) and top/bottom offset (y) - */ - void SetAlternativeOffset(Vector2 offset); - - /** * Returns the current state of the popup. * @return The state of the popup see enum State */ @@ -316,12 +316,6 @@ public: void AddPopupOptions(); /** - * Set Boundary that Popup should stay within - * @param[in] boundingRectangle coordinates of bounding box from Top Left - */ - void SetPopupBoundary( const Rect& boundingRectangle ); - - /** * Get Visible size of the Popup, excludes content that needs scrolling * @return Vector3 size of Popup */ @@ -370,6 +364,12 @@ private: void ApplyTailConstraint(); /** + * Create Layer to be used with stencil to allow scrolling of buttons which do not fit in visible popup + * @param[in] size of the layer. + */ + void CreateLayer( const Vector2& size ); + + /** * Create a stencil to clip the scroll view content * @param[in] size of the stencil. */ @@ -421,7 +421,8 @@ private: private: State mState; ///< Popup State. - Layer mRoot; ///< The actor which all popup content is added to (i.e. panel and buttons) + Layer mRoot; ///< The actor which all popup content is added to (i.e. panel and buttons) + Actor mButtons; ///< Actor which holds all the buttons, sensitivity can be set on all buttons via this actor ImageActor mBackground; ///< The background popup panel ImageActor mBackgroundEffect; ///< The background effect ImageActor mBackgroundLine; ///< The background line @@ -433,10 +434,10 @@ private: float mPopupTailXPosition; ///< X position of PopUp tail. Vector2 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. + Layer mLayer; ///< Layer to be used with Stencil Actor mStencil; ///< Stencil to clip scrollview Toolkit::ScrollView mScrollView; ///< Scrollview to house the popup @@ -450,8 +451,6 @@ private: Vector4 mTextColor; // Color of the popup text. Vector4 mTextPressedColor; // Color of the popup text when pressed. - Rect mBoundingRect; // Boundary that Popup must stay within. - // Priority of Options/Buttons in the Cut and Paste pop-up, higher priority buttons are displayed first, left to right. std::size_t mSelectOptionPriority; // Position of Select Button std::size_t mSelectAllOptionPriority; // Position of Select All button -- 2.7.4