X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fcontrols%2Ftext-controls%2Ftext-editor-impl.cpp;h=0bdc8c1d3cabd9c347f5d5d71e6b11016fbe60b8;hp=72503a522ee402324be6956caf1b8a77c7358823;hb=4946918df0bb894b946175b13529c656893c440a;hpb=19179e76939a18697e6919177a4c561586e8d30b 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 72503a5..0bdc8c1 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -20,7 +20,6 @@ // EXTERNAL INCLUDES #include -#include #include #include #include @@ -150,13 +149,18 @@ DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "grabHandleColor DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "enableGrabHandlePopup", BOOLEAN, ENABLE_GRAB_HANDLE_POPUP ) DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "inputMethodSettings", MAP, INPUT_METHOD_SETTINGS ) DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "inputFilter", MAP, INPUT_FILTER ) - -DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "textChanged", SIGNAL_TEXT_CHANGED ) -DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "inputStyleChanged", SIGNAL_INPUT_STYLE_CHANGED) -DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "maxLengthReached", SIGNAL_MAX_LENGTH_REACHED ) -DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "anchorClicked", SIGNAL_ANCHOR_CLICKED ) -DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "inputFiltered", SIGNAL_INPUT_FILTERED ) - +DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "ellipsis", BOOLEAN, ELLIPSIS ) +DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "ellipsisPosition", INTEGER, ELLIPSIS_POSITION ) +DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "minLineSize", FLOAT, MIN_LINE_SIZE ) + +DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "textChanged", SIGNAL_TEXT_CHANGED ) +DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "inputStyleChanged", SIGNAL_INPUT_STYLE_CHANGED ) +DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "maxLengthReached", SIGNAL_MAX_LENGTH_REACHED ) +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_SIGNAL_REGISTRATION(Toolkit, TextEditor, "selectionCleared", SIGNAL_SELECTION_CLEARED ) DALI_TYPE_REGISTRATION_END() // clang-format on @@ -490,13 +494,8 @@ void TextEditor::SetProperty(BaseObject* object, Property::Index index, const Pr } case Toolkit::TextEditor::Property::LINE_SPACING: { - // The line spacing isn't supported by the TextEditor. Since it's supported - // by the TextLabel for now it must be ignored. The property is being shadowed - // locally so its value isn't affected. const float lineSpacing = value.Get(); - impl.mLineSpacing = lineSpacing; - // set it to 0.0 due to missing implementation - impl.mController->SetDefaultLineSpacing(0.0f); + impl.mController->SetDefaultLineSpacing(lineSpacing); impl.mRenderer.Reset(); break; } @@ -698,7 +697,7 @@ void TextEditor::SetProperty(BaseObject* object, Property::Index index, const Pr } case Toolkit::DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION: { - impl.mController->SetMatchSystemLanguageDirection(value.Get()); + impl.mController->SetMatchLayoutDirection(value.Get() ? DevelText::MatchLayoutDirection::LOCALE : DevelText::MatchLayoutDirection::CONTENTS); break; } case Toolkit::DevelTextEditor::Property::MAX_LENGTH: @@ -765,7 +764,7 @@ void TextEditor::SetProperty(BaseObject* object, Property::Index index, const Pr { uint32_t position = static_cast(value.Get()); DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p PRIMARY_CURSOR_POSITION %d\n", impl.mController.Get(), position); - if(impl.mController->SetPrimaryCursorPosition(position)) + if(impl.mController->SetPrimaryCursorPosition(position, impl.HasKeyInputFocus())) { impl.SetKeyInputFocus(); } @@ -813,6 +812,33 @@ void TextEditor::SetProperty(BaseObject* object, Property::Index index, const Pr } break; } + case Toolkit::DevelTextEditor::Property::ELLIPSIS: + { + const bool ellipsis = value.Get(); + DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p ELLIPSIS %d\n", impl.mController.Get(), ellipsis); + + impl.mController->SetTextElideEnabled(ellipsis); + break; + } + case Toolkit::DevelTextEditor::Property::ELLIPSIS_POSITION: + { + DevelText::EllipsisPosition::Type ellipsisPositionType(static_cast(-1)); // Set to invalid value to ensure a valid mode does get set + if(GetEllipsisPositionTypeEnumeration(value, ellipsisPositionType)) + { + DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p EllipsisPosition::Type %d\n", impl.mController.Get(), ellipsisPositionType); + impl.mController->SetEllipsisPosition(ellipsisPositionType); + } + break; + } + case Toolkit::DevelTextEditor::Property::MIN_LINE_SIZE: + { + const float minLineSize = value.Get(); + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextEditor %p MIN_LINE_SIZE %f\n", impl.mController.Get(), minLineSize); + + impl.mController->SetDefaultLineSize(minLineSize); + impl.mRenderer.Reset(); + break; + } } // switch } // texteditor } @@ -992,9 +1018,7 @@ Property::Value TextEditor::GetProperty(BaseObject* object, Property::Index inde } case Toolkit::TextEditor::Property::LINE_SPACING: { - // LINE_SPACING isn't implemented for the TextEditor. Returning - // only shadowed value, not the real one. - value = impl.mLineSpacing; + value = impl.mController->GetDefaultLineSpacing(); break; } case Toolkit::TextEditor::Property::INPUT_LINE_SPACING: @@ -1119,7 +1143,7 @@ Property::Value TextEditor::GetProperty(BaseObject* object, Property::Index inde } case Toolkit::DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION: { - value = impl.mController->IsMatchSystemLanguageDirection(); + value = impl.mController->GetMatchLayoutDirection() != DevelText::MatchLayoutDirection::CONTENTS; break; } case Toolkit::DevelTextEditor::Property::MAX_LENGTH: @@ -1193,6 +1217,21 @@ Property::Value TextEditor::GetProperty(BaseObject* object, Property::Index inde value = map; break; } + case Toolkit::DevelTextEditor::Property::ELLIPSIS: + { + value = impl.mController->IsTextElideEnabled(); + break; + } + case Toolkit::DevelTextEditor::Property::ELLIPSIS_POSITION: + { + value = impl.mController->GetEllipsisPosition(); + break; + } + case Toolkit::DevelTextEditor::Property::MIN_LINE_SIZE: + { + value = impl.mController->GetDefaultLineSize(); + break; + } } //switch } @@ -1216,6 +1255,44 @@ void TextEditor::SelectNone() } } +void TextEditor::SelectText(const uint32_t start, const uint32_t end) +{ + if(mController && mController->IsShowingRealText()) + { + mController->SelectText(start, end); + SetKeyInputFocus(); + } +} + +string TextEditor::CopyText() +{ + string copiedText = ""; + if(mController && mController->IsShowingRealText()) + { + copiedText = mController->CopyText(); + } + return copiedText; +} + +string TextEditor::CutText() +{ + string cutText = ""; + if(mController && mController->IsShowingRealText()) + { + cutText = mController->CutText(); + } + return cutText; +} + +void TextEditor::PasteText() +{ + if(mController) + { + SetKeyInputFocus(); //Giving focus to the editor that was passed to the PasteText in case the passed editor (current editor) doesn't have focus. + mController->PasteText(); + } +} + void TextEditor::ScrollBy(Vector2 scroll) { if(mController && mController->IsShowingRealText()) @@ -1267,11 +1344,26 @@ DevelTextEditor::AnchorClickedSignalType& TextEditor::AnchorClickedSignal() return mAnchorClickedSignal; } +DevelTextEditor::CursorPositionChangedSignalType& TextEditor::CursorPositionChangedSignal() +{ + return mCursorPositionChangedSignal; +} + DevelTextEditor::InputFilteredSignalType& TextEditor::InputFilteredSignal() { return mInputFilteredSignal; } +DevelTextEditor::SelectionChangedSignalType& TextEditor::SelectionChangedSignal() +{ + return mSelectionChangedSignal; +} + +DevelTextEditor::SelectionClearedSignalType& TextEditor::SelectionClearedSignal() +{ + return mSelectionClearedSignal; +} + Text::ControllerPtr TextEditor::GetTextController() { return mController; @@ -1308,6 +1400,14 @@ bool TextEditor::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* editorImpl.AnchorClickedSignal().Connect(tracker, functor); } } + else if(0 == strcmp(signalName.c_str(), SIGNAL_CURSOR_POSITION_CHANGED)) + { + if(editor) + { + Internal::TextEditor& editorImpl(GetImpl(editor)); + editorImpl.CursorPositionChangedSignal().Connect(tracker, functor); + } + } else if(0 == strcmp(signalName.c_str(), SIGNAL_INPUT_FILTERED)) { if(editor) @@ -1316,6 +1416,22 @@ bool TextEditor::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* 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 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 @@ -1376,9 +1492,12 @@ void TextEditor::OnInitialize() Dali::LayoutDirection::Type layoutDirection = static_cast(stage.GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get()); mController->SetLayoutDirection(layoutDirection); + self.LayoutDirectionChangedSignal().Connect(this, &TextEditor::OnLayoutDirectionChanged); + // Forward input events to controller EnableGestureDetection(static_cast(GestureType::TAP | GestureType::PAN | GestureType::LONG_PRESS)); GetTapGestureDetector().SetMaximumTapsRequired(2); + GetTapGestureDetector().ReceiveAllTapEvents(true); self.TouchedSignal().Connect(this, &TextEditor::OnTouched); @@ -1501,15 +1620,8 @@ void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container) Vector2 contentSize(size.x - (padding.start + padding.end), size.y - (padding.top + padding.bottom)); // Support Right-To-Left of padding - Dali::LayoutDirection::Type layoutDirection; - if(mController->IsMatchSystemLanguageDirection()) - { - layoutDirection = static_cast(DevelWindow::Get(self).GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get()); - } - else - { - layoutDirection = static_cast(self.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get()); - } + Dali::LayoutDirection::Type layoutDirection = mController->GetLayoutDirection(self); + if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection) { std::swap(padding.start, padding.end); @@ -1553,6 +1665,21 @@ void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container) RenderText(updateTextType); } + if(mCursorPositionChanged) + { + EmitCursorPositionChangedSignal(); + } + + if(mSelectionChanged) + { + 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. @@ -1813,11 +1940,17 @@ void TextEditor::TextDeleted(unsigned int position, unsigned int length, const s } } -void TextEditor::CursorMoved(unsigned int position) +void TextEditor::CursorPositionChanged(unsigned int oldPosition, unsigned int newPosition) { if(Accessibility::IsUp()) { - Control::Impl::GetAccessibilityObject(Self())->EmitTextCursorMoved(position); + Control::Impl::GetAccessibilityObject(Self())->EmitTextCursorMoved(newPosition); + } + + if((oldPosition != newPosition) && !mCursorPositionChanged) + { + mCursorPositionChanged = true; + mOldPosition = oldPosition; } } @@ -1906,12 +2039,56 @@ void TextEditor::AnchorClicked(const std::string& href) mAnchorClickedSignal.Emit(handle, href.c_str(), href.length()); } +void TextEditor::EmitCursorPositionChangedSignal() +{ + Dali::Toolkit::TextEditor handle(GetOwner()); + mCursorPositionChanged = false; + mCursorPositionChangedSignal.Emit(handle, mOldPosition); +} + void TextEditor::InputFiltered(Toolkit::InputFilter::Property::Type type) { Dali::Toolkit::TextEditor handle(GetOwner()); mInputFilteredSignal.Emit(handle, type); } +void TextEditor::EmitSelectionChangedSignal() +{ + Dali::Toolkit::TextEditor handle(GetOwner()); + mSelectionChangedSignal.Emit(handle, mOldSelectionStart, mOldSelectionEnd); + 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; + + if(mOldSelectionStart > mOldSelectionEnd) + { + //swap + uint32_t temp = mOldSelectionStart; + mOldSelectionStart = mOldSelectionEnd; + mOldSelectionEnd = temp; + } + } +} + void TextEditor::AddDecoration(Actor& actor, bool needsClipping) { if(actor) @@ -2172,6 +2349,11 @@ void TextEditor::SetEditable(bool editable) } } +void TextEditor::OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type) +{ + mController->ChangedLayoutDirection(); +} + TextEditor::TextEditor() : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)), mAnimationPeriod(0.0f, 0.0f), @@ -2184,7 +2366,13 @@ TextEditor::TextEditor() mScrollAnimationEnabled(false), mScrollBarEnabled(false), mScrollStarted(false), - mTextChanged(false) + mTextChanged(false), + mCursorPositionChanged(false), + mSelectionChanged(false), + mSelectionCleared(false), + mOldPosition(0u), + mOldSelectionStart(0u), + mOldSelectionEnd(0u) { } @@ -2253,10 +2441,10 @@ bool TextEditor::AccessibleImpl::SetCursorOffset(size_t offset) return true; } -Dali::Accessibility::Range TextEditor::AccessibleImpl::GetTextAtOffset( size_t offset, Dali::Accessibility::TextBoundary boundary) +Dali::Accessibility::Range TextEditor::AccessibleImpl::GetTextAtOffset(size_t offset, Dali::Accessibility::TextBoundary boundary) { - auto self = Toolkit::TextEditor::DownCast(Self()); - auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get(); + auto self = Toolkit::TextEditor::DownCast(Self()); + auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get(); auto textSize = text.size(); auto range = Dali::Accessibility::Range{}; @@ -2277,7 +2465,7 @@ Dali::Accessibility::Range TextEditor::AccessibleImpl::GetTextAtOffset( size_t o case Dali::Accessibility::TextBoundary::LINE: { auto textString = text.c_str(); - auto breaks = std::vector(textSize, 0); + auto breaks = std::vector(textSize, 0); if(boundary == Dali::Accessibility::TextBoundary::WORD) { @@ -2352,8 +2540,8 @@ Dali::Accessibility::Range TextEditor::AccessibleImpl::GetRangeOfSelection(size_ return {}; } - auto self = Toolkit::TextEditor::DownCast(Self()); - auto controller = Dali::Toolkit::GetImpl(self).GetTextController(); + auto self = Toolkit::TextEditor::DownCast(Self()); + auto controller = Dali::Toolkit::GetImpl(self).GetTextController(); std::string value{}; controller->RetrieveSelection(value); auto indices = controller->GetSelectionIndexes(); @@ -2436,7 +2624,7 @@ Dali::Accessibility::States TextEditor::AccessibleImpl::CalculateStates() { using namespace Dali::Accessibility; - auto states = DevelControl::AccessibleImpl::CalculateStates(); + auto states = DevelControl::AccessibleImpl::CalculateStates(); states[State::EDITABLE] = true; states[State::FOCUSABLE] = true; @@ -2451,7 +2639,7 @@ Dali::Accessibility::States TextEditor::AccessibleImpl::CalculateStates() bool TextEditor::AccessibleImpl::InsertText(size_t startPosition, std::string text) { - auto self = Toolkit::TextEditor::DownCast(Self()); + auto self = Toolkit::TextEditor::DownCast(Self()); auto insertedText = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get(); insertedText.insert(startPosition, text);