const std::string DEFAULT_DEVICE_NAME("hwKeyboard");
+static bool gSelectionChangedCallbackCalled;
+static uint32_t oldSelectionStart;
+static uint32_t oldSelectionEnd;
static bool gAnchorClickedCallBackCalled;
static bool gAnchorClickedCallBackNotCalled;
static bool gTextChangedCallBackCalled;
bool* mCallbackFlag;
};
+static void TestSelectionChangedCallback(TextEditor control, uint32_t oldStart, uint32_t oldEnd)
+{
+ tet_infoline(" TestSelectionChangedCallback");
+
+ gSelectionChangedCallbackCalled = true;
+ oldSelectionStart = oldStart;
+ oldSelectionEnd = oldEnd;
+}
+
static void TestAnchorClickedCallback(TextEditor control, const char* href, unsigned int hrefLength)
{
tet_infoline(" TestAnchorClickedCallback");
DALI_TEST_EQUALS(oldCursorPos, 5, TEST_LOCATION);
END_TEST;
+}
+
+int utcDaliTextEditorSelectionChangedSignal(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextEditorSelectionChangedSignal");
+
+ TextEditor editor = TextEditor::New();
+ DALI_TEST_CHECK( editor );
+
+ application.GetScene().Add( editor );
+
+ // connect to the selection changed signal.
+ ConnectionTracker* testTracker = new ConnectionTracker();
+ DevelTextEditor::SelectionChangedSignal(editor).Connect(&TestSelectionChangedCallback);
+ bool selectionChangedSignal = false;
+ editor.ConnectSignal( testTracker, "selectionChanged", CallbackFunctor(&selectionChangedSignal) );
+
+ 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.
+ application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Select some text in the right of the current cursor position
+ application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_SHIFT_LEFT, 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 ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, oldSelectionEnd, TEST_LOCATION);
+
+ gSelectionChangedCallbackCalled = false;
+
+ application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, 6, TEST_LOCATION);
+ DALI_TEST_EQUALS(oldSelectionEnd, 7, TEST_LOCATION);
+
+ gSelectionChangedCallbackCalled = false;
+
+ 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(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, 6, TEST_LOCATION);
+ DALI_TEST_EQUALS(oldSelectionEnd, 8, TEST_LOCATION);
+
+ gSelectionChangedCallbackCalled = false;
+ editor.SetKeyInputFocus();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DevelTextEditor::SelectText( editor ,0, 5 );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, oldSelectionEnd, TEST_LOCATION);
+
+ gSelectionChangedCallbackCalled = false;
+
+ editor.SetProperty( DevelTextEditor::Property::PRIMARY_CURSOR_POSITION, 3);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, 0, TEST_LOCATION);
+ DALI_TEST_EQUALS(oldSelectionEnd, 5, TEST_LOCATION);
+
+ gSelectionChangedCallbackCalled = false;
+
+ // select all text
+ DevelTextEditor::SelectWholeText(editor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, oldSelectionEnd, TEST_LOCATION);
+
+ gSelectionChangedCallbackCalled = false;
+
+ // select none
+ DevelTextEditor::SelectNone(editor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, 0, TEST_LOCATION);
+ DALI_TEST_EQUALS(oldSelectionEnd, 23, TEST_LOCATION);
+
+ END_TEST;
}
\ No newline at end of file
const int KEY_A_CODE = 38;
const int KEY_D_CODE = 40;
+const int KEY_SHIFT_MODIFIER = 257;
+
const std::string DEFAULT_DEVICE_NAME("hwKeyboard");
+static bool gSelectionChangedCallbackCalled;
+static uint32_t oldSelectionStart;
+static uint32_t oldSelectionEnd;
static bool gAnchorClickedCallBackCalled;
static bool gAnchorClickedCallBackNotCalled;
static bool gTextChangedCallBackCalled;
bool* mCallbackFlag;
};
+static void TestSelectionChangedCallback(TextField control, uint32_t oldStart, uint32_t oldEnd)
+{
+ tet_infoline(" TestSelectionChangedCallback");
+
+ gSelectionChangedCallbackCalled = true;
+ oldSelectionStart = oldStart;
+ oldSelectionEnd = oldEnd;
+}
+
static void TestAnchorClickedCallback(TextField control, const char* href, unsigned int hrefLength)
{
tet_infoline(" TestAnchorClickedCallback");
DALI_TEST_EQUALS(oldCursorPos, 5, TEST_LOCATION);
END_TEST;
+}
+
+int utcDaliTextFieldSelectionChangedSignal(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldSelectionChangedSignal");
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ application.GetScene().Add( field );
+
+ // connect to the selection changed signal.
+ ConnectionTracker* testTracker = new ConnectionTracker();
+ DevelTextField::SelectionChangedSignal(field).Connect(&TestSelectionChangedCallback);
+ bool selectionChangedSignal = false;
+ field.ConnectSignal( testTracker, "selectionChanged", CallbackFunctor(&selectionChangedSignal) );
+
+ field.SetProperty( TextField::Property::TEXT, "Hello world Hello 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 field
+ TestGenerateTap( application, 3.0f, 25.0f );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Select some text in the right of the current cursor position
+ application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_SHIFT_LEFT, 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 ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, oldSelectionEnd, TEST_LOCATION);
+
+ gSelectionChangedCallbackCalled = false;
+
+ application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, 0, TEST_LOCATION);
+ DALI_TEST_EQUALS(oldSelectionEnd, 1, TEST_LOCATION);
+
+ gSelectionChangedCallbackCalled = false;
+
+ 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(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, 0, TEST_LOCATION);
+ DALI_TEST_EQUALS(oldSelectionEnd, 2, TEST_LOCATION);
+
+ gSelectionChangedCallbackCalled = false;
+ field.SetKeyInputFocus();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DevelTextField::SelectText( field ,0, 5 );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, oldSelectionEnd, TEST_LOCATION);
+
+ gSelectionChangedCallbackCalled = false;
+
+ field.SetProperty( DevelTextField::Property::PRIMARY_CURSOR_POSITION, 3);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, 0, TEST_LOCATION);
+ DALI_TEST_EQUALS(oldSelectionEnd, 5, TEST_LOCATION);
+
+ gSelectionChangedCallbackCalled = false;
+
+ // select all text
+ DevelTextField::SelectWholeText(field);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, oldSelectionEnd, TEST_LOCATION);
+
+ gSelectionChangedCallbackCalled = false;
+
+ // select none
+ DevelTextField::SelectNone(field);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(gSelectionChangedCallbackCalled);
+ DALI_TEST_EQUALS(oldSelectionStart, 0, TEST_LOCATION);
+ DALI_TEST_EQUALS(oldSelectionEnd, 23, TEST_LOCATION);
+
+ END_TEST;
}
\ No newline at end of file
return GetImpl(textEditor).InputFilteredSignal();
}
+SelectionChangedSignalType& SelectionChangedSignal(TextEditor textEditor)
+{
+ return GetImpl(textEditor).SelectionChangedSignal();
+}
+
void SelectWholeText(TextEditor textEditor)
{
GetImpl(textEditor).SelectWholeText();
DALI_TOOLKIT_API InputFilteredSignalType& InputFilteredSignal(TextEditor textEditor);
/**
+ * @brief selection changed signal type.
+ *
+ * @note Signal
+ * - uint32_t : selection start before the change.
+ * - uint32_t : selection end before the change.
+ */
+using SelectionChangedSignalType = Signal<void(TextEditor, uint32_t, uint32_t)>;
+
+/**
+ * @brief This signal is emitted when the selection has been changed.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ * void YourCallbackName( TextEditor textEditor, uint32_t oldStart, uint32_t oldEnd);
+ * @endcode
+ * @param[in] textEditor The instance of TextEditor.
+ * @return The signal to connect to
+ */
+DALI_TOOLKIT_API SelectionChangedSignalType& SelectionChangedSignal(TextEditor textEditor);
+
+/**
* @brief Select the whole text of TextEditor.
*
* @param[in] textEditor The instance of TextEditor.
return GetImpl(textField).InputFilteredSignal();
}
+SelectionChangedSignalType& SelectionChangedSignal(TextField textField)
+{
+ return GetImpl(textField).SelectionChangedSignal();
+}
+
void SelectWholeText(TextField textField)
{
GetImpl(textField).SelectWholeText();
DALI_TOOLKIT_API InputFilteredSignalType& InputFilteredSignal(TextField textField);
/**
+ * @brief selection changed signal type.
+ *
+ * @note Signal
+ * - uint32_t : selection start before the change.
+ * - uint32_t : selection end before the change.
+ */
+using SelectionChangedSignalType = Signal<void(TextField, uint32_t, uint32_t)>;
+
+/**
+ * @brief This signal is emitted when the selection has been changed.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ * void YourCallbackName( TextField textField, uint32_t oldStart, uint32_t oldEnd);
+ * @endcode
+ * @param[in] textField The instance of TextField.
+ * @return The signal to connect to
+ */
+DALI_TOOLKIT_API SelectionChangedSignalType& SelectionChangedSignal(TextField textField);
+
+/**
* @brief Select the whole text of TextField.
*
* @param[in] textField The instance of TextField.
DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "anchorClicked", SIGNAL_ANCHOR_CLICKED )
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_TYPE_REGISTRATION_END()
// clang-format on
return mInputFilteredSignal;
}
+DevelTextEditor::SelectionChangedSignalType& TextEditor::SelectionChangedSignal()
+{
+ return mSelectionChangedSignal;
+}
+
Text::ControllerPtr TextEditor::GetTextController()
{
return mController;
editorImpl.InputFilteredSignal().Connect(tracker, functor);
}
}
+ else if(0 == strcmp(signalName.c_str(), SIGNAL_SELECTION_CHANGED))
+ {
+ if(editor)
+ {
+ Internal::TextEditor& editorImpl(GetImpl(editor));
+ editorImpl.SelectionChangedSignal().Connect(tracker, functor);
+ }
+ }
else
{
// signalName does not match any signal
EmitCursorPositionChangedSignal();
}
+ if(mSelectionChanged)
+ {
+ EmitSelectionChangedSignal();
+ }
+
// 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.
mInputFilteredSignal.Emit(handle, type);
}
+void TextEditor::EmitSelectionChangedSignal()
+{
+ Dali::Toolkit::TextEditor handle(GetOwner());
+ mSelectionChangedSignal.Emit(handle, mOldSelectionStart, mOldSelectionEnd);
+ mSelectionChanged = false;
+}
+
+void TextEditor::SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t newStart, uint32_t newEnd)
+{
+ if(((oldStart != newStart) || (oldEnd != newEnd)) && !mSelectionChanged)
+ {
+ mSelectionChanged = true;
+ mOldSelectionStart = oldStart;
+ mOldSelectionEnd = oldEnd;
+
+ if(mOldSelectionStart > mOldSelectionEnd)
+ {
+ //swap
+ uint32_t temp = mOldSelectionStart;
+ mOldSelectionStart = mOldSelectionEnd;
+ mOldSelectionEnd = temp;
+ }
+ }
+}
+
void TextEditor::AddDecoration(Actor& actor, bool needsClipping)
{
if(actor)
mScrollBarEnabled(false),
mScrollStarted(false),
mTextChanged(false),
- mCursorPositionChanged(false)
+ mCursorPositionChanged(false),
+ mSelectionChanged(false)
{
}
DevelTextEditor::InputFilteredSignalType& InputFilteredSignal();
/**
+ * @copydoc Dali::Toollkit::TextEditor::SelectionChangedSignal()
+ */
+ DevelTextEditor::SelectionChangedSignalType& SelectionChangedSignal();
+
+ /**
* 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.
void InputStyleChanged(Text::InputStyle::Mask inputStyleMask) override;
/**
+ * @copydoc Text::SelectableControlInterface::SelectionChanged()
+ */
+ void SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t newStart, uint32_t newEnd) override;
+
+ /**
* @copydoc Text::EditableControlInterface::AddDecoration()
*/
void AddDecoration(Actor& actor, bool needsClipping) override;
void EmitTextChangedSignal();
/**
+ * @brief Emits SelectionChanged signal.
+ */
+ void EmitSelectionChangedSignal();
+
+ /**
* @brief set RenderActor's position with new scrollPosition
*
* Apply updated scroll position or start scroll animation if VerticalScrollAnimation is enabled
Toolkit::DevelTextEditor::AnchorClickedSignalType mAnchorClickedSignal;
Toolkit::DevelTextEditor::InputFilteredSignalType mInputFilteredSignal;
Toolkit::DevelTextEditor::CursorPositionChangedSignalType mCursorPositionChangedSignal;
+ Toolkit::DevelTextEditor::SelectionChangedSignalType mSelectionChangedSignal;
InputMethodContext mInputMethodContext;
Text::ControllerPtr mController;
bool mScrollStarted : 1;
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().
//args for cursor PositionChanged event
unsigned int mOldPosition;
+ //args for selection changed event
+ uint32_t mOldSelectionStart;
+ uint32_t mOldSelectionEnd;
+
/**
* @brief This structure is to connect TextEditor with Accessible functions.
*/
DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "anchorClicked", SIGNAL_ANCHOR_CLICKED )
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_TYPE_REGISTRATION_END()
// clang-format on
fieldImpl.InputFilteredSignal().Connect(tracker, functor);
}
}
+ else if(0 == strcmp(signalName.c_str(), SIGNAL_SELECTION_CHANGED))
+ {
+ if(field)
+ {
+ Internal::TextField& fieldImpl(GetImpl(field));
+ fieldImpl.SelectionChangedSignal().Connect(tracker, functor);
+ }
+ }
else
{
// signalName does not match any signal
return mInputFilteredSignal;
}
+DevelTextField::SelectionChangedSignalType& TextField::SelectionChangedSignal()
+{
+ return mSelectionChangedSignal;
+}
+
void TextField::OnInitialize()
{
Actor self = Self();
EmitCursorPositionChangedSignal();
}
+ if(mSelectionChanged)
+ {
+ EmitSelectionChangedSignal();
+ }
+
// 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.
mInputFilteredSignal.Emit(handle, type);
}
+void TextField::EmitSelectionChangedSignal()
+{
+ Dali::Toolkit::TextField handle(GetOwner());
+ mSelectionChangedSignal.Emit(handle, mOldSelectionStart, mOldSelectionEnd);
+ mSelectionChanged = false;
+}
+
+void TextField::SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t newStart, uint32_t newEnd)
+{
+ if(((oldStart != newStart) || (oldEnd != newEnd)) && !mSelectionChanged)
+ {
+ mSelectionChanged = true;
+ mOldSelectionStart = oldStart;
+ mOldSelectionEnd = oldEnd;
+
+ if(mOldSelectionStart > mOldSelectionEnd)
+ {
+ //swap
+ uint32_t temp = mOldSelectionStart;
+ mOldSelectionStart = mOldSelectionEnd;
+ mOldSelectionEnd = temp;
+ }
+ }
+}
+
void TextField::AddDecoration(Actor& actor, bool needsClipping)
{
if(actor)
mExceedPolicy(Dali::Toolkit::TextField::EXCEED_POLICY_CLIP),
mHasBeenStaged(false),
mTextChanged(false),
- mCursorPositionChanged(false)
+ mCursorPositionChanged(false),
+ mSelectionChanged(false)
{
}
*/
DevelTextField::InputFilteredSignalType& InputFilteredSignal();
+ /**
+ * @copydoc TextField::SelectionChangedSignal()
+ */
+ DevelTextField::SelectionChangedSignalType& SelectionChangedSignal();
+
private: // From Control
/**
* @copydoc Control::OnInitialize()
void InputStyleChanged(Text::InputStyle::Mask inputStyleMask) override;
/**
+ * @copydoc Text::SelectableControlInterface::SelectionChanged()
+ */
+ void SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t newStart, uint32_t newEnd) override;
+
+ /**
* @copydoc Text::EditableControlInterface::AddDecoration()
*/
void AddDecoration(Actor& actor, bool needsClipping) override;
void EmitCursorPositionChangedSignal();
/**
+ * @brief Emits SelectionChanged signal.
+ */
+ void EmitSelectionChangedSignal();
+
+ /**
* @brief Callback function for when the layout is changed.
* @param[in] actor The actor whose layoutDirection is changed.
* @param[in] type The layoutDirection.
Toolkit::DevelTextField::AnchorClickedSignalType mAnchorClickedSignal;
Toolkit::DevelTextField::InputFilteredSignalType mInputFilteredSignal;
Toolkit::DevelTextField::CursorPositionChangedSignalType mCursorPositionChangedSignal;
+ Toolkit::DevelTextField::SelectionChangedSignalType mSelectionChangedSignal;
InputMethodContext mInputMethodContext;
Text::ControllerPtr mController;
bool mHasBeenStaged : 1;
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().
//args for cursor position changed event
unsigned int mOldPosition;
+ //args for selection changed event
+ uint32_t mOldSelectionStart;
+ uint32_t mOldSelectionEnd;
+
protected:
/**
* @brief This structure is to connect TextField with Accessible functions.
// Init selection position
if(controller.mImpl->mEventData->mState == EventData::SELECTING)
{
+ uint32_t oldStart, oldEnd;
+ oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
+ oldEnd = controller.mImpl->mEventData->mRightSelectionPosition;
+
controller.mImpl->mEventData->mLeftSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
+
+ if(controller.mImpl->mSelectableControlInterface != nullptr)
+ {
+ controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mPrimaryCursorPosition, controller.mImpl->mEventData->mPrimaryCursorPosition);
+ }
}
controller.mImpl->ChangeState(EventData::INACTIVE);
// Release the active highlight.
if(controller.mImpl->mEventData->mState == EventData::SELECTING)
{
+ uint32_t oldStart, oldEnd;
+ oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
+ oldEnd = controller.mImpl->mEventData->mRightSelectionPosition;
+
controller.mImpl->ChangeState(EventData::EDITING);
// Update selection position.
controller.mImpl->mEventData->mLeftSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
controller.mImpl->mEventData->mUpdateCursorPosition = true;
+
+ if(controller.mImpl->mSelectableControlInterface != nullptr)
+ {
+ controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mLeftSelectionPosition, controller.mImpl->mEventData->mRightSelectionPosition);
+ }
+
controller.mImpl->RequestRelayout();
}
return false;
if(NULL != controller.mImpl->mEventData)
{
+ uint32_t oldStart, oldEnd;
+ oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
+ oldEnd = controller.mImpl->mEventData->mRightSelectionPosition;
+
// When the text is being modified, delay cursor blinking
controller.mImpl->mEventData->mDecorator->DelayCursorBlink();
// Update selection position after modifying the text
controller.mImpl->mEventData->mLeftSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
+
+ if(controller.mImpl->mSelectableControlInterface != nullptr && controller.mImpl->mEventData->mState == EventData::SELECTING)
+ {
+ controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mLeftSelectionPosition, controller.mImpl->mEventData->mRightSelectionPosition);
+ }
}
// DISCARD temporary text
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);
+ }
}
selecting = true;
}
0.f - scrollPosition.y,
Controller::NoTextTap::HIGHLIGHT);
+ uint32_t oldStart = eventData.mLeftSelectionPosition;
+ uint32_t oldEnd = eventData.mRightSelectionPosition;
+
eventData.mLeftSelectionPosition = 0u;
eventData.mRightSelectionPosition = model->mLogicalModel->mText.Count();
+
+ if(impl.mSelectableControlInterface != nullptr)
+ {
+ impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+ }
}
}
}
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);
eventData.mUpdateCursorPosition = true;
eventData.mUpdateInputStyle = true;
eventData.mScrollAfterUpdatePosition = true;
+
+ if(impl.mSelectableControlInterface != nullptr)
+ {
+ impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+ }
}
}
}
if(start != end)
{
+ uint32_t oldStart = impl.mEventData->mLeftSelectionPosition;
+ uint32_t oldEnd = impl.mEventData->mRightSelectionPosition;
+
// Calculates the logical position from the x,y coords.
impl.RepositionSelectionHandles(0.f - scrollPosition.x, 0.f - scrollPosition.y, Controller::NoTextTap::HIGHLIGHT);
impl.mEventData->mLeftSelectionPosition = start;
impl.mEventData->mRightSelectionPosition = end;
+
+ if(impl.mSelectableControlInterface != nullptr)
+ {
+ impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, start, end);
+ }
}
}
}
matchedCharacter);
EventData& eventData = *impl.mEventData;
+ uint32_t oldStart = eventData.mLeftSelectionPosition;
+ uint32_t oldEnd = eventData.mRightSelectionPosition;
if(Event::GRAB_HANDLE_EVENT == event.type)
{
eventData.mIsLeftHandleSelected = false;
eventData.mIsRightHandleSelected = true;
}
+
+ if((impl.mSelectableControlInterface != nullptr) || eventData.mUpdateRightSelectionPosition || eventData.mUpdateLeftSelectionPosition)
+ {
+ impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+ }
}
void ControllerImplEventHandler::OnHandleReleased(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled, const bool handleStopScrolling)
}
EventData& eventData = *impl.mEventData;
+ uint32_t oldStart = eventData.mLeftSelectionPosition;
+ uint32_t oldEnd = eventData.mRightSelectionPosition;
if(Event::GRAB_HANDLE_EVENT == event.type)
{
}
}
+ if((impl.mSelectableControlInterface != nullptr) || eventData.mUpdateRightSelectionPosition || eventData.mUpdateLeftSelectionPosition)
+ {
+ impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+ }
+
eventData.mDecoratorUpdated = true;
}
position.y - scrollPosition.y,
CharacterHitTest::SCROLL,
matchedCharacter);
+ uint32_t oldStart = eventData.mLeftSelectionPosition;
+ uint32_t oldEnd = eventData.mRightSelectionPosition;
if(leftSelectionHandleEvent)
{
impl.RepositionSelectionHandles();
eventData.mScrollAfterUpdatePosition = !isSmoothHandlePanEnabled;
+
+ if(impl.mSelectableControlInterface != nullptr)
+ {
+ impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+ }
}
}
eventData.mDecoratorUpdated = true;
if(mEventData->mSelectionEnabled && (pStart || pEnd))
{
- uint32_t length = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
+ uint32_t length = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
+ uint32_t oldStart = mEventData->mLeftSelectionPosition;
+ uint32_t oldEnd = mEventData->mRightSelectionPosition;
if(pStart)
{
mEventData->mUpdateLeftSelectionPosition = true;
mEventData->mUpdateRightSelectionPosition = true;
}
+
+ if(mSelectableControlInterface != nullptr)
+ {
+ mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
+ }
}
}
// If there is no focus, only the value is updated.
if(focused)
{
+ bool wasInSelectingState = mEventData->mState == EventData::SELECTING;
+ uint32_t oldStart = mEventData->mLeftSelectionPosition;
+ uint32_t oldEnd = mEventData->mRightSelectionPosition;
ChangeState(EventData::EDITING);
mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition;
mEventData->mUpdateCursorPosition = true;
+
+ if(mSelectableControlInterface != nullptr && wasInSelectingState)
+ {
+ mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
+ }
+
ScrollTextToMatchCursor();
}
void Controller::Impl::SetSelection(int start, int end)
{
+ uint32_t oldStart = mEventData->mLeftSelectionPosition;
+ uint32_t oldEnd = mEventData->mRightSelectionPosition;
+
mEventData->mLeftSelectionPosition = start;
mEventData->mRightSelectionPosition = end;
mEventData->mUpdateCursorPosition = true;
+
+ if(mSelectableControlInterface != nullptr)
+ {
+ mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, start, end);
+ }
}
std::pair<int, int> Controller::Impl::GetSelectionIndexes() const
(EventData::EDITING_WITH_GRAB_HANDLE == eventData->mState) ||
(EventData::EDITING_WITH_PASTE_POPUP == eventData->mState))
{
+ if((impl.mSelectableControlInterface != nullptr) && (EventData::SELECTING == eventData->mState))
+ {
+ impl.mSelectableControlInterface->SelectionChanged(eventData->mLeftSelectionPosition, eventData->mRightSelectionPosition, eventData->mPrimaryCursorPosition, eventData->mPrimaryCursorPosition);
+ }
+
impl.ChangeState(EventData::EDITING);
}
}
* @return The seletced text.
*/
virtual string GetSelectedText() const = 0;
+
+ /**
+ * @brief Called when the selection has been changed.
+ *
+ * @param oldStart the selection handles start position before the change.
+ * @param oldEnd the selection handles end position before the change.
+ * @param newStart the selection handles start position after the change.
+ * @param newEnd the selection handles end position after the change.
+ */
+ virtual void SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t newStart, uint32_t newEnd) = 0;
};
} // namespace Text
if(characterHit || (Controller::NoTextTap::HIGHLIGHT == action))
{
+ uint32_t oldStart = eventData->mLeftSelectionPosition;
+ uint32_t oldEnd = eventData->mRightSelectionPosition;
+
impl.ChangeState(EventData::SELECTING);
eventData->mLeftSelectionPosition = selectionStart;
// Cursor to be positioned at end of selection so if selection interrupted and edit mode restarted the cursor will be at end of selection
eventData->mPrimaryCursorPosition = std::max(eventData->mLeftSelectionPosition, eventData->mRightSelectionPosition);
+
+ if(impl.mSelectableControlInterface != nullptr)
+ {
+ impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData->mLeftSelectionPosition, eventData->mRightSelectionPosition);
+ }
}
else if(Controller::NoTextTap::SHOW_SELECTION_POPUP == action)
{