37#include <guichan/graphics.hpp>
38#include <guichan/font.hpp>
39#include <guichan/cliprectangle.hpp>
46static void replaceKeys(std::string &text)
48 auto keyStart = text.find(
"###");
50 while (keyStart != std::string::npos)
52 const auto keyEnd = text.find(
";", keyStart + 3);
53 if (keyEnd == std::string::npos)
56 std::string_view key(text.data() + keyStart + 3, keyEnd - keyStart - 3);
59 if (key.size() > 3 && key.substr(0, 3) ==
"key")
65 text.replace(keyStart, keyEnd - keyStart + 1, keyName);
66 keyStart = text.find(
"###", keyStart + keyName.size());
70 keyStart = text.find(
"###", keyEnd + 1);
96 , fontHeight(font->getHeight())
97 , minusWidth(font->getWidth(
"-"))
98 , tildeWidth(font->getWidth(
"~"))
99 , lineHeight(fontHeight)
100 , textColor(palette.getColor(
Theme::TEXT))
101 , textOutlineColor(palette.getOutlineColor(
Theme::TEXT))
103 , outlineColor(textOutlineColor)
126 addMouseListener(
this);
133 std::string_view::size_type start = 0;
134 std::string_view::size_type end = 0;
135 while (end != std::string::npos)
137 end = rows.find(
'\n', start);
138 addRow(rows.substr(start, end - start));
151 auto linkStart = row.find(
"@@");
152 while (linkStart != std::string::npos)
154 const auto linkSep = row.find(
"|", linkStart);
155 const auto linkEnd = row.find(
"@@", linkSep);
157 if (linkSep == std::string::npos || linkEnd == std::string::npos)
161 link.
link = row.substr(linkStart + 2, linkSep - (linkStart + 2));
162 link.
caption = row.substr(linkSep + 1, linkEnd - (linkSep + 1));
166 const int id = atoi(link.
link.c_str());
173 newRow.
text += row.substr(0, linkStart);
176 row = row.substr(linkEnd + 2);
179 newRow.
text +=
"##>";
181 linkStart = row.find(
"@@");
193 replaceKeys(newRow.
text);
197 context.
y = getHeight();
202 setWidth(newRow.
width);
206 int removedHeight = 0;
209 removedHeight +=
mTextRows.front().height;
212 if (removedHeight > 0)
216 for (
auto &part : row.parts)
217 part.y -= removedHeight;
219 for (
auto &link : row.links)
220 link.rect.y -= removedHeight;
224 setHeight(context.
y - removedHeight);
262 const gcn::ClipRectangle &cr =
graphics->getCurrentClipArea();
263 int yStart = cr.y - cr.yOffset;
264 int yEnd = yStart + cr.height;
276 const gcn::Rectangle &rect = link.rect;
288 rect.y + rect.height,
290 rect.y + rect.height);
298 for (
const auto &part : row.parts)
300 if (part.y + 50 < yStart)
311 part.outlineColor.has_value() ||
mOutline,
330 setHeight(context.
y);
340 context.
font = getFont();
344 const int startY = context.
y;
347 unsigned linkIndex = 0;
348 bool wrapped =
false;
354 for (x = 0; x < getWidth(); x += context.
minusWidth - 1)
359 row.
width = getWidth();
360 row.
height = context.
y - startY;
365 auto prevColor = context.
color;
370 for (std::string::size_type start = 0, end = std::string::npos;
371 start != std::string::npos;
372 start = end, end = std::string::npos)
385 while (row.
text.size() > start + 2 && row.
text.find(
"##", start) == start)
387 const char c = row.
text.at(start + 2);
393 context.
color = prevColor;
397 prevColor = context.
color;
406 context.
font = getFont();
412 context.
color = palette.getColor(*colorId);
413 context.
outlineColor = palette.getOutlineColor(*colorId);
425 if (c ==
'<' && linkIndex < row.
links.size())
427 auto &link = row.
links[linkIndex];
430 link.rect.y = context.
y;
431 link.rect.width = context.
font->getWidth(link.caption) + 1;
439 if (start >= row.
text.length())
444 end = row.
text.find(
"##", start + 1);
446 std::string::size_type len =
447 end == std::string::npos ? end : end - start;
449 std::string part = row.
text.substr(start, len);
450 int partWidth = context.
font->getWidth(part);
455 && (x + partWidth) > getWidth())
466 end = row.
text.rfind(
' ', end);
469 if (end == std::string::npos || end <= start)
472 end = row.
text.size();
478 while ((row.
text[end] & 192) == 128)
482 part = row.
text.substr(start, end - start + 1);
483 partWidth = context.
font->getWidth(part);
485 while (end > start && partWidth > 0
486 && (x + partWidth) > getWidth());
510 row.
width = std::max(row.
width, x + partWidth);
519 row.
height = context.
y - startY;
528 for (
const auto &link : row.links)
530 if (link.contains(x, y))
void addRows(std::string_view rows)
Adds one or more text rows to the browser, separated by ' '.
void mouseMoved(gcn::MouseEvent &event) override
void updateHoveredLink(int x, int y)
void mouseExited(gcn::MouseEvent &event) override
BrowserBox(Mode mode=AUTO_SIZE)
void draw(gcn::Graphics *graphics) override
Draws the browser box.
unsigned int mHighlightMode
std::optional< BrowserLink > mHoveredLink
void addRow(std::string_view row)
Adds a text row to the browser.
void layoutTextRow(TextRow &row, LayoutContext &context)
Layers out the given row of text starting at the given context position.
LinkHandler * mLinkHandler
void clearRows()
Remove all rows.
@ AUTO_WRAP
Maybe it needs a fix or to be redone.
std::deque< TextRow > mTextRows
bool mUseLinksAndUserColors
void mousePressed(gcn::MouseEvent &event) override
Handles mouse actions.
void relayoutText()
Relayouts all text rows and returns the new height of the BrowserBox.
A central point of control for graphics.
void drawText(const std::string &text, int x, int y, gcn::Graphics::Alignment alignment, const gcn::Color &color, gcn::Font *font, bool outline=false, bool shadow=false, const std::optional< gcn::Color > &outlineColor={}, const std::optional< gcn::Color > &shadowColor={})
void setColor(const gcn::Color &color) override
Theme * getTheme() const
The global GUI theme.
void setCursorType(Cursor cursor)
Sets which cursor should be used.
const ItemInfo & get(int id) const
std::string_view getKeyName(std::string_view configName) const
Get the key name by providing the keys config name.
virtual void handleLink(const std::string &link)=0
Class controlling the game's color palette.
const Palette & getPalette(size_t index) const
static std::optional< int > getColorIdForChar(char c)
Returns the color ID associated with a character, if it exists.
bool passed() const
Returns whether the timer has passed.
void set(uint32_t ms=0)
Sets the timer with an optional duration in milliseconds.
A wrapper around SDL_ttf for allowing the use of TrueType fonts.
ItemDB * itemDb
Items info database.
gcn::Font * boldFont
Bolded text font.
bool startsWith(std::string_view str, std::string_view prefix)
Returns whether a string starts with a given prefix.
LayoutContext(gcn::Font *font, const Palette &palette)
const gcn::Color textColor
std::optional< gcn::Color > outlineColor
LinePart linePart(int x, std::string text)
const std::optional< gcn::Color > textOutlineColor
std::vector< LinePart > parts
std::vector< BrowserLink > links