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=4e6fc1f1f7b5ec09f2e91a9ddfd210cc202520d4;hp=02594712039ddedb370e7bfb3810171f5eeda9cb;hb=0512ac82e2c23d8eada7840b5a72cdabe13a5f54;hpb=e8a0d6cffda02a66a542fe89240fb41bc7c08215 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 0259471..4e6fc1f 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,6 @@ // INTERNAL INCLUDES #include -#include #include #include #include @@ -146,6 +145,7 @@ DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "verticalScrollP DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "enableEditing", BOOLEAN, ENABLE_EDITING ) DALI_DEVEL_PROPERTY_REGISTRATION_READ_ONLY(Toolkit, TextEditor, "selectedText", STRING, SELECTED_TEXT ) DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "fontSizeScale", FLOAT, FONT_SIZE_SCALE ) +DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "enableFontSizeScale", BOOLEAN, ENABLE_FONT_SIZE_SCALE ) DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "primaryCursorPosition", INTEGER, PRIMARY_CURSOR_POSITION ) DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "grabHandleColor", VECTOR4, GRAB_HANDLE_COLOR ) DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "enableGrabHandlePopup", BOOLEAN, ENABLE_GRAB_HANDLE_POPUP ) @@ -154,6 +154,10 @@ DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "inputFilter", 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_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "strikethrough", MAP, STRIKETHROUGH ) +DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "inputStrikethrough", MAP, INPUT_STRIKETHROUGH ) +DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "characterSpacing", FLOAT, CHARACTER_SPACING ) +DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "relativeLineSize", FLOAT, RELATIVE_LINE_SIZE ) DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "textChanged", SIGNAL_TEXT_CHANGED ) DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "inputStyleChanged", SIGNAL_INPUT_STYLE_CHANGED ) @@ -163,6 +167,7 @@ DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "inputFiltered", SIGNAL_IN 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_SIGNAL_REGISTRATION(Toolkit, TextEditor, "selectionStarted", SIGNAL_SELECTION_STARTED ) DALI_TYPE_REGISTRATION_END() // clang-format on @@ -215,6 +220,11 @@ Toolkit::TextEditor::InputStyle::Mask ConvertInputStyle(Text::InputStyle::Mask i { editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::OUTLINE); } + if(InputStyle::NONE != static_cast(inputStyleMask & InputStyle::INPUT_STRIKETHROUGH)) + { + editorInputStyleMask = static_cast(editorInputStyleMask | Toolkit::TextEditor::InputStyle::STRIKETHROUGH); + } + return editorInputStyleMask; } @@ -341,6 +351,16 @@ float TextEditor::GetVerticalScrollPosition() return 0; } +Vector TextEditor::GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const +{ + return mController->GetTextSize(startIndex, endIndex); +} + +Vector TextEditor::GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const +{ + return mController->GetTextPosition(startIndex, endIndex); +} + string TextEditor::GetSelectedText() const { string selectedText = ""; @@ -386,6 +406,11 @@ DevelTextEditor::SelectionClearedSignalType& TextEditor::SelectionClearedSignal( return mSelectionClearedSignal; } +DevelTextEditor::SelectionStartedSignalType& TextEditor::SelectionStartedSignal() +{ + return mSelectionStartedSignal; +} + Text::ControllerPtr TextEditor::GetTextController() { return mController; @@ -454,6 +479,14 @@ bool TextEditor::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* editorImpl.SelectionClearedSignal().Connect(tracker, functor); } } + else if(0 == strcmp(signalName.c_str(), SIGNAL_SELECTION_STARTED)) + { + if(editor) + { + Internal::TextEditor& editorImpl(GetImpl(editor)); + editorImpl.SelectionStartedSignal().Connect(tracker, functor); + } + } else { // signalName does not match any signal @@ -478,6 +511,11 @@ Toolkit::TextEditor::ScrollStateChangedSignalType& TextEditor::ScrollStateChange return mScrollStateChangedSignal; } +void TextEditor::OnAccessibilityStatusChanged() +{ + CommonTextUtils::SynchronizeTextAnchorsInParent(Self(), mController, mAnchorActors); +} + void TextEditor::OnInitialize() { Actor self = Self(); @@ -565,9 +603,11 @@ void TextEditor::OnInitialize() self.Add(mStencil); DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) { - return std::unique_ptr( - new AccessibleImpl(actor, Dali::Accessibility::Role::ENTRY)); + return std::make_unique(actor, Dali::Accessibility::Role::ENTRY); }); + + Accessibility::Bridge::EnabledSignal().Connect(this, &TextEditor::OnAccessibilityStatusChanged); + Accessibility::Bridge::DisabledSignal().Connect(this, &TextEditor::OnAccessibilityStatusChanged); } void TextEditor::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change) @@ -659,6 +699,11 @@ void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container) mActiveLayer.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top)); ResizeActor(mActiveLayer, contentSize); } + if(mCursorLayer) + { + mCursorLayer.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top)); + ResizeActor(mCursorLayer, contentSize); + } // If there is text changed, callback is called. if(mTextChanged) @@ -692,6 +737,11 @@ void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container) EmitCursorPositionChangedSignal(); } + if(mSelectionStarted) + { + EmitSelectionStartedSignal(); + } + if(mSelectionChanged) { EmitSelectionChangedSignal(); @@ -724,7 +774,7 @@ void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container) void TextEditor::RenderText(Text::Controller::UpdateTextType updateTextType) { - CommonTextUtils::RenderText(Self(), mRenderer, mController, mDecorator, mAlignmentOffset, mRenderableActor, mBackgroundActor, mStencil, mClippingDecorationActors, updateTextType); + CommonTextUtils::RenderText(Self(), mRenderer, mController, mDecorator, mAlignmentOffset, mRenderableActor, mBackgroundActor, mStencil, mClippingDecorationActors, mAnchorActors, updateTextType); if(mRenderableActor) { ApplyScrollPosition(); @@ -857,26 +907,17 @@ void TextEditor::RequestTextRelayout() void TextEditor::TextInserted(unsigned int position, unsigned int length, const std::string& content) { - if(Accessibility::IsUp()) - { - Control::Impl::GetAccessibilityObject(Self())->EmitTextInserted(position, length, content); - } + GetAccessibleObject()->EmitTextInserted(position, length, content); } void TextEditor::TextDeleted(unsigned int position, unsigned int length, const std::string& content) { - if(Accessibility::IsUp()) - { - Control::Impl::GetAccessibilityObject(Self())->EmitTextDeleted(position, length, content); - } + GetAccessibleObject()->EmitTextDeleted(position, length, content); } void TextEditor::CursorPositionChanged(unsigned int oldPosition, unsigned int newPosition) { - if(Accessibility::IsUp()) - { - Control::Impl::GetAccessibilityObject(Self())->EmitTextCursorMoved(newPosition); - } + GetAccessibleObject()->EmitTextCursorMoved(newPosition); if((oldPosition != newPosition) && !mCursorPositionChanged) { @@ -949,6 +990,13 @@ void TextEditor::EmitSelectionClearedSignal() mSelectionCleared = false; } +void TextEditor::EmitSelectionStartedSignal() +{ + Dali::Toolkit::TextEditor handle(GetOwner()); + mSelectionStartedSignal.Emit(handle); + mSelectionStarted = false; +} + void TextEditor::SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t newStart, uint32_t newEnd) { if(((oldStart != newStart) || (oldEnd != newEnd)) && !mSelectionChanged) @@ -957,6 +1005,13 @@ void TextEditor::SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t n { mSelectionCleared = true; } + else + { + if(oldStart == oldEnd) + { + mSelectionStarted = true; + } + } mSelectionChanged = true; mOldSelectionStart = oldStart; @@ -972,7 +1027,7 @@ void TextEditor::SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t n } } -void TextEditor::AddDecoration(Actor& actor, bool needsClipping) +void TextEditor::AddDecoration(Actor& actor, DecorationType type, bool needsClipping) { if(actor) { @@ -980,16 +1035,27 @@ void TextEditor::AddDecoration(Actor& actor, bool needsClipping) { mClippingDecorationActors.push_back(actor); } - else + + // If the actor is a layer type, add it. + if(type == DecorationType::ACTIVE_LAYER) + { + AddLayer(mActiveLayer, actor); + } + else if(type == DecorationType::CURSOR_LAYER) { - actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); - actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); - Self().Add(actor); - mActiveLayer = actor; + AddLayer(mCursorLayer, actor); } } } +void TextEditor::AddLayer(Actor& layer, Actor& actor) +{ + actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + Self().Add(actor); + layer = actor; +} + void TextEditor::SetTextSelectionRange(const uint32_t* start, const uint32_t* end) { if(mController && mController->IsShowingRealText()) @@ -1256,7 +1322,8 @@ TextEditor::TextEditor() mSelectionCleared(false), mOldPosition(0u), mOldSelectionStart(0u), - mOldSelectionEnd(0u) + mOldSelectionEnd(0u), + mSelectionStarted(false) { } @@ -1271,273 +1338,31 @@ TextEditor::~TextEditor() } } -std::string TextEditor::AccessibleImpl::GetName() +std::string TextEditor::TextEditorAccessible::GetName() const { - auto self = Toolkit::TextEditor::DownCast(Self()); - return self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get(); + return GetWholeText(); } -std::string TextEditor::AccessibleImpl::GetText(size_t startOffset, size_t endOffset) +const std::vector& TextEditor::TextEditorAccessible::GetTextAnchors() const { - if(endOffset <= startOffset) - { - return {}; - } - auto self = Toolkit::TextEditor::DownCast(Self()); - auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get(); - if(startOffset > text.size() || endOffset > text.size()) - { - return {}; - } - - return text.substr(startOffset, endOffset - startOffset); + return Toolkit::GetImpl(self).mAnchorActors; } -size_t TextEditor::AccessibleImpl::GetCharacterCount() +Toolkit::Text::ControllerPtr TextEditor::TextEditorAccessible::GetTextController() const { auto self = Toolkit::TextEditor::DownCast(Self()); - auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get(); - - return text.size(); -} - -size_t TextEditor::AccessibleImpl::GetCursorOffset() -{ - auto slf = Toolkit::TextEditor::DownCast(Self()); - return Dali::Toolkit::GetImpl(slf).GetTextController()->GetCursorPosition(); -} - -bool TextEditor::AccessibleImpl::SetCursorOffset(size_t offset) -{ - auto slf = Toolkit::TextEditor::DownCast(Self()); - auto txt = slf.GetProperty(Toolkit::TextEditor::Property::TEXT).Get(); - if(offset > txt.size()) - { - return false; - } - - auto& slfImpl = Dali::Toolkit::GetImpl(slf); - slfImpl.GetTextController()->ResetCursorPosition(offset); - slfImpl.RequestTextRelayout(); - return true; + return Toolkit::GetImpl(self).GetTextController(); } -Dali::Accessibility::Range TextEditor::AccessibleImpl::GetTextAtOffset(size_t offset, Dali::Accessibility::TextBoundary boundary) +void TextEditor::TextEditorAccessible::RequestTextRelayout() { - auto self = Toolkit::TextEditor::DownCast(Self()); - auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get(); - auto textSize = text.size(); - - auto range = Dali::Accessibility::Range{}; + auto self = Toolkit::TextEditor::DownCast(Self()); + auto& selfImpl = Toolkit::GetImpl(self); - switch(boundary) - { - case Dali::Accessibility::TextBoundary::CHARACTER: - { - if(offset < textSize) - { - range.content = text[offset]; - range.startOffset = offset; - range.endOffset = offset + 1; - } - break; - } - case Dali::Accessibility::TextBoundary::WORD: - case Dali::Accessibility::TextBoundary::LINE: - { - auto textString = text.c_str(); - auto breaks = std::vector(textSize, 0); - - if(boundary == Dali::Accessibility::TextBoundary::WORD) - { - Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast(textString), textSize, "", breaks.data()); - } - else - { - Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast(textString), textSize, "", breaks.data()); - } - - auto index = 0u; - auto counter = 0u; - while(index < textSize && counter <= offset) - { - auto start = index; - if(breaks[index]) - { - while(breaks[index]) - { - index++; - } - counter++; - } - else - { - if(boundary == Dali::Accessibility::TextBoundary::WORD) - { - index++; - } - if(boundary == Dali::Accessibility::TextBoundary::LINE) - { - counter++; - } - } - - if((counter > 0) && ((counter - 1) == offset)) - { - range.content = text.substr(start, index - start + 1); - range.startOffset = start; - range.endOffset = index + 1; - } - - if(boundary == Dali::Accessibility::TextBoundary::LINE) - { - index++; - } - } - break; - } - case Dali::Accessibility::TextBoundary::SENTENCE: - { - /* not supported by default */ - break; - } - case Dali::Accessibility::TextBoundary::PARAGRAPH: - { - /* Paragraph is not supported by libunibreak library */ - break; - } - default: - break; - } - - return range; -} - -Dali::Accessibility::Range TextEditor::AccessibleImpl::GetRangeOfSelection(size_t selectionIndex) -{ - // Since DALi supports only one selection indexes higher than 0 are ignored - if(selectionIndex > 0) - { - return {}; - } - - auto self = Toolkit::TextEditor::DownCast(Self()); - auto controller = Dali::Toolkit::GetImpl(self).GetTextController(); - std::string value{}; - controller->RetrieveSelection(value); - auto indices = controller->GetSelectionIndexes(); - - return {static_cast(indices.first), static_cast(indices.second), value}; -} - -bool TextEditor::AccessibleImpl::RemoveSelection(size_t selectionIndex) -{ - // Since DALi supports only one selection indexes higher than 0 are ignored - if(selectionIndex > 0) - { - return false; - } - - auto self = Toolkit::TextEditor::DownCast(Self()); - Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(0, 0); - return true; -} - -bool TextEditor::AccessibleImpl::SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset) -{ - // Since DALi supports only one selection indexes higher than 0 are ignored - if(selectionIndex > 0) - { - return false; - } - - auto self = Toolkit::TextEditor::DownCast(Self()); - Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(startOffset, endOffset); - return true; -} - -bool TextEditor::AccessibleImpl::CopyText(size_t startPosition, size_t endPosition) -{ - if(endPosition <= startPosition) - { - return false; - } - - auto self = Toolkit::TextEditor::DownCast(Self()); - auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get(); - Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition)); - - return true; -} - -bool TextEditor::AccessibleImpl::CutText(size_t startPosition, size_t endPosition) -{ - if(endPosition <= startPosition) - { - return false; - } - - auto self = Toolkit::TextEditor::DownCast(Self()); - auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get(); - Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition)); - - self.SetProperty(Toolkit::TextEditor::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition)); - - return true; -} - -bool TextEditor::AccessibleImpl::DeleteText(size_t startPosition, size_t endPosition) -{ - if(endPosition <= startPosition) - { - return false; - } - - auto self = Toolkit::TextEditor::DownCast(Self()); - auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get(); - - self.SetProperty(Toolkit::TextEditor::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition)); - - return true; -} - -Dali::Accessibility::States TextEditor::AccessibleImpl::CalculateStates() -{ - using namespace Dali::Accessibility; - - auto states = DevelControl::AccessibleImpl::CalculateStates(); - states[State::EDITABLE] = true; - states[State::FOCUSABLE] = true; - - Toolkit::Control focusControl = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl(); - if(mSelf == focusControl) - { - states[State::FOCUSED] = true; - } - - return states; -} - -bool TextEditor::AccessibleImpl::InsertText(size_t startPosition, std::string text) -{ - auto self = Toolkit::TextEditor::DownCast(Self()); - auto insertedText = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get(); - - insertedText.insert(startPosition, text); - - self.SetProperty(Toolkit::TextEditor::Property::TEXT, std::move(insertedText)); - - return true; -} - -bool TextEditor::AccessibleImpl::SetTextContents(std::string newContents) -{ - auto self = Toolkit::TextEditor::DownCast(Self()); - self.SetProperty(Toolkit::TextEditor::Property::TEXT, std::move(newContents)); - return true; + selfImpl.RequestTextRelayout(); } } // namespace Internal