109 lines
2.7 KiB
C++
109 lines
2.7 KiB
C++
#include <SDL2/SDL_ttf.h>
|
|
|
|
#include "font.hh"
|
|
#include "TextWidget.hh"
|
|
|
|
TextWidget::TextWidget(TTF_Font *font, std::string text, int width, int height, std::string name)
|
|
: Widget(width, height, std::move(name)), text_(std::move(text)), font_(font),
|
|
textSurf_(nullptr)
|
|
{
|
|
layout();
|
|
}
|
|
|
|
TextWidget::~TextWidget()
|
|
{
|
|
}
|
|
|
|
void TextWidget::setText(std::string text)
|
|
{
|
|
if (text != text_) {
|
|
text_ = std::move(text);
|
|
invalidateGL();
|
|
textSurf_.release();
|
|
layout();
|
|
}
|
|
}
|
|
|
|
void TextWidget::setForegroundColor(SDL_Color fg)
|
|
{
|
|
Widget::setForegroundColor(fg);
|
|
|
|
// Trigger text rerender
|
|
textSurf_.release();
|
|
layout();
|
|
}
|
|
|
|
void TextWidget::layout(Widget *caller)
|
|
{
|
|
int width, height;
|
|
std::tie(width, height) = Widget::baseLayout(caller);
|
|
|
|
// Determine text size
|
|
int textWidth, textHeight;
|
|
if ((height == 0) || (width == 0)) {
|
|
if(TTF_SizeUTF8(font_, text_.c_str(), &textWidth, &textHeight) != 0)
|
|
throw TTFException{};
|
|
}
|
|
|
|
bool multiline = false;
|
|
if (height == 0) {
|
|
if (width != 0) {
|
|
textSurf_.reset(TTF_RenderUTF8_Blended_Wrapped(font_,
|
|
text_.c_str(),
|
|
fg_, width - padLeft_ - padRight_));
|
|
if (!textSurf_)
|
|
throw TTFException{};
|
|
|
|
multiline = true;
|
|
// TODO: Get proper tight bounding box for multiline text
|
|
height = textSurf_->h - // TTF_FontLineSkip(font_.getFont())
|
|
+ padTop_ + padBottom_;
|
|
} else {
|
|
width = textWidth + padLeft_ + padRight_;
|
|
height = textHeight + padTop_ + padBottom_;
|
|
}
|
|
}
|
|
|
|
if (width == 0) {
|
|
width = textWidth + padLeft_ + padRight_;
|
|
}
|
|
|
|
if ((width != realWidth_) || (height != realHeight_) || !textSurf_) {
|
|
if (!multiline) {
|
|
textSurf_.reset(TTF_RenderUTF8_Blended(font_, text_.c_str(), fg_));
|
|
|
|
if (!textSurf_)
|
|
throw TTFException{};
|
|
}
|
|
|
|
if ((width != realWidth_) || (height != realHeight_)) {
|
|
bool parentLayout = false;
|
|
if (parent_ && (caller != parent_) &&
|
|
(((width != realWidth_) && ((parent_->getWidth() == WRAP_CONTENT) ||
|
|
(parent_->getWidth() == WRAP_CONTENT_FILL))) ||
|
|
((height != realHeight_) && ((parent_->getHeight() == WRAP_CONTENT) ||
|
|
(parent_->getHeight() == WRAP_CONTENT_FILL)))))
|
|
parentLayout = true;
|
|
|
|
realWidth_ = width;
|
|
realHeight_ = height;
|
|
if (parentLayout)
|
|
_layout(*parent_);
|
|
|
|
printf("TextWidget %s now %d, %d\n", name_.c_str(), realWidth_, realHeight_);
|
|
}
|
|
|
|
invalidateGL();
|
|
}
|
|
}
|
|
|
|
void TextWidget::render(SDL_Surface *dst, SDL_Rect *dstRect) const
|
|
{
|
|
Widget::render(dst, dstRect);
|
|
|
|
SDL_Rect rect = calcContentRect(dst, dstRect, textSurf_->clip_rect);
|
|
|
|
if (SDL_BlitSurface(textSurf_.get(), nullptr, dst, &rect) != 0)
|
|
throw SDLException{};
|
|
}
|