From 203bdadca9e318c3f6e20882608188180bbc7031 Mon Sep 17 00:00:00 2001 From: CommanderRedYT Date: Fri, 3 Mar 2023 17:47:49 +0100 Subject: [PATCH] initial commit --- CMakeLists.txt | 2 + src/displaywithtitle.cpp | 9 ++- src/displaywithtitle.h | 9 ++- src/menudisplay.cpp | 2 +- src/menudisplay.h | 26 ++++---- src/widgets/scrolllabel.cpp | 129 ++++++++++++++++++++++++++++++++++++ src/widgets/scrolllabel.h | 51 ++++++++++++++ 7 files changed, 211 insertions(+), 17 deletions(-) create mode 100644 src/widgets/scrolllabel.cpp create mode 100644 src/widgets/scrolllabel.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 24aec5f..c1e6031 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ set(headers src/widgets/label.h src/widgets/progressbar.h src/widgets/reverseprogressbar.h + src/widgets/scrolllabel.h src/widgets/slider.h src/widgets/variablerangeprogressbar.h src/widgets/variablerangereverseprogressbar.h @@ -93,6 +94,7 @@ set(sources src/widgets/label.cpp src/widgets/progressbar.cpp src/widgets/reverseprogressbar.cpp + src/widgets/scrolllabel.cpp src/widgets/slider.cpp src/widgets/variablerangeprogressbar.cpp src/widgets/variablerangereverseprogressbar.cpp diff --git a/src/displaywithtitle.cpp b/src/displaywithtitle.cpp index 59a1d1a..6e22483 100644 --- a/src/displaywithtitle.cpp +++ b/src/displaywithtitle.cpp @@ -10,7 +10,11 @@ void DisplayWithTitle::initScreen(TftInterface &tft) { Base::initScreen(tft); - m_titleLabel.start(tft); + // m_titleLabel.construct(5, 5); // 230, 25 + if (!m_titleLabel) + m_titleLabel.construct(5, 5, tft.width() - SCROLLMARGIN, 500); + + m_titleLabel->start(tft); // tft.fillRect(0, 0, tft.width(), 35, TFT_GREY); @@ -21,7 +25,8 @@ void DisplayWithTitle::redraw(TftInterface &tft) { Base::redraw(tft); - m_titleLabel.redraw(tft, title(), TFT_GREY, TFT_BLACK, 4); + if (m_titleLabel) + m_titleLabel->redraw(tft, title(), TFT_GREY, TFT_BLACK, 4); } } // namespace espgui diff --git a/src/displaywithtitle.h b/src/displaywithtitle.h index ebc4feb..d5ae2ec 100644 --- a/src/displaywithtitle.h +++ b/src/displaywithtitle.h @@ -1,9 +1,12 @@ #pragma once +// 3rdparty lib includes +#include + // local includes #include "display.h" #include "titleinterface.h" -#include "widgets/label.h" +#include "widgets/scrolllabel.h" namespace espgui { @@ -21,7 +24,9 @@ public: void redraw(TftInterface &tft) override; private: - Label m_titleLabel{5, 5}; // 230, 25 + static constexpr const auto SCROLLMARGIN = 40; + + cpputils::DelayedConstruction m_titleLabel; }; } // namespace espgui diff --git a/src/menudisplay.cpp b/src/menudisplay.cpp index 72f7f00..183e018 100644 --- a/src/menudisplay.cpp +++ b/src/menudisplay.cpp @@ -26,7 +26,7 @@ void MenuDisplay::initScreen(TftInterface &tft) Base::initScreen(tft); for (auto &label : m_labels) - label.start(tft); + label.start(tft, tft.width() - SCROLLMARGIN); runForEveryMenuItem([](MenuItem &item){ item.start(); diff --git a/src/menudisplay.h b/src/menudisplay.h index 35c2800..b320311 100644 --- a/src/menudisplay.h +++ b/src/menudisplay.h @@ -16,7 +16,7 @@ // local includes #include "displaywithtitle.h" #include "textinterface.h" -#include "widgets/label.h" +#include "widgets/scrolllabel.h" #include "menuitem.h" #include "backinterface.h" @@ -110,37 +110,39 @@ private: static constexpr auto topMargin = 39; static constexpr auto lineHeight = 27; static constexpr auto verticalSpacing = 2; + static constexpr auto SCROLLMARGIN = 90; - std::array m_labels {{ + using LabelClass = ScrollLabel; + std::array m_labels {{ #if CONFIG_ESPGUI_MENUDISPLAY_ROWS >= 1 - Label{horizontalSpacing + iconWidth, topMargin+(0*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight + LabelClass{horizontalSpacing + iconWidth, topMargin+(0*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight #endif #if CONFIG_ESPGUI_MENUDISPLAY_ROWS >= 2 - Label{horizontalSpacing + iconWidth, topMargin+(1*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight + LabelClass{horizontalSpacing + iconWidth, topMargin+(1*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight #endif #if CONFIG_ESPGUI_MENUDISPLAY_ROWS >= 3 - Label{horizontalSpacing + iconWidth, topMargin+(2*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight + LabelClass{horizontalSpacing + iconWidth, topMargin+(2*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight #endif #if CONFIG_ESPGUI_MENUDISPLAY_ROWS >= 4 - Label{horizontalSpacing + iconWidth, topMargin+(3*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight + LabelClass{horizontalSpacing + iconWidth, topMargin+(3*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight #endif #if CONFIG_ESPGUI_MENUDISPLAY_ROWS >= 5 - Label{horizontalSpacing + iconWidth, topMargin+(4*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight + LabelClass{horizontalSpacing + iconWidth, topMargin+(4*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight #endif #if CONFIG_ESPGUI_MENUDISPLAY_ROWS >= 6 - Label{horizontalSpacing + iconWidth, topMargin+(5*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight + LabelClass{horizontalSpacing + iconWidth, topMargin+(5*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight #endif #if CONFIG_ESPGUI_MENUDISPLAY_ROWS >= 7 - Label{horizontalSpacing + iconWidth, topMargin+(6*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight + LabelClass{horizontalSpacing + iconWidth, topMargin+(6*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight #endif #if CONFIG_ESPGUI_MENUDISPLAY_ROWS >= 8 - Label{horizontalSpacing + iconWidth, topMargin+(7*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight + LabelClass{horizontalSpacing + iconWidth, topMargin+(7*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight #endif #if CONFIG_ESPGUI_MENUDISPLAY_ROWS >= 9 - Label{horizontalSpacing + iconWidth, topMargin+(8*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight + LabelClass{horizontalSpacing + iconWidth, topMargin+(8*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight #endif #if CONFIG_ESPGUI_MENUDISPLAY_ROWS >= 10 - Label{horizontalSpacing + iconWidth, topMargin+(9*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight + LabelClass{horizontalSpacing + iconWidth, topMargin+(9*(lineHeight+verticalSpacing))}, // 240-(horizontalSpacing*2)-iconWidth, lineHeight #endif }}; diff --git a/src/widgets/scrolllabel.cpp b/src/widgets/scrolllabel.cpp new file mode 100644 index 0000000..2023a80 --- /dev/null +++ b/src/widgets/scrolllabel.cpp @@ -0,0 +1,129 @@ +#include "scrolllabel.h" + +// system includes +#include + +// 3rdparty lib includes +#include +#include + +// local includes +#include "tftinterface.h" +#include "richtextrenderer.h" + +using namespace std::chrono_literals; + +namespace espgui { +ScrollLabel::ScrollLabel(int x, int y, int width, int scrollSpeed) : + m_x{x}, + m_y{y}, + m_width{width}, + m_scrollSpeed{scrollSpeed}, + m_lastScrollTime{espchrono::millis_clock::now()}, + m_scrollOffset{0} +{} + +ScrollLabel::ScrollLabel(int x, int y) : + m_x{x}, + m_y{y}, + m_width{std::nullopt}, + m_scrollSpeed{500}, + m_lastScrollTime{espchrono::millis_clock::now()}, + m_scrollOffset{0} +{} + +void ScrollLabel::start(TftInterface &tft) +{ + m_lastStr.clear(); + m_lastFont = -1; + m_lastColor = -1; + + m_lastWidth = 0; + m_lastHeight = 0; + + //m_lastScrollTime = espchrono::millis_clock::now(); + //m_scrollOffset = 0; +} + +void ScrollLabel::start(TftInterface &tft, int width) +{ + m_width = width; + start(tft); +} + +void ScrollLabel::redraw(TftInterface &tft, std::string_view str, uint16_t color, uint16_t bgcolor, uint8_t font, bool forceRedraw) +{ + espgui::FontRenderer fontRenderer{tft}; + redraw(tft, fontRenderer, str, color, bgcolor, font, forceRedraw); +} + +void ScrollLabel::redraw(TftInterface &tft, FontRenderer &fontRenderer, std::string_view str, uint16_t color, uint16_t bgcolor, uint8_t font, bool forceRedraw) +{ + const auto char_width = fontRenderer.textWidth(str, font) / std::max(1U, str.length()); + const auto max_chars = m_width ? (*m_width / std::max(1U, char_width)) : 0; + bool scroll = (str.length() > max_chars && m_width); + + // ESP_LOGI("ScrollLabel", "str: %s, scrolling: %s, strlen: %d, maxchars: %d", str.data(), str.length() > max_chars ? "true" : "false", str.length(), max_chars); + + if (m_lastStr == str && + m_lastColor == color && + m_lastFont == font && + !forceRedraw && + (str.length() <= max_chars || !m_width)) + return; + + if (str.contains("&")) + scroll = false; + + if (scroll) + { + const auto now = espchrono::millis_clock::now(); + const auto elapsed = espchrono::ago(m_lastScrollTime); + if (elapsed > (m_scrollSpeed * (m_scrollOffset == 0 ? 3ms : 1ms))) + { + m_lastScrollTime = now; + m_scrollOffset++; + if (m_scrollOffset > str.length() - max_chars) + m_scrollOffset = 0; + } + str = str.substr(m_scrollOffset, max_chars); + } + else + m_scrollOffset = 0; + + if (m_lastColor == color && + m_lastFont == font && + m_lastStrScroll == str) + return; + + const auto renderedWidth = renderRichText(tft, fontRenderer, str, m_x, m_y, color, bgcolor, font); + const auto renderedHeight = fontRenderer.fontHeight(font); + + if (renderedWidth < m_lastWidth) + tft.fillRect(m_x + renderedWidth, m_y, + m_lastWidth - renderedWidth, m_lastHeight, + bgcolor); + + if (renderedHeight < m_lastHeight) + tft.fillRect(m_x, m_y + renderedHeight, + renderedWidth, m_lastHeight - renderedHeight, + bgcolor); + + m_lastStr = str; + m_lastColor = color; + m_lastFont = font; + + m_lastWidth = renderedWidth; + m_lastHeight = renderedHeight; + + m_lastStrScroll = str; +} + +void ScrollLabel::clear(TftInterface &tft, uint16_t bgcolor) +{ + if (m_lastWidth || m_lastHeight) + tft.fillRect(m_x, m_y, m_lastWidth, m_lastHeight, bgcolor); + + start(tft); +} +} // namespace espgui diff --git a/src/widgets/scrolllabel.h b/src/widgets/scrolllabel.h new file mode 100644 index 0000000..317c106 --- /dev/null +++ b/src/widgets/scrolllabel.h @@ -0,0 +1,51 @@ +#pragma once + +// system includes +#include +#include + +// 3rdparty lib includes +#include + +// forward declares +namespace espgui { +class TftInterface; +class FontRenderer; +} // namespace espgui + +namespace espgui { +class ScrollLabel +{ +public: + ScrollLabel(int x, int y, int width, int scrollSpeed); + ScrollLabel(int x, int y); + + int x() const { return m_x; } + int y() const { return m_y; } + const std::optional& width() { return m_width; } + int scrollSpeed() const { return m_scrollSpeed; } + + void start(TftInterface &tft); + void start(TftInterface &tft, int width); + void redraw(TftInterface &tft, std::string_view str, uint16_t color, uint16_t bgcolor, uint8_t font, bool forceRedraw = false); + void redraw(TftInterface &tft, FontRenderer &fontRenderer, std::string_view str, uint16_t color, uint16_t bgcolor, uint8_t font, bool forceRedraw = false); + void clear(TftInterface &tft, uint16_t bgcolor); + +private: + const int m_x; + const int m_y; + std::optional m_width; + const int m_scrollSpeed; + + std::string m_lastStr; + std::string m_lastStrScroll; + uint16_t m_lastColor; + uint8_t m_lastFont; + + int m_lastWidth; + int m_lastHeight; + + espchrono::millis_clock::time_point m_lastScrollTime; + int m_scrollOffset; +}; +} // namespace espgui