From: David Steele Date: Fri, 27 Aug 2021 11:43:07 +0000 (+0000) Subject: Merge "DALi Version 2.0.41" into devel/master X-Git-Tag: dali_2.0.42~7 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=01ed81eed53f178254888ce2205c14e258cfc270;hp=f3fc04895978267e3856e911595e71c67568f7a7 Merge "DALi Version 2.0.41" into devel/master --- diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index 0d0b8bc..02dff2e 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"); @@ -4447,6 +4455,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 7e9c6eb..e8bf4b6 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -127,6 +127,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; @@ -218,6 +219,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"); @@ -4383,6 +4391,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 74a57e6..f3f073b 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 345368d..177be64 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 e9a609f..e5abdfa 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 4dff21d..10d79e8 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 7a3b4ba..47e4c0a 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 @@ -1358,6 +1359,11 @@ DevelTextEditor::SelectionChangedSignalType& TextEditor::SelectionChangedSignal( return mSelectionChangedSignal; } +DevelTextEditor::SelectionClearedSignalType& TextEditor::SelectionClearedSignal() +{ + return mSelectionClearedSignal; +} + Text::ControllerPtr TextEditor::GetTextController() { return mController; @@ -1418,6 +1424,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 @@ -1660,6 +1674,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. @@ -2039,10 +2058,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; @@ -2336,7 +2367,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 aff671a..bc28781 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. @@ -413,6 +418,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 @@ -473,6 +483,7 @@ private: // Data Toolkit::DevelTextEditor::InputFilteredSignalType mInputFilteredSignal; Toolkit::DevelTextEditor::CursorPositionChangedSignalType mCursorPositionChangedSignal; Toolkit::DevelTextEditor::SelectionChangedSignalType mSelectionChangedSignal; + Toolkit::DevelTextEditor::SelectionClearedSignalType mSelectionClearedSignal; InputMethodContext mInputMethodContext; Text::ControllerPtr mController; @@ -502,6 +513,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 c6fd205..6e08da1 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 @@ -1301,6 +1302,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 @@ -1345,6 +1354,11 @@ DevelTextField::SelectionChangedSignalType& TextField::SelectionChangedSignal() return mSelectionChangedSignal; } +DevelTextField::SelectionClearedSignalType& TextField::SelectionClearedSignal() +{ + return mSelectionClearedSignal; +} + void TextField::OnInitialize() { Actor self = Self(); @@ -1551,6 +1565,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. @@ -1947,10 +1966,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; @@ -2103,7 +2134,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 0b24ff0..0472aa8 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() @@ -383,6 +388,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. @@ -428,6 +438,7 @@ private: // Data Toolkit::DevelTextField::InputFilteredSignalType mInputFilteredSignal; Toolkit::DevelTextField::CursorPositionChangedSignalType mCursorPositionChangedSignal; Toolkit::DevelTextField::SelectionChangedSignalType mSelectionChangedSignal; + Toolkit::DevelTextField::SelectionClearedSignalType mSelectionClearedSignal; InputMethodContext mInputMethodContext; Text::ControllerPtr mController; @@ -449,6 +460,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 e24e8aa..e298a5a 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(); } @@ -708,12 +719,11 @@ void ControllerImplEventHandler::OnSelectNoneEvent(Controller::Impl& impl) EventData& eventData = *impl.mEventData; if(eventData.mSelectionEnabled && eventData.mState == EventData::SELECTING) { - eventData.mPrimaryCursorPosition = 0u; uint32_t oldStart = eventData.mLeftSelectionPosition; uint32_t oldEnd = eventData.mRightSelectionPosition; eventData.mLeftSelectionPosition = eventData.mRightSelectionPosition = eventData.mPrimaryCursorPosition; - impl.ChangeState(EventData::INACTIVE); + impl.ChangeState(EventData::EDITING); eventData.mUpdateCursorPosition = true; eventData.mUpdateInputStyle = true; eventData.mScrollAfterUpdatePosition = true; 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); + } } } diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp index 2f29ac0..75fa62e 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp @@ -524,11 +524,11 @@ uint32_t VectorAnimationTask::GetStoppedFrame(uint32_t startFrame, uint32_t endF VectorAnimationTask::TimePoint VectorAnimationTask::CalculateNextFrameTime(bool renderNow) { - // std::chrono::time_point template has second parameter duration which defaults to the std::chrono::system_clock supported + // std::chrono::time_point template has second parameter duration which defaults to the std::chrono::steady_clock supported // duration. In some C++11 implementations it is a milliseconds duration, so it fails to compile unless mNextFrameStartTime // is casted to use the default duration. mNextFrameStartTime = std::chrono::time_point_cast(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds)); - auto current = std::chrono::system_clock::now(); + auto current = std::chrono::steady_clock::now(); if(renderNow) { mNextFrameStartTime = current; diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h index c14cc10..3c0b8e3 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h @@ -47,7 +47,7 @@ class VectorAnimationTask : public RefObject public: using UploadCompletedSignalType = Dali::VectorAnimationRenderer::UploadCompletedSignalType; - using TimePoint = std::chrono::time_point; + using TimePoint = std::chrono::time_point; /** * Flags for re-sending data to the vector animation thread diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp index a5b1166..97634f6 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp @@ -216,7 +216,7 @@ void VectorAnimationThread::Rasterize() { VectorAnimationTaskPtr nextTask = *it; - auto currentTime = std::chrono::system_clock::now(); + auto currentTime = std::chrono::steady_clock::now(); auto nextFrameTime = nextTask->GetNextFrameTime(); #if defined(DEBUG_ENABLED) @@ -300,7 +300,7 @@ VectorAnimationThread::SleepThread::~SleepThread() Join(); } -void VectorAnimationThread::SleepThread::SleepUntil(std::chrono::time_point timeToSleepUntil) +void VectorAnimationThread::SleepThread::SleepUntil(std::chrono::time_point timeToSleepUntil) { ConditionalWait::ScopedLock lock(mConditionalWait); mSleepTimePoint = timeToSleepUntil; @@ -316,7 +316,7 @@ void VectorAnimationThread::SleepThread::Run() while(!mDestroyThread) { bool needToSleep; - std::chrono::time_point sleepTimePoint; + std::chrono::time_point sleepTimePoint; { ConditionalWait::ScopedLock lock(mConditionalWait); @@ -330,7 +330,7 @@ void VectorAnimationThread::SleepThread::Run() if(needToSleep) { #if defined(DEBUG_ENABLED) - auto sleepDuration = std::chrono::duration_cast(mSleepTimePoint - std::chrono::system_clock::now()); + auto sleepDuration = std::chrono::duration_cast(mSleepTimePoint - std::chrono::steady_clock::now()); DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationThread::SleepThread::Run: [sleep duration = %lld]\n", sleepDuration.count()); #endif diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h index 86fec43..8190e7b 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h @@ -139,7 +139,7 @@ private: /** * @brief Sleeps untile the specified time point. */ - void SleepUntil(std::chrono::time_point timeToSleepUntil); + void SleepUntil(std::chrono::time_point timeToSleepUntil); protected: /** @@ -154,7 +154,7 @@ private: private: ConditionalWait mConditionalWait; std::unique_ptr mAwakeCallback; - std::chrono::time_point mSleepTimePoint; + std::chrono::time_point mSleepTimePoint; const Dali::LogFactoryInterface& mLogFactory; bool mNeedToSleep; bool mDestroyThread;