From 183bdd4e867d8daad0b91a1ea717cc28a53bf28d Mon Sep 17 00:00:00 2001 From: abdullah Date: Sun, 22 Aug 2021 17:46:28 +0300 Subject: [PATCH] Add SelectionCleared signal added signal which will be called when selection has been cleared void OnSelectionCleared(TextEditor textEditor) Change-Id: Icce352f1709549b86e9697d28588c32ba89affc4 --- .../src/dali-toolkit/utc-Dali-TextEditor.cpp | 142 +++++++++++++++++++++ .../src/dali-toolkit/utc-Dali-TextField.cpp | 142 +++++++++++++++++++++ .../controls/text-controls/text-editor-devel.cpp | 5 + .../controls/text-controls/text-editor-devel.h | 17 +++ .../controls/text-controls/text-field-devel.cpp | 5 + .../controls/text-controls/text-field-devel.h | 17 +++ .../controls/text-controls/text-editor-impl.cpp | 34 ++++- .../controls/text-controls/text-editor-impl.h | 12 ++ .../controls/text-controls/text-field-impl.cpp | 34 ++++- .../controls/text-controls/text-field-impl.h | 12 ++ .../text/text-controller-impl-event-handler.cpp | 23 +++- .../internal/text/text-controller-text-updater.cpp | 8 ++ 12 files changed, 443 insertions(+), 8 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index 9aef457..7d19f70 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp @@ -136,6 +136,7 @@ const std::string DEFAULT_DEVICE_NAME("hwKeyboard"); static bool gSelectionChangedCallbackCalled; static uint32_t oldSelectionStart; static uint32_t oldSelectionEnd; +static bool gSelectionClearedCallbackCalled; static bool gAnchorClickedCallBackCalled; static bool gAnchorClickedCallBackNotCalled; static bool gTextChangedCallBackCalled; @@ -161,6 +162,13 @@ struct CallbackFunctor bool* mCallbackFlag; }; +static void TestSelectionClearedCallback(TextEditor control) +{ + tet_infoline(" TestSelectionClearedCallback"); + + gSelectionClearedCallbackCalled = true; +} + static void TestSelectionChangedCallback(TextEditor control, uint32_t oldStart, uint32_t oldEnd) { tet_infoline(" TestSelectionChangedCallback"); @@ -4156,6 +4164,140 @@ int utcDaliTextEditorCursorPositionChangedSignal(void) END_TEST; } +int utcDaliTextEditorSelectionClearedSignal(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextEditorSelectionClearedSignal"); + + TextEditor editor = TextEditor::New(); + DALI_TEST_CHECK( editor ); + + application.GetScene().Add( editor ); + + // connect to the selection changed signal. + ConnectionTracker* testTracker = new ConnectionTracker(); + DevelTextEditor::SelectionClearedSignal(editor).Connect(&TestSelectionClearedCallback); + bool selectionClearedSignal = false; + editor.ConnectSignal( testTracker, "selectionCleared", CallbackFunctor(&selectionClearedSignal) ); + + editor.SetProperty( TextEditor::Property::TEXT, "Hello\nworld\nHello world" ); + editor.SetProperty( TextEditor::Property::POINT_SIZE, 10.f ); + editor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) ); + editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Tap on the text editor + TestGenerateTap( application, 3.0f, 25.0f ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Move to second line of the text & Select some text in the right of the current cursor position + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + // remove selection + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_ESCAPE, 0, 0, Integration::KeyEvent::UP, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(gSelectionClearedCallbackCalled); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Tap on the text editor + TestGenerateTap( application, 3.0f, 25.0f ); + + // Render and notify + application.SendNotification(); + application.Render(); + + gSelectionClearedCallbackCalled = false; + + // Move to second line of the text & select. + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + //remove selection + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(gSelectionClearedCallbackCalled); + + gSelectionClearedCallbackCalled = false; + + // Render and notify + application.SendNotification(); + application.Render(); + + // Move to second line of the text & select. + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + // replace C with selected text + application.ProcessEvent( GenerateKey( "c", "", "c", KEY_C_CODE, 0, 0, Integration::KeyEvent::DOWN, "c", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(gSelectionClearedCallbackCalled); + + gSelectionClearedCallbackCalled = false; + + // Render and notify + application.SendNotification(); + application.Render(); + + DevelTextEditor::SelectText( editor ,1, 3 ); + + // Render and notify + application.SendNotification(); + application.Render(); + + editor.SetProperty( DevelTextEditor::Property::PRIMARY_CURSOR_POSITION, 3); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(gSelectionClearedCallbackCalled); + + gSelectionClearedCallbackCalled = false; + + DevelTextEditor::SelectText( editor ,1, 3 ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // select none + DevelTextEditor::SelectNone(editor); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(gSelectionClearedCallbackCalled); + + END_TEST; +} + int utcDaliTextEditorSelectionChangedSignal(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp index eafc4d5..6cfdf90 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -128,6 +128,7 @@ const std::string DEFAULT_DEVICE_NAME("hwKeyboard"); static bool gSelectionChangedCallbackCalled; static uint32_t oldSelectionStart; static uint32_t oldSelectionEnd; +static bool gSelectionClearedCallbackCalled; static bool gAnchorClickedCallBackCalled; static bool gAnchorClickedCallBackNotCalled; static bool gTextChangedCallBackCalled; @@ -219,6 +220,13 @@ struct CallbackFunctor bool* mCallbackFlag; }; +static void TestSelectionClearedCallback(TextField control) +{ + tet_infoline(" TestSelectionClearedCallback"); + + gSelectionClearedCallbackCalled = true; +} + static void TestSelectionChangedCallback(TextField control, uint32_t oldStart, uint32_t oldEnd) { tet_infoline(" TestSelectionChangedCallback"); @@ -4104,6 +4112,140 @@ int utcDaliTextFieldCursorPositionChangedSignal(void) END_TEST; } +int utcDaliTextFieldSelectionClearedSignal(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextFieldSelectionClearedSignal"); + + TextField field = TextField::New(); + DALI_TEST_CHECK( field ); + + application.GetScene().Add( field ); + + // connect to the selection changed signal. + ConnectionTracker* testTracker = new ConnectionTracker(); + DevelTextField::SelectionClearedSignal(field).Connect(&TestSelectionClearedCallback); + bool selectionClearedSignal = false; + field.ConnectSignal( testTracker, "selectionCleared", CallbackFunctor(&selectionClearedSignal) ); + + field.SetProperty( TextField::Property::TEXT, "Hello\nworld\nHello world" ); + field.SetProperty( TextField::Property::POINT_SIZE, 10.f ); + field.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) ); + field.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT ); + field.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Tap on the text editor + TestGenerateTap( application, 3.0f, 25.0f ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Move to second line of the text & Select some text in the right of the current cursor position + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + // remove selection + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_ESCAPE, 0, 0, Integration::KeyEvent::UP, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(gSelectionClearedCallbackCalled); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Tap on the text editor + TestGenerateTap( application, 3.0f, 25.0f ); + + // Render and notify + application.SendNotification(); + application.Render(); + + gSelectionClearedCallbackCalled = false; + + // Move to second line of the text & select. + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + //remove selection + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(gSelectionClearedCallbackCalled); + + gSelectionClearedCallbackCalled = false; + + // Render and notify + application.SendNotification(); + application.Render(); + + // Move to second line of the text & select. + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + // replace D with selected text + application.ProcessEvent( GenerateKey( "D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(gSelectionClearedCallbackCalled); + + gSelectionClearedCallbackCalled = false; + + // Render and notify + application.SendNotification(); + application.Render(); + + DevelTextField::SelectText( field ,1, 3 ); + + // Render and notify + application.SendNotification(); + application.Render(); + + field.SetProperty( DevelTextField::Property::PRIMARY_CURSOR_POSITION, 3); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(gSelectionClearedCallbackCalled); + + gSelectionClearedCallbackCalled = false; + + DevelTextField::SelectText( field ,1, 3 ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // select none + DevelTextField::SelectNone(field); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(gSelectionClearedCallbackCalled); + + END_TEST; +} + int utcDaliTextFieldSelectionChangedSignal(void) { ToolkitTestApplication application; diff --git a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp index 33fc4e7..fdd6e77 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp +++ b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp @@ -55,6 +55,11 @@ SelectionChangedSignalType& SelectionChangedSignal(TextEditor textEditor) return GetImpl(textEditor).SelectionChangedSignal(); } +SelectionClearedSignalType& SelectionClearedSignal(TextEditor textEditor) +{ + return GetImpl(textEditor).SelectionClearedSignal(); +} + void SelectWholeText(TextEditor textEditor) { GetImpl(textEditor).SelectWholeText(); diff --git a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h index 53a63e2..19abc12 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h +++ b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h @@ -397,6 +397,23 @@ using SelectionChangedSignalType = Signal; DALI_TOOLKIT_API SelectionChangedSignalType& SelectionChangedSignal(TextEditor textEditor); /** + * @brief selection cleared signal type. + */ +using SelectionClearedSignalType = Signal; + +/** + * @brief This signal is emitted when the selection has been cleared. + * + * A callback of the following type may be connected: + * @code + * void YourCallbackName( TextEditor textEditor); + * @endcode + * @param[in] textEditor The instance of TextEditor. + * @return The signal to connect to + */ +DALI_TOOLKIT_API SelectionClearedSignalType& SelectionClearedSignal(TextEditor textEditor); + +/** * @brief Select the whole text of TextEditor. * * @param[in] textEditor The instance of TextEditor. 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 0d9ef15..98e6aa3 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp +++ b/dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp @@ -50,6 +50,11 @@ SelectionChangedSignalType& SelectionChangedSignal(TextField textField) return GetImpl(textField).SelectionChangedSignal(); } +SelectionClearedSignalType& SelectionClearedSignal(TextField textField) +{ + return GetImpl(textField).SelectionClearedSignal(); +} + void SelectWholeText(TextField textField) { GetImpl(textField).SelectWholeText(); 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 59f192d..2471cc4 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h +++ b/dali-toolkit/devel-api/controls/text-controls/text-field-devel.h @@ -319,6 +319,23 @@ using SelectionChangedSignalType = Signal; DALI_TOOLKIT_API SelectionChangedSignalType& SelectionChangedSignal(TextField textField); /** + * @brief selection cleared signal type. + */ +using SelectionClearedSignalType = Signal; + +/** + * @brief This signal is emitted when the selection has been cleared. + * + * A callback of the following type may be connected: + * @code + * void YourCallbackName( TextField textField); + * @endcode + * @param[in] textField The instance of TextField. + * @return The signal to connect to + */ +DALI_TOOLKIT_API SelectionClearedSignalType& SelectionClearedSignal(TextField textField); + +/** * @brief Select the whole text of TextField. * * @param[in] textField The instance of TextField. diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp index 8236064..77cd93d 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -160,6 +160,7 @@ DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "anchorClicked", SIGNAL_AN DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "inputFiltered", SIGNAL_INPUT_FILTERED ) DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "cursorPositionChanged", SIGNAL_CURSOR_POSITION_CHANGED) DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "selectionChanged", SIGNAL_SELECTION_CHANGED ) +DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "selectionCleared", SIGNAL_SELECTION_CLEARED ) DALI_TYPE_REGISTRATION_END() // clang-format on @@ -1329,6 +1330,11 @@ DevelTextEditor::SelectionChangedSignalType& TextEditor::SelectionChangedSignal( return mSelectionChangedSignal; } +DevelTextEditor::SelectionClearedSignalType& TextEditor::SelectionClearedSignal() +{ + return mSelectionClearedSignal; +} + Text::ControllerPtr TextEditor::GetTextController() { return mController; @@ -1389,6 +1395,14 @@ bool TextEditor::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* editorImpl.SelectionChangedSignal().Connect(tracker, functor); } } + else if(0 == strcmp(signalName.c_str(), SIGNAL_SELECTION_CLEARED)) + { + if(editor) + { + Internal::TextEditor& editorImpl(GetImpl(editor)); + editorImpl.SelectionClearedSignal().Connect(tracker, functor); + } + } else { // signalName does not match any signal @@ -1631,6 +1645,11 @@ void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container) EmitSelectionChangedSignal(); } + if(mSelectionCleared) + { + EmitSelectionClearedSignal(); + } + // The text-editor emits signals when the input style changes. These changes of style are // detected during the relayout process (size negotiation), i.e after the cursor has been moved. Signals // can't be emitted during the size negotiation as the callbacks may update the UI. @@ -2010,10 +2029,22 @@ void TextEditor::EmitSelectionChangedSignal() mSelectionChanged = false; } +void TextEditor::EmitSelectionClearedSignal() +{ + Dali::Toolkit::TextEditor handle(GetOwner()); + mSelectionClearedSignal.Emit(handle); + mSelectionCleared = false; +} + void TextEditor::SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t newStart, uint32_t newEnd) { if(((oldStart != newStart) || (oldEnd != newEnd)) && !mSelectionChanged) { + if(newStart == newEnd) + { + mSelectionCleared = true; + } + mSelectionChanged = true; mOldSelectionStart = oldStart; mOldSelectionEnd = oldEnd; @@ -2307,7 +2338,8 @@ TextEditor::TextEditor() mScrollStarted(false), mTextChanged(false), mCursorPositionChanged(false), - mSelectionChanged(false) + mSelectionChanged(false), + mSelectionCleared(false) { } diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h index d76b41b..d20e8ea 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h @@ -108,6 +108,11 @@ public: DevelTextEditor::SelectionChangedSignalType& SelectionChangedSignal(); /** + * @copydoc Dali::Toollkit::TextEditor::SelectionClearedSignal() + */ + DevelTextEditor::SelectionClearedSignalType& SelectionClearedSignal(); + + /** * Connects a callback function with the object's signals. * @param[in] object The object providing the signal. * @param[in] tracker Used to disconnect the signal. @@ -398,6 +403,11 @@ private: // Implementation void EmitSelectionChangedSignal(); /** + * @brief Emits SelectionCleared signal. + */ + void EmitSelectionClearedSignal(); + + /** * @brief set RenderActor's position with new scrollPosition * * Apply updated scroll position or start scroll animation if VerticalScrollAnimation is enabled @@ -458,6 +468,7 @@ private: // Data Toolkit::DevelTextEditor::InputFilteredSignalType mInputFilteredSignal; Toolkit::DevelTextEditor::CursorPositionChangedSignalType mCursorPositionChangedSignal; Toolkit::DevelTextEditor::SelectionChangedSignalType mSelectionChangedSignal; + Toolkit::DevelTextEditor::SelectionClearedSignalType mSelectionClearedSignal; InputMethodContext mInputMethodContext; Text::ControllerPtr mController; @@ -487,6 +498,7 @@ private: // Data bool mTextChanged : 1; ///< If true, emits TextChangedSignal in next OnRelayout(). bool mCursorPositionChanged : 1; ///< If true, emits CursorPositionChangedSignal at the end of OnRelayout(). bool mSelectionChanged : 1; ///< If true, emits SelectionChangedSignal at the end of OnRelayout(). + bool mSelectionCleared : 1; ///< If true, emits SelectionClearedSignal at the end of OnRelayout(). //args for cursor PositionChanged event unsigned int mOldPosition; 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 a806c70..5e6d740 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -147,6 +147,7 @@ DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "anchorClicked", SIGNAL_ANC DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "inputFiltered", SIGNAL_INPUT_FILTERED ) DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "cursorPositionChanged", SIGNAL_CURSOR_POSITION_CHANGED) DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "selectionChanged", SIGNAL_SELECTION_CHANGED ) +DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "selectionCleared", SIGNAL_SELECTION_CLEARED ) DALI_TYPE_REGISTRATION_END() // clang-format on @@ -1272,6 +1273,14 @@ bool TextField::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* fieldImpl.SelectionChangedSignal().Connect(tracker, functor); } } + else if(0 == strcmp(signalName.c_str(), SIGNAL_SELECTION_CLEARED)) + { + if(field) + { + Internal::TextField& fieldImpl(GetImpl(field)); + fieldImpl.SelectionClearedSignal().Connect(tracker, functor); + } + } else { // signalName does not match any signal @@ -1316,6 +1325,11 @@ DevelTextField::SelectionChangedSignalType& TextField::SelectionChangedSignal() return mSelectionChangedSignal; } +DevelTextField::SelectionClearedSignalType& TextField::SelectionClearedSignal() +{ + return mSelectionClearedSignal; +} + void TextField::OnInitialize() { Actor self = Self(); @@ -1522,6 +1536,11 @@ void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container) EmitSelectionChangedSignal(); } + if(mSelectionCleared) + { + EmitSelectionClearedSignal(); + } + // The text-field emits signals when the input style changes. These changes of style are // detected during the relayout process (size negotiation), i.e after the cursor has been moved. Signals // can't be emitted during the size negotiation as the callbacks may update the UI. @@ -1918,10 +1937,22 @@ void TextField::EmitSelectionChangedSignal() mSelectionChanged = false; } +void TextField::EmitSelectionClearedSignal() +{ + Dali::Toolkit::TextField handle(GetOwner()); + mSelectionClearedSignal.Emit(handle); + mSelectionCleared = false; +} + void TextField::SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t newStart, uint32_t newEnd) { if(((oldStart != newStart) || (oldEnd != newEnd)) && !mSelectionChanged) { + if(newStart == newEnd) + { + mSelectionCleared = true; + } + mSelectionChanged = true; mOldSelectionStart = oldStart; mOldSelectionEnd = oldEnd; @@ -2074,7 +2105,8 @@ TextField::TextField() mHasBeenStaged(false), mTextChanged(false), mCursorPositionChanged(false), - mSelectionChanged(false) + mSelectionChanged(false), + mSelectionCleared(false) { } 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 5cc7e78..4711036 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.h @@ -131,6 +131,11 @@ public: */ DevelTextField::SelectionChangedSignalType& SelectionChangedSignal(); + /** + * @copydoc TextField::SelectionClearedSignal() + */ + DevelTextField::SelectionClearedSignalType& SelectionClearedSignal(); + private: // From Control /** * @copydoc Control::OnInitialize() @@ -368,6 +373,11 @@ private: // Implementation void EmitSelectionChangedSignal(); /** + * @brief Emits SelectionCleared signal. + */ + void EmitSelectionClearedSignal(); + + /** * @brief Callback function for when the layout is changed. * @param[in] actor The actor whose layoutDirection is changed. * @param[in] type The layoutDirection. @@ -413,6 +423,7 @@ private: // Data Toolkit::DevelTextField::InputFilteredSignalType mInputFilteredSignal; Toolkit::DevelTextField::CursorPositionChangedSignalType mCursorPositionChangedSignal; Toolkit::DevelTextField::SelectionChangedSignalType mSelectionChangedSignal; + Toolkit::DevelTextField::SelectionClearedSignalType mSelectionClearedSignal; InputMethodContext mInputMethodContext; Text::ControllerPtr mController; @@ -434,6 +445,7 @@ private: // Data bool mTextChanged : 1; ///< If true, emits TextChangedSignal in next OnRelayout(). bool mCursorPositionChanged : 1; ///< If true, emits CursorPositionChangedSignal at the end of OnRelayout(). bool mSelectionChanged : 1; ///< If true, emits SelectionChangedSignal at the end of OnRelayout(). + bool mSelectionCleared : 1; ///< If true, emits SelectionClearedSignal at the end of OnRelayout(). //args for cursor position changed event unsigned int mOldPosition; diff --git a/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp b/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp index 06898b6..60c4c54 100644 --- a/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp +++ b/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp @@ -286,6 +286,8 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const ModelPtr& model = impl.mModel; LogicalModelPtr& logicalModel = model->mLogicalModel; VisualModelPtr& visualModel = model->mVisualModel; + uint32_t oldSelStart = eventData.mLeftSelectionPosition; + uint32_t oldSelEnd = eventData.mRightSelectionPosition; CharacterIndex& primaryCursorPosition = eventData.mPrimaryCursorPosition; CharacterIndex previousPrimaryCursorPosition = primaryCursorPosition; @@ -397,6 +399,11 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const // Update selection position after moving the cursor eventData.mLeftSelectionPosition = primaryCursorPosition; eventData.mRightSelectionPosition = primaryCursorPosition; + + if(impl.mSelectableControlInterface != nullptr && eventData.mDecorator->IsHighlightVisible()) + { + impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition); + } } if(isShiftModifier && impl.IsShowingRealText() && eventData.mShiftSelectionFlag) @@ -410,14 +417,11 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const int cursorPositionDelta = primaryCursorPosition - previousPrimaryCursorPosition; if(cursorPositionDelta > 0 || eventData.mRightSelectionPosition > 0u) // Check the boundary { - uint32_t oldStart = eventData.mLeftSelectionPosition; - uint32_t oldEnd = eventData.mRightSelectionPosition; - eventData.mRightSelectionPosition += cursorPositionDelta; if(impl.mSelectableControlInterface != nullptr) { - impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition); + impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition); } } selecting = true; @@ -477,8 +481,10 @@ void ControllerImplEventHandler::OnTapEvent(Controller::Impl& impl, const Event& if(impl.IsShowingRealText()) { // Convert from control's coords to text's coords. - const float xPosition = event.p2.mFloat - model->mScrollPosition.x; - const float yPosition = event.p3.mFloat - model->mScrollPosition.y; + const float xPosition = event.p2.mFloat - model->mScrollPosition.x; + const float yPosition = event.p3.mFloat - model->mScrollPosition.y; + uint32_t oldSelStart = eventData.mLeftSelectionPosition; + uint32_t oldSelEnd = eventData.mRightSelectionPosition; // Keep the tap 'x' position. Used to move the cursor. eventData.mCursorHookPositionX = xPosition; @@ -493,6 +499,11 @@ void ControllerImplEventHandler::OnTapEvent(Controller::Impl& impl, const Event& CharacterHitTest::TAP, matchedCharacter); + if(impl.mSelectableControlInterface != nullptr && eventData.mDecorator->IsHighlightVisible()) + { + impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, eventData.mPrimaryCursorPosition, eventData.mPrimaryCursorPosition); + } + // When the cursor position is changing, delay cursor blinking eventData.mDecorator->DelayCursorBlink(); } diff --git a/dali-toolkit/internal/text/text-controller-text-updater.cpp b/dali-toolkit/internal/text/text-controller-text-updater.cpp index c200c38..75ea73c 100644 --- a/dali-toolkit/internal/text/text-controller-text-updater.cpp +++ b/dali-toolkit/internal/text/text-controller-text-updater.cpp @@ -607,6 +607,9 @@ bool Controller::TextUpdater::RemoveSelectedText(Controller& controller) if(EventData::SELECTING == impl.mEventData->mState) { std::string removedString; + uint32_t oldSelStart = impl.mEventData->mLeftSelectionPosition; + uint32_t oldSelEnd = impl.mEventData->mRightSelectionPosition; + impl.RetrieveSelection(removedString, true); if(!removedString.empty()) @@ -623,6 +626,11 @@ bool Controller::TextUpdater::RemoveSelectedText(Controller& controller) RemoveTextAnchor(controller, cursorOffset, numberOfCharacters, previousCursorIndex); } + + if(impl.mSelectableControlInterface != nullptr) + { + impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, impl.mEventData->mPrimaryCursorPosition, impl.mEventData->mPrimaryCursorPosition); + } } } -- 2.7.4