~aleteoryx/muditaos

bc76f7360e4d73958e0ab7596f685a570212295b — Przemyslaw Brudny 5 years ago 6b02f54
[EGD-5684] Add RichText empty line support

Added RichText option to add empty line. Tests added. Fixed
scroll up navigation line first char calculation.
M enabled_unittests => enabled_unittests +1 -0
@@ 143,6 143,7 @@ TESTS_LIST["catch2-gui-text"]="
    Text addition bounds - text widget size restricted;
    Text addition bounds - text widget line size restricted;
    Text addition bounds - multiple limits tests;
    RichText newline and empty lines tests;
    TextBlock Ctor/Dtor ;
    Text block - set/update/get text;
    Text block - remove text;

M module-gui/gui/widgets/RichTextParser.cpp => module-gui/gui/widgets/RichTextParser.cpp +19 -5
@@ 325,8 325,8 @@ struct walker : pugi::xml_tree_walker
    std::list<gui::TextFormat> style_stack;
    text::CustomTokens tokens;

    bool add_newline = false;
    bool adding_tokens = false;
    bool add_empty_line = false;
    bool adding_tokens  = false;

  public:
    walker(gui::TextFormat entry_style, ::text::CustomTokens::TokenMap &&tokens) : tokens{std::move(tokens)}


@@ 398,8 398,17 @@ struct walker : pugi::xml_tree_walker

    auto push_newline_node(pugi::xml_node &)
    {
        if (blocks.size() != 0u) {
            blocks.back().setEnd(gui::TextBlock::End::Newline);
        if (!blocks.empty()) {
            if (blocks.back().getEnd() != gui::TextBlock::End::Newline) {
                blocks.back().setEnd(gui::TextBlock::End::Newline);
                add_empty_line = false;
            }
            else {
                add_empty_line = true;
            }
        }
        else {
            add_empty_line = true;
        }
    }



@@ 462,7 471,12 @@ struct walker : pugi::xml_tree_walker

    auto pop_newline_node(pugi::xml_node &node)
    {
        if (blocks.size() != 0u) {
        if (add_empty_line) {
            blocks.emplace_back(gui::TextBlock("", std::make_unique<gui::TextFormat>(style_stack.back())));
            add_empty_line = false;
        }

        if (!blocks.empty()) {
            blocks.back().setEnd(gui::TextBlock::End::Newline);
        }
    }

M module-gui/gui/widgets/TextLine.hpp => module-gui/gui/widgets/TextLine.hpp +9 -1
@@ 3,6 3,7 @@

#pragma once

#include <numeric>
#include <list>
#include "Common.hpp"
#include "Label.hpp"


@@ 73,7 74,14 @@ namespace gui
        /// count of elements in whole TextLine
        [[nodiscard]] unsigned int count() const noexcept
        {
            return lineContent.size();
            return std::accumulate(lineContent.begin(), lineContent.end(), 0U, [](const auto sum, const auto &content) {
                return sum + content->getTextLength();
            });
        }

        [[nodiscard]] bool empty() const noexcept
        {
            return ((end == TextBlock::End::Newline && count() == 1) || (end == TextBlock::End::None && count() == 0));
        }

        [[nodiscard]] Length width() const noexcept

M module-gui/gui/widgets/TextLineCursor.cpp => module-gui/gui/widgets/TextLineCursor.cpp +5 -1
@@ 52,7 52,11 @@ namespace gui
                                         : 0;

        auto newLineAtBeginningSubtraction =
            previousLine->getEnd() == TextBlock::End::Newline && selectedLineCursorPosition == 0 ? 1 : 0;
            (previousLine->getEnd() == TextBlock::End::Newline) && (selectedLineCursorPosition == 0) &&
                    (selectedLineNumber >= 2) &&
                    (text->lines->getLine(selectedLineNumber - 2)->getEnd() == TextBlock::End::None)
                ? 1
                : 0;

        auto moveCount = selectedLineCursorPosition + previousLineEndAddition + previousLineMoveCount -
                         newLineAtBeginningSubtraction;

M module-gui/test/test-catch-text/test-gui-Text.cpp => module-gui/test/test-catch-text/test-gui-Text.cpp +114 -0
@@ 65,6 65,18 @@ namespace gui
            return lines->get();
        }

        [[nodiscard]] auto lineGet(unsigned int nr)
        {
            auto line = lines->get().begin();

            if (nr >= lines->size()) {
                nr = lines->size() - 1;
            }

            std::advance(line, nr);
            return line;
        }

        [[nodiscard]] auto *getInputMode()
        {
            return mode;


@@ 957,3 969,105 @@ TEST_CASE("Text addition bounds - multiple limits tests")
        REQUIRE(text->getText().length() != signsLimit);
    }
}

TEST_CASE("RichText newline and empty lines tests")
{
    std::string testStringBlock1 = "Test String 1";
    std::string testStringBlock2 = "Test String 2";
    std::string testStringBlock3 = "Test String 3";
    std::string emptyParagraph   = "<p></p>";

    SECTION("Paragraph inside no newlines blocks")
    {
        mockup::fontManager();
        using namespace gui;
        auto text = std::make_unique<gui::TestText>();
        text->setMaximumSize(600, 200);

        text->addRichText("<text>" + testStringBlock1 + "<p>" + testStringBlock2 + "</p>" + testStringBlock3 +
                          "</text>");

        REQUIRE(text->linesSize() == 3);
        REQUIRE((*text->lineGet(0)).getText(0) == testStringBlock1 + "\n");
        REQUIRE((*text->lineGet(1)).getText(0) == testStringBlock2 + "\n");
        REQUIRE((*text->lineGet(2)).getText(0) == testStringBlock3);
    }

    SECTION("Two empty paragraphs at beginning")
    {
        mockup::fontManager();
        using namespace gui;
        auto text = std::make_unique<gui::TestText>();
        text->setMaximumSize(600, 200);

        text->addRichText("<text>" + emptyParagraph + emptyParagraph + testStringBlock1 + testStringBlock2 +
                          testStringBlock3 + "</text>");

        REQUIRE(text->linesSize() == 3);
        REQUIRE((*text->lineGet(0)).getText(0) == "\n");
        REQUIRE((*text->lineGet(1)).getText(0) == "\n");
        REQUIRE((*text->lineGet(2)).getText(0) == testStringBlock1 + testStringBlock2 + testStringBlock3);
    }

    SECTION("Two empty paragraphs at end")
    {
        mockup::fontManager();
        using namespace gui;
        auto text = std::make_unique<gui::TestText>();
        text->setMaximumSize(600, 200);

        text->addRichText("<text>" + testStringBlock1 + testStringBlock2 + testStringBlock3 + emptyParagraph +
                          emptyParagraph + "</text>");

        REQUIRE(text->linesSize() == 3);
        REQUIRE((*text->lineGet(0)).getText(0) == testStringBlock1 + testStringBlock2 + testStringBlock3 + "\n");
        REQUIRE((*text->lineGet(1)).getText(0) == "\n");
        REQUIRE((*text->lineGet(2)).getText(0) == "");
    }

    SECTION("One empty paragraphs at beginning, one in center and one at end")
    {
        mockup::fontManager();
        using namespace gui;
        auto text = std::make_unique<gui::TestText>();
        text->setMaximumSize(600, 200);

        text->addRichText("<text>" + emptyParagraph + testStringBlock1 + emptyParagraph + testStringBlock2 +
                          testStringBlock3 + emptyParagraph + "</text>");

        REQUIRE(text->linesSize() == 4);
        REQUIRE((*text->lineGet(0)).getText(0) == "\n");
        REQUIRE((*text->lineGet(1)).getText(0) == testStringBlock1 + "\n");
        REQUIRE((*text->lineGet(2)).getText(0) == testStringBlock2 + testStringBlock3 + "\n");
        REQUIRE((*text->lineGet(3)).getText(0) == "");
    }

    SECTION("Text inside paragraph at beginning")
    {
        mockup::fontManager();
        using namespace gui;
        auto text = std::make_unique<gui::TestText>();
        text->setMaximumSize(600, 200);

        text->addRichText("<text><p>" + testStringBlock1 + "</p>" + testStringBlock2 + testStringBlock3 + "</text>");

        REQUIRE(text->linesSize() == 2);
        REQUIRE((*text->lineGet(0)).getText(0) == testStringBlock1 + "\n");
        REQUIRE((*text->lineGet(1)).getText(0) == testStringBlock2 + testStringBlock3);
    }

    SECTION("Text empty paragraph and text inside paragraph at beginning")
    {
        mockup::fontManager();
        using namespace gui;
        auto text = std::make_unique<gui::TestText>();
        text->setMaximumSize(600, 200);

        text->addRichText("<text>" + emptyParagraph + "<p>" + testStringBlock1 + "</p></text>");

        REQUIRE(text->linesSize() == 3);
        REQUIRE((*text->lineGet(0)).getText(0) == "\n");
        REQUIRE((*text->lineGet(1)).getText(0) == testStringBlock1 + "\n");
        REQUIRE((*text->lineGet(2)).getText(0) == "");
    }
}