M changelog.md => changelog.md +1 -0
@@ 10,6 10,7 @@
* `[cellular]` Added change PIN functionality
* `[cellular]` Added possibility of unlock SIM card (no PIN on start) functionality
* `[testing]` Added test harness with message sending case
+* `[text]` Text input boundaries support added (max signs or max widget area).
### Changed
M module-gui/gui/widgets/Lines.cpp => module-gui/gui/widgets/Lines.cpp +63 -97
@@ 4,129 4,95 @@
#include "Lines.hpp"
#include "TextLineCursor.hpp"
#include "Text.hpp"
+#include "RawFont.hpp"
+
+#if DEBUG_GUI_TEXT_LINES == 1
+#define debug_text_lines(...) LOG_DEBUG(__VA_ARGS__)
+#else
+#define debug_text_lines(...)
+#endif
namespace gui
{
// LEFT/RIGHT/UP/DOWN
- auto Lines::checkNavigationBounds(TextLineCursor &cursor, InputEvent event) -> gui::InputBound
- {
- auto dir = inputToNavigation(event);
- if (dir == NavigationDirection::NONE) {
- return InputBound::UNDEFINED;
- }
-
- auto screen_bound = scroll_position + max_lines_count - 1;
- auto lines_bound = lines.size() - 1;
-
- if (dir == NavigationDirection::UP || dir == NavigationDirection::LEFT) {
- screen_bound = 0;
- lines_bound = 0;
- }
-
- if (dir == NavigationDirection::LEFT && cursor.getPosOnScreen() > 0) {
- return InputBound::CAN_MOVE;
- }
-
- unsigned int pos = cursor.BlockCursor::getPosition();
- auto textLine = getTextLine(cursor.getScreenLine());
-
- if (textLine == nullptr) {
- return InputBound::NO_DATA;
- }
-
- size_t lineLength = textLine->length();
- if (dir == NavigationDirection::RIGHT && pos < lineLength) {
- return InputBound::CAN_MOVE;
- }
-
- if (cursor.getScreenLine() >= lines_bound) {
- return InputBound::NO_DATA;
+ auto Lines::linesVAlign(Length parentSize) -> void
+ {
+ for (auto &line : lines) {
+ line.alignV(text->getAlignment(Axis::Y), parentSize, linesHeight());
}
+ }
- if (cursor.getScreenLine() >= screen_bound) {
- return InputBound::HIT_BOUND;
+ auto Lines::linesHAlign(Length parentSize) -> void
+ {
+ for (auto &line : lines) {
+ line.alignH(text->getAlignment(Axis::X), parentSize);
}
-
- return InputBound::CAN_MOVE;
}
- auto Lines::checkAdditionBounds(TextLineCursor &cursor, InputEvent event) -> gui::InputBound
+ auto Lines::draw(BlockCursor &drawCursor, Length w, Length h, Position lineYPosition, Position lineXPosition)
+ -> void
{
- auto keymap = parent->mode != nullptr ? parent->mode->get() : "";
- auto code = gui::Profiles::get(keymap).get(event.key.key_code, 0);
+ while (true) {
+ auto textLine = gui::TextLine(drawCursor, w);
- auto format = cursor->getFormat();
- uint32_t line = cursor.getScreenLine();
- TextLine *textLine = getTextLine(line);
+ if (textLine.length() == 0 && textLine.getLineEnd()) {
+ debug_text_lines("cant show more text from this document");
+ break;
+ }
- if (textLine == nullptr || !cursor) {
- return InputBound::CAN_ADD;
- }
+ if (lineYPosition + textLine.height() > h) { // no more space for next line
+ debug_text_lines("no more space for next text_line: %d + %" PRIu32 " > %" PRIu32,
+ lineYPosition,
+ textLine.height(),
+ h);
+ break;
+ }
- auto bound = textLine->checkBounds(cursor, code, format);
- if (bound == InputBound::CANT_PROCESS && line == scroll_position) {
- // TODO -> to be corrected in next PR
- return InputBound::CAN_ADD;
- }
+ emplace(std::move(textLine));
+ auto &line = last();
- return InputBound::CAN_ADD;
- }
+ line.setPosition(lineXPosition, lineYPosition);
+ line.setParent(text);
- auto Lines::checkRemovalBounds(TextLineCursor &cursor, InputEvent event) -> gui::InputBound
- {
- if (lines.empty()) {
- return InputBound::CANT_PROCESS;
+ lineYPosition += line.height();
}
+ }
- // TODO -> to be corrected in next PR
- return InputBound::CAN_REMOVE;
+ auto Lines::draw(BlockCursor &drawCursor,
+ Length w,
+ Length h,
+ Position lineYPosition,
+ Position lineXPosition,
+ unsigned int linesCount) -> void
+ {
+ Length initHeight = text->getTextFormat().getFont()->info.line_height;
- uint32_t line = cursor.getScreenLine();
- uint32_t pos = cursor.getPosOnScreen();
+ while (true) {
+ auto textLine =
+ gui::TextLine(drawCursor, w, initHeight, underLine, UnderlineDrawMode::WholeLine, underLinePadding);
- if (pos == 0) {
- if (line == scroll_position + max_lines_count) {
- return InputBound::HIT_BOUND;
- }
- if (line == 0) {
- return InputBound::CANT_PROCESS;
+ if (textLine.height() > 0 && initHeight != textLine.height()) {
+ initHeight = textLine.height();
}
- }
- return InputBound::CAN_REMOVE;
- }
-
- void Lines::updateScrollPosition(NavigationDirection dir, unsigned int lines_to_scroll)
- {
- if (dir == NavigationDirection::UP) {
- scroll_position -= lines_to_scroll;
- }
+ if (lineYPosition + initHeight > h) {
+ break;
+ }
- if (dir == NavigationDirection::DOWN) {
- scroll_position += lines_to_scroll;
- }
- }
+ if (lines.size() >= linesCount) {
+ break;
+ }
- void Lines::linesVAlign(Length parentSize)
- {
- for (auto &line : lines) {
- line.alignV(parent->getAlignment(Axis::Y), parentSize, linesHeight());
- }
- }
+ emplace(std::move(textLine));
+ auto &line = last();
+ line.setPosition(lineXPosition, lineYPosition);
+ line.setParent(text);
- void Lines::linesHAlign(Length parentSize)
- {
- for (auto &line : lines) {
- line.alignH(parent->getAlignment(Axis::X), parentSize);
+ lineYPosition += line.height();
}
}
- void Lines::draw(TextCursor &cursor)
- {
- parent->drawLines();
- }
-
TextLine *Lines::getTextLine(uint32_t line)
{
if (lines.empty() || line >= lines.size()) {
@@ 135,6 101,6 @@ namespace gui
auto it = std::next(lines.begin(), line);
return &*it;
- } // namespace gui
+ }
-} // namespace gui>
\ No newline at end of file
+} // namespace gui
M module-gui/gui/widgets/Lines.hpp => module-gui/gui/widgets/Lines.hpp +40 -10
@@ 22,21 22,24 @@ namespace gui
class Lines
{
- Text *parent = nullptr;
+ Text *text = nullptr;
std::list<TextLine> lines;
uint32_t max_lines_count = 4;
uint32_t scroll_position = 0;
+ bool underLine = false;
+ Position underLinePadding = 0;
+
public:
- Lines(Text *parent) : parent(parent)
+ Lines(Text *text) : text(text)
{}
~Lines() = default;
void erase()
{
- if (parent != nullptr) {
+ if (text != nullptr) {
for (auto &line : lines) {
line.erase();
}
@@ 64,6 67,11 @@ namespace gui
return lines.size();
}
+ [[nodiscard]] auto empty() const noexcept -> bool
+ {
+ return lines.empty();
+ }
+
auto maxWidth()
{
unsigned int w = 0;
@@ 83,14 91,36 @@ namespace gui
return h;
}
- void draw(TextCursor &cursor);
+ auto setUnderLine(bool val) -> void
+ {
+ underLine = val;
+ }
+
+ auto getUnderLine() -> bool
+ {
+ return underLine;
+ }
+
+ auto setUnderLinePadding(Position val) -> void
+ {
+ underLinePadding = val;
+ }
+
+ auto getUnderLinePadding() -> Position
+ {
+ return underLinePadding;
+ }
+
+ auto draw(BlockCursor &drawCursor, Length w, Length h, Position lineYPosition, Position lineXPosition) -> void;
+ auto draw(BlockCursor &drawCursor,
+ Length w,
+ Length h,
+ Position lineYPosition,
+ Position lineXPosition,
+ unsigned int linesCount) -> void;
- void linesHAlign(Length parentSize);
- void linesVAlign(Length parentSize);
- auto checkNavigationBounds(TextLineCursor &cursor, InputEvent event) -> InputBound;
- auto checkAdditionBounds(TextLineCursor &cursor, InputEvent event) -> InputBound;
- auto checkRemovalBounds(TextLineCursor &cursor, InputEvent event) -> InputBound;
- void updateScrollPosition(NavigationDirection scroll, unsigned int lines_to_scroll = 1);
+ auto linesHAlign(Length parentSize) -> void;
+ auto linesVAlign(Length parentSize) -> void;
protected:
TextLine *getTextLine(uint32_t line);
M module-gui/gui/widgets/Text.cpp => module-gui/gui/widgets/Text.cpp +426 -149
@@ 95,10 95,29 @@ namespace gui
void Text::setTextType(TextType type)
{}
+ void Text::setTextLimitType(TextLimitType limitType, unsigned int val)
+ {
+ auto it = std::find_if(limitsList.begin(), limitsList.end(), [&limitType](const TextLimit &limitOnList) {
+ return limitOnList.limitType == limitType;
+ });
+
+ if (it != limitsList.end()) {
+ (*it).limitValue = val;
+ }
+ else {
+ limitsList.emplace_back(TextLimit{limitType, val});
+ }
+ }
+
+ void Text::clearTextLimits()
+ {
+ limitsList.clear();
+ }
+
void Text::setUnderline(const bool val)
{
- if (underline != val) {
- underline = val;
+ if (lines->getUnderLine() != val) {
+ lines->setUnderLine(val);
drawLines();
}
}
@@ 106,8 125,7 @@ namespace gui
void Text::setText(const UTF8 &text)
{
debug_text("setText: %s", text.c_str());
- /// TODO here should be format passed
- setText(std::make_unique<TextDocument>(textToTextBlocks(text, format.getFont(), TextBlock::End::None)));
+ setText(std::make_unique<TextDocument>(textToTextBlocks(text, format)));
}
void Text::setText(std::unique_ptr<TextDocument> &&doc)
@@ 196,12 214,6 @@ namespace gui
buildCursor();
}
- std::tuple<NavigationDirection, uint32_t> scrollView(const TextCursor &cursor)
- {
- uint32_t scrolledLines = 1;
- return {NavigationDirection::UP, scrolledLines};
- }
-
bool Text::onInput(const InputEvent &evt)
{
if (Rect::onInput(evt)) {
@@ 228,7 240,7 @@ namespace gui
debug_text("handleNavigation");
return true;
}
- if (handleBackspace(evt)) {
+ if (handleRemovalChar(evt)) {
debug_text("handleBackspace");
return true;
}
@@ 287,69 299,21 @@ namespace gui
return true;
}
- bool Text::handleNavigation(const InputEvent &inputEvent)
+ auto Text::getSizeMinusPadding(Axis axis, Area val) -> Length
{
- if (!inputEvent.isShortPress()) {
- return false;
- }
+ auto size = area(val).size(axis);
- if (lines->checkNavigationBounds(*cursor, inputEvent) == InputBound::CAN_MOVE) {
-
- if (isMode(EditMode::SCROLL) && (inputEvent.is(KeyCode::KEY_LEFT) || inputEvent.is(KeyCode::KEY_RIGHT))) {
- debug_text("Text in scroll mode ignores left/right navigation");
- return false;
- }
- auto ret = cursor->moveCursor(inputToNavigation(inputEvent));
- debug_text("moveCursor: %s", c_str(ret));
- if (ret == TextCursor::Move::Start || ret == TextCursor::Move::End) {
- debug_text("scrolling needs implementing");
- return false;
- }
- if (ret != TextCursor::Move::Error) {
- return true;
- }
+ if (size <= padding.getSumInAxis(axis)) {
+ size = 0;
}
-
- return false;
- }
-
- bool Text::handleEnter()
- {
- return false;
- }
-
- bool Text::addChar(uint32_t utf_value)
- {
- cursor->addChar(utf_value);
- auto block = document->getBlock(cursor);
-
- if (block == nullptr) {
- return false;
+ else {
+ size -= padding.getSumInAxis(axis);
}
- debug_text("value: %d, block len: %d", utf_value, block->length());
- return true;
+ return size;
}
- void Text::drawCursor()
+ auto Text::applyParentSizeRestrictions() -> void
{
- cursor->updateView();
- }
-
- void Text::drawLines()
- {
- lines->erase();
-
- auto sizeMinusPadding = [&](Axis axis, Area val) {
- auto size = area(val).size(axis);
- if (size <= padding.getSumInAxis(axis)) {
- size = 0;
- }
- else {
- size -= padding.getSumInAxis(axis);
- }
- return size;
- };
-
// Check if Parent does not have max size restrictions.
if (this->parent != nullptr) {
area(Area::Max).w = parent->area(Area::Max).w != 0 ? std::min(parent->area(Area::Max).w, area(Area::Max).w)
@@ 357,71 321,50 @@ namespace gui
area(Area::Max).h = parent->area(Area::Max).h != 0 ? std::min(parent->area(Area::Max).h, area(Area::Max).h)
: area(Area::Max).h;
}
+ }
- Length w = sizeMinusPadding(Axis::X, Area::Max);
- Length h = sizeMinusPadding(Axis::Y, Area::Max);
+ auto Text::drawCursor() -> void
+ {
+ cursor->updateView();
+ }
+
+ auto Text::drawLines() -> void
+ {
+ lines->erase();
- auto lineYPosition = padding.top;
+ applyParentSizeRestrictions();
BlockCursor drawCursor(cursor->getDocument(), 0, 0, getTextFormat().getFont());
debug_text("--> START drawLines: {%" PRIu32 ", %" PRIu32 "}", w, h);
- auto lineXPosition = padding.left;
- do {
- auto textLine = gui::TextLine(drawCursor, w);
+ lines->draw(drawCursor,
+ getSizeMinusPadding(Axis::X, Area::Max),
+ getSizeMinusPadding(Axis::Y, Area::Max),
+ padding.top,
+ padding.left);
- if (textLine.length() == 0 && textLine.getLineEnd()) {
- debug_text("cant show more text from this document");
- break;
- }
+ calculateAndRequestSize();
- if (lineYPosition + textLine.height() > h) { // no more space for next line
- debug_text("no more space for next text_line: %d + %" PRIu32 " > %" PRIu32,
- lineYPosition,
- textLine.height(),
- h);
- lineYPosition += textLine.height();
- break;
- }
+ lines->linesHAlign(getSizeMinusPadding(Axis::X, Area::Normal));
+ lines->linesVAlign(getSizeMinusPadding(Axis::Y, Area::Normal));
- // for each different text which fits in line, addWidget last - to not trigger callbacks to parent
- // on resizes while not needed, after detach there can be no `break` othervise there will be leak - hence
- // detach
- lines->emplace(std::move(textLine));
- auto &line = lines->last();
-
- line.setPosition(lineXPosition, lineYPosition);
- line.setParent(this);
-
- lineYPosition += line.height();
-
- debug_text(
- "debug text drawing: \n cursor pos: %d line length: %d : document length "
- "%d \n x: %d, y: %d \n%s \n, lines count %lu",
- drawCursor.getPosition(),
- lines->last().length(),
- document->getText().length(),
- lineXPosition,
- lineYPosition,
- [&]() -> std::string {
- std::string text = document->getText();
- return text;
- }()
- .c_str(),
- lines->size());
- } while (true);
+ debug_text("<- END\n");
+ }
+ auto Text::calculateAndRequestSize() -> void
+ {
// silly case resize - there request space and all is nice
// need to at least erase last line if it wont fit
// should be done on each loop
{
- Length hUsed = lineYPosition + padding.bottom;
+ Length hUsed = padding.top + lines->linesHeight() + padding.bottom;
Length wUsed = lines->maxWidth() + padding.getSumInAxis(Axis::X);
if (lines->size() == 0) {
debug_text("No lines to show, try to at least fit in cursor");
- if (format.getFont() != nullptr && lineYPosition < format.getFont()->info.line_height) {
+ if (format.getFont() != nullptr &&
+ padding.top + lines->linesHeight() < format.getFont()->info.line_height) {
hUsed = format.getFont()->info.line_height;
wUsed = TextCursor::default_width;
debug_text("empty line height: %d", hUsed);
@@ 436,11 379,6 @@ namespace gui
debug_text("No free height for text!");
}
}
-
- lines->linesHAlign(sizeMinusPadding(Axis::X, Area::Normal));
- lines->linesVAlign(sizeMinusPadding(Axis::Y, Area::Normal));
-
- debug_text("<- END\n");
}
}
@@ 466,14 404,22 @@ namespace gui
void Text::buildDocument(const UTF8 &text)
{
- buildDocument(std::make_unique<TextDocument>(textToTextBlocks(text, format.getFont(), TextBlock::End::None)));
+ buildDocument(std::make_unique<TextDocument>(textToTextBlocks(text, format)));
}
void Text::buildDocument(std::unique_ptr<TextDocument> &&document_moved)
{
- document = std::move(document_moved);
- debug_text("document text: %s", document->getText().c_str());
+ if (document_moved == nullptr) {
+ debug_text("Passed invalid document, returning without setting it");
+ return;
+ }
+ document->destroy();
buildCursor();
+
+ for (const auto &block : document_moved->getBlocks()) {
+ *cursor << block;
+ }
+ debug_text("document text: %s", document->getText().c_str());
drawLines();
}
@@ 491,7 437,7 @@ namespace gui
cursor->setVisible(focus && isMode(EditMode::EDIT));
}
- bool Text::handleRotateInputMode(const InputEvent &inputEvent)
+ auto Text::handleRotateInputMode(const InputEvent &inputEvent) -> bool
{
if (mode != nullptr && inputEvent.isShortPress() && inputEvent.keyCode == gui::KeyCode::KEY_AST) {
mode->next();
@@ 500,7 446,7 @@ namespace gui
return false;
}
- bool Text::handleRestoreInputModeUI(const InputEvent &inputEvent)
+ auto Text::handleRestoreInputModeUI(const InputEvent &inputEvent) -> bool
{
if (mode != nullptr && inputEvent.isKeyRelease()) {
mode->show_restore();
@@ 508,7 454,7 @@ namespace gui
return false;
}
- bool Text::handleSelectSpecialChar(const InputEvent &inputEvent)
+ auto Text::handleSelectSpecialChar(const InputEvent &inputEvent) -> bool
{
if (mode != nullptr && inputEvent.isLongPress() && inputEvent.keyCode == gui::KeyCode::KEY_AST) {
@@ 518,53 464,73 @@ namespace gui
return false;
}
- bool Text::handleActivation(const InputEvent &inputEvent)
+ auto Text::handleActivation(const InputEvent &inputEvent) -> bool
{
return inputEvent.isShortPress() && inputEvent.is(KeyCode::KEY_AST) && Rect::onActivated(nullptr);
}
- bool Text::handleBackspace(const InputEvent &inputEvent)
+ auto Text::handleNavigation(const InputEvent &inputEvent) -> bool
+ {
+ if (!inputEvent.isShortPress()) {
+ return false;
+ }
+
+ if (isMode(EditMode::SCROLL) && (inputEvent.is(KeyCode::KEY_LEFT) || inputEvent.is(KeyCode::KEY_RIGHT))) {
+ debug_text("Text in scroll mode ignores left/right navigation");
+ return false;
+ }
+ auto ret = cursor->moveCursor(inputToNavigation(inputEvent));
+ debug_text("moveCursor: %s", c_str(ret));
+ if (ret == TextCursor::Move::Start || ret == TextCursor::Move::End) {
+ debug_text("scrolling needs implementing");
+ return false;
+ }
+ if (ret != TextCursor::Move::Error) {
+ return true;
+ }
+
+ return false;
+ }
+
+ bool Text::handleRemovalChar(const InputEvent &inputEvent)
{
if (!isMode(EditMode::EDIT)) {
return false;
}
- if (lines->checkRemovalBounds(*cursor, inputEvent) == InputBound::CAN_REMOVE) {
- if (inputEvent.isShortPress() && inputEvent.is(key_signs_remove)) {
- if (!document->isEmpty() && removeChar()) {
- onTextChanged();
- drawLines();
- }
- return true;
+ if (inputEvent.isShortPress() && inputEvent.is(key_signs_remove)) {
+ if (!document->isEmpty() && removeChar()) {
+ onTextChanged();
+ drawLines();
}
+ return true;
}
return false;
}
bool Text::handleAddChar(const InputEvent &inputEvent)
{
- if (inputEvent.isShortPress() == false || !isMode(EditMode::EDIT)) {
+ if (!inputEvent.isShortPress() || !isMode(EditMode::EDIT)) {
return false;
}
- if (lines->checkAdditionBounds(*cursor, inputEvent) == InputBound::CAN_ADD) {
+ auto code = translator.handle(inputEvent.key, mode ? mode->get() : "");
+
+ if (code != KeyProfile::none_key && checkAdditionBounds(code) == InputBound::CAN_ADD) {
- auto code = translator.handle(inputEvent.key, mode ? mode->get() : "");
debug_text("handleAddChar %d -> Begin", code);
debug_text("%s times: %" PRIu32, inputEvent.str().c_str(), translator.getTimes());
- if (code != KeyProfile::none_key) {
- /// if we have multi press in non digit mode - we need to replace char and put next char from translator
- if (!(mode->is(InputMode::digit) || (mode->is(InputMode::phone))) && translator.getTimes() > 0) {
- removeChar();
- }
- addChar(code);
- onTextChanged();
- drawLines();
+ /// if we have multi press in non digit mode - we need to replace char and put next char from translator
+ if (!(mode->is(InputMode::digit) || (mode->is(InputMode::phone))) && translator.getTimes() > 0) {
+ removeChar();
+ }
+ addChar(code);
+ onTextChanged();
+ drawLines();
- debug_text("handleAddChar -> End(true)");
+ debug_text("handleAddChar -> End(true)");
- return true;
- }
+ return true;
}
debug_text("handleAdChar -> End(false)");
@@ 576,16 542,327 @@ namespace gui
if (!inputEvent.isLongPress()) {
return false;
}
+
auto val = toNumeric(inputEvent.keyCode);
- if (val != InvalidNumericKeyCode) {
+
+ if (val != InvalidNumericKeyCode && checkAdditionBounds(val) == InputBound::CAN_ADD) {
+
addChar(intToAscii(val));
onTextChanged();
drawLines();
return true;
}
+
return false;
}
+ auto Text::makePreDrawLines(const uint32_t utfVal) -> std::unique_ptr<Lines>
+ {
+ auto preDrawLines = std::make_unique<Lines>(this);
+ auto documentCopy = *cursor->getDocument();
+ auto formatCopy = getTextFormat().getFont();
+
+ applyParentSizeRestrictions();
+
+ BlockCursor preDrawCursor(&documentCopy, 0, 0, formatCopy);
+ preDrawCursor.addChar(utfVal);
+
+ preDrawLines->draw(
+ preDrawCursor, getSizeMinusPadding(Axis::X, Area::Max), text::npos, padding.top, padding.left);
+
+ return preDrawLines;
+ }
+
+ auto Text::makePreDrawLines(const TextBlock &textBlock) -> std::unique_ptr<Lines>
+ {
+ auto preDrawLines = std::make_unique<Lines>(this);
+ auto documentCopy = *cursor->getDocument();
+ auto formatCopy = getTextFormat().getFont();
+ auto preDrawTextBlock = TextBlock(textBlock);
+ auto preDrawTextEnd = textBlock.getEnd();
+
+ applyParentSizeRestrictions();
+
+ BlockCursor preDrawCursor(&documentCopy, 0, 0, formatCopy);
+
+ applyParentSizeRestrictions();
+
+ preDrawCursor.addTextBlock(std::move(preDrawTextBlock));
+
+ if (preDrawTextEnd == TextBlock::End::Newline) {
+ documentCopy.append(TextBlock("", formatCopy, TextBlock::End::None));
+ }
+
+ preDrawLines->draw(
+ preDrawCursor, getSizeMinusPadding(Axis::X, Area::Max), text::npos, padding.top, padding.left);
+
+ return preDrawLines;
+ }
+
+ auto Text::checkMaxSignsLimit(unsigned int limitVal) -> InputBound
+ {
+ if (getText().length() >= limitVal) {
+ debug_text("Text at max signs count can't add more");
+ return InputBound::HIT_BOUND;
+ }
+ else {
+ return InputBound::CAN_ADD;
+ }
+ }
+
+ auto Text::checkMaxSignsLimit(const TextBlock &textBlock, unsigned int limitVal)
+ -> std::tuple<InputBound, TextBlock>
+ {
+ if (getText().length() >= limitVal) {
+ debug_text("Text at max signs count can't add more.");
+ return {InputBound::HIT_BOUND, textBlock};
+ }
+ else if (getText().length() + textBlock.length() >= limitVal) {
+
+ // Split existing block into smaller one that can still fit and return it
+ auto availableSpace = limitVal - getText().length();
+ auto partBlockText = textBlock.getText().substr(0, availableSpace);
+ auto blockFormat = textBlock.getFormat();
+
+ debug_text("Text at max sign count adding part of block. Original: %s, Fit part %s",
+ textBlock.getText().c_str(),
+ partBlockText.c_str());
+
+ return {InputBound::CAN_ADD_PART, TextBlock(partBlockText, std::make_unique<TextFormat>(*blockFormat))};
+ }
+ else {
+ return {InputBound::CAN_ADD, textBlock};
+ }
+ }
+
+ auto Text::checkMaxSizeLimit(uint32_t utfVal) -> InputBound
+ {
+ auto returnValue = InputBound::CAN_ADD;
+
+ auto preDrawLines = makePreDrawLines(utfVal);
+
+ debug_text("Text lines height: %d, preDraw height: %d, Widget max h: %d",
+ lines->linesHeight(),
+ preDrawLines->linesHeight(),
+ area(Area::Max).h);
+
+ if (preDrawLines->maxWidth() == 0 ||
+ preDrawLines->linesHeight() + getPadding().getSumInAxis(Axis::Y) > area(Area::Max).h) {
+
+ debug_text("Text at max size can't add more");
+ preDrawLines->erase();
+ returnValue = InputBound::HIT_BOUND;
+ }
+
+ preDrawLines->erase();
+ return returnValue;
+ }
+
+ auto Text::checkMaxSizeLimit(const TextBlock &textBlock) -> std::tuple<InputBound, TextBlock>
+ {
+ auto preDrawLines = makePreDrawLines(textBlock);
+
+ debug_text("Text lines height: %d, preDraw height: %d, Widget max h: %d",
+ lines->linesHeight(),
+ preDrawLines->linesHeight(),
+ area(Area::Max).h);
+
+ if (preDrawLines->maxWidth() == 0) {
+ preDrawLines->erase();
+ return {InputBound::HIT_BOUND, textBlock};
+ }
+
+ if (preDrawLines->linesHeight() + getPadding().getSumInAxis(Axis::Y) > area(Area::Max).h) {
+
+ debug_text("Text at max size can't add whole bock, try to split");
+
+ for (unsigned int signCounter = textBlock.length(); signCounter != 0; signCounter--) {
+
+ preDrawLines->erase();
+
+ auto partBlockText = textBlock.getText().substr(0, signCounter);
+ auto blockFormat = textBlock.getFormat();
+
+ preDrawLines = makePreDrawLines(TextBlock(partBlockText, std::make_unique<TextFormat>(*blockFormat)));
+
+ debug_text("Text lines height: %d, preDraw height: %d, Widget max h: %d",
+ lines->linesHeight(),
+ preDrawLines->linesHeight(),
+ area(Area::Max).h);
+
+ if (preDrawLines->linesHeight() + getPadding().getSumInAxis(Axis::Y) <= area(Area::Max).h) {
+
+ preDrawLines->erase();
+
+ debug_text("Text at max size adding part of block. Original: %s, Fit part %s",
+ textBlock.getText().c_str(),
+ partBlockText.c_str());
+
+ return {InputBound::CAN_ADD_PART,
+ TextBlock(partBlockText, std::make_unique<TextFormat>(*blockFormat))};
+ }
+ }
+
+ preDrawLines->erase();
+ // If not a part of block can fit return hit bound.
+ return {InputBound::HIT_BOUND, textBlock};
+ }
+
+ preDrawLines->erase();
+ return {InputBound::CAN_ADD, textBlock};
+ }
+
+ auto Text::checkMaxLinesLimit(uint32_t utfVal, unsigned int limitVal) -> InputBound
+ {
+ auto returnValue = InputBound::CAN_ADD;
+
+ auto preDrawLines = makePreDrawLines(utfVal);
+
+ debug_text("Text lines height: %d, preDraw height: %d, Widget max h: %d",
+ lines->linesHeight(),
+ preDrawLines->linesHeight(),
+ area(Area::Max).h);
+
+ if (preDrawLines->size() > limitVal) {
+
+ debug_text("Text at max size can't add more");
+ preDrawLines->erase();
+ returnValue = InputBound::HIT_BOUND;
+ }
+
+ preDrawLines->erase();
+ return returnValue;
+ }
+
+ auto Text::checkMaxLinesLimit(const TextBlock &textBlock, unsigned int limitVal)
+ -> std::tuple<InputBound, TextBlock>
+ {
+ auto preDrawLines = makePreDrawLines(textBlock);
+
+ debug_text("Text lines height: %d, preDraw height: %d, Widget max h: %d",
+ lines->linesHeight(),
+ preDrawLines->linesHeight(),
+ area(Area::Max).h);
+
+ if (preDrawLines->maxWidth() == 0) {
+ preDrawLines->erase();
+ return {InputBound::HIT_BOUND, textBlock};
+ }
+
+ if (preDrawLines->size() > limitVal) {
+
+ debug_text("Text at max line size can't add whole bock, try to split");
+
+ for (unsigned int signCounter = textBlock.length(); signCounter != 0; signCounter--) {
+
+ preDrawLines->erase();
+
+ auto partBlockText = textBlock.getText().substr(0, signCounter);
+ auto blockFormat = textBlock.getFormat();
+
+ preDrawLines = makePreDrawLines(TextBlock(partBlockText, std::make_unique<TextFormat>(*blockFormat)));
+
+ debug_text("Text lines height: %d, preDraw height: %d, Widget max h: %d",
+ lines->linesHeight(),
+ preDrawLines->linesHeight(),
+ area(Area::Max).h);
+
+ if (preDrawLines->size() <= limitVal) {
+
+ preDrawLines->erase();
+
+ debug_text("Text at max line size adding part of block. Original: %s, Fit part %s",
+ textBlock.getText().c_str(),
+ partBlockText.c_str());
+
+ return {InputBound::CAN_ADD_PART,
+ TextBlock(partBlockText, std::make_unique<TextFormat>(*blockFormat))};
+ }
+ }
+
+ preDrawLines->erase();
+ // If not a part of block can fit return hit bound.
+ return {InputBound::HIT_BOUND, textBlock};
+ }
+
+ preDrawLines->erase();
+ return {InputBound::CAN_ADD, textBlock};
+ }
+
+ auto Text::checkAdditionBounds(const uint32_t utfVal) -> InputBound
+ {
+ auto returnValue = InputBound::CAN_ADD;
+
+ for (auto limit : limitsList) {
+
+ switch (limit.limitType) {
+ case TextLimitType::MAX_SIGNS_COUNT:
+ returnValue = checkMaxSignsLimit(limit.limitValue);
+ break;
+ case TextLimitType::MAX_LINES:
+ returnValue = checkMaxLinesLimit(utfVal, limit.limitValue);
+ break;
+ case TextLimitType::MAX_SIZE:
+ returnValue = checkMaxSizeLimit(utfVal);
+ break;
+ default:
+ break;
+ }
+
+ if (returnValue == InputBound::HIT_BOUND) {
+ return returnValue;
+ }
+ }
+ return returnValue;
+ }
+
+ auto Text::checkAdditionBounds(const TextBlock &textBlock) -> std::tuple<InputBound, TextBlock>
+ {
+ std::tuple<InputBound, TextBlock> returnValue = {InputBound::CAN_ADD, textBlock};
+ auto shortestProcessedBlock = textBlock;
+
+ for (auto limit : limitsList) {
+
+ switch (limit.limitType) {
+ case TextLimitType::MAX_SIGNS_COUNT:
+ returnValue = checkMaxSignsLimit(textBlock, limit.limitValue);
+ break;
+ case TextLimitType::MAX_LINES:
+ returnValue = checkMaxLinesLimit(textBlock, limit.limitValue);
+ break;
+ case TextLimitType::MAX_SIZE:
+ returnValue = checkMaxSizeLimit(textBlock);
+ break;
+ default:
+ break;
+ }
+
+ if (std::get<0>(returnValue) == InputBound::CAN_ADD_PART) {
+ if (std::get<1>(returnValue).length() < shortestProcessedBlock.length()) {
+ shortestProcessedBlock = std::get<1>(returnValue);
+ }
+ }
+
+ if (std::get<0>(returnValue) == InputBound::HIT_BOUND) {
+ return returnValue;
+ }
+ }
+
+ return {std::get<0>(returnValue), shortestProcessedBlock};
+ }
+
+ bool Text::addChar(uint32_t utf_value)
+ {
+ cursor->addChar(utf_value);
+ auto block = document->getBlock(cursor);
+
+ if (block == nullptr) {
+ return false;
+ }
+ debug_text("value: %d, block len: %d", utf_value, block->length());
+ return true;
+ }
+
bool Text::removeChar()
{
if (!document->isEmpty()) {
@@ 619,6 896,6 @@ namespace gui
// Move cursor to backup position from end of document.
cursor->TextCursor::moveCursor(NavigationDirection::LEFT, cursorPosDiff);
}
- };
+ }
} /* namespace gui */
M module-gui/gui/widgets/Text.hpp => module-gui/gui/widgets/Text.hpp +29 -15
@@ 76,20 76,39 @@ namespace gui
protected:
TextType textType = TextType::MULTI_LINE;
+ std::list<TextLimit> limitsList;
+
/// points to default text font to use
- bool underline = false;
TextFormat format;
- auto moveCursor(const NavigationDirection &direction, std::unique_ptr<TextDocument> &document) -> bool;
+ auto handleRotateInputMode(const InputEvent &inputEvent) -> bool;
+ auto handleRestoreInputModeUI(const InputEvent &inputEvent) -> bool;
+ auto handleSelectSpecialChar(const InputEvent &inputEvent) -> bool;
+ auto handleActivation(const InputEvent &inputEvent) -> bool;
auto handleNavigation(const InputEvent &inputEvent) -> bool;
- auto handleEnter() -> bool;
+ auto handleRemovalChar(const InputEvent &inputEvent) -> bool;
+ auto handleDigitLongPress(const InputEvent &inputEvent) -> bool;
+ auto handleAddChar(const InputEvent &inputEvent) -> bool;
+
+ [[nodiscard]] auto getSizeMinusPadding(Axis axis, Area val) -> Length;
+ auto applyParentSizeRestrictions() -> void;
+ auto calculateAndRequestSize() -> void;
+ auto makePreDrawLines(const uint32_t utfVal) -> std::unique_ptr<Lines>;
+ auto makePreDrawLines(const TextBlock &textBlock) -> std::unique_ptr<Lines>;
+
+ auto checkMaxSignsLimit(unsigned int limitVal) -> InputBound;
+ auto checkMaxSignsLimit(const TextBlock &textBlock, unsigned int limitVal) -> std::tuple<InputBound, TextBlock>;
+ auto checkMaxSizeLimit(uint32_t utfVal) -> InputBound;
+ auto checkMaxSizeLimit(const TextBlock &textBlock) -> std::tuple<InputBound, TextBlock>;
+ auto checkMaxLinesLimit(uint32_t utfVal, unsigned int limitVal) -> InputBound;
+ auto checkMaxLinesLimit(const TextBlock &textBlock, unsigned int limitVal) -> std::tuple<InputBound, TextBlock>;
void preBuildDrawListHookImplementation(std::list<Command> &commands);
/// redrawing lines
/// it redraws visible lines on screen and if needed requests resize in parent
- virtual void drawLines();
+ virtual auto drawLines() -> void;
/// redrawing cursor
- void drawCursor();
+ auto drawCursor() -> void;
public:
/// Callback when text changed
@@ 110,7 129,9 @@ namespace gui
void setEditMode(EditMode mode);
void setTextType(TextType type);
- void setUnderline(const bool val);
+ void setTextLimitType(TextLimitType limitType, unsigned int val = 0);
+ void clearTextLimits();
+ void setUnderline(bool val);
virtual void setText(const UTF8 &text);
void setText(std::unique_ptr<TextDocument> &&document);
@@ 162,17 183,10 @@ namespace gui
public:
TextChangedCallback textChangedCallback;
- bool handleRotateInputMode(const InputEvent &inputEvent);
- bool handleRestoreInputModeUI(const InputEvent &inputEvent);
- bool handleSelectSpecialChar(const InputEvent &inputEvent);
- bool handleActivation(const InputEvent &inputEvent);
- bool handleBackspace(const InputEvent &inputEvent);
- bool handleDigitLongPress(const InputEvent &inputEvent);
- bool handleAddChar(const InputEvent &inputEvent);
-
+ auto checkAdditionBounds(uint32_t utfVal) -> InputBound;
+ auto checkAdditionBounds(const TextBlock &textBlock) -> std::tuple<InputBound, TextBlock>;
bool addChar(uint32_t utf8);
bool removeChar();
- InputBound processBound(InputBound bound, const InputEvent &event);
void onTextChanged();
};
M module-gui/gui/widgets/TextBlock.cpp => module-gui/gui/widgets/TextBlock.cpp +10 -0
@@ 30,6 30,16 @@ namespace gui
end = p.end;
}
+ TextBlock &TextBlock::operator=(const TextBlock &p)
+ {
+ if (this != &p) {
+ text = p.text;
+ format = std::make_unique<TextFormat>(*p.format);
+ end = p.end;
+ }
+ return *this;
+ }
+
const UTF8 &TextBlock::getText() const
{
return text;
M module-gui/gui/widgets/TextBlock.hpp => module-gui/gui/widgets/TextBlock.hpp +2 -0
@@ 50,5 50,7 @@ namespace gui
void addChar(uint32_t utf_val, unsigned int pos);
bool isEmpty() const;
+
+ TextBlock &operator=(const TextBlock &);
};
} // namespace gui
M module-gui/gui/widgets/TextBlockCursor.cpp => module-gui/gui/widgets/TextBlockCursor.cpp +6 -1
@@ 210,9 210,14 @@ namespace gui
void BlockCursor::addTextBlock(TextBlock &&textblock)
{
- if (textblock.length() == 0) {
+
+ if (textblock.length() == 0 && document->blocks.empty() && textblock.getEnd() != TextBlock::End::Newline) {
+ return;
+ }
+ else if (textblock.length() == 0 && ((--blocksEnd())->getEnd() != TextBlock::End::Newline)) {
return;
}
+
if (document->isEmpty()) {
resetNpos();
}
M module-gui/gui/widgets/TextBlockCursor.hpp => module-gui/gui/widgets/TextBlockCursor.hpp +3 -2
@@ 85,9 85,10 @@ namespace gui
[[nodiscard]] auto checkAndInvalidateBlockChanged() -> bool
{
if (blockChanged) {
- blockChanged = true;
+ blockChanged = false;
+ return true;
}
- return blockChanged;
+ return false;
}
[[nodiscard]] auto checkLastNewLine() -> bool
M module-gui/gui/widgets/TextConstants.hpp => module-gui/gui/widgets/TextConstants.hpp +17 -10
@@ 13,11 13,24 @@ namespace gui
const char newline = '\n';
}; // namespace text
+ enum class TextLimitType
+ {
+ MAX_SIZE,
+ MAX_LINES,
+ MAX_SIGNS_COUNT
+ };
+
+ struct TextLimit
+ {
+ TextLimitType limitType;
+ unsigned int limitValue;
+ };
+
enum class ExpandMode
{
EXPAND_UP,
EXPAND_DOWN,
- EXPAND_NONE // defult
+ EXPAND_NONE // default
};
enum class EditMode
@@ 35,15 48,9 @@ namespace gui
enum class InputBound
{
- UNDEFINED = 0x000,
-
- CANT_PROCESS = 0x100,
- NO_DATA = 0x101,
- HIT_BOUND = 0x110,
-
- CAN_ADD = 0x1000,
- CAN_MOVE = 0x10000,
- CAN_REMOVE = 0x100000
+ CAN_ADD,
+ CAN_ADD_PART,
+ HIT_BOUND
};
} // namespace gui
M module-gui/gui/widgets/TextCursor.cpp => module-gui/gui/widgets/TextCursor.cpp +23 -15
@@ 164,30 164,38 @@ namespace gui
moveCursor(NavigationDirection::RIGHT);
}
- TextCursor &TextCursor::operator<<(const UTF8 &text)
+ TextCursor &TextCursor::operator<<(const UTF8 &textString)
{
- for (unsigned int i = 0; i < text.length(); ++i) {
- addChar(text[i]);
+ for (unsigned int i = 0; i < textString.length(); ++i) {
+ if (text->checkAdditionBounds(textString[i]) == InputBound::CAN_ADD) {
+ addChar(textString[i]);
+ }
+ else {
+ break;
+ }
}
return *this;
}
- TextCursor &TextCursor::operator<<(TextBlock textblock)
+ TextCursor &TextCursor::operator<<(const TextBlock &textBlock)
{
- auto len = textblock.length();
- auto end = textblock.getEnd();
+ auto [addBoundResult, processedTextBlock] = text->checkAdditionBounds(textBlock);
- BlockCursor::addTextBlock(std::move(textblock));
+ if (addBoundResult == InputBound::CAN_ADD || addBoundResult == InputBound::CAN_ADD_PART) {
- // +1 is for block barrier
- for (unsigned int i = 0; i < len + 1; ++i) {
- moveCursor(NavigationDirection::RIGHT);
- }
+ auto len = processedTextBlock.length();
+ auto end = processedTextBlock.getEnd();
- // If new added block ends with newline split it for additional empty block at end
- if (end == TextBlock::End::Newline) {
- document->addNewline(*this, TextBlock::End::Newline);
- moveCursor(NavigationDirection::RIGHT);
+ BlockCursor::addTextBlock(std::move(processedTextBlock));
+
+ // +1 is for block barrier
+ moveCursor(NavigationDirection::RIGHT, len + 1);
+
+ // If new added block ends with newline split it for additional empty block at end
+ if (end == TextBlock::End::Newline) {
+ document->addNewline(*this, TextBlock::End::Newline);
+ moveCursor(NavigationDirection::RIGHT);
+ }
}
return *this;
M module-gui/gui/widgets/TextCursor.hpp => module-gui/gui/widgets/TextCursor.hpp +1 -1
@@ 58,7 58,7 @@ namespace gui
// TODO this can move our text out of bonds ( and might need calling expand() in Text)
void addChar(uint32_t utf_val);
TextCursor &operator<<(const UTF8 &);
- TextCursor &operator<<(TextBlock);
+ TextCursor &operator<<(const TextBlock &);
void removeChar();
[[nodiscard]] auto getPosOnScreen() const
M module-gui/gui/widgets/TextFixedSize.cpp => module-gui/gui/widgets/TextFixedSize.cpp +13 -51
@@ 1,3 1,4 @@
+
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
@@ 9,7 10,7 @@ namespace gui
TextFixedSize::TextFixedSize(Item *parent, Position x, Position y, Length w, Length h) : Text(parent, x, y, w, h)
{
setEditMode(EditMode::EDIT);
- underline = true;
+ lines->setUnderLine(true);
}
void TextFixedSize::setLines(const unsigned int val)
@@ 22,8 23,8 @@ namespace gui
void TextFixedSize::setUnderlinePadding(Position val)
{
- if (underlinePadding != val) {
- underlinePadding = val;
+ if (lines->getUnderLinePadding() != val) {
+ lines->setUnderLinePadding(val);
drawLines();
}
}
@@ 32,55 33,16 @@ namespace gui
{
lines->erase();
- auto sizeMinusPadding = [&](Axis axis, Area val) {
- auto size = area(val).size(axis);
- if (size <= padding.getSumInAxis(axis)) {
- size = 0;
- }
- else {
- size -= padding.getSumInAxis(axis);
- }
- return size;
- };
-
- uint32_t w = sizeMinusPadding(Axis::X, Area::Normal);
- uint32_t h = sizeMinusPadding(Axis::Y, Area::Normal);
- auto line_y_position = padding.top;
-
- BlockCursor draw_cursor(cursor->getDocument(), 0, 0, getTextFormat().getFont());
-
- unsigned int currentLine = 0;
- unsigned int lineHeight = format.getFont()->info.line_height + underlinePadding;
-
- auto line_x_position = padding.left;
- do {
- auto text_line =
- gui::TextLine(draw_cursor, w, lineHeight, underline, UnderlineDrawMode::WholeLine, underlinePadding);
-
- if (text_line.height() > 0 && lineHeight != text_line.height()) {
- lineHeight = text_line.height();
- }
-
- if (line_y_position + lineHeight > h) {
- break;
- }
-
- if (currentLine >= linesCount) {
- break;
- }
-
- lines->emplace(std::move(text_line));
- auto &line = lines->last();
- line.setPosition(line_x_position, line_y_position);
- line.setParent(this);
-
- line_y_position += lineHeight;
-
- currentLine++;
+ BlockCursor drawCursor(cursor->getDocument(), 0, 0, getTextFormat().getFont());
- } while (true);
+ lines->draw(drawCursor,
+ getSizeMinusPadding(Axis::X, Area::Normal),
+ getSizeMinusPadding(Axis::Y, Area::Normal),
+ padding.top,
+ padding.left,
+ linesCount);
- lines->linesHAlign(sizeMinusPadding(Axis::X, Area::Normal));
- lines->linesVAlign(sizeMinusPadding(Axis::Y, Area::Normal));
+ lines->linesHAlign(getSizeMinusPadding(Axis::X, Area::Normal));
+ lines->linesVAlign(getSizeMinusPadding(Axis::Y, Area::Normal));
}
} // namespace gui
M module-gui/gui/widgets/TextFixedSize.hpp => module-gui/gui/widgets/TextFixedSize.hpp +0 -1
@@ 12,7 12,6 @@ namespace gui
{
protected:
unsigned int linesCount = style::text::maxTextLines;
- Position underlinePadding = 0;
void drawLines() override;
M module-gui/gui/widgets/TextLine.cpp => module-gui/gui/widgets/TextLine.cpp +8 -16
@@ 54,18 54,22 @@ namespace gui
return;
}
+ // check if max provided width is enought to enter one char at least
+ if (max_width < text_format->getFont()->getCharPixelWidth(text[0])) {
+ lineEnd = true;
+ return;
+ }
+
auto can_show = text_format->getFont()->getCharCountInSpace(text, max_width - width_used);
// we can show nothing - this is the end of this line
if (can_show == 0) {
- auto item = buildUITextPart(" ", text_format);
- width_used += item->getTextNeedSpace();
+ auto item = buildUITextPart("", text_format);
+ width_used = item->getTextNeedSpace();
height_used = std::max(height_used, item->getTextHeight());
-
elements_to_show_in_line.emplace_back(item);
end = localCursor->getEnd();
- ++localCursor;
return;
}
@@ 291,16 295,4 @@ namespace gui
}
}
- auto TextLine::checkBounds(TextLineCursor &cursor, uint32_t utf_value, const TextFormat *format) -> InputBound
- {
- auto font = format->getFont();
- auto text = getText(0);
- text.insertCode(utf_value);
-
- if ((font->getPixelWidth(text)) <= max_width) {
- return InputBound::CAN_ADD;
- }
-
- return InputBound::CANT_PROCESS;
- }
} // namespace gui
M module-gui/gui/widgets/TextLine.hpp => module-gui/gui/widgets/TextLine.hpp +0 -1
@@ 122,6 122,5 @@ namespace gui
void alignH(Alignment align, Length parent_length) const;
void alignV(Alignment align, Length parent_length, Length lines_height);
auto getText(unsigned int pos) const -> UTF8;
- auto checkBounds(TextLineCursor &cursor, uint32_t utf_value, const TextFormat *format) -> InputBound;
};
} // namespace gui
M module-gui/gui/widgets/TextParse.cpp => module-gui/gui/widgets/TextParse.cpp +4 -3
@@ 25,10 25,11 @@ namespace gui
std::stringstream ss(text.c_str());
std::string line;
while (std::getline(ss, line)) {
- if (!blocks.empty()) {
- blocks.back().setEnd(TextBlock::End::Newline);
+ auto block = TextBlock(line, std::make_unique<TextFormat>(format));
+ if (ss.good()) {
+ block.setEnd(TextBlock::End::Newline);
}
- blocks.emplace_back(TextBlock(line, std::make_unique<TextFormat>(format)));
+ blocks.emplace_back(block);
}
addEmptyBlockOnNewline(blocks, format);
M module-gui/test/test-catch-text/CMakeLists.txt => module-gui/test/test-catch-text/CMakeLists.txt +0 -1
@@ 15,7 15,6 @@ add_catch2_executable(
test-gui-TextParse.cpp
test-gui-Font.cpp
test-gui-TextLineCursor.cpp
- test-gui-TextBounds.cpp
INCLUDE
..
../mock/
M module-gui/test/test-catch-text/test-gui-Text.cpp => module-gui/test/test-catch-text/test-gui-Text.cpp +647 -0
@@ 16,6 16,8 @@
#include <algorithm>
#include <mock/BlockFactory.hpp>
#include <RawFont.hpp>
+#include "Font.hpp"
+#include "RichTextParser.hpp"
TEST_CASE("Text ctor")
{
@@ 310,3 312,648 @@ TEST_CASE("Text backup and restore tests")
REQUIRE(text->getCursorPos() == testStringTwoLines.length() - cursorMoveN);
}
}
+
+TEST_CASE("Text addition bounds - text sings count restricted")
+{
+ std::string testStringOneLine = "Test String 1";
+ std::string testStringTwoLines = "Test String 1\n Test String 2";
+
+ std::string richTextTwoLines =
+ "<text font='gt_pressura' color='12' size='30'>Test</text><text size='25'>String</text><text size='20' "
+ "weight='bold'>1</text><br></br><text>Test String 2</text>";
+
+ SECTION("Adding text to max signs count set to 0")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, 0);
+
+ text->addText(testStringOneLine);
+
+ REQUIRE(text->getText().empty());
+ }
+
+ SECTION("Adding text to max signs count set to 1")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, 1);
+
+ text->addText(testStringOneLine);
+
+ REQUIRE(text->getText().length() == 1);
+ }
+
+ SECTION("Adding two lines text to max signs count set to one line sings count")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, testStringOneLine.length());
+
+ text->addText(testStringTwoLines);
+
+ REQUIRE(text->getText().length() == testStringOneLine.length());
+ }
+
+ SECTION("Adding two lines text to max signs count set to two line sings count")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, testStringTwoLines.length());
+
+ text->addText(testStringTwoLines);
+
+ REQUIRE(text->getText().length() == testStringTwoLines.length());
+ }
+
+ SECTION("Adding TextBlock with max sign count lower than block size")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, testStringOneLine.length());
+
+ text->addText(TextBlock(testStringTwoLines, Font(27).raw(), TextBlock::End::None));
+
+ REQUIRE(text->getText().length() == testStringOneLine.length());
+ REQUIRE(text->getText().length() != testStringTwoLines.length());
+ }
+
+ SECTION("Adding TextBlock with max sign count greater than block and adding more text after")
+ {
+ auto additionalSpace = 5;
+ auto textLimit = testStringOneLine.length() + additionalSpace;
+
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, textLimit);
+
+ text->addText(TextBlock(testStringOneLine, Font(27).raw(), TextBlock::End::None));
+
+ REQUIRE(text->getText().length() == testStringOneLine.length());
+
+ text->addText(testStringOneLine);
+
+ REQUIRE(text->getText().length() == testStringOneLine.length() + additionalSpace);
+ }
+
+ SECTION("Adding RichText with max sign count lower than block size")
+ {
+ unsigned int signCountRestricted = 5;
+
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, signCountRestricted);
+
+ text->addRichText(richTextTwoLines);
+
+ REQUIRE(text->getText().length() == signCountRestricted);
+ }
+
+ SECTION("Adding RichText with max sign count greater than block and adding more text after")
+ {
+ auto additionalSpace = 5;
+
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+
+ auto format = text->getTextFormat();
+ auto parsedRichText = gui::text::RichTextParser().parse(richTextTwoLines, &format);
+ auto textLimit = parsedRichText->getText().length() + additionalSpace;
+
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, textLimit);
+
+ text->addRichText(richTextTwoLines);
+
+ REQUIRE(text->getText().length() == parsedRichText->getText().length());
+
+ text->addText(testStringOneLine);
+
+ REQUIRE(text->getText().length() == parsedRichText->getText().length() + additionalSpace);
+ }
+}
+
+TEST_CASE("Text addition bounds - text widget size restricted")
+{
+ std::string testStringOneLine = "Test String 1";
+ std::string testStringTwoLines = "Test String 1\nTest String 2";
+
+ std::string testStringFirstLine = "Test String 1";
+ std::string testStringSecondLine = "Test String 2";
+
+ std::string richTextTwoLines =
+ "<text font='gt_pressura' color='12' size='30'>Test </text><text size='25'>String </text><text size='20' "
+ "weight='bold'>1</text><br></br><text>Test String 2</text>";
+
+ SECTION("Adding text to 0 size text and no parent to grant size")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(0, 0);
+
+ text->addText(testStringOneLine);
+
+ REQUIRE(text->getText().empty());
+ }
+
+ SECTION("Adding text to text with parent max size set to not fit")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ BoxLayout layout = BoxLayout(nullptr, 0, 0, 0, 0);
+ layout.setMaximumSize(10, 10);
+ layout.addWidget(text);
+
+ text->addText(testStringOneLine);
+
+ REQUIRE(text->getText().empty());
+ }
+
+ SECTION("Adding two lines text to text with no parent and size set to fit one line")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(200, 30);
+
+ text->addText(testStringTwoLines);
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText() == testStringOneLine);
+ REQUIRE(text->getText() != testStringTwoLines);
+ }
+
+ SECTION("Adding two lines text to text with no parent and size set to fit two line")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(200, 60);
+
+ text->addText(testStringTwoLines);
+
+ REQUIRE(text->linesSize() == 2);
+ REQUIRE(text->getText() != testStringOneLine);
+ REQUIRE(text->getText() == testStringTwoLines);
+ }
+
+ SECTION("Adding two lines text to text with space for two lines and parent size set to fit one line")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(200, 60);
+ BoxLayout layout = BoxLayout(nullptr, 0, 0, 0, 0);
+ layout.setMaximumSize(200, 30);
+ layout.addWidget(text);
+
+ text->addText(testStringTwoLines);
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText() == testStringOneLine);
+ REQUIRE(text->getText() != testStringTwoLines);
+ }
+
+ SECTION("Adding text block to 0 size text and no parent to grant size")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(0, 0);
+
+ text->addText(TextBlock(testStringOneLine, Font(27).raw(), TextBlock::End::None));
+
+ REQUIRE(text->getText().empty());
+ }
+
+ SECTION("Adding text block to text with parent max size set to not fit")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ BoxLayout layout = BoxLayout(nullptr, 0, 0, 0, 0);
+ layout.setMaximumSize(10, 10);
+ layout.addWidget(text);
+
+ text->addText(TextBlock(testStringOneLine, Font(27).raw(), TextBlock::End::None));
+
+ REQUIRE(text->getText().empty());
+ }
+
+ SECTION("Adding two lines text block to text with no parent and size set to fit one line")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(150, 30);
+
+ text->addText(TextBlock(testStringFirstLine, Font(27).raw(), TextBlock::End::Newline));
+ text->addText(TextBlock(testStringSecondLine, Font(27).raw(), TextBlock::End::None));
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText() == testStringFirstLine);
+ REQUIRE(text->getText() != testStringTwoLines);
+ }
+
+ SECTION("Adding two lines text block to text with no parent and size set to fit two line")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(200, 60);
+
+ text->addText(TextBlock(testStringFirstLine, Font(27).raw(), TextBlock::End::Newline));
+ text->addText(TextBlock(testStringSecondLine, Font(27).raw(), TextBlock::End::None));
+
+ REQUIRE(text->linesSize() == 2);
+ REQUIRE(text->getText() != testStringFirstLine);
+ REQUIRE(text->getText() == testStringTwoLines);
+ }
+
+ SECTION("Adding two lines text block to text with space for two lines and parent size set to fit one line")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(200, 60);
+ BoxLayout layout = BoxLayout(nullptr, 0, 0, 0, 0);
+ layout.setMaximumSize(150, 30);
+ layout.addWidget(text);
+
+ text->addText(TextBlock(testStringFirstLine, Font(27).raw(), TextBlock::End::Newline));
+ text->addText(TextBlock(testStringSecondLine, Font(27).raw(), TextBlock::End::None));
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText() == testStringFirstLine);
+ REQUIRE(text->getText() != testStringTwoLines);
+ }
+
+ SECTION("Adding RichText to 0 size text and no parent to grant size")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(0, 0);
+
+ text->addRichText(richTextTwoLines);
+
+ REQUIRE(text->getText().empty());
+ }
+
+ SECTION("Adding RichText to text with parent max size set to not fit")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ BoxLayout layout = BoxLayout(nullptr, 0, 0, 0, 0);
+ layout.setMaximumSize(10, 10);
+ layout.addWidget(text);
+
+ text->addRichText(richTextTwoLines);
+
+ REQUIRE(text->getText().empty());
+ }
+
+ SECTION("Adding two lines RichText to text with no parent and size set to fit one line")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(160, 40);
+
+ text->addRichText(richTextTwoLines);
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText() == testStringFirstLine);
+ REQUIRE(text->getText() != testStringTwoLines);
+ }
+
+ SECTION("Adding two lines RichText to text with no parent and size set to fit two line")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(200, 80);
+
+ text->addRichText(richTextTwoLines);
+
+ REQUIRE(text->linesSize() == 2);
+ REQUIRE(text->getText() != testStringFirstLine);
+ REQUIRE(text->getText() == testStringTwoLines);
+ }
+
+ SECTION("Adding two lines RichText to text with space for two lines and parent size set to fit one line")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(200, 80);
+ BoxLayout layout = BoxLayout(nullptr, 0, 0, 0, 0);
+ layout.setMaximumSize(160, 40);
+ layout.addWidget(text);
+
+ text->addRichText(richTextTwoLines);
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText() == testStringFirstLine);
+ REQUIRE(text->getText() != testStringTwoLines);
+ }
+}
+
+TEST_CASE("Text addition bounds - text widget line size restricted")
+{
+ std::string testStringOneLine = "Test String 1";
+ std::string testStringTwoLines = "Test String 1\nTest String 2";
+
+ std::string testStringFirstLine = "Test String 1";
+ std::string testStringSecondLine = "Test String 2";
+
+ std::string richTextTwoLines =
+ "<text font='gt_pressura' color='12' size='30'>Test </text><text size='25'>String </text><text size='20' "
+ "weight='bold'>1</text><br></br><text>Test String 2</text>";
+
+ SECTION("Adding text to 0 line size text")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 0);
+ text->setMaximumSize(150, 100);
+
+ text->addText(testStringOneLine);
+
+ REQUIRE(text->getText().empty());
+ }
+
+ SECTION("Adding two lines text to 1 line size text")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 1);
+ text->setMaximumSize(150, 100);
+
+ text->addText(testStringTwoLines);
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText() == testStringOneLine);
+ REQUIRE(text->getText() != testStringTwoLines);
+ }
+
+ SECTION("Adding two lines text to 2 line size text")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 2);
+ text->setMaximumSize(150, 100);
+
+ text->addText(testStringTwoLines);
+
+ REQUIRE(text->linesSize() == 2);
+ REQUIRE(text->getText() == testStringTwoLines);
+ REQUIRE(text->getText() != testStringOneLine);
+ }
+
+ SECTION("Adding text block to 0 line size text")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 0);
+ text->setMaximumSize(150, 100);
+
+ text->addText(TextBlock(testStringOneLine, Font(27).raw(), TextBlock::End::None));
+
+ REQUIRE(text->getText().empty());
+ }
+
+ SECTION("Adding two block lines text to 1 line size text")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 1);
+ text->setMaximumSize(150, 100);
+
+ text->addText(TextBlock(testStringFirstLine, Font(27).raw(), TextBlock::End::Newline));
+ text->addText(TextBlock(testStringSecondLine, Font(27).raw(), TextBlock::End::None));
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText() == testStringOneLine);
+ REQUIRE(text->getText() != testStringTwoLines);
+ }
+
+ SECTION("Adding two lines text to 2 line size text")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 2);
+ text->setMaximumSize(150, 100);
+
+ text->addText(TextBlock(testStringFirstLine, Font(27).raw(), TextBlock::End::Newline));
+ text->addText(TextBlock(testStringSecondLine, Font(27).raw(), TextBlock::End::None));
+
+ REQUIRE(text->linesSize() == 2);
+ REQUIRE(text->getText() == testStringTwoLines);
+ REQUIRE(text->getText() != testStringOneLine);
+ }
+
+ SECTION("Adding RichText to 0 line size text")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 0);
+ text->setMaximumSize(150, 100);
+
+ text->addRichText(richTextTwoLines);
+
+ REQUIRE(text->getText().empty());
+ }
+
+ SECTION("Adding two lines RichText to 1 line size text")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 1);
+ text->setMaximumSize(160, 100);
+
+ text->addRichText(richTextTwoLines);
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText() == testStringFirstLine);
+ REQUIRE(text->getText() != testStringTwoLines);
+ }
+
+ SECTION("Adding two lines RichText to 2 line size text")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 2);
+ text->setMaximumSize(160, 100);
+
+ text->addRichText(richTextTwoLines);
+
+ REQUIRE(text->linesSize() == 2);
+ REQUIRE(text->getText() == testStringTwoLines);
+ REQUIRE(text->getText() != testStringFirstLine);
+ }
+}
+
+TEST_CASE("Text addition bounds - multiple limits tests")
+{
+ std::string testStringOneLine = "Test String 1";
+ std::string testStringTwoLines = "Test String 1\nTest String 2";
+
+ std::string richTextTwoLines =
+ "<text font='gt_pressura' color='12' size='30'>Test </text><text size='25'>String </text><text size='20' "
+ "weight='bold'>1</text><br></br><text>Test String 2</text>";
+
+ SECTION("Adding text to lower limit set to signs count and size and lines on higher limit")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 2);
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, testStringOneLine.length());
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(150, 100);
+
+ text->addText(testStringTwoLines);
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText() == testStringOneLine);
+ REQUIRE(text->getText().length() == testStringOneLine.length());
+ }
+
+ SECTION("Adding text to lower limit set to lines count and size and signs count on higher limit")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+
+ unsigned int signsLimit = 100;
+
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 1);
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, signsLimit);
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(150, 100);
+
+ text->addText(testStringOneLine);
+ text->addText(testStringOneLine);
+ text->addText(testStringOneLine);
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText().length() != signsLimit);
+ }
+
+ SECTION("Adding text to lower limit set to size and lines size and signs count on higher limit")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+
+ unsigned int signsLimit = 100;
+
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 3);
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, signsLimit);
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(140, 30);
+
+ text->addText(testStringOneLine);
+ text->addText(testStringOneLine);
+ text->addText(testStringOneLine);
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText() == testStringOneLine);
+ REQUIRE(text->getText().length() != signsLimit);
+ }
+
+ SECTION("Adding RichText to lower limit set to signs count and size and lines on higher limit")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+
+ auto format = text->getTextFormat();
+ auto parsedRichText = gui::text::RichTextParser().parse(richTextTwoLines, &format);
+
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 4);
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, parsedRichText->getText().length());
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(300, 100);
+
+ text->addRichText(richTextTwoLines);
+
+ REQUIRE(text->linesSize() == 2);
+ REQUIRE(text->getText().length() == parsedRichText->getText().length());
+ }
+
+ SECTION("Adding RichText to lower limit set to lines count and size and signs count on higher limit")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+
+ unsigned int signsLimit = 100;
+
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 1);
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, signsLimit);
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(300, 100);
+
+ text->addRichText(richTextTwoLines);
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText().length() != signsLimit);
+ }
+
+ SECTION("Adding RichText to lower limit set to size and lines size and signs count on higher limit")
+ {
+ mockup::fontManager();
+ using namespace gui;
+ auto text = new gui::TestText();
+
+ unsigned int signsLimit = 100;
+
+ text->setTextLimitType(gui::TextLimitType::MAX_LINES, 3);
+ text->setTextLimitType(gui::TextLimitType::MAX_SIGNS_COUNT, signsLimit);
+ text->setTextLimitType(gui::TextLimitType::MAX_SIZE);
+ text->setMaximumSize(140, 30);
+
+ text->addRichText(richTextTwoLines);
+
+ REQUIRE(text->linesSize() == 1);
+ REQUIRE(text->getText().length() != signsLimit);
+ }
+}<
\ No newline at end of file
D module-gui/test/test-catch-text/test-gui-TextBounds.cpp => module-gui/test/test-catch-text/test-gui-TextBounds.cpp +0 -84
@@ 1,84 0,0 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
-// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
-#include <catch2/catch.hpp>
-#include <limits>
-#include <module-gui/gui/widgets/TextBlock.hpp>
-#include <mock/buildTextDocument.hpp>
-#include <module-gui/gui/widgets/Text.hpp>
-#include <mock/multi-line-string.hpp>
-
-// To be corrected with Text scrolling and Bounds
-TEST_CASE("Text bounds", "[.]")
-{
- using namespace gui;
-
- auto key_up = gui::InputEvent(
- {
- RawKey::State::Released,
- bsp::KeyCodes::Undefined,
- },
- gui::InputEvent::State::keyReleasedShort,
- gui::KeyCode::KEY_UP);
-
- auto key_left = gui::InputEvent(
- {
- RawKey::State::Released,
- bsp::KeyCodes::Undefined,
- },
- gui::InputEvent::State::keyReleasedShort,
- gui::KeyCode::KEY_LEFT);
-
- auto key_down = gui::InputEvent(
- {
- RawKey::State::Released,
- bsp::KeyCodes::Undefined,
- },
- gui::InputEvent::State::keyReleasedShort,
- gui::KeyCode::KEY_DOWN);
-
- auto texts = mockup::lineStrings(6);
- auto [document, font] = mockup::buildMultilineTestDocument(texts);
-
- auto text = gui::Text();
- text.setText(std::make_unique<gui::TextDocument>(document));
- text.setFont(font);
-
- SECTION("moving cursor - hit bound")
- {
- auto lines = Lines(&text);
- auto cursor = new gui::TextLineCursor(&text);
-
- lines.emplace(TextLine(*cursor, 1000));
- lines.emplace(TextLine(*cursor, 1000));
- lines.emplace(TextLine(*cursor, 1000));
- lines.emplace(TextLine(*cursor, 1000));
- lines.emplace(TextLine(*cursor, 1000));
-
- cursor->moveCursor(NavigationDirection::DOWN);
- cursor->moveCursor(NavigationDirection::DOWN);
- cursor->moveCursor(NavigationDirection::DOWN);
-
- auto bound = lines.checkNavigationBounds(*cursor, key_down);
-
- REQUIRE(bound == InputBound::HIT_BOUND);
- }
-
- SECTION("moving cursor - reach data end")
- {
- auto lines = Lines(&text);
- auto cursor = new gui::TextLineCursor(&text);
-
- lines.emplace(TextLine(*cursor, 100));
- auto bound = lines.checkNavigationBounds(*cursor, key_up);
- REQUIRE(bound == InputBound::NO_DATA);
-
- cursor->moveCursor(NavigationDirection::RIGHT);
- bound = lines.checkNavigationBounds(*cursor, key_left);
- REQUIRE(bound == InputBound::CAN_MOVE);
-
- cursor->moveCursor(NavigationDirection::DOWN);
- bound = lines.checkNavigationBounds(*cursor, key_up);
- REQUIRE(bound == InputBound::NO_DATA);
- }
-}