X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Ftext-controller-impl.cpp;h=f287daf84cc80827c1434efa9d84f9b3d670631c;hb=478e477e07fde916953748d2cd4befc0326bfc34;hp=fcd3bed8cac574fc63434751f7cf3f1e9f22bf81;hpb=f382cfe22850eb6a81d15da5c59401670d9c4646;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index fcd3bed..f287daf 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -19,20 +19,20 @@ #include // EXTERNAL INCLUDES -#include -#include -#include #include +#include +#include +#include // INTERNAL INCLUDES -#include -#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -46,26 +46,16 @@ 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 namespace Dali::Toolkit::Text { - namespace { - void SetDefaultInputStyle(InputStyle& inputStyle, const FontDefaults* const fontDefaults, const Vector4& textColor) { // Sets the default text's color. @@ -350,7 +340,7 @@ void ChangeTextControllerState(Controller::Impl& impl, EventData::State newState decorator->StopCursorBlink(); decorator->SetHandleActive(GRAB_HANDLE, false); if(eventData->mDecorator->IsHandleActive(LEFT_SELECTION_HANDLE) || - decorator->IsHandleActive(RIGHT_SELECTION_HANDLE)) + decorator->IsHandleActive(RIGHT_SELECTION_HANDLE)) { decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false); decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false); @@ -496,6 +486,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 +524,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; @@ -645,7 +690,6 @@ bool Controller::Impl::SetDefaultLineSpacing(float lineSpacing) if(std::fabs(lineSpacing - mLayoutEngine.GetDefaultLineSpacing()) > Math::MACHINE_EPSILON_1000) { mLayoutEngine.SetDefaultLineSpacing(lineSpacing); - mRecalculateNaturalSize = true; RelayoutForNewLineSize(); return true; @@ -658,7 +702,6 @@ bool Controller::Impl::SetDefaultLineSize(float lineSize) if(std::fabs(lineSize - mLayoutEngine.GetDefaultLineSize()) > Math::MACHINE_EPSILON_1000) { mLayoutEngine.SetDefaultLineSize(lineSize); - mRecalculateNaturalSize = true; RelayoutForNewLineSize(); return true; @@ -666,6 +709,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 +1458,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 @@ -1547,8 +1466,13 @@ void Controller::Impl::RelayoutForNewLineSize() mTextUpdateInfo.mNumberOfCharactersToAdd = mModel->mLogicalModel->mText.Count(); mOperationsPending = static_cast(mOperationsPending | LAYOUT); + mTextUpdateInfo.mFullRelayoutNeeded = true; + + // Need to recalculate natural size + mRecalculateNaturalSize = true; + //remove selection - if(mEventData && mEventData->mState == EventData::SELECTING) + if((mEventData != nullptr) && (mEventData->mState == EventData::SELECTING)) { ChangeState(EventData::EDITING); } @@ -1570,7 +1494,7 @@ void Controller::Impl::ProcessInputStyleChangedSignals() // Emit the input style changed signal for each mask std::for_each(mEventData->mInputStyleChangedQueue.begin(), mEventData->mInputStyleChangedQueue.end(), - [&](const auto mask) { mEditableControlInterface->InputStyleChanged(mask); } ); + [&](const auto mask) { mEditableControlInterface->InputStyleChanged(mask); }); } mEventData->mInputStyleChangedQueue.Clear(); @@ -1801,7 +1725,7 @@ void Controller::Impl::SetVerticalAlignment(VerticalAlignment::Type alignment) { // Set the alignment. mModel->mVerticalAlignment = alignment; - mOperationsPending = static_cast(mOperationsPending | ALIGN); + mOperationsPending = static_cast(mOperationsPending | ALIGN); RequestRelayout(); } } @@ -1881,7 +1805,6 @@ void Controller::Impl::ClearStyleData() mModel->mLogicalModel->ClearFontDescriptionRuns(); } - void Controller::Impl::ResetScrollPosition() { if(mEventData)