From f7afcaf3b5cd7cd9aa3c937b680a525ecbbc8332 Mon Sep 17 00:00:00 2001 From: Huayong Xu Date: Mon, 8 Apr 2019 13:53:19 +0800 Subject: [PATCH] Select the whole text of TextField. In some cases, the whole text of text-field need be selected, and grab_handle and its popup need be disabled. Change-Id: I5c1b5d5287509adf6357f25050c1831215f43f08 Signed-off-by: Huayong Xu --- .../utc-Dali-Text-Controller.cpp | 43 ++++++++++++++ .../src/dali-toolkit/utc-Dali-TextField.cpp | 59 ++++++++++++++++++- .../controls/text-controls/text-field-devel.cpp | 5 ++ .../controls/text-controls/text-field-devel.h | 17 +++++- .../controls/text-controls/text-field-impl.cpp | 29 ++++++++++ .../controls/text-controls/text-field-impl.h | 5 ++ .../internal/text/text-controller-impl.cpp | 10 ++-- dali-toolkit/internal/text/text-controller.cpp | 67 +++++++++++++--------- dali-toolkit/internal/text/text-controller.h | 41 +++++++++---- 9 files changed, 231 insertions(+), 45 deletions(-) diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp index d37a1db..95f7697 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -1002,3 +1003,45 @@ int UtcDaliTextControllerCheckInputFontPointSizeChanged(void) END_TEST; } + +int UtcDaliTextControllerSelectEvent(void) +{ + tet_infoline(" UtcDaliTextControllerSelectEvent"); + ToolkitTestApplication application; + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + // Configures the text controller similarly to the text-field. + ConfigureTextField( controller ); + + // Set the text + const std::string text("Hello World!"); + controller->SetText( text ); + + // Select the whole text. + controller->SelectEvent( 0.f, 0.f, false ); + + // Perform a relayout + const Size size( Dali::Stage::GetCurrent().GetSize() ); + controller->Relayout(size); + + // Get the implementation of the text controller + Controller::Impl& mImpl = Controller::Impl::GetImplementation( *controller.Get() ); + + // Check if the whole text is selected or not. + std::string retrieved_text; + mImpl.RetrieveSelection( retrieved_text, false ); + DALI_TEST_EQUALS( "Hello", retrieved_text, TEST_LOCATION ); + + // Select the whole text. + controller->SelectEvent( 0.f, 0.f, true ); + + // Perform a relayout + controller->Relayout( size ); + + mImpl.RetrieveSelection( retrieved_text, false ); + DALI_TEST_EQUALS( text, retrieved_text, TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp index 893d26a..4c126be 100755 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -102,6 +102,7 @@ const char* const PROPERTY_NAME_ELLIPSIS = "ellipsis const char* const PROPERTY_NAME_ENABLE_SHIFT_SELECTION = "enableShiftSelection"; const char* const PROPERTY_NAME_ENABLE_GRAB_HANDLE = "enableGrabHandle"; const char* const PROPERTY_NAME_MATCH_SYSTEM_LANGUAGE_DIRECTION = "matchSystemLanguageDirection"; +const char* const PROPERTY_NAME_ENABLE_GRAB_HANDLE_POPUP = "enableGrabHandlePopup"; const Vector4 PLACEHOLDER_TEXT_COLOR( 0.8f, 0.8f, 0.8f, 0.8f ); const Dali::Vector4 LIGHT_BLUE( 0.75f, 0.96f, 1.f, 1.f ); // The text highlight color. @@ -539,6 +540,7 @@ int UtcDaliTextFieldGetPropertyP(void) DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_ENABLE_SHIFT_SELECTION ) == DevelTextField::Property::ENABLE_SHIFT_SELECTION ); DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_ENABLE_GRAB_HANDLE ) == DevelTextField::Property::ENABLE_GRAB_HANDLE ); DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_MATCH_SYSTEM_LANGUAGE_DIRECTION ) == DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_ENABLE_GRAB_HANDLE_POPUP ) == DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP ); END_TEST; } @@ -993,6 +995,11 @@ int UtcDaliTextFieldSetPropertyP(void) field.SetProperty( Actor::Property::LAYOUT_DIRECTION, LayoutDirection::RIGHT_TO_LEFT ); DALI_TEST_EQUALS( field.GetProperty( Actor::Property::LAYOUT_DIRECTION ), static_cast( LayoutDirection::RIGHT_TO_LEFT ), TEST_LOCATION ); + // Test the ENABLE_GRAB_HANDLE_POPUP property + DALI_TEST_CHECK( field.GetProperty( DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP ) ); + field.SetProperty( DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP, false ); + DALI_TEST_CHECK( !field.GetProperty( DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP ) ); + application.SendNotification(); application.Render(); @@ -2927,7 +2934,6 @@ int utcDaliTextFieldLayoutDirectionCoverage(void) END_TEST; } - int UtcDaliTextFieldGetInputMethodContext(void) { ToolkitTestApplication application; @@ -2939,3 +2945,54 @@ int UtcDaliTextFieldGetInputMethodContext(void) END_TEST; } +int UtcDaliTextFieldSelectWholeText(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextFieldSelectWholeText "); + + TextField textField = TextField::New(); + + Stage::GetCurrent().Add( textField ); + + textField.SetSize( 300.f, 50.f ); + textField.SetParentOrigin( ParentOrigin::TOP_LEFT ); + textField.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( 1u, textField.GetChildCount(), TEST_LOCATION ); + + DevelTextField::SelectWholeText( textField ); + + application.SendNotification(); + application.Render(); + + // Nothing should have been selected. The number of children is still 1 + DALI_TEST_EQUALS( 1u, textField.GetChildCount(), TEST_LOCATION ); + + textField.SetProperty( TextField::Property::TEXT, "Hello world" ); + + application.SendNotification(); + application.Render(); + + DevelTextField::SelectWholeText( textField ); + + application.SendNotification(); + application.Render(); + + // Should be 2 children, the stencil and the layer + DALI_TEST_EQUALS( 2u, textField.GetChildCount(), TEST_LOCATION ); + + // The offscreen root actor should have two actors: the renderer and the highlight actor. + Actor stencil = textField.GetChildAt( 0u ); + + // The highlight actor is drawn first, so is the first actor in the list + Renderer highlight = stencil.GetChildAt( 0u ).GetRendererAt( 0u ); + DALI_TEST_CHECK( highlight ); + + END_TEST; +} diff --git a/dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp b/dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp index f9b739c..a53ef4a 100755 --- a/dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp +++ b/dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp @@ -33,6 +33,11 @@ InputMethodContext GetInputMethodContext( TextField textField ) return GetImpl( textField ).GetInputMethodContext(); } +void SelectWholeText( TextField textField ) +{ + GetImpl( textField ).SelectWholeText(); +} + } // namespace DevelText } // namespace Toolkit diff --git a/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h b/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h index cef786a..5e92a92 100755 --- a/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h +++ b/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h @@ -107,7 +107,14 @@ namespace Property * @details Name "matchSystemLanguageDirection", type (Property::BOOLEAN), Read/Write * @note The default value is false */ - MATCH_SYSTEM_LANGUAGE_DIRECTION = ELLIPSIS + 3 + MATCH_SYSTEM_LANGUAGE_DIRECTION = ELLIPSIS + 3, + + /** + * @brief Enables the grab handle popup for text selection. + * @details Name "enableGrabHandlePopup", type Property::BOOLEAN. + * @note The default value is true, which means the grab handle popup is enabled by default. + */ + ENABLE_GRAB_HANDLE_POPUP = ELLIPSIS + 4 }; } // namespace Property @@ -120,6 +127,14 @@ namespace Property */ DALI_TOOLKIT_API InputMethodContext GetInputMethodContext( TextField textField ); +/** + * @brief Select the whole text of TextField. + * + * @param[in] textField The instance of TextField. + * @return InputMethodContext instance. + */ +DALI_TOOLKIT_API void SelectWholeText( TextField textField ); + } // namespace DevelText } // namespace Toolkit diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp index 5270ea9..bf953ec 100755 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -133,6 +133,7 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "ellipsis", DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "enableShiftSelection", BOOLEAN, ENABLE_SHIFT_SELECTION ) DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "enableGrabHandle", BOOLEAN, ENABLE_GRAB_HANDLE ) DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "matchSystemLanguageDirection", BOOLEAN, MATCH_SYSTEM_LANGUAGE_DIRECTION ) +DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "enableGrabHandlePopup", BOOLEAN, ENABLE_GRAB_HANDLE_POPUP ) DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "textChanged", SIGNAL_TEXT_CHANGED ) DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "maxLengthReached", SIGNAL_MAX_LENGTH_REACHED ) @@ -764,6 +765,17 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr } break; } + case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP: + { + if (impl.mController) + { + const bool grabHandlePopupEnabled = value.Get(); + DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p ENABLE_GRAB_HANDLE_POPUP %d\n", impl.mController.Get(), grabHandlePopupEnabled); + + impl.mController->SetGrabHandlePopupEnabled(grabHandlePopupEnabled); + break; + } + } } // switch } // textfield } @@ -1171,12 +1183,29 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde } break; } + case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP: + { + if (impl.mController) + { + value = impl.mController->IsGrabHandlePopupEnabled(); + } + break; + } } //switch } return value; } +void TextField::SelectWholeText() +{ + if( mController && mController->IsShowingRealText() ) + { + mController->SelectEvent( 0.f, 0.f, true ); + SetKeyInputFocus(); + } +} + InputMethodContext TextField::GetInputMethodContext() { return mInputMethodContext; diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.h b/dali-toolkit/internal/controls/text-controls/text-field-impl.h index 495f789..3b1062e 100755 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.h @@ -102,6 +102,11 @@ public: */ Toolkit::TextField::InputStyleChangedSignalType& InputStyleChangedSignal(); + /** + * @brief Called to select the whole texts. + */ + void SelectWholeText(); + private: // From Control /** diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index acf6291..09395d0 100755 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -1847,15 +1847,13 @@ void Controller::Impl::OnSelectAllEvent() if( mEventData->mSelectionEnabled ) { - ChangeState( EventData::SELECTING ); + // Calculates the logical position from the start. + RepositionSelectionHandles( 0.f - mModel->mScrollPosition.x, + 0.f - mModel->mScrollPosition.y, + Controller::NoTextTap::HIGHLIGHT ); mEventData->mLeftSelectionPosition = 0u; mEventData->mRightSelectionPosition = mModel->mLogicalModel->mText.Count(); - - mEventData->mScrollAfterUpdatePosition = true; - mEventData->mUpdateLeftSelectionPosition = true; - mEventData->mUpdateRightSelectionPosition = true; - mEventData->mUpdateHighlightBox = true; } } diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 58bf52a..e0c63c8 100755 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -435,6 +435,11 @@ void Controller::SetLayoutDirection( Dali::LayoutDirection::Type layoutDirection mImpl->mLayoutDirection = layoutDirection; } +bool Controller::IsShowingRealText() const +{ + return mImpl->IsShowingRealText(); +} + void Controller::SetLineWrapMode( Text::LineWrap::Mode lineWrapMode ) { @@ -522,6 +527,16 @@ bool Controller::IsGrabHandleEnabled() const return mImpl->mEventData->mGrabHandleEnabled; } +void Controller::SetGrabHandlePopupEnabled(bool enabled) +{ + mImpl->mEventData->mGrabHandlePopupEnabled = enabled; +} + +bool Controller::IsGrabHandlePopupEnabled() const +{ + return mImpl->mEventData->mGrabHandlePopupEnabled; +} + // public : Update void Controller::SetText( const std::string& text ) @@ -2814,6 +2829,32 @@ void Controller::LongPressEvent( Gesture::State state, float x, float y ) } } +void Controller::SelectEvent( float x, float y, bool selectAll ) +{ + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SelectEvent\n" ); + + if( NULL != mImpl->mEventData ) + { + if( selectAll ) + { + Event event( Event::SELECT_ALL ); + mImpl->mEventData->mEventQueue.push_back( event ); + } + else + { + Event event( Event::SELECT ); + event.p2.mFloat = x; + event.p3.mFloat = y; + mImpl->mEventData->mEventQueue.push_back( event ); + } + + mImpl->mEventData->mCheckScrollAmount = true; + mImpl->mEventData->mIsLeftHandleSelected = true; + mImpl->mEventData->mIsRightHandleSelected = true; + mImpl->RequestRelayout(); + } +} + InputMethodContext::CallbackData Controller::OnInputMethodContextEvent( InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent ) { // Whether the text needs to be relaid-out. @@ -3862,32 +3903,6 @@ void Controller::TextDeletedEvent() mImpl->mOperationsPending = ALL_OPERATIONS; } -void Controller::SelectEvent( float x, float y, bool selectAll ) -{ - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SelectEvent\n" ); - - if( NULL != mImpl->mEventData ) - { - if( selectAll ) - { - Event event( Event::SELECT_ALL ); - mImpl->mEventData->mEventQueue.push_back( event ); - } - else - { - Event event( Event::SELECT ); - event.p2.mFloat = x; - event.p3.mFloat = y; - mImpl->mEventData->mEventQueue.push_back( event ); - } - - mImpl->mEventData->mCheckScrollAmount = true; - mImpl->mEventData->mIsLeftHandleSelected = true; - mImpl->mEventData->mIsRightHandleSelected = true; - mImpl->RequestRelayout(); - } -} - bool Controller::DeleteEvent( int keyCode ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::KeyEvent %p KeyCode : %d \n", this, keyCode ); diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 592b19d..f105e0c 100755 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -421,6 +421,20 @@ public: // Configure the text controller. bool IsGrabHandleEnabled() const; /** + * @brief Enable or disable the grab handles for text selection. + * + * @param[in] enabled Whether to enable the grab handles + */ + void SetGrabHandlePopupEnabled( bool enabled ); + + /** + * @brief Returns whether the grab handles are enabled. + * + * @return True if the grab handles are enabled + */ + bool IsGrabHandlePopupEnabled() const; + + /** * @brief Sets input type to password * * @note The string is displayed hidden character @@ -1261,6 +1275,11 @@ public: // Queries & retrieves. */ void SetLayoutDirection( Dali::LayoutDirection::Type layoutDirection ); + /** + * @brief Retrieves if showing real text or not. + * @return The value of showing real text. + */ + bool IsShowingRealText() const; public: // Relayout. @@ -1341,6 +1360,17 @@ public: // Text-input Event Queuing. void LongPressEvent( Gesture::State state, float x, float y ); /** + * @brief Creates a selection event. + * + * It could be called from the TapEvent (double tap) or when the text selection popup's sellect all button is pressed. + * + * @param[in] x The x position relative to the top-left of the parent control. + * @param[in] y The y position relative to the top-left of the parent control. + * @param[in] selectAll Whether the whole text is selected. + */ + void SelectEvent( float x, float y, bool selectAll ); + + /** * @brief Event received from input method context * * @param[in] inputMethodContext The input method context. @@ -1475,17 +1505,6 @@ private: // Events. void TextDeletedEvent(); /** - * @brief Creates a selection event. - * - * It could be called from the TapEvent (double tap) or when the text selection popup's sellect all button is pressed. - * - * @param[in] x The x position relative to the top-left of the parent control. - * @param[in] y The y position relative to the top-left of the parent control. - * @param[in] selectAll Whether the whole text is selected. - */ - void SelectEvent( float x, float y, bool selectAll ); - - /** * @brief Helper to KeyEvent() to handle the backspace or delete key case. * * @param[in] keyCode The keycode for the key pressed -- 2.7.4