From 7c13cc0c065ae22e7ad0deaea4f56730ff050c5c Mon Sep 17 00:00:00 2001 From: Adeel Kazmi Date: Wed, 24 Nov 2021 13:23:03 +0000 Subject: [PATCH] Removed some redundant methods from TextController & Moved some code to other files Change-Id: Ib57da54aa520a15f346e24be93e35a18caa0315b --- dali-toolkit/internal/file.list | 1 + .../text/text-controller-background-actor.cpp | 229 +++++++++++++++ .../text/text-controller-background-actor.h | 41 +++ .../text/text-controller-event-handler.cpp | 49 ++-- .../internal/text/text-controller-event-handler.h | 63 +++++ .../internal/text/text-controller-impl.cpp | 313 ++++++++------------- dali-toolkit/internal/text/text-controller-impl.h | 35 ++- .../text/text-controller-placeholder-handler.cpp | 8 +- .../text/text-controller-placeholder-handler.h | 2 +- .../internal/text/text-controller-relayouter.cpp | 29 +- .../internal/text/text-controller-relayouter.h | 5 +- .../internal/text/text-controller-text-updater.cpp | 5 +- .../internal/text/text-controller-text-updater.h | 58 +++- dali-toolkit/internal/text/text-controller.cpp | 206 +------------- dali-toolkit/internal/text/text-controller.h | 129 --------- 15 files changed, 587 insertions(+), 586 deletions(-) create mode 100644 dali-toolkit/internal/text/text-controller-background-actor.cpp create mode 100644 dali-toolkit/internal/text/text-controller-background-actor.h diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index b9c7d23..8438261 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -158,6 +158,7 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/hyphenator.cpp ${toolkit_src_dir}/text/text-enumerations-impl.cpp ${toolkit_src_dir}/text/text-controller.cpp + ${toolkit_src_dir}/text/text-controller-background-actor.cpp ${toolkit_src_dir}/text/text-controller-event-handler.cpp ${toolkit_src_dir}/text/text-controller-impl.cpp ${toolkit_src_dir}/text/text-controller-impl-data-clearer.cpp diff --git a/dali-toolkit/internal/text/text-controller-background-actor.cpp b/dali-toolkit/internal/text/text-controller-background-actor.cpp new file mode 100644 index 0000000..dda514f --- /dev/null +++ b/dali-toolkit/internal/text/text-controller-background-actor.cpp @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// HEADER +#include + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali::Toolkit::Text +{ + +namespace +{ +struct BackgroundVertex +{ + Vector2 mPosition; ///< Vertex posiiton + Vector4 mColor; ///< Vertex color +}; + +struct BackgroundMesh +{ + Vector mVertices; ///< container of vertices + Vector mIndices; ///< container of indices +}; +} // unnamed namespace + +Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr& textVisualModel, Shader& textShaderBackground) +{ + // NOTE: Currently we only support background color for left-to-right text. + + Actor actor; + + Length numberOfGlyphs = textView.GetNumberOfGlyphs(); + if(numberOfGlyphs > 0u) + { + Vector glyphs; + glyphs.Resize(numberOfGlyphs); + + Vector positions; + positions.Resize(numberOfGlyphs); + + // Get the line where the glyphs are laid-out. + const LineRun* lineRun = textVisualModel->mLines.Begin(); + float alignmentOffset = lineRun->alignmentOffset; + numberOfGlyphs = textView.GetGlyphs(glyphs.Begin(), + positions.Begin(), + alignmentOffset, + 0u, + numberOfGlyphs); + + glyphs.Resize(numberOfGlyphs); + positions.Resize(numberOfGlyphs); + + const GlyphInfo* const glyphsBuffer = glyphs.Begin(); + const Vector2* const positionsBuffer = positions.Begin(); + + BackgroundMesh mesh; + mesh.mVertices.Reserve(4u * glyphs.Size()); + mesh.mIndices.Reserve(6u * glyphs.Size()); + + const Vector2 textSize = textView.GetLayoutSize(); + + const float offsetX = alignmentOffset + textSize.width * 0.5f; + const float offsetY = textSize.height * 0.5f; + + const Vector4* const backgroundColorsBuffer = textView.GetBackgroundColors(); + const ColorIndex* const backgroundColorIndicesBuffer = textView.GetBackgroundColorIndices(); + const Vector4& defaultBackgroundColor = textVisualModel->IsBackgroundEnabled() ? textVisualModel->GetBackgroundColor() : Color::TRANSPARENT; + + Vector4 quad; + uint32_t numberOfQuads = 0u; + Length yLineOffset = 0; + Length prevLineIndex = 0; + LineIndex lineIndex; + Length numberOfLines; + + for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i) + { + const GlyphInfo& glyph = *(glyphsBuffer + i); + + // Get the background color of the character. + // The color index zero is reserved for the default background color (i.e. Color::TRANSPARENT) + const bool isMarkupBackground = textView.IsMarkupBackgroundColorSet(); + const ColorIndex backgroundColorIndex = isMarkupBackground ? *(backgroundColorIndicesBuffer + i) : 0u; + const bool isDefaultBackgroundColor = (0u == backgroundColorIndex); + const Vector4& backgroundColor = isDefaultBackgroundColor ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u); + + textVisualModel->GetNumberOfLines(i, 1, lineIndex, numberOfLines); + Length lineHeight = lineRun[lineIndex].ascender + -(lineRun[lineIndex].descender) + lineRun[lineIndex].lineSpacing; + + if(lineIndex != prevLineIndex) + { + yLineOffset += lineHeight; + } + + // Only create quads for glyphs with a background color + if(backgroundColor != Color::TRANSPARENT) + { + const Vector2 position = *(positionsBuffer + i); + + if(i == 0u && glyphSize == 1u) // Only one glyph in the whole text + { + quad.x = position.x; + quad.y = yLineOffset; + quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width); + quad.w = lineHeight; + } + else if((lineIndex != prevLineIndex) || (i == 0u)) // The first glyph in the line + { + quad.x = position.x; + quad.y = yLineOffset; + quad.z = quad.x - glyph.xBearing + glyph.advance; + quad.w = quad.y + lineHeight; + } + else if(i == glyphSize - 1u) // The last glyph in the whole text + { + quad.x = position.x - glyph.xBearing; + quad.y = yLineOffset; + quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width); + quad.w = quad.y + lineHeight; + } + else // The glyph in the middle of the text + { + quad.x = position.x - glyph.xBearing; + quad.y = yLineOffset; + quad.z = quad.x + glyph.advance; + quad.w = quad.y + lineHeight; + } + + BackgroundVertex vertex; + + // Top left + vertex.mPosition.x = quad.x - offsetX; + vertex.mPosition.y = quad.y - offsetY; + vertex.mColor = backgroundColor; + mesh.mVertices.PushBack(vertex); + + // Top right + vertex.mPosition.x = quad.z - offsetX; + vertex.mPosition.y = quad.y - offsetY; + vertex.mColor = backgroundColor; + mesh.mVertices.PushBack(vertex); + + // Bottom left + vertex.mPosition.x = quad.x - offsetX; + vertex.mPosition.y = quad.w - offsetY; + vertex.mColor = backgroundColor; + mesh.mVertices.PushBack(vertex); + + // Bottom right + vertex.mPosition.x = quad.z - offsetX; + vertex.mPosition.y = quad.w - offsetY; + vertex.mColor = backgroundColor; + mesh.mVertices.PushBack(vertex); + + // Six indices in counter clockwise winding + mesh.mIndices.PushBack(1u + 4 * numberOfQuads); + mesh.mIndices.PushBack(0u + 4 * numberOfQuads); + mesh.mIndices.PushBack(2u + 4 * numberOfQuads); + mesh.mIndices.PushBack(2u + 4 * numberOfQuads); + mesh.mIndices.PushBack(3u + 4 * numberOfQuads); + mesh.mIndices.PushBack(1u + 4 * numberOfQuads); + + numberOfQuads++; + } + + if(lineIndex != prevLineIndex) + { + prevLineIndex = lineIndex; + } + } + + // Only create the background actor if there are glyphs with background color + if(mesh.mVertices.Count() > 0u) + { + Property::Map quadVertexFormat; + quadVertexFormat["aPosition"] = Property::VECTOR2; + quadVertexFormat["aColor"] = Property::VECTOR4; + + VertexBuffer quadVertices = VertexBuffer::New(quadVertexFormat); + quadVertices.SetData(&mesh.mVertices[0], mesh.mVertices.Size()); + + Geometry quadGeometry = Geometry::New(); + quadGeometry.AddVertexBuffer(quadVertices); + quadGeometry.SetIndexBuffer(&mesh.mIndices[0], mesh.mIndices.Size()); + + if(!textShaderBackground) + { + textShaderBackground = Shader::New(SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_VERT, SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_FRAG); + } + + Dali::Renderer renderer = Dali::Renderer::New(quadGeometry, textShaderBackground); + renderer.SetProperty(Dali::Renderer::Property::BLEND_MODE, BlendMode::ON); + renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT); + + actor = Actor::New(); + actor.SetProperty(Dali::Actor::Property::NAME, "TextBackgroundColorActor"); + actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + actor.SetProperty(Actor::Property::SIZE, textSize); + actor.SetProperty(Actor::Property::COLOR_MODE, USE_OWN_MULTIPLY_PARENT_COLOR); + actor.AddRenderer(renderer); + } + } + + return actor; +} + +} // namespace Dali::Toolkit::Text diff --git a/dali-toolkit/internal/text/text-controller-background-actor.h b/dali-toolkit/internal/text/text-controller-background-actor.h new file mode 100644 index 0000000..5ad9084 --- /dev/null +++ b/dali-toolkit/internal/text/text-controller-background-actor.h @@ -0,0 +1,41 @@ +#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_BACKGROUND_ACTOR_H +#define DALI_TOOLKIT_TEXT_CONTROLLER_BACKGROUND_ACTOR_H + +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali::Toolkit::Text +{ +class View; + +/** + * @brief Create an actor that renders the text background color + * + * @return the created actor or an empty handle if no background color needs to be rendered. + */ +Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr& textVisualModel, Shader& textShaderBackground); + +} // namespace Dali::Toolkit::Text + +#endif // DALI_TOOLKIT_TEXT_CONTROLLER_BACKGROUND_ACTOR_H diff --git a/dali-toolkit/internal/text/text-controller-event-handler.cpp b/dali-toolkit/internal/text/text-controller-event-handler.cpp index 5d78405..7494cb6 100644 --- a/dali-toolkit/internal/text/text-controller-event-handler.cpp +++ b/dali-toolkit/internal/text/text-controller-event-handler.cpp @@ -26,6 +26,8 @@ // INTERNAL INCLUDES #include #include +#include +#include #include namespace @@ -66,7 +68,7 @@ void Controller::EventHandler::KeyboardFocusGainEvent(Controller& controller) if(controller.mImpl->IsShowingPlaceholderText()) { // Show alternative placeholder-text when editing - controller.ShowPlaceholderText(); + PlaceholderHandler::ShowPlaceholderText(*controller.mImpl); } controller.mImpl->RequestRelayout(); @@ -102,7 +104,7 @@ void Controller::EventHandler::KeyboardFocusLostEvent(Controller& controller) if(!controller.mImpl->IsShowingRealText()) { // Revert to regular placeholder-text when not editing - controller.ShowPlaceholderText(); + PlaceholderHandler::ShowPlaceholderText(*controller.mImpl); } } } @@ -237,7 +239,7 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE else if((Dali::DALI_KEY_BACKSPACE == keyCode) || (Dali::DevelKey::DALI_KEY_DELETE == keyCode)) { - textChanged = controller.DeleteEvent(keyCode); + textChanged = DeleteEvent(controller, keyCode); // Will request for relayout. relayoutNeeded = true; @@ -302,7 +304,7 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE // InputMethodContext is no longer handling key-events controller.mImpl->ClearPreEditFlag(); - controller.InsertText(refinedKey, COMMIT); + TextUpdater::InsertText(controller, refinedKey, COMMIT); textChanged = true; @@ -419,7 +421,7 @@ void Controller::EventHandler::TapEvent(Controller& controller, unsigned int tap if(controller.mImpl->IsShowingPlaceholderText() && !controller.mImpl->IsFocusedPlaceholderAvailable()) { // Hide placeholder text - controller.ResetText(); + TextUpdater::ResetText(controller); } if(EventData::INACTIVE == state) @@ -598,18 +600,18 @@ void Controller::EventHandler::ProcessModifyEvents(Controller& controller) // A (single) replace event should come first, otherwise we wasted time processing NOOP events DALI_ASSERT_DEBUG(it == events.Begin() && "Unexpected TEXT_REPLACED event"); - controller.TextReplacedEvent(); + TextReplacedEvent(controller); } else if(ModifyEvent::TEXT_INSERTED == event.type) { - controller.TextInsertedEvent(); + TextInsertedEvent(controller); } else if(ModifyEvent::TEXT_DELETED == event.type) { // Placeholder-text cannot be deleted if(!controller.mImpl->IsShowingPlaceholderText()) { - controller.TextDeletedEvent(); + TextDeletedEvent(controller); } } } @@ -711,22 +713,18 @@ bool Controller::EventHandler::DeleteEvent(Controller& controller, int keyCode) if(EventData::SELECTING == controller.mImpl->mEventData->mState) { - removed = controller.RemoveSelectedText(); + removed = TextUpdater::RemoveSelectedText(controller); } else if((controller.mImpl->mEventData->mPrimaryCursorPosition > 0) && (keyCode == Dali::DALI_KEY_BACKSPACE)) { // Remove the character before the current cursor position - removed = controller.RemoveText(-1, - 1, - UPDATE_INPUT_STYLE); + removed = TextUpdater::RemoveText(controller, -1, 1, UPDATE_INPUT_STYLE); } else if((controller.mImpl->mEventData->mPrimaryCursorPosition < controller.mImpl->mModel->mLogicalModel->mText.Count()) && (keyCode == Dali::DevelKey::DALI_KEY_DELETE)) { // Remove the character after the current cursor position - removed = controller.RemoveText(0, - 1, - UPDATE_INPUT_STYLE); + removed = TextUpdater::RemoveText(controller, 0, 1, UPDATE_INPUT_STYLE); } if(removed) @@ -738,7 +736,7 @@ bool Controller::EventHandler::DeleteEvent(Controller& controller, int keyCode) } else { - controller.ShowPlaceholderText(); + PlaceholderHandler::ShowPlaceholderText(*controller.mImpl); } controller.mImpl->mEventData->mUpdateCursorPosition = true; controller.mImpl->mEventData->mScrollAfterDelete = true; @@ -760,23 +758,24 @@ InputMethodContext::CallbackData Controller::EventHandler::OnInputMethodContextE { case InputMethodContext::COMMIT: { - controller.InsertText(inputMethodContextEvent.predictiveString, Text::Controller::COMMIT); + TextUpdater::InsertText(controller, inputMethodContextEvent.predictiveString, Text::Controller::COMMIT); requestRelayout = true; retrieveCursor = true; break; } case InputMethodContext::PRE_EDIT: { - controller.InsertText(inputMethodContextEvent.predictiveString, Text::Controller::PRE_EDIT); + TextUpdater::InsertText(controller, inputMethodContextEvent.predictiveString, Text::Controller::PRE_EDIT); requestRelayout = true; retrieveCursor = true; break; } case InputMethodContext::DELETE_SURROUNDING: { - const bool textDeleted = controller.RemoveText(inputMethodContextEvent.cursorOffset, - inputMethodContextEvent.numberOfChars, - DONT_UPDATE_INPUT_STYLE); + const bool textDeleted = TextUpdater::RemoveText(controller, + inputMethodContextEvent.cursorOffset, + inputMethodContextEvent.numberOfChars, + DONT_UPDATE_INPUT_STYLE); if(textDeleted) { @@ -787,7 +786,7 @@ InputMethodContext::CallbackData Controller::EventHandler::OnInputMethodContextE } else { - controller.ShowPlaceholderText(); + PlaceholderHandler::ShowPlaceholderText(*controller.mImpl); } controller.mImpl->mEventData->mUpdateCursorPosition = true; controller.mImpl->mEventData->mScrollAfterDelete = true; @@ -882,7 +881,7 @@ void Controller::EventHandler::PasteClipboardItemEvent(Controller& controller) controller.mImpl->SetClipboardHideEnable(false); // Paste - controller.PasteText(stringToPaste); + TextUpdater::PasteText(controller, stringToPaste); controller.mImpl->SetClipboardHideEnable(true); } @@ -972,14 +971,14 @@ void Controller::EventHandler::TextPopupButtonTouched(Controller& controller, Da if(controller.mImpl->mEventData->mSelectionEnabled) { // Creates a SELECT event. - controller.SelectEvent(currentCursorPosition.x, currentCursorPosition.y, SelectionType::INTERACTIVE); + SelectEvent(controller, currentCursorPosition.x, currentCursorPosition.y, SelectionType::INTERACTIVE); } break; } case Toolkit::TextSelectionPopup::SELECT_ALL: { // Creates a SELECT_ALL event - controller.SelectEvent(0.f, 0.f, SelectionType::ALL); + SelectEvent(controller, 0.f, 0.f, SelectionType::ALL); break; } case Toolkit::TextSelectionPopup::CLIPBOARD: diff --git a/dali-toolkit/internal/text/text-controller-event-handler.h b/dali-toolkit/internal/text/text-controller-event-handler.h index 6e6e068..0028890 100644 --- a/dali-toolkit/internal/text/text-controller-event-handler.h +++ b/dali-toolkit/internal/text/text-controller-event-handler.h @@ -37,19 +37,82 @@ namespace Text { struct Controller::EventHandler { + /// @copydoc Text::Controller::KeyboardFocusGainEvent + /// @param[in] controller A reference to the controller class static void KeyboardFocusGainEvent(Controller& controller); + + /// @copydoc Text::Controller::KeyboardFocusLostEvent + /// @param[in] controller A reference to the controller class static void KeyboardFocusLostEvent(Controller& controller); + + /// @copydoc Text::Controller::KeyEvent + /// @param[in] controller A reference to the controller class static bool KeyEvent(Controller& controller, const Dali::KeyEvent& keyEvent); + + /// @copydoc Text::Controller::AnchorEvent + /// @param[in] controller A reference to the controller class static void AnchorEvent(Controller& controller, float x, float y); + + /// @copydoc Text::Controller::TapEvent + /// @param[in] controller A reference to the controller class static void TapEvent(Controller& controller, unsigned int tapCount, float x, float y); + + /// @copydoc Text::Controller::PanEvent + /// @param[in] controller A reference to the controller class static void PanEvent(Controller& controller, GestureState state, const Vector2& displacement); + + /// @copydoc Text::Controller::LongPressEvent + /// @param[in] controller A reference to the controller class static void LongPressEvent(Controller& controller, GestureState state, float x, float y); + + /// @copydoc Text::Controller::SelectEvent + /// @param[in] controller A reference to the controller class static void SelectEvent(Controller& controller, float x, float y, SelectionType selectType); + + /** + * @brief Creates a selection event with a selection index. + * + * It could be called from the SelectText(). + * The start and end parameters are passed through the event. + * + * @param[in] controller A reference to the controller class + * @param[in] start The start selection position. + * @param[in] end The end selection position. + * @param[in] selection type like the range. + */ static void SelectEvent(Controller& controller, const uint32_t start, const uint32_t end, SelectionType selectType); + + /** + * @brief Process queued events which modify the model. + * @param[in] controller A reference to the controller class + */ static void ProcessModifyEvents(Controller& controller); + + /** + * @brief Used to process an event queued from SetText() + * @param[in] controller A reference to the controller class + */ static void TextReplacedEvent(Controller& controller); + + /** + * @brief Used to process an event queued from key events etc. + * @param[in] controller A reference to the controller class + */ static void TextInsertedEvent(Controller& controller); + + /** + * @brief Used to process an event queued from backspace key etc. + * @param[in] controller A reference to the controller class + */ static void TextDeletedEvent(Controller& controller); + + /** + * @brief Helper to KeyEvent() to handle the backspace or delete key case. + * + * @param[in] controller A reference to the controller class + * @param[in] keyCode The keycode for the key pressed + * @return True if a character was deleted. + */ static bool DeleteEvent(Controller& controller, int keyCode); static InputMethodContext::CallbackData OnInputMethodContextEvent(Controller& controller, diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index fcd3bed..35ad959 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -21,18 +21,18 @@ // EXTERNAL INCLUDES #include #include -#include +#include #include // INTERNAL INCLUDES -#include -#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -46,17 +46,9 @@ namespace Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS"); #endif -struct BackgroundVertex -{ - Vector2 mPosition; ///< Vertex posiiton - Vector4 mColor; ///< Vertex color -}; +constexpr float MAX_FLOAT = std::numeric_limits::max(); -struct BackgroundMesh -{ - Vector mVertices; ///< container of vertices - Vector mIndices; ///< container of indices -}; +const std::string EMPTY_STRING(""); } // namespace @@ -496,6 +488,19 @@ Length Controller::Impl::GetNumberOfWhiteSpaces(CharacterIndex index) const return numberOfWhiteSpaces; } +void Controller::Impl::GetText(std::string& text) const +{ + if(!IsShowingPlaceholderText()) + { + // Retrieves the text string. + GetText(0u, text); + } + else + { + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::GetText %p empty (but showing placeholder)\n", this); + } +} + void Controller::Impl::GetText(CharacterIndex index, std::string& text) const { // Get the total number of characters. @@ -521,6 +526,48 @@ Dali::LayoutDirection::Type Controller::Impl::GetLayoutDirection(Dali::Actor& ac } } +Toolkit::DevelText::TextDirection::Type Controller::Impl::GetTextDirection() +{ + if(mUpdateTextDirection) + { + // Operations that can be done only once until the text changes. + const OperationsMask onlyOnceOperations = static_cast(CONVERT_TO_UTF32 | + GET_SCRIPTS | + VALIDATE_FONTS | + GET_LINE_BREAKS | + BIDI_INFO | + SHAPE_TEXT | + GET_GLYPH_METRICS); + + // Set the update info to relayout the whole text. + mTextUpdateInfo.mParagraphCharacterIndex = 0u; + mTextUpdateInfo.mRequestedNumberOfCharacters = mModel->mLogicalModel->mText.Count(); + + // Make sure the model is up-to-date before layouting + UpdateModel(onlyOnceOperations); + + Vector3 naturalSize; + Relayouter::DoRelayout(*this, + Size(MAX_FLOAT, MAX_FLOAT), + static_cast(onlyOnceOperations | + LAYOUT | REORDER | UPDATE_DIRECTION), + naturalSize.GetVectorXY()); + + // Do not do again the only once operations. + mOperationsPending = static_cast(mOperationsPending & ~onlyOnceOperations); + + // Clear the update info. This info will be set the next time the text is updated. + mTextUpdateInfo.Clear(); + + // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT. + mTextUpdateInfo.mFullRelayoutNeeded = true; + + mUpdateTextDirection = false; + } + + return mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT; +} + void Controller::Impl::CalculateTextUpdateIndices(Length& numberOfCharacters) { mTextUpdateInfo.mParagraphCharacterIndex = 0u; @@ -666,6 +713,64 @@ bool Controller::Impl::SetDefaultLineSize(float lineSize) return false; } +string Controller::Impl::GetSelectedText() +{ + string text; + if(EventData::SELECTING == mEventData->mState) + { + RetrieveSelection(text, false); + } + return text; +} + +string Controller::Impl::CopyText() +{ + string text; + RetrieveSelection(text, false); + SendSelectionToClipboard(false); // Text not modified + + mEventData->mUpdateCursorPosition = true; + + RequestRelayout(); // Cursor, Handles, Selection Highlight, Popup + + return text; +} + +string Controller::Impl::CutText() +{ + string text; + RetrieveSelection(text, false); + + if(!IsEditable()) + { + return EMPTY_STRING; + } + + SendSelectionToClipboard(true); // Synchronous call to modify text + mOperationsPending = ALL_OPERATIONS; + + if((0u != mModel->mLogicalModel->mText.Count()) || + !IsPlaceholderAvailable()) + { + QueueModifyEvent(ModifyEvent::TEXT_DELETED); + } + else + { + PlaceholderHandler::ShowPlaceholderText(*this); + } + + mEventData->mUpdateCursorPosition = true; + mEventData->mScrollAfterDelete = true; + + RequestRelayout(); + + if(nullptr != mEditableControlInterface) + { + mEditableControlInterface->TextChanged(true); + } + return text; +} + void Controller::Impl::SetTextSelectionRange(const uint32_t* pStart, const uint32_t* pEnd) { if(nullptr == mEventData) @@ -1357,188 +1462,6 @@ void Controller::Impl::RequestRelayout() } } -Actor Controller::Impl::CreateBackgroundActor() -{ - // NOTE: Currently we only support background color for left-to-right text. - - Actor actor; - - Length numberOfGlyphs = mView.GetNumberOfGlyphs(); - if(numberOfGlyphs > 0u) - { - Vector glyphs; - glyphs.Resize(numberOfGlyphs); - - Vector positions; - positions.Resize(numberOfGlyphs); - - // Get the line where the glyphs are laid-out. - const LineRun* lineRun = mModel->mVisualModel->mLines.Begin(); - float alignmentOffset = lineRun->alignmentOffset; - numberOfGlyphs = mView.GetGlyphs(glyphs.Begin(), - positions.Begin(), - alignmentOffset, - 0u, - numberOfGlyphs); - - glyphs.Resize(numberOfGlyphs); - positions.Resize(numberOfGlyphs); - - const GlyphInfo* const glyphsBuffer = glyphs.Begin(); - const Vector2* const positionsBuffer = positions.Begin(); - - BackgroundMesh mesh; - mesh.mVertices.Reserve(4u * glyphs.Size()); - mesh.mIndices.Reserve(6u * glyphs.Size()); - - const Vector2 textSize = mView.GetLayoutSize(); - - const float offsetX = alignmentOffset + textSize.width * 0.5f; - const float offsetY = textSize.height * 0.5f; - - const Vector4* const backgroundColorsBuffer = mView.GetBackgroundColors(); - const ColorIndex* const backgroundColorIndicesBuffer = mView.GetBackgroundColorIndices(); - const Vector4& defaultBackgroundColor = mModel->mVisualModel->IsBackgroundEnabled() ? mModel->mVisualModel->GetBackgroundColor() : Color::TRANSPARENT; - - Vector4 quad; - uint32_t numberOfQuads = 0u; - Length yLineOffset = 0; - Length prevLineIndex = 0; - LineIndex lineIndex; - Length numberOfLines; - - for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i) - { - const GlyphInfo& glyph = *(glyphsBuffer + i); - - // Get the background color of the character. - // The color index zero is reserved for the default background color (i.e. Color::TRANSPARENT) - const bool isMarkupBackground = mView.IsMarkupBackgroundColorSet(); - const ColorIndex backgroundColorIndex = isMarkupBackground ? *(backgroundColorIndicesBuffer + i) : 0u; - const bool isDefaultBackgroundColor = (0u == backgroundColorIndex); - const Vector4& backgroundColor = isDefaultBackgroundColor ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u); - - mModel->mVisualModel->GetNumberOfLines(i, 1, lineIndex, numberOfLines); - Length lineHeight = lineRun[lineIndex].ascender + -(lineRun[lineIndex].descender) + lineRun[lineIndex].lineSpacing; - - if(lineIndex != prevLineIndex) - { - yLineOffset += lineHeight; - } - - // Only create quads for glyphs with a background color - if(backgroundColor != Color::TRANSPARENT) - { - const Vector2 position = *(positionsBuffer + i); - - if(i == 0u && glyphSize == 1u) // Only one glyph in the whole text - { - quad.x = position.x; - quad.y = yLineOffset; - quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width); - quad.w = lineHeight; - } - else if((lineIndex != prevLineIndex) || (i == 0u)) // The first glyph in the line - { - quad.x = position.x; - quad.y = yLineOffset; - quad.z = quad.x - glyph.xBearing + glyph.advance; - quad.w = quad.y + lineHeight; - } - else if(i == glyphSize - 1u) // The last glyph in the whole text - { - quad.x = position.x - glyph.xBearing; - quad.y = yLineOffset; - quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width); - quad.w = quad.y + lineHeight; - } - else // The glyph in the middle of the text - { - quad.x = position.x - glyph.xBearing; - quad.y = yLineOffset; - quad.z = quad.x + glyph.advance; - quad.w = quad.y + lineHeight; - } - - BackgroundVertex vertex; - - // Top left - vertex.mPosition.x = quad.x - offsetX; - vertex.mPosition.y = quad.y - offsetY; - vertex.mColor = backgroundColor; - mesh.mVertices.PushBack(vertex); - - // Top right - vertex.mPosition.x = quad.z - offsetX; - vertex.mPosition.y = quad.y - offsetY; - vertex.mColor = backgroundColor; - mesh.mVertices.PushBack(vertex); - - // Bottom left - vertex.mPosition.x = quad.x - offsetX; - vertex.mPosition.y = quad.w - offsetY; - vertex.mColor = backgroundColor; - mesh.mVertices.PushBack(vertex); - - // Bottom right - vertex.mPosition.x = quad.z - offsetX; - vertex.mPosition.y = quad.w - offsetY; - vertex.mColor = backgroundColor; - mesh.mVertices.PushBack(vertex); - - // Six indices in counter clockwise winding - mesh.mIndices.PushBack(1u + 4 * numberOfQuads); - mesh.mIndices.PushBack(0u + 4 * numberOfQuads); - mesh.mIndices.PushBack(2u + 4 * numberOfQuads); - mesh.mIndices.PushBack(2u + 4 * numberOfQuads); - mesh.mIndices.PushBack(3u + 4 * numberOfQuads); - mesh.mIndices.PushBack(1u + 4 * numberOfQuads); - - numberOfQuads++; - } - - if(lineIndex != prevLineIndex) - { - prevLineIndex = lineIndex; - } - } - - // Only create the background actor if there are glyphs with background color - if(mesh.mVertices.Count() > 0u) - { - Property::Map quadVertexFormat; - quadVertexFormat["aPosition"] = Property::VECTOR2; - quadVertexFormat["aColor"] = Property::VECTOR4; - - VertexBuffer quadVertices = VertexBuffer::New(quadVertexFormat); - quadVertices.SetData(&mesh.mVertices[0], mesh.mVertices.Size()); - - Geometry quadGeometry = Geometry::New(); - quadGeometry.AddVertexBuffer(quadVertices); - quadGeometry.SetIndexBuffer(&mesh.mIndices[0], mesh.mIndices.Size()); - - if(!mShaderBackground) - { - mShaderBackground = Shader::New(SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_VERT, SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_FRAG); - } - - Dali::Renderer renderer = Dali::Renderer::New(quadGeometry, mShaderBackground); - renderer.SetProperty(Dali::Renderer::Property::BLEND_MODE, BlendMode::ON); - renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT); - - actor = Actor::New(); - actor.SetProperty(Dali::Actor::Property::NAME, "TextBackgroundColorActor"); - actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); - actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); - actor.SetProperty(Actor::Property::SIZE, textSize); - actor.SetProperty(Actor::Property::COLOR_MODE, USE_OWN_MULTIPLY_PARENT_COLOR); - actor.AddRenderer(renderer); - } - } - - return actor; -} - void Controller::Impl::RelayoutForNewLineSize() { // relayout all characters diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index e86aed8..3c72bdb 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -524,6 +524,13 @@ struct Controller::Impl Length GetNumberOfWhiteSpaces(CharacterIndex index) const; /** + * @brief Retrieve any text previously set. + * + * @param[out] text A string of UTF-8 characters. + */ + void GetText(std::string& text) const; + + /** * @brief Retrieve any text previously set starting from the given @p index. * * @param[in] index The character index from where to retrieve the text. @@ -551,6 +558,12 @@ struct Controller::Impl Dali::LayoutDirection::Type GetLayoutDirection(Dali::Actor& actor) const; /** + * @brief Checks text direction. + * @return The text direction. + */ + Toolkit::DevelText::TextDirection::Type GetTextDirection(); + + /** * @brief Calculates the start character index of the first paragraph to be updated and * the end character index of the last paragraph to be updated. * @@ -616,6 +629,21 @@ struct Controller::Impl bool SetPrimaryCursorPosition(CharacterIndex index, bool focused); /** + * @copydoc Text::SelectableControlInterface::GetSelectedText() + */ + string GetSelectedText(); + + /** + * @copydoc Text::EditableControlInterface::CopyText() + */ + string CopyText(); + + /** + * @copydoc Text::EditableControlInterface::CutText() + */ + string CutText(); + + /** * @copydoc Text::SelectableControlInterface::SetTextSelectionRange() */ void SetTextSelectionRange(const uint32_t* pStart, const uint32_t* pEndf); @@ -756,13 +784,6 @@ struct Controller::Impl void ScrollTextToMatchCursor(); /** - * @brief Create an actor that renders the text background color - * - * @return the created actor or an empty handle if no background color needs to be rendered. - */ - Actor CreateBackgroundActor(); - - /** * @brief fill needed relayout parameters when line size is changed & request relayout. */ void RelayoutForNewLineSize(); diff --git a/dali-toolkit/internal/text/text-controller-placeholder-handler.cpp b/dali-toolkit/internal/text/text-controller-placeholder-handler.cpp index d649371..312ecb5 100644 --- a/dali-toolkit/internal/text/text-controller-placeholder-handler.cpp +++ b/dali-toolkit/internal/text/text-controller-placeholder-handler.cpp @@ -61,7 +61,7 @@ void Controller::PlaceholderHandler::SetPlaceholderTextElideEnabled(Controller& if(controller.mImpl->IsShowingPlaceholderText() || (0u == controller.mImpl->mModel->mLogicalModel->mText.Count())) { - controller.ShowPlaceholderText(); + ShowPlaceholderText(*controller.mImpl); } } @@ -87,7 +87,7 @@ void Controller::PlaceholderHandler::SetPlaceholderText(Controller& controller, if(controller.mImpl->IsShowingPlaceholderText() || (0u == controller.mImpl->mModel->mLogicalModel->mText.Count())) { - controller.ShowPlaceholderText(); + ShowPlaceholderText(*controller.mImpl); } } } @@ -443,10 +443,8 @@ void Controller::PlaceholderHandler::GetPlaceholderProperty(Controller& controll } } -void Controller::PlaceholderHandler::ShowPlaceholderText(Controller& controller) +void Controller::PlaceholderHandler::ShowPlaceholderText(Controller::Impl& impl) { - Controller::Impl& impl = *controller.mImpl; - if(impl.IsPlaceholderAvailable()) { EventData*& eventData = impl.mEventData; diff --git a/dali-toolkit/internal/text/text-controller-placeholder-handler.h b/dali-toolkit/internal/text/text-controller-placeholder-handler.h index ac2ba1b..9c81eb1 100644 --- a/dali-toolkit/internal/text/text-controller-placeholder-handler.h +++ b/dali-toolkit/internal/text/text-controller-placeholder-handler.h @@ -55,7 +55,7 @@ struct Controller::PlaceholderHandler static const Vector4& GetPlaceholderTextColor(const Controller& controller); static void SetPlaceholderProperty(Controller& controller, const Property::Map& map); static void GetPlaceholderProperty(Controller& controller, Property::Map& map); - static void ShowPlaceholderText(Controller& controller); + static void ShowPlaceholderText(Controller::Impl& impl); static void CreatePlaceholderFont(Controller& controller); }; diff --git a/dali-toolkit/internal/text/text-controller-relayouter.cpp b/dali-toolkit/internal/text/text-controller-relayouter.cpp index c38f92e..3013b73 100644 --- a/dali-toolkit/internal/text/text-controller-relayouter.cpp +++ b/dali-toolkit/internal/text/text-controller-relayouter.cpp @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include +#include #include namespace @@ -94,7 +95,7 @@ Size Controller::Relayouter::CalculateLayoutSizeOnRequiredControllerSize(Control // Store the actual control's size to restore later. const Size actualControlSize = visualModel->mControlSize; - DoRelayout(controller, + DoRelayout(impl, requestedControllerSize, static_cast(onlyOnceOperations | requestedOperationsMask), @@ -125,7 +126,7 @@ Vector3 Controller::Relayouter::GetNaturalSize(Controller& controller) Vector3 naturalSizeVec3; // Make sure the model is up-to-date before layouting - controller.ProcessModifyEvents(); + EventHandler::ProcessModifyEvents(controller); Controller::Impl& impl = *controller.mImpl; ModelPtr& model = impl.mModel; @@ -187,7 +188,7 @@ bool Controller::Relayouter::CheckForTextFit(Controller& controller, float point // Make sure the model is up-to-date before layouting impl.UpdateModel(onlyOnceOperations); - DoRelayout(controller, + DoRelayout(impl, Size(layoutSize.width, MAX_FLOAT), static_cast(onlyOnceOperations | LAYOUT), textSize); @@ -271,7 +272,7 @@ float Controller::Relayouter::GetHeightForWidth(Controller& controller, float wi DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetHeightForWidth %p width %f\n", &controller, width); // Make sure the model is up-to-date before layouting - controller.ProcessModifyEvents(); + EventHandler::ProcessModifyEvents(controller); Controller::Impl& impl = *controller.mImpl; ModelPtr& model = impl.mModel; @@ -407,12 +408,12 @@ Controller::UpdateTextType Controller::Relayouter::Relayout(Controller& controll } // Make sure the model is up-to-date before layouting. - controller.ProcessModifyEvents(); + EventHandler::ProcessModifyEvents(controller); bool updated = impl.UpdateModel(operationsPending); // Layout the text. Size layoutSize; - updated = DoRelayout(controller, size, operationsPending, layoutSize) || updated; + updated = DoRelayout(impl, size, operationsPending, layoutSize) || updated; if(updated) { @@ -436,7 +437,7 @@ Controller::UpdateTextType Controller::Relayouter::Relayout(Controller& controll if(!isEditable || !controller.IsMultiLineEnabled()) { // After doing the text layout, the vertical offset to place the actor in the desired position can be calculated. - controller.CalculateVerticalOffset(size); + CalculateVerticalOffset(controller, size); } if(isEditable) @@ -464,13 +465,11 @@ Controller::UpdateTextType Controller::Relayouter::Relayout(Controller& controll return updateTextType; } -bool Controller::Relayouter::DoRelayout(Controller& controller, const Size& size, OperationsMask operationsRequired, Size& layoutSize) +bool Controller::Relayouter::DoRelayout(Controller::Impl& impl, const Size& size, OperationsMask operationsRequired, Size& layoutSize) { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::DoRelayout %p size %f,%f\n", &controller, size.width, size.height); + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::Relayouter::DoRelayout %p size %f,%f\n", &impl, size.width, size.height); bool viewUpdated(false); - Controller::Impl& impl = *controller.mImpl; - // Calculate the operations to be done. const OperationsMask operations = static_cast(impl.mOperationsPending & operationsRequired); @@ -505,7 +504,7 @@ bool Controller::Relayouter::DoRelayout(Controller& controller, const Size& size (lastIndex > charactersToGlyph.Count() && charactersToGlyph.Count() > 0u)) { std::string currentText; - controller.GetText(currentText); + impl.GetText(currentText); DALI_LOG_ERROR("Controller::DoRelayout: Attempting to access invalid buffer\n"); DALI_LOG_ERROR("Current text is: %s\n", currentText.c_str()); @@ -636,10 +635,10 @@ bool Controller::Relayouter::DoRelayout(Controller& controller, const Size& size } #if defined(DEBUG_ENABLED) std::string currentText; - controller.GetText(currentText); - DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::DoRelayout [%p] mImpl->mIsTextDirectionRTL[%s] [%s]\n", &controller, (impl.mIsTextDirectionRTL) ? "true" : "false", currentText.c_str()); + impl.GetText(currentText); + DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::Relayouter::DoRelayout [%p] mImpl->mIsTextDirectionRTL[%s] [%s]\n", &impl, (impl.mIsTextDirectionRTL) ? "true" : "false", currentText.c_str()); #endif - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::DoRelayout, view updated %s\n", (viewUpdated ? "true" : "false")); + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::Relayouter::DoRelayout, view updated %s\n", (viewUpdated ? "true" : "false")); return viewUpdated; } diff --git a/dali-toolkit/internal/text/text-controller-relayouter.h b/dali-toolkit/internal/text/text-controller-relayouter.h index 1b586b2..decca97 100644 --- a/dali-toolkit/internal/text/text-controller-relayouter.h +++ b/dali-toolkit/internal/text/text-controller-relayouter.h @@ -85,13 +85,14 @@ struct Controller::Relayouter /** * @brief Called by the Controller to do certain operations when relayouting. * - * @param[in] controller A reference to the controller class + * @param[in] impl A reference to the controller impl class * @param[in] size The size to set * @param[in] operationsRequired The operations we need to do * @param[in/out] layoutSize The Layout size which can be updated depending on the result of the performed operations * @return */ - static bool DoRelayout(Controller& controller, const Size& size, OperationsMask operationsRequired, Size& layoutSize); + + static bool DoRelayout(Controller::Impl& impl, const Size& size, OperationsMask operationsRequired, Size& layoutSize); /** * @brief Called by the Controller to calculate the veritcal offset give the control size. diff --git a/dali-toolkit/internal/text/text-controller-text-updater.cpp b/dali-toolkit/internal/text/text-controller-text-updater.cpp index 8a19786..0bcb97f 100644 --- a/dali-toolkit/internal/text/text-controller-text-updater.cpp +++ b/dali-toolkit/internal/text/text-controller-text-updater.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include namespace @@ -141,7 +142,7 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string& } else { - controller.ShowPlaceholderText(); + PlaceholderHandler::ShowPlaceholderText(impl); } unsigned int oldCursorPos = (nullptr != eventData ? eventData->mPrimaryCursorPosition : 0); @@ -405,7 +406,7 @@ void Controller::TextUpdater::InsertText(Controller& controller, const std::stri impl.IsPlaceholderAvailable()) { // Show place-holder if empty after removing the pre-edit text - controller.ShowPlaceholderText(); + PlaceholderHandler::ShowPlaceholderText(impl); eventData->mUpdateCursorPosition = true; impl.ClearPreEditFlag(); } diff --git a/dali-toolkit/internal/text/text-controller-text-updater.h b/dali-toolkit/internal/text/text-controller-text-updater.h index f512940..1070966 100644 --- a/dali-toolkit/internal/text/text-controller-text-updater.h +++ b/dali-toolkit/internal/text/text-controller-text-updater.h @@ -39,32 +39,64 @@ struct Controller::TextUpdater /// @param[in] controller The controller static void SetText(Controller& controller, const std::string& text); - /// @copydoc Text::Contoller::InsertText - /// @param[in] controller The controller + /** + * @brief Called by editable UI controls when key events are received. + * + * @param[in] controller The controller + * @param[in] text The text to insert. + * @param[in] type Used to distinguish between regular key events and InputMethodContext events. + */ static void InsertText(Controller& controller, const std::string& text, Controller::InsertType type); - /// @copydoc Text::Contoller::PasteText + /// @copydoc Text::EditableControlInterface::PasteText() /// @param[in] controller The controller static void PasteText(Controller& controller, const std::string& stringToPaste); - /// @copydoc Text::Contoller::RemoveText - /// @param[in] controller The controller + /** + * @brief Remove a given number of characters + * + * When predictve text is used the pre-edit text is removed and inserted again with the new characters. + * The UpdateInputStyleType @type parameter if set to DONT_UPDATE_INPUT_STYLE avoids to update the input + * style when pre-edit text is removed. + * + * @param[in] controller The controller + * @param[in] cursorOffset Start position from the current cursor position to start deleting characters. + * @param[in] numberOfCharacters The number of characters to delete from the cursorOffset. + * @param[in] type Whether to update the input style. + * @return True if the remove was successful. + */ static bool RemoveText(Controller& controller, int cursorOffset, int numberOfCharacters, UpdateInputStyleType type); - /// @copydoc Text::Contoller::RemoveSelectedText - /// @param[in] controller The controller + /** + * @brief Checks if text is selected and if so removes it. + * @param[in] controller The controller + * @return true if text was removed + */ static bool RemoveSelectedText(Controller& controller); - /// @copydoc Text::Contoller::ResetText - /// @param[in] controller The controller + /** + * @brief Used to remove the text included the placeholder text. + * @param[in] controller The controller + */ static void ResetText(Controller& controller); - /// @copydoc Text::Contoller::InsertTextAnchor - /// @param[in] controller The controller + /** + * @brief Update anchor position from given number of inserted characters. + * + * @param[in] controller The controller + * @param[in] numberOfCharacters The number of inserted characters. + * @param[in] previousCursorIndex A cursor position before event occurs. + */ static void InsertTextAnchor(Controller& controller, int numberOfCharacters, CharacterIndex previousCursorIndex); - /// @copydoc Text::Contoller::RemoveTextAnchor - /// @param[in] controller The controller + /** + * @brief Update anchor position from given number of removed characters. + * + * @param[in] controller The controller + * @param[in] cursorOffset Start position from the current cursor position to start deleting characters. + * @param[in] numberOfCharacters The number of removed characters. + * @param[in] previousCursorIndex A cursor position before event occurs. + */ static void RemoveTextAnchor(Controller& controller, int cursorOffset, int numberOfCharacters, CharacterIndex previousCursorIndex); }; diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 88eb9ef..757d54a 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -28,6 +28,7 @@ // INTERNAL INCLUDES #include +#include #include #include #include @@ -43,8 +44,6 @@ namespace Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS"); #endif -constexpr float MAX_FLOAT = std::numeric_limits::max(); - const std::string EMPTY_STRING(""); template @@ -315,15 +314,7 @@ void Controller::SetLayoutDirection(Dali::LayoutDirection::Type layoutDirection) Dali::LayoutDirection::Type Controller::GetLayoutDirection(Dali::Actor& actor) const { - if(mImpl->mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::LOCALE || - (mImpl->mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::INHERIT && !mImpl->mIsLayoutDirectionChanged)) - { - return static_cast(DevelWindow::Get(actor).GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get()); - } - else - { - return static_cast(actor.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get()); - } + return mImpl->GetLayoutDirection(actor); } bool Controller::IsShowingRealText() const @@ -474,15 +465,7 @@ void Controller::SetText(const std::string& text) void Controller::GetText(std::string& text) const { - if(!mImpl->IsShowingPlaceholderText()) - { - // Retrieves the text string. - mImpl->GetText(0u, text); - } - else - { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::GetText %p empty (but showing placeholder)\n", this); - } + mImpl->GetText(text); } void Controller::SetPlaceholderText(PlaceholderType type, const std::string& text) @@ -1215,45 +1198,9 @@ void Controller::GetPlaceholderProperty(Property::Map& map) Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection() { // Make sure the model is up-to-date before layouting - ProcessModifyEvents(); - - if(mImpl->mUpdateTextDirection) - { - // Operations that can be done only once until the text changes. - const OperationsMask onlyOnceOperations = static_cast(CONVERT_TO_UTF32 | - GET_SCRIPTS | - VALIDATE_FONTS | - GET_LINE_BREAKS | - BIDI_INFO | - SHAPE_TEXT | - GET_GLYPH_METRICS); - - // Set the update info to relayout the whole text. - mImpl->mTextUpdateInfo.mParagraphCharacterIndex = 0u; - mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count(); - - // Make sure the model is up-to-date before layouting - mImpl->UpdateModel(onlyOnceOperations); - - Vector3 naturalSize; - DoRelayout(Size(MAX_FLOAT, MAX_FLOAT), - static_cast(onlyOnceOperations | - LAYOUT | REORDER | UPDATE_DIRECTION), - naturalSize.GetVectorXY()); - - // Do not do again the only once operations. - mImpl->mOperationsPending = static_cast(mImpl->mOperationsPending & ~onlyOnceOperations); - - // Clear the update info. This info will be set the next time the text is updated. - mImpl->mTextUpdateInfo.Clear(); - - // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT. - mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true; - - mImpl->mUpdateTextDirection = false; - } + EventHandler::ProcessModifyEvents(*this); - return mImpl->mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT; + return mImpl->GetTextDirection(); } Toolkit::DevelText::VerticalLineAlignment::Type Controller::GetVerticalLineAlignment() const @@ -1337,11 +1284,6 @@ void Controller::SelectEvent(float x, float y, SelectionType selectType) EventHandler::SelectEvent(*this, x, y, selectType); } -void Controller::SelectEvent(const uint32_t start, const uint32_t end, SelectionType selectType) -{ - EventHandler::SelectEvent(*this, start, end, selectType); -} - void Controller::SetTextSelectionRange(const uint32_t* start, const uint32_t* end) { if(mImpl->mEventData) @@ -1351,7 +1293,7 @@ void Controller::SetTextSelectionRange(const uint32_t* start, const uint32_t* en mImpl->mEventData->mIsRightHandleSelected = true; mImpl->SetTextSelectionRange(start, end); mImpl->RequestRelayout(); - KeyboardFocusGainEvent(); + EventHandler::KeyboardFocusGainEvent(*this); } } @@ -1375,7 +1317,7 @@ bool Controller::SetPrimaryCursorPosition(CharacterIndex index, bool focused) mImpl->mEventData->mCheckScrollAmount = true; if(mImpl->SetPrimaryCursorPosition(index, focused) && focused) { - KeyboardFocusGainEvent(); + EventHandler::KeyboardFocusGainEvent(*this); return true; } } @@ -1384,75 +1326,32 @@ bool Controller::SetPrimaryCursorPosition(CharacterIndex index, bool focused) void Controller::SelectWholeText() { - SelectEvent(0.f, 0.f, SelectionType::ALL); + EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::ALL); } void Controller::SelectNone() { - SelectEvent(0.f, 0.f, SelectionType::NONE); + EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::NONE); } void Controller::SelectText(const uint32_t start, const uint32_t end) { - SelectEvent(start, end, SelectionType::RANGE); + EventHandler::SelectEvent(*this, start, end, SelectionType::RANGE); } string Controller::GetSelectedText() const { - string text; - if(EventData::SELECTING == mImpl->mEventData->mState) - { - mImpl->RetrieveSelection(text, false); - } - return text; + return mImpl->GetSelectedText(); } string Controller::CopyText() { - string text; - mImpl->RetrieveSelection(text, false); - mImpl->SendSelectionToClipboard(false); // Text not modified - - mImpl->mEventData->mUpdateCursorPosition = true; - - mImpl->RequestRelayout(); // Cursor, Handles, Selection Highlight, Popup - - return text; + return mImpl->CopyText(); } string Controller::CutText() { - string text; - mImpl->RetrieveSelection(text, false); - - if(!IsEditable()) - { - return EMPTY_STRING; - } - - mImpl->SendSelectionToClipboard(true); // Synchronous call to modify text - mImpl->mOperationsPending = ALL_OPERATIONS; - - if((0u != mImpl->mModel->mLogicalModel->mText.Count()) || - !mImpl->IsPlaceholderAvailable()) - { - mImpl->QueueModifyEvent(ModifyEvent::TEXT_DELETED); - } - else - { - ShowPlaceholderText(); - } - - mImpl->mEventData->mUpdateCursorPosition = true; - mImpl->mEventData->mScrollAfterDelete = true; - - mImpl->RequestRelayout(); - - if(nullptr != mImpl->mEditableControlInterface) - { - mImpl->mEditableControlInterface->TextChanged(true); - } - return text; + return mImpl->CutText(); } void Controller::PasteText() @@ -1527,83 +1426,6 @@ void Controller::DisplayTimeExpired() mImpl->RequestRelayout(); } -void Controller::InsertText(const std::string& text, Controller::InsertType type) -{ - TextUpdater::InsertText(*this, text, type); -} - -void Controller::PasteText(const std::string& stringToPaste) -{ - TextUpdater::PasteText(*this, stringToPaste); -} - -bool Controller::RemoveText(int cursorOffset, int numberOfCharacters, UpdateInputStyleType type) -{ - return TextUpdater::RemoveText(*this, cursorOffset, numberOfCharacters, type); -} - -bool Controller::RemoveSelectedText() -{ - return TextUpdater::RemoveSelectedText(*this); -} - -void Controller::InsertTextAnchor(int numberOfCharacters, CharacterIndex previousCursorIndex) -{ - TextUpdater::InsertTextAnchor(*this, numberOfCharacters, previousCursorIndex); -} - -void Controller::RemoveTextAnchor(int cursorOffset, int numberOfCharacters, CharacterIndex previousCursorIndex) -{ - TextUpdater::RemoveTextAnchor(*this, cursorOffset, numberOfCharacters, previousCursorIndex); -} - -bool Controller::DoRelayout(const Size& size, OperationsMask operationsRequired, Size& layoutSize) -{ - return Relayouter::DoRelayout(*this, size, operationsRequired, layoutSize); -} - -void Controller::CalculateVerticalOffset(const Size& controlSize) -{ - Relayouter::CalculateVerticalOffset(*this, controlSize); -} - -void Controller::ProcessModifyEvents() -{ - EventHandler::ProcessModifyEvents(*this); -} - -void Controller::TextReplacedEvent() -{ - EventHandler::TextReplacedEvent(*this); -} - -void Controller::TextInsertedEvent() -{ - EventHandler::TextInsertedEvent(*this); -} - -void Controller::TextDeletedEvent() -{ - EventHandler::TextDeletedEvent(*this); -} - -bool Controller::DeleteEvent(int keyCode) -{ - return EventHandler::DeleteEvent(*this, keyCode); -} - -// private : Helpers. - -void Controller::ResetText() -{ - TextUpdater::ResetText(*this); -} - -void Controller::ShowPlaceholderText() -{ - PlaceholderHandler::ShowPlaceholderText(*this); -} - void Controller::ResetCursorPosition(CharacterIndex cursorIndex) { // Reset the cursor position @@ -1641,7 +1463,7 @@ bool Controller::ShouldClearFocusOnEscape() const Actor Controller::CreateBackgroundActor() { - return mImpl->CreateBackgroundActor(); + return CreateControllerBackgroundActor(mImpl->mView, mImpl->mModel->mVisualModel, mImpl->mShaderBackground); } void Controller::GetAnchorActors(std::vector& anchorActors) diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 1752e3a..a582110 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -1636,18 +1636,6 @@ public: // Text-input Event Queuing. void SelectEvent(float x, float y, SelectionType selection); /** - * @brief Creates a selection event with a selection index. - * - * It could be called from the SelectText(). - * The start and end parameters are passed through the event. - * - * @param[in] start The start selection position. - * @param[in] end The end selection position. - * @param[in] selection type like the range. - */ - void SelectEvent(const uint32_t start, const uint32_t end, SelectionType selection); - - /** * @copydoc Text::SelectableControlInterface::SetTextSelectionRange() */ void SetTextSelectionRange(const uint32_t* start, const uint32_t* end); @@ -1802,123 +1790,6 @@ protected: // Inherit from HiddenText. */ void DisplayTimeExpired() override; -private: // Update. - /** - * @brief Called by editable UI controls when key events are received. - * - * @param[in] text The text to insert. - * @param[in] type Used to distinguish between regular key events and InputMethodContext events. - */ - void InsertText(const std::string& text, InsertType type); - - /** - * @copydoc Text::EditableControlInterface::PasteText() - */ - void PasteText(const std::string& stringToPaste); - - /** - * @brief Remove a given number of characters - * - * When predictve text is used the pre-edit text is removed and inserted again with the new characters. - * The UpdateInputStyleType @type parameter if set to DONT_UPDATE_INPUT_STYLE avoids to update the input - * style when pre-edit text is removed. - * - * @param[in] cursorOffset Start position from the current cursor position to start deleting characters. - * @param[in] numberOfCharacters The number of characters to delete from the cursorOffset. - * @param[in] type Whether to update the input style. - * @return True if the remove was successful. - */ - bool RemoveText(int cursorOffset, - int numberOfCharacters, - UpdateInputStyleType type); - - /** - * @brief Checks if text is selected and if so removes it. - * @return true if text was removed - */ - bool RemoveSelectedText(); - - /** - * @brief Update anchor position from given number of inserted characters. - * - * @param[in] numberOfCharacters The number of inserted characters. - * @param[in] previousCursorIndex A cursor position before event occurs. - */ - void InsertTextAnchor(int numberOfCharacters, - CharacterIndex previousCursorIndex); - - /** - * @brief Update anchor position from given number of removed characters. - * - * @param[in] cursorOffset Start position from the current cursor position to start deleting characters. - * @param[in] numberOfCharacters The number of removed characters. - * @param[in] previousCursorIndex A cursor position before event occurs. - */ - void RemoveTextAnchor(int cursorOffset, - int numberOfCharacters, - CharacterIndex previousCursorIndex); - -private: // Relayout. - /** - * @brief Lays-out the text. - * - * GetNaturalSize(), GetHeightForWidth() and Relayout() calls this method. - * - * @param[in] size A the size of a bounding box to layout text within. - * @param[in] operations The layout operations which need to be done. - * @param[out] layoutSize The size of the laid-out text. - */ - bool DoRelayout(const Size& size, - OperationsMask operations, - Size& layoutSize); - - /** - * @brief Calulates the vertical offset to align the text inside the bounding box. - * - * @param[in] size The size of the bounding box. - */ - void CalculateVerticalOffset(const Size& size); - -private: // Events. - /** - * @brief Process queued events which modify the model. - */ - void ProcessModifyEvents(); - - /** - * @brief Used to process an event queued from SetText() - */ - void TextReplacedEvent(); - - /** - * @brief Used to process an event queued from key events etc. - */ - void TextInsertedEvent(); - - /** - * @brief Used to process an event queued from backspace key etc. - */ - void TextDeletedEvent(); - - /** - * @brief Helper to KeyEvent() to handle the backspace or delete key case. - * - * @param[in] keyCode The keycode for the key pressed - * @return True if a character was deleted. - */ - bool DeleteEvent(int keyCode); - -private: // Helpers. - /** - * @brief Used to remove the text included the placeholder text. - */ - void ResetText(); - - /** - * @brief Helper to show the place holder text.. - */ - void ShowPlaceholderText(); - private: // Private contructors & copy operator. /** * @brief Private constructor. -- 2.7.4