#pragma once #include #include class ScrollingTextDisplay { private: TFT_eSprite* sprite; int yPos; int maxWidth; int xPos; int textWidth; unsigned long lastTick; unsigned long holdTick; bool isScrolling; std::function postDrawCallback; int usedW; int usedH; static const unsigned long SCROLL_INTERVAL = 5; static const unsigned long HOLD_DURATION = 2000; static const int SCROLL_GAP = 10; public: ScrollingTextDisplay(TFT_eSprite* spr, int y, int maxW, int inuseW = -1, int inuseH = -1 ) : sprite(spr), yPos(y), maxWidth(maxW), xPos(0), textWidth(0), lastTick(0), holdTick(0), isScrolling(false), postDrawCallback(nullptr), usedW(inuseW), usedH(inuseH) {} void setPostDrawCallback(std::function callback) { postDrawCallback = callback; } void update(const String& text, bool status, uint16_t activeColor, uint16_t activeSmooth, uint16_t dropoutColor, uint16_t dropoutSmooth, uint16_t backgroundColor) { textWidth = sprite->textWidth(text); if(textWidth < maxWidth) { xPos = 0; isScrolling = false; drawText(text, status, activeColor, activeSmooth, dropoutColor, dropoutSmooth, backgroundColor); } else { if(!isScrolling) holdTick = millis(); isScrolling = true; if(millis() - lastTick >= SCROLL_INTERVAL) { if(xPos <= -(textWidth + SCROLL_GAP)) xPos = 0; if(xPos == 0) { if(millis() - holdTick >= HOLD_DURATION) { xPos--; holdTick = millis(); } } else { xPos--; holdTick = millis(); } drawText(text, status, activeColor, activeSmooth, dropoutColor, dropoutSmooth, backgroundColor); lastTick = millis(); } } } void reset() { xPos = 0; holdTick = millis(); lastTick = millis(); } void setYPosition(int y) { yPos = y; } bool getIsScrolling() const { return isScrolling; } private: void drawText(const String& text, bool status, uint16_t activeColor, uint16_t activeSmooth, uint16_t dropoutColor, uint16_t dropoutSmooth, uint16_t backgroundColor) { if(usedW > 0 && usedH > 0) { sprite->fillSprite(TFT_TRANSPARENT); sprite->fillRect(0, 0, usedW, usedH, backgroundColor); sprite->setViewport(0, 0, usedW, usedH); if(status) sprite->setTextColor(activeColor, activeSmooth, false); else sprite->setTextColor(dropoutColor, dropoutSmooth, false); sprite->drawString(text, xPos, 0); if(isScrolling) sprite->drawString(text, xPos + textWidth + SCROLL_GAP, 0); sprite->resetViewport(); } else { sprite->fillSprite(backgroundColor); if(status) sprite->setTextColor(activeColor, activeSmooth, false); else sprite->setTextColor(dropoutColor, dropoutSmooth, false); sprite->drawString(text, xPos, 0); if(isScrolling) sprite->drawString(text, xPos + textWidth + SCROLL_GAP, 0); } sprite->fillRect(0, sprite->fontHeight(), sprite->width(), sprite->height() - sprite->fontHeight(), TFT_TRANSPARENT); if(postDrawCallback) postDrawCallback(sprite, false); sprite->pushSprite(35, yPos, TFT_TRANSPARENT); } };