Implemented rich text rendering
This commit is contained in:
@@ -13,6 +13,7 @@ set(headers
|
|||||||
src/iconinterface.h
|
src/iconinterface.h
|
||||||
src/menudisplay.h
|
src/menudisplay.h
|
||||||
src/menuitem.h
|
src/menuitem.h
|
||||||
|
src/richtextrenderer.h
|
||||||
src/screenmanager.h
|
src/screenmanager.h
|
||||||
src/tftinstance.h
|
src/tftinstance.h
|
||||||
src/textinterface.h
|
src/textinterface.h
|
||||||
@@ -39,6 +40,7 @@ set(sources
|
|||||||
src/changevaluedisplay_sntp_sync_mode_t.cpp
|
src/changevaluedisplay_sntp_sync_mode_t.cpp
|
||||||
src/menudisplay.cpp
|
src/menudisplay.cpp
|
||||||
src/screenmanager.cpp
|
src/screenmanager.cpp
|
||||||
|
src/richtextrenderer.cpp
|
||||||
src/tftinstance.cpp
|
src/tftinstance.cpp
|
||||||
src/icons/back.cpp
|
src/icons/back.cpp
|
||||||
src/icons/checked.cpp
|
src/icons/checked.cpp
|
||||||
|
129
src/richtextrenderer.cpp
Normal file
129
src/richtextrenderer.cpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#include "richtextrenderer.h"
|
||||||
|
|
||||||
|
// system includes
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
// 3rdparty lib includes
|
||||||
|
#include <strutils.h>
|
||||||
|
|
||||||
|
namespace espgui {
|
||||||
|
|
||||||
|
void richTextEscape(std::string &subject)
|
||||||
|
{
|
||||||
|
cpputils::stringReplaceAll('&', "&&", subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string richTextEscape(std::string_view subject)
|
||||||
|
{
|
||||||
|
return cpputils::stringReplaceAll('&', "&&", subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t renderRichText(std::string_view str, int32_t poX, int32_t poY)
|
||||||
|
{
|
||||||
|
return renderRichText(str, poX, poY, tft.textfont);
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t renderRichText(std::string_view str, int32_t poX, int32_t poY, uint8_t font)
|
||||||
|
{
|
||||||
|
if (str.empty())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const auto oldColor = tft.textcolor;
|
||||||
|
|
||||||
|
int16_t width{};
|
||||||
|
|
||||||
|
again:
|
||||||
|
if (const auto index = str.find('&'); index != std::string_view::npos)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::string_view tempStr{std::begin(str), index};
|
||||||
|
if (!tempStr.empty())
|
||||||
|
{
|
||||||
|
const auto addedWith = tft.drawString(tempStr, poX, poY, font);
|
||||||
|
poX += addedWith;
|
||||||
|
width += addedWith;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto newIter = std::begin(str) + index + 1;
|
||||||
|
if (newIter != std::end(str))
|
||||||
|
{
|
||||||
|
switch (const auto controlChar = *newIter)
|
||||||
|
{
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
{
|
||||||
|
const auto color = [&controlChar](){
|
||||||
|
switch (controlChar)
|
||||||
|
{
|
||||||
|
case '0': return TFT_RED;
|
||||||
|
case '1': return TFT_GREEN;
|
||||||
|
case '2': return TFT_BLUE;
|
||||||
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
|
}();
|
||||||
|
|
||||||
|
tft.setTextColor(color, tft.textbgcolor);
|
||||||
|
|
||||||
|
auto newNewIter = newIter + 1;
|
||||||
|
if (newNewIter != std::end(str))
|
||||||
|
{
|
||||||
|
str = std::string_view(newNewIter, std::distance(newNewIter, std::end(str)));
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// case '&':
|
||||||
|
// {
|
||||||
|
// const char buf[1] = { '&' };
|
||||||
|
// const auto addedWith = tft.drawString(std::string_view{buf, std::size(buf)}, poX, poY, font);
|
||||||
|
// poX += addedWith;
|
||||||
|
// width += addedWith;
|
||||||
|
|
||||||
|
// auto newNewIter = newIter + 1;
|
||||||
|
// if (newNewIter != std::end(str))
|
||||||
|
// {
|
||||||
|
// str = std::string_view(newNewIter, std::distance(newNewIter, std::end(str)));
|
||||||
|
// goto again;
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
const char buf[2] = { '&', controlChar };
|
||||||
|
const auto addedWith = tft.drawString(std::string_view{buf, std::size(buf)}, poX, poY, font);
|
||||||
|
poX += addedWith;
|
||||||
|
width += addedWith;
|
||||||
|
|
||||||
|
auto newNewIter = newIter + 1;
|
||||||
|
if (newNewIter != std::end(str))
|
||||||
|
{
|
||||||
|
str = std::string_view(newNewIter, std::distance(newNewIter, std::end(str)));
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char buf[1] = { '&' };
|
||||||
|
const auto addedWith = tft.drawString(std::string_view{buf, std::size(buf)}, poX, poY, font);
|
||||||
|
poX += addedWith;
|
||||||
|
width += addedWith;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!str.empty())
|
||||||
|
{
|
||||||
|
const auto addedWith = tft.drawString(str, poX, poY, font);
|
||||||
|
poX += addedWith;
|
||||||
|
width += addedWith;
|
||||||
|
}
|
||||||
|
|
||||||
|
tft.setTextColor(oldColor, tft.textbgcolor);
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace espgui
|
18
src/richtextrenderer.h
Normal file
18
src/richtextrenderer.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// system includes
|
||||||
|
#include <string_view>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// local includes
|
||||||
|
#include "tftinstance.h"
|
||||||
|
|
||||||
|
namespace espgui {
|
||||||
|
|
||||||
|
void richTextEscape(std::string &subject);
|
||||||
|
std::string richTextEscape(std::string_view subject);
|
||||||
|
|
||||||
|
int16_t renderRichText(std::string_view str, int32_t poX, int32_t poY);
|
||||||
|
int16_t renderRichText(std::string_view str, int32_t poX, int32_t poY, uint8_t font);
|
||||||
|
|
||||||
|
} // namespace espgui
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
// local includes
|
// local includes
|
||||||
#include "tftinstance.h"
|
#include "tftinstance.h"
|
||||||
|
#include "richtextrenderer.h"
|
||||||
|
|
||||||
namespace espgui {
|
namespace espgui {
|
||||||
Label::Label(int x, int y) :
|
Label::Label(int x, int y) :
|
||||||
@@ -28,7 +29,7 @@ void Label::redraw(std::string_view str, bool forceRedraw)
|
|||||||
!forceRedraw)
|
!forceRedraw)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto renderedWidth = str.empty() ? 0 : tft.drawString(str.data(), m_x, m_y);
|
const auto renderedWidth = renderRichText(str, m_x, m_y);
|
||||||
const auto renderedHeight = tft.fontHeight();
|
const auto renderedHeight = tft.fontHeight();
|
||||||
|
|
||||||
if (renderedWidth < m_lastWidth)
|
if (renderedWidth < m_lastWidth)
|
||||||
|
Reference in New Issue
Block a user