From ccb1140dd671a9ed76a62177285c4119182478d2 Mon Sep 17 00:00:00 2001 From: Agnelo Vaz Date: Thu, 18 Jun 2015 14:28:48 +0100 Subject: [PATCH] TextSelectionPopup follows Handles and button change with state and other improvements Pixel align positioning of Popup and padding Show Copy and Cut when in Selecting State Change-Id: I5e8a02fae89cf096f3e6319eb8f500aaf0ea6741 Signed-off-by: Agnelo Vaz --- .../dali-toolkit/utc-Dali-TextSelectionPopup.cpp | 8 +- .../text-controls/text-selection-popup.cpp | 5 -- .../controls/text-controls/text-selection-popup.h | 6 -- .../text-controls/text-selection-popup-impl.cpp | 25 ++---- .../text-controls/text-selection-popup-impl.h | 7 +- .../text-controls/text-selection-toolbar-impl.cpp | 4 +- .../internal/text/decorator/text-decorator.cpp | 91 ++++++++++++++++------ .../internal/text/text-controller-impl.cpp | 12 ++- dali-toolkit/internal/text/text-controller-impl.h | 1 + dali-toolkit/internal/text/text-controller.cpp | 24 ++++-- 10 files changed, 110 insertions(+), 73 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextSelectionPopup.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextSelectionPopup.cpp index b248e01..84046fd 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextSelectionPopup.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextSelectionPopup.cpp @@ -41,7 +41,7 @@ int UtcDaliToolkitTextSelectionPopupNewP(void) DALI_TEST_CHECK( !textSelectionPopup ); - textSelectionPopup = TextSelectionPopup::New(); + textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY ); DALI_TEST_CHECK( textSelectionPopup ); END_TEST; @@ -61,7 +61,7 @@ int UtcDaliToolkitTextSelectionPopupCopyConstructorP(void) ToolkitTestApplication application; TextSelectionPopup textSelectionPopup; - textSelectionPopup = TextSelectionPopup::New(); + textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY ); TextSelectionPopup copy( textSelectionPopup ); DALI_TEST_CHECK( copy == textSelectionPopup ); @@ -85,7 +85,7 @@ int UtcDaliToolkitTextSelectionPopupAssignmentOperatorP(void) { ToolkitTestApplication application; TextSelectionPopup textSelectionPopup; - textSelectionPopup = TextSelectionPopup::New(); + textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY ); TextSelectionPopup copy; copy = textSelectionPopup; @@ -97,7 +97,7 @@ int UtcDaliToolkitTextSelectionPopupDownCastP(void) { ToolkitTestApplication application; TextSelectionPopup textSelectionPopup; - textSelectionPopup = TextSelectionPopup::New(); + textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY ); TextSelectionPopup cast = TextSelectionPopup::DownCast( textSelectionPopup ); diff --git a/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.cpp b/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.cpp index 7cf97da..a1237f2 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.cpp +++ b/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.cpp @@ -29,11 +29,6 @@ namespace Dali namespace Toolkit { -TextSelectionPopup TextSelectionPopup::New() -{ - return Internal::TextSelectionPopup::New(); -} - TextSelectionPopup TextSelectionPopup::New( Buttons enabledButtons ) { return Internal::TextSelectionPopup::New( enabledButtons ); diff --git a/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h b/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h index 292d5c5..c2ad190 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h +++ b/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h @@ -88,12 +88,6 @@ public: }; /** - * Create the TextSelectionPopup control. - * @return A handle to the TextSelectionPopup control. - */ - static TextSelectionPopup New(); - - /** * Create the TextSelectionPopup control with the given set of buttons. * @param[in] enabledButtons The given set of buttons to enable * @return A handle to the TextSelectionPopup control. diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp index 28a3d18..ee0d950 100644 --- a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp @@ -47,7 +47,7 @@ namespace const Dali::Vector4 DEFAULT_POPUP_LINE_COLOR( Dali::Vector4( 0.69f, 0.93f, 0.93f, 1.0f ) ); const Dali::Vector4 DEFAULT_OPTION_ICON( Dali::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); -const Dali::Vector4 DEFAULT_OPTION_ICON_PRESSED( Dali::Vector4( 0.5f, 1.0f, 1.0f, 1.0f ) ); +const Dali::Vector4 DEFAULT_OPTION_ICON_PRESSED( Dali::Vector4( 0.12f, 0.56f, 1.0f, 1.0f ) ); const std::string DEFAULT_POPUP_BACKGROUND_IMAGE( DALI_IMAGE_DIR "selection-popup-bg#.png" ); const std::string OPTION_ICON_CLIPBOARD( DALI_IMAGE_DIR "copy_paste_icon_clipboard.png" ); @@ -88,7 +88,7 @@ const char* const OPTION_CLIPBOARD("option-clipboard"); BaseHandle Create() { - return Toolkit::TextSelectionPopup::New(); + return Toolkit::TextSelectionPopup::New( Toolkit::TextSelectionPopup::NONE ); } // Setup properties, signals and actions using the type-registry. @@ -111,20 +111,6 @@ DALI_TYPE_REGISTRATION_END() } // namespace -Dali::Toolkit::TextSelectionPopup TextSelectionPopup::New() -{ - // Create the implementation, temporarily owned by this handle on stack - IntrusivePtr< TextSelectionPopup > impl = new TextSelectionPopup(); - - // Pass ownership to CustomActor handle - Dali::Toolkit::TextSelectionPopup handle( *impl ); - - // Second-phase init of the implementation - // This can only be done after the CustomActor connection has been made... - impl->Initialize(); - - return handle; -} Dali::Toolkit::TextSelectionPopup TextSelectionPopup::New( Toolkit::TextSelectionPopup::Buttons buttonsToEnable ) { @@ -535,7 +521,7 @@ Dali::Image TextSelectionPopup::GetButtonImage( Toolkit::TextSelectionPopup::But optionPressedContainer.SetDrawMode( DrawMode::OVERLAY ); optionPressedContainer.SetFitHeight( 0 ); optionPressedContainer.SetFitWidth( 0 ); - optionPressedContainer.SetBackgroundColor(Color::RED); //todo member variable + optionPressedContainer.SetBackgroundColor( mPressedColor ); #ifdef DECORATOR_DEBUG optionContainer.SetName("optionContainer"); @@ -556,7 +542,7 @@ Dali::Image TextSelectionPopup::GetButtonImage( Toolkit::TextSelectionPopup::But Padding padding; padding.left = 24.0f; padding.right = 24.0f; - padding.top = 13.0f; + padding.top = 14.0f; padding.bottom = 14.0f; captionTextLabel.SetPadding( padding ); pressedCaptionTextLabel.SetPadding( padding ); @@ -574,7 +560,6 @@ Dali::Image TextSelectionPopup::GetButtonImage( Toolkit::TextSelectionPopup::But icon.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); pressedIcon.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); icon.SetColor( mIconColor ); - pressedIcon.SetColor( mIconPressedColor ); if ( showCaption & showIcons ) { @@ -677,7 +662,7 @@ TextSelectionPopup::TextSelectionPopup() mEnabledButtons( Toolkit::TextSelectionPopup::NONE ), mLineColor( DEFAULT_POPUP_LINE_COLOR ), mIconColor( DEFAULT_OPTION_ICON ), - mIconPressedColor( DEFAULT_OPTION_ICON_PRESSED ), + mPressedColor( DEFAULT_OPTION_ICON_PRESSED ), mSelectOptionPriority( 1 ), mSelectAllOptionPriority ( 2 ), mCutOptionPriority ( 3 ), diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h index 3650977..8d75848 100644 --- a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h @@ -97,11 +97,6 @@ public: }; /** - * @copydoc Dali::Toollkit::TextSelectionPopup::New() - */ - static Toolkit::TextSelectionPopup New(); - - /** * @brief New constructor with provided buttons to enable. * @param[in] buttonsToEnable bit mask of buttons to enable * @return A handle to the TextSelectionPopup control. @@ -228,7 +223,7 @@ private: // Data Vector4 mLineColor; // Color of the line around the text input popup Vector4 mIconColor; // Color of the popup icon. - Vector4 mIconPressedColor; // Color of the popup icon when pressed. + Vector4 mPressedColor; // Color of the popup option when pressed. // 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 diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.cpp index 4b25f77..3ff40b3 100644 --- a/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.cpp @@ -43,8 +43,6 @@ namespace { const Dali::Vector2 DEFAULT_MAX_SIZE( 400.0f, 65.0f ); ///< The maximum size of the Toolbar. -} // namespace - BaseHandle Create() { return Toolkit::TextSelectionToolbar::New(); @@ -58,6 +56,8 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionToolbar, "max-size", VECTOR2, DALI_TYPE_REGISTRATION_END() +} // namespace + Dali::Toolkit::TextSelectionToolbar TextSelectionToolbar::New() { // Create the implementation, temporarily owned by this handle on stack diff --git a/dali-toolkit/internal/text/decorator/text-decorator.cpp b/dali-toolkit/internal/text/decorator/text-decorator.cpp index ef6a54f..392fde1 100644 --- a/dali-toolkit/internal/text/decorator/text-decorator.cpp +++ b/dali-toolkit/internal/text/decorator/text-decorator.cpp @@ -80,6 +80,8 @@ const char* DEFAULT_SELECTION_HANDLE_ONE_PRESSED( DALI_IMAGE_DIR "text-input-sel const char* DEFAULT_SELECTION_HANDLE_TWO_RELEASED( DALI_IMAGE_DIR "text-input-selection-handle-right.png" ); const char* DEFAULT_SELECTION_HANDLE_TWO_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-right-press.png" ); +const int DEFAULT_POPUP_OFFSET( -100.0f ); // Vertical offset of Popup from cursor or handles position. + const Dali::Vector3 DEFAULT_GRAB_HANDLE_RELATIVE_SIZE( 1.5f, 2.0f, 1.0f ); const Dali::Vector3 DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE( 1.5f, 1.5f, 1.0f ); @@ -213,6 +215,19 @@ struct Decorator::Impl : public ConnectionTracker bool flipped : 1; }; + struct PopupImpl + { + PopupImpl() + : position(), + offset( DEFAULT_POPUP_OFFSET ) + { + } + + TextSelectionPopup actor; + Vector3 position; + int offset; + }; + Impl( ControllerInterface& controller ) : mController( controller ), mEnabledPopupButtons( TextSelectionPopup::NONE ), @@ -386,22 +401,24 @@ struct Decorator::Impl : public ConnectionTracker if ( mActiveCopyPastePopup ) { - if ( !mCopyPastePopup ) + // todo Swap UnparentAndReset for DeterminePositionPopup() if mCopyPastePopup.actor valid Once the issue with the labels disappearing is fixed. + UnparentAndReset( mCopyPastePopup.actor ); + if ( !mCopyPastePopup.actor ) { - mCopyPastePopup = TextSelectionPopup::New( mEnabledPopupButtons ); + mCopyPastePopup.actor = TextSelectionPopup::New( mEnabledPopupButtons ); #ifdef DECORATOR_DEBUG - mCopyPastePopup.SetName("mCopyPastePopup"); + mCopyPastePopup.actor.SetName("mCopyPastePopup"); #endif - mCopyPastePopup.SetAnchorPoint( AnchorPoint::CENTER ); - mCopyPastePopup.OnRelayoutSignal().Connect( this, &Decorator::Impl::PopUpRelayoutComplete ); // Position popup after size negotiation - mActiveLayer.Add ( mCopyPastePopup ); + mCopyPastePopup.actor.SetAnchorPoint( AnchorPoint::CENTER ); + mCopyPastePopup.actor.OnRelayoutSignal().Connect( this, &Decorator::Impl::PopupRelayoutComplete ); // Position popup after size negotiation + mActiveLayer.Add ( mCopyPastePopup.actor ); } } else { - if ( mCopyPastePopup ) + if ( mCopyPastePopup.actor ) { - UnparentAndReset( mCopyPastePopup ); + UnparentAndReset( mCopyPastePopup.actor ); } } } @@ -416,21 +433,43 @@ struct Decorator::Impl : public ConnectionTracker mHighlightPosition += scrollOffset; } - void PopUpRelayoutComplete( Actor actor ) + void DeterminePositionPopup() { - // Size negotiation for CopyPastePopup complete so can get the size and constrain position within bounding box. + if ( !mActiveCopyPastePopup ) + { + return; + } - mCopyPastePopup.OnRelayoutSignal().Disconnect( this, &Decorator::Impl::PopUpRelayoutComplete ); + if ( mHandle[LEFT_SELECTION_HANDLE].active || mHandle[RIGHT_SELECTION_HANDLE].active ) + { + float minHandleXPosition = std::min ( mHandle[LEFT_SELECTION_HANDLE].position.x, mHandle[RIGHT_SELECTION_HANDLE].position.x ); + float maxHandleXPosition = std::max ( mHandle[LEFT_SELECTION_HANDLE].position.x, mHandle[RIGHT_SELECTION_HANDLE].position.x ); - Vector3 popupPosition( mCursor[PRIMARY_CURSOR].position.x, mCursor[PRIMARY_CURSOR].position.y -100.0f , 0.0f); //todo 100 to be an offset Property + float minHandleYPosition = std::min ( mHandle[LEFT_SELECTION_HANDLE].position.y, mHandle[RIGHT_SELECTION_HANDLE].position.y ); - Vector3 popupSize = Vector3( mCopyPastePopup.GetRelayoutSize( Dimension::WIDTH ), mCopyPastePopup.GetRelayoutSize( Dimension::HEIGHT ), 0.0f ); + mCopyPastePopup.position.x = minHandleXPosition + ( ( maxHandleXPosition - minHandleXPosition ) *0.5f ); + mCopyPastePopup.position.y = minHandleYPosition + mCopyPastePopup.offset; + } + else + { + mCopyPastePopup.position = Vector3( mCursor[PRIMARY_CURSOR].position.x, mCursor[PRIMARY_CURSOR].position.y -100.0f , 0.0f ); //todo 100 to be an offset Property + } + + Vector3 popupSize = Vector3( mCopyPastePopup.actor.GetRelayoutSize( Dimension::WIDTH ), mCopyPastePopup.actor.GetRelayoutSize( Dimension::HEIGHT ), 0.0f ); + + GetConstrainedPopupPosition( mCopyPastePopup.position, popupSize, AnchorPoint::CENTER, mActiveLayer, mBoundingBox ); + + SetUpPopupPositionNotifications(); - GetConstrainedPopupPosition( popupPosition, popupSize, AnchorPoint::CENTER, mActiveLayer, mBoundingBox ); + mCopyPastePopup.actor.SetPosition( mCopyPastePopup.position ); + } - SetUpPopUpPositionNotifications(); + void PopupRelayoutComplete( Actor actor ) + { + // Size negotiation for CopyPastePopup complete so can get the size and constrain position within bounding box. + mCopyPastePopup.actor.OnRelayoutSignal().Disconnect( this, &Decorator::Impl::PopupRelayoutComplete ); - mCopyPastePopup.SetPosition( popupPosition ); //todo grabhandle(cursor) or selection handle positions to be used + DeterminePositionPopup(); } void CreateCursor( ImageActor& cursor, const Vector4& color ) @@ -1007,11 +1046,11 @@ struct Decorator::Impl : public ConnectionTracker // if can't be positioned above, then position below row. alternativeYPosition = AlternatePopUpPositionRelativeToCursor(); - mCopyPastePopup.SetY( alternativeYPosition ); + mCopyPastePopup.actor.SetY( alternativeYPosition ); } - void SetUpPopUpPositionNotifications( ) + void SetUpPopupPositionNotifications( ) { // Note Property notifications ignore any set anchor point so conditions must allow for this. Default is Top Left. @@ -1020,11 +1059,11 @@ struct Decorator::Impl : public ConnectionTracker Vector4 worldCoordinatesBoundingBox; LocalToWorldCoordinatesBoundingBox( mBoundingBox, worldCoordinatesBoundingBox ); - float popupHeight = mCopyPastePopup.GetRelayoutSize( Dimension::HEIGHT); + float popupHeight = mCopyPastePopup.actor.GetRelayoutSize( Dimension::HEIGHT); - PropertyNotification verticalExceedNotification = mCopyPastePopup.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - OutsideCondition( worldCoordinatesBoundingBox.y + popupHeight/2, - worldCoordinatesBoundingBox.w - popupHeight/2 ) ); + PropertyNotification verticalExceedNotification = mCopyPastePopup.actor.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, + OutsideCondition( worldCoordinatesBoundingBox.y + popupHeight * 0.5f, + worldCoordinatesBoundingBox.w - popupHeight * 0.5f ) ); verticalExceedNotification.NotifySignal().Connect( this, &Decorator::Impl::PopUpLeavesVerticalBoundary ); } @@ -1061,6 +1100,11 @@ struct Decorator::Impl : public ConnectionTracker } requiredPopupPosition.x = requiredPopupPosition.x + xOffSetToKeepWithinBounds; + + // Prevent pixel mis-alignment by rounding down. + requiredPopupPosition.x = static_cast( requiredPopupPosition.x ); + requiredPopupPosition.y = static_cast( requiredPopupPosition.y ); + } void FlipSelectionHandleImages() @@ -1166,7 +1210,8 @@ struct Decorator::Impl : public ConnectionTracker ImageActor mPrimaryCursor; ImageActor mSecondaryCursor; MeshActor mHighlightMeshActor; ///< Mesh Actor to display highlight - TextSelectionPopup mCopyPastePopup; + + PopupImpl mCopyPastePopup; TextSelectionPopup::Buttons mEnabledPopupButtons; /// Bit mask of currently enabled Popup buttons Image mHandleImages[HANDLE_TYPE_COUNT][HANDLE_IMAGE_TYPE_COUNT]; diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index fb2bf2b..24e38c2 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -847,7 +847,17 @@ void Controller::Impl::ChangeState( EventData::State newState ) mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true ); if( mEventData->mGrabHandlePopupEnabled ) { - TextSelectionPopup::Buttons selectedButtons = TextSelectionPopup::Buttons( TextSelectionPopup::COPY ); + TextSelectionPopup::Buttons selectedButtons = TextSelectionPopup::Buttons( TextSelectionPopup::CUT | TextSelectionPopup::COPY ); + mEventData->mDecorator->SetEnabledPopupButtons( selectedButtons ); + mEventData->mDecorator->SetPopupActive( true ); + } + mEventData->mDecoratorUpdated = true; + } + else if ( EventData::SELECTION_CHANGED == mEventData->mState ) + { + if( mEventData->mGrabHandlePopupEnabled ) + { + TextSelectionPopup::Buttons selectedButtons = TextSelectionPopup::Buttons( TextSelectionPopup::CUT | TextSelectionPopup::COPY ); mEventData->mDecorator->SetEnabledPopupButtons( selectedButtons ); mEventData->mDecorator->SetPopupActive( true ); } diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index 81125da..326770d 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -99,6 +99,7 @@ struct EventData { INACTIVE, SELECTING, + SELECTION_CHANGED, EDITING, EDITING_WITH_POPUP, GRAB_HANDLE_PANNING, diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 3b36ed3..f63944a 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -47,6 +47,12 @@ const float MAX_FLOAT = std::numeric_limits::max(); const std::string EMPTY_STRING(""); +float ConvertToEven( float value ) +{ + int intValue(static_cast( value )); + return static_cast(intValue % 2 == 0) ? intValue : (intValue + 1); +} + } // namespace namespace Dali @@ -533,6 +539,9 @@ Vector3 Controller::GetNaturalSize() DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize cached %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z ); } + naturalSize.x = ConvertToEven( naturalSize.x ); + naturalSize.y = ConvertToEven( naturalSize.y ); + return naturalSize; } @@ -1312,11 +1321,7 @@ void Controller::TapEvent( unsigned int tapCount, float x, float y ) if( !isShowingPlaceholderText && tapDuringEditMode ) { - // Grab handle is not shown until a tap is received whilst EDITING - if( tapDuringEditMode ) - { - mImpl->mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true ); - } + mImpl->mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true ); mImpl->mEventData->mDecorator->SetPopupActive( false ); } @@ -1326,7 +1331,14 @@ void Controller::TapEvent( unsigned int tapCount, float x, float y ) mImpl->mEventData->mSelectionEnabled && ( 2u == tapCount ) ) { - mImpl->ChangeState( EventData::SELECTING ); + if ( mImpl->mEventData->mState == EventData::SELECTING ) + { + mImpl->ChangeState( EventData::SELECTION_CHANGED ); + } + else + { + mImpl->ChangeState( EventData::SELECTING ); + } } } -- 2.7.4