From: abdullah Date: Mon, 26 Jul 2021 06:42:30 +0000 (+0300) Subject: Support line spacing & min line size in texteditor X-Git-Tag: dali_2.0.41~12^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=094ca4278df850c7870382c3896476a1bd1c9b7b;hp=-c Support line spacing & min line size in texteditor support texteditor to have properties like textlabel. line spacing set the space between lines. min line size set the total line size (we internally take the max between line size vs font line size) Change-Id: I2cccc910406db181561ff5e7274b997b60b44737 --- 094ca4278df850c7870382c3896476a1bd1c9b7b diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index 9b1d0ff..5003bea 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp @@ -1005,6 +1005,11 @@ int UtcDaliTextEditorSetPropertyP(void) application.SendNotification(); application.Render(); + // Check the line size property + DALI_TEST_EQUALS( editor.GetProperty( DevelTextEditor::Property::MIN_LINE_SIZE ), 0.0f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + editor.SetProperty( DevelTextEditor::Property::MIN_LINE_SIZE, 50.f ); + DALI_TEST_EQUALS( editor.GetProperty( DevelTextEditor::Property::MIN_LINE_SIZE ), 50.0f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + END_TEST; } @@ -3975,4 +3980,54 @@ int UtcDaliToolkitTextEditorEllipsisPositionProperty(void) DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION ); END_TEST; +} + +int UtcDaliTextEditorLineSpacing(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorLineSpacing "); + + TextEditor textEditor = TextEditor::New(); + textEditor.SetProperty( Actor::Property::SIZE, Vector2( 400.0f, 400.f ) ); + application.GetScene().Add( textEditor ); + application.SendNotification(); + application.Render(); + + textEditor.SetProperty( TextEditor::Property::TEXT, "Line #1\nLine #2\nLine #3" ); + textEditor.SetProperty( DevelTextEditor::Property::LINE_SPACING, 0 ); + + Vector3 sizeBefore = textEditor.GetNaturalSize(); + + textEditor.SetProperty( DevelTextEditor::Property::LINE_SPACING, 20 ); + + //add 20 for each line 20 * 3 + DALI_TEST_EQUALS(sizeBefore.height + 60.0f, textEditor.GetNaturalSize().height, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTextEditorMinLineSize(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorMinLineSize "); + + TextEditor textEditor = TextEditor::New(); + textEditor.SetProperty( Actor::Property::SIZE, Vector2( 400.0f, 400.f ) ); + application.GetScene().Add( textEditor ); + application.SendNotification(); + application.Render(); + + textEditor.SetProperty( TextEditor::Property::TEXT, "Line #1\nLine #2\nLine #3" ); + textEditor.SetProperty( DevelTextEditor::Property::MIN_LINE_SIZE, 0 ); + + Vector3 sizeBefore = textEditor.GetNaturalSize(); + + textEditor.SetProperty( DevelTextEditor::Property::MIN_LINE_SIZE, 60 ); + + DALI_TEST_NOT_EQUALS( sizeBefore, textEditor.GetNaturalSize(), 0.0f, TEST_LOCATION); + + //60 * 3 lines + DALI_TEST_EQUALS(180.0f, textEditor.GetNaturalSize().height, TEST_LOCATION); + + END_TEST; } \ No newline at end of file diff --git a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h index 2d14542..7a6442a 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h +++ b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h @@ -267,6 +267,13 @@ enum Type * @see DevelText::EllipsisPosition */ ELLIPSIS_POSITION, + + /** + * @brief Sets the height of the line in points. + * @details Name "minLineSize", type Property::FLOAT. + * @note If the font size is larger than the line size, it works with the font size. + */ + MIN_LINE_SIZE, }; } // namespace Property diff --git a/dali-toolkit/devel-api/text/text-utils-devel.cpp b/dali-toolkit/devel-api/text/text-utils-devel.cpp index 9609a3b..41d7126 100644 --- a/dali-toolkit/devel-api/text/text-utils-devel.cpp +++ b/dali-toolkit/devel-api/text/text-utils-devel.cpp @@ -828,7 +828,7 @@ void Ellipsis(const RendererParameters& textParameters, TextAbstraction::TextRen { Length finalNumberOfGlyphs = 0u; - if((line.ascender - line.descender) > textLayoutArea.height) + if((GetLineHeight(line)) > textLayoutArea.height) { // The height of the line is bigger than the height of the text area. // Show the ellipsis glyph even if it doesn't fit in the text area. @@ -1524,7 +1524,7 @@ Dali::Property::Array RenderForLastIndex(RendererParameters& textParameters) const LineRun& line = *(lines.Begin() + index); numberOfCharacters += line.characterRun.numberOfCharacters; - lineOffset = lineSize > 0.f ? lineSize : (line.ascender + -line.descender); + lineOffset = lineSize > 0.f ? lineSize : GetLineHeight(line); penY += lineOffset; if((penY + lineOffset) > boundingBox) { 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 dd67a85..8dee30e 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -151,6 +151,7 @@ DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "inputMethodSett DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "inputFilter", MAP, INPUT_FILTER ) 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) @@ -491,13 +492,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; } @@ -832,6 +828,15 @@ void TextEditor::SetProperty(BaseObject* object, Property::Index index, const Pr } 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 } @@ -1011,9 +1016,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: @@ -1222,6 +1225,11 @@ Property::Value TextEditor::GetProperty(BaseObject* object, Property::Index inde value = impl.mController->GetEllipsisPosition(); break; } + case Toolkit::DevelTextEditor::Property::MIN_LINE_SIZE: + { + value = impl.mController->GetDefaultLineSize(); + break; + } } //switch } @@ -2291,10 +2299,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{}; @@ -2315,7 +2323,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) { @@ -2390,8 +2398,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(); @@ -2474,7 +2482,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; @@ -2489,7 +2497,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); diff --git a/dali-toolkit/internal/text/cursor-helper-functions.cpp b/dali-toolkit/internal/text/cursor-helper-functions.cpp index 1df142c..c2d35d9 100644 --- a/dali-toolkit/internal/text/cursor-helper-functions.cpp +++ b/dali-toolkit/internal/text/cursor-helper-functions.cpp @@ -155,9 +155,7 @@ LineIndex GetClosestLine(VisualModelPtr visualModel, { const LineRun& lineRun = *it; - // The line height is the addition of the line ascender and the line descender. - // However, the line descender has a negative value, hence the subtraction. - totalHeight += lineRun.ascender - lineRun.descender; + totalHeight += GetLineHeight(lineRun); if(visualY < totalHeight) { @@ -186,9 +184,7 @@ float CalculateLineOffset(const Vector& lines, { const LineRun& lineRun = *it; - // The line height is the addition of the line ascender and the line descender. - // However, the line descender has a negative value, hence the subtraction. - offset += lineRun.ascender - lineRun.descender; + offset += GetLineHeight(lineRun); } return offset; @@ -495,9 +491,7 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, cursorInfo.lineOffset = CalculateLineOffset(parameters.visualModel->mLines, newLineIndex); - // The line height is the addition of the line ascender and the line descender. - // However, the line descender has a negative value, hence the subtraction. - cursorInfo.lineHeight = newLine.ascender - newLine.descender; + cursorInfo.lineHeight = GetLineHeight(newLine); // Set the primary cursor's height. cursorInfo.primaryCursorHeight = cursorInfo.lineHeight; @@ -543,9 +537,7 @@ void GetCursorPosition(GetCursorPositionParameters& parameters, cursorInfo.lineOffset = CalculateLineOffset(parameters.visualModel->mLines, lineIndex); - // The line height is the addition of the line ascender and the line descender. - // However, the line descender has a negative value, hence the subtraction. - cursorInfo.lineHeight = line.ascender - line.descender; + cursorInfo.lineHeight = GetLineHeight(line); // Calculate the primary cursor. diff --git a/dali-toolkit/internal/text/layouts/layout-engine.cpp b/dali-toolkit/internal/text/layouts/layout-engine.cpp index b27f634..695d950 100644 --- a/dali-toolkit/internal/text/layouts/layout-engine.cpp +++ b/dali-toolkit/internal/text/layouts/layout-engine.cpp @@ -36,6 +36,12 @@ namespace Toolkit { namespace Text { +float GetLineHeight(const LineRun lineRun) +{ + // The line height is the addition of the line ascender, the line descender and the line spacing. + // However, the line descender has a negative value, hence the subtraction. + return lineRun.ascender - lineRun.descender + lineRun.lineSpacing; +} namespace Layout { namespace @@ -1275,7 +1281,7 @@ struct Engine::Impl layoutSize.width = layoutParameters.boundingBox.width; if(layoutSize.height < Math::MACHINE_EPSILON_1000) { - layoutSize.height += (lineRun->ascender + -lineRun->descender) + lineRun->lineSpacing; + layoutSize.height += GetLineHeight(*lineRun); } const Vector& bidirectionalLinesInfo = layoutParameters.textModel->mLogicalModel->mBidirectionalLineInfo; @@ -1382,7 +1388,7 @@ struct Engine::Impl layoutSize.width = lineRun.width; } - layoutSize.height += (lineRun.ascender + -lineRun.descender) + lineRun.lineSpacing; + layoutSize.height += GetLineHeight(lineRun); } /** @@ -1433,7 +1439,7 @@ struct Engine::Impl lineRun.lineSpacing += mDefaultLineSpacing; - layoutSize.height += (lineRun.ascender + -lineRun.descender) + lineRun.lineSpacing; + layoutSize.height += GetLineHeight(lineRun); } /** @@ -1457,7 +1463,7 @@ struct Engine::Impl layoutSize.width = line.width; } - layoutSize.height += (line.ascender + -line.descender) + line.lineSpacing; + layoutSize.height += GetLineHeight(line); } } diff --git a/dali-toolkit/internal/text/line-run.h b/dali-toolkit/internal/text/line-run.h index ff826e6..52c47a1 100644 --- a/dali-toolkit/internal/text/line-run.h +++ b/dali-toolkit/internal/text/line-run.h @@ -48,6 +48,13 @@ struct LineRun CharacterRun characterRunForSecondHalfLine; ///< The initial character index and the number of characters of the run for the second half of line. }; +/** + * @brief Get the line height for the specified line run. + * + * @param[in] lineRun The line runs to get the height for. + */ +float GetLineHeight(const LineRun lineRun); + } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp b/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp index 2aafff7..f8aa7a5 100644 --- a/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp +++ b/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp @@ -338,7 +338,7 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const const LineRun& line = *(visualModel->mLines.Begin() + previousLineIndex); // Get the next hit 'y' point. - const float hitPointY = cursorInfo.lineOffset - 0.5f * (line.ascender - line.descender); + const float hitPointY = cursorInfo.lineOffset - 0.5f * GetLineHeight(line); // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index. bool matchedCharacter = false; @@ -374,7 +374,7 @@ void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const const LineRun& line = *(visualModel->mLines.Begin() + lineIndex + 1u); // Get the next hit 'y' point. - const float hitPointY = cursorInfo.lineOffset + cursorInfo.lineHeight + 0.5f * (line.ascender - line.descender); + const float hitPointY = cursorInfo.lineOffset + cursorInfo.lineHeight + 0.5f * GetLineHeight(line); // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index. bool matchedCharacter = false; diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index dce67ff..b058e26 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -1219,12 +1219,31 @@ const std::string& Controller::GetDefaultOutlineProperties() const return EMPTY_STRING; } +void Controller::RelayoutForNewLineSize() +{ + // relayout all characters + mImpl->mTextUpdateInfo.mCharacterIndex = 0; + mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters; + mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count(); + mImpl->mOperationsPending = static_cast(mImpl->mOperationsPending | LAYOUT); + + //remove selection + if((mImpl->mEventData != nullptr) && (mImpl->mEventData->mState == EventData::SELECTING)) + { + mImpl->ChangeState(EventData::EDITING); + } + + mImpl->RequestRelayout(); +} + bool Controller::SetDefaultLineSpacing(float lineSpacing) { if(std::fabs(lineSpacing - mImpl->mLayoutEngine.GetDefaultLineSpacing()) > Math::MACHINE_EPSILON_1000) { mImpl->mLayoutEngine.SetDefaultLineSpacing(lineSpacing); mImpl->mRecalculateNaturalSize = true; + + RelayoutForNewLineSize(); return true; } return false; @@ -1241,6 +1260,8 @@ bool Controller::SetDefaultLineSize(float lineSize) { mImpl->mLayoutEngine.SetDefaultLineSize(lineSize); mImpl->mRecalculateNaturalSize = true; + + RelayoutForNewLineSize(); return true; } return false; diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 8c388b9..109be1a 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -1874,6 +1874,11 @@ private: // Helpers. */ void ResetScrollPosition(); + /** + * @brief fill needed relayout parameters when line size is changed & request relayout. + */ + void RelayoutForNewLineSize(); + private: // Private contructors & copy operator. /** * @brief Private constructor. diff --git a/dali-toolkit/internal/text/text-selection-handle-controller.cpp b/dali-toolkit/internal/text/text-selection-handle-controller.cpp index 0601750..b082510 100644 --- a/dali-toolkit/internal/text/text-selection-handle-controller.cpp +++ b/dali-toolkit/internal/text/text-selection-handle-controller.cpp @@ -144,9 +144,7 @@ void SelectionHandleController::Reposition(Controller::Impl& impl) lineRun += firstLineIndex; - // The line height is the addition of the line ascender and the line descender. - // However, the line descender has a negative value, hence the subtraction. - selectionBoxInfo->lineHeight = lineRun->ascender - lineRun->descender; + selectionBoxInfo->lineHeight = GetLineHeight(*lineRun); GlyphIndex lastGlyphOfLine = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1u; @@ -275,9 +273,7 @@ void SelectionHandleController::Reposition(Controller::Impl& impl) // Update the line's vertical offset. selectionBoxInfo->lineOffset = currentLineOffset + currentLineHeight; - // The line height is the addition of the line ascender and the line descender. - // However, the line descender has a negative value, hence the subtraction. - selectionBoxInfo->lineHeight = lineRun->ascender - lineRun->descender; + selectionBoxInfo->lineHeight = GetLineHeight(*lineRun); } } } diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index f8a2722..a5a6b3b 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -225,7 +225,7 @@ Length View::GetGlyphs(GlyphInfo* glyphs, lastGlyphIndexOfLine = (line->isSplitToTwoHalves ? line->glyphRunSecondHalf.glyphIndex + line->glyphRunSecondHalf.numberOfGlyphs : line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs) - 1u; - penY += line->ascender; + penY += line->ascender + line->lineSpacing; } } } @@ -265,7 +265,7 @@ Length View::GetGlyphs(GlyphInfo* glyphs, const LineRun& elidedLine = *ellipsisLine; if((1u == numberOfLines) && - (elidedLine.ascender - elidedLine.descender > mImpl->mVisualModel->mControlSize.height)) + (GetLineHeight(elidedLine) > mImpl->mVisualModel->mControlSize.height)) { // Replace the first glyph with ellipsis glyph auto indexOfFirstGlyph = (ellipsisPosition == DevelText::EllipsisPosition::START) ? startIndexOfEllipsis : 0u;