Add capability of max width wrapping to message box. Takes out the need to add manual line breaks to messages.

This commit is contained in:
Dario 2025-01-13 21:02:58 -03:00
parent 0e8dbe797b
commit 39b0aeb2dc
2 changed files with 81 additions and 19 deletions

View file

@ -256,28 +256,88 @@ inline std::string Truncate(const std::string& input, size_t maxLength, bool use
return input; return input;
} }
inline std::vector<std::string> Split(const char* str, char delimiter) inline std::vector<std::string> Split(const char* strStart, const ImFont *font, float fontSize, float maxWidth)
{ {
if (!strStart)
return {};
std::vector<std::string> result; std::vector<std::string> result;
float textWidth = 0.0f;
if (!str) float lineWidth = 0.0f;
return result; const float scale = fontSize / font->FontSize;
const char *str = strStart;
const char* start = str; const char *strEnd = strStart + strlen(strStart);
const char* current = str; const char *lineStart = strStart;
const bool wordWrapEnabled = (maxWidth > 0.0f);
while (*current) const char *wordWrapEOL = nullptr;
while (*str != 0)
{ {
if (*current == delimiter) if (wordWrapEnabled)
{ {
result.emplace_back(start, current - start); if (wordWrapEOL == nullptr)
start = current + 1; {
wordWrapEOL = font->CalcWordWrapPositionA(scale, str, strEnd, maxWidth - lineWidth);
}
if (str >= wordWrapEOL)
{
if (textWidth < lineWidth)
textWidth = lineWidth;
result.emplace_back(lineStart, str);
lineWidth = 0.0f;
wordWrapEOL = nullptr;
while (str < strEnd && ImCharIsBlankA(*str))
str++;
if (*str == '\n')
str++;
lineStart = str;
continue;
}
} }
current++; const char *prevStr = str;
unsigned int c = (unsigned int)*str;
if (c < 0x80)
str += 1;
else
str += ImTextCharFromUtf8(&c, str, strEnd);
if (c < 32)
{
if (c == '\n')
{
result.emplace_back(lineStart, str - 1);
lineStart = str;
textWidth = ImMax(textWidth, lineWidth);
lineWidth = 0.0f;
continue;
}
if (c == '\r')
{
lineStart = str;
continue;
}
}
const float charWidth = ((int)c < font->IndexAdvanceX.Size ? font->IndexAdvanceX.Data[c] : font->FallbackAdvanceX) * scale;
if (lineWidth + charWidth >= maxWidth)
{
str = prevStr;
break;
}
lineWidth += charWidth;
} }
result.emplace_back(start); if (str != lineStart)
{
result.emplace_back(lineStart, str);
}
return result; return result;
} }
@ -298,14 +358,14 @@ inline ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float
return { x, y }; return { x, y };
} }
inline ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float lineMargin, const char* text) inline ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float maxWidth, float lineMargin, const char* text)
{ {
return MeasureCentredParagraph(font, fontSize, lineMargin, Split(text, '\n')); return MeasureCentredParagraph(font, fontSize, lineMargin, Split(text, font, fontSize, maxWidth));
} }
inline void DrawCentredParagraph(const ImFont* font, float fontSize, const ImVec2& centre, float lineMargin, const char* text, std::function<void(const char*, ImVec2)> drawMethod) inline void DrawCentredParagraph(const ImFont* font, float fontSize, float maxWidth, const ImVec2& centre, float lineMargin, const char* text, std::function<void(const char*, ImVec2)> drawMethod)
{ {
auto lines = Split(text, '\n'); auto lines = Split(text, font, fontSize, maxWidth);
auto paragraphSize = MeasureCentredParagraph(font, fontSize, lineMargin, lines); auto paragraphSize = MeasureCentredParagraph(font, fontSize, lineMargin, lines);
auto offsetY = 0.0f; auto offsetY = 0.0f;

View file

@ -288,8 +288,9 @@ void MessageWindow::Draw()
ImVec2 centre = { res.x / 2, res.y / 2 }; ImVec2 centre = { res.x / 2, res.y / 2 };
float maxWidth = Scale(640.0f);
auto fontSize = Scale(28); auto fontSize = Scale(28);
auto textSize = MeasureCentredParagraph(g_fntSeurat, fontSize, 5, g_text.c_str()); auto textSize = MeasureCentredParagraph(g_fntSeurat, fontSize, maxWidth, 5, g_text.c_str());
auto textMarginX = Scale(37); auto textMarginX = Scale(37);
auto textMarginY = Scale(45); auto textMarginY = Scale(45);
@ -325,6 +326,7 @@ void MessageWindow::Draw()
( (
g_fntSeurat, g_fntSeurat,
fontSize, fontSize,
maxWidth,
{ centre.x, centre.y + Scale(3) }, { centre.x, centre.y + Scale(3) },
5, 5,
g_text.c_str(), g_text.c_str(),