Added WidgetText. Fixed some things. Updated README

This commit is contained in:
2025-12-04 17:23:53 +02:00
parent 58abb91c64
commit 56e07e1080
8 changed files with 473 additions and 8 deletions

View File

@@ -5,7 +5,7 @@
class Widget
{
private:
protected:
// Internal surface for drawing
SDL_Surface* m_surface;

223
Widgets/WidgetText.cpp Normal file
View File

@@ -0,0 +1,223 @@
#include "WidgetText.h"
using std::string;
static SDL_Surface* render_text(bool should_wrap, TTF_Font* font, const string& text, SDL_Color color, Uint32 wrap_size)
{
SDL_Surface* txt_surface = nullptr;
if (should_wrap)
{
txt_surface = TTF_RenderUTF8_Solid_Wrapped(font, text.c_str(), color, wrap_size);
}
else
{
txt_surface = TTF_RenderUTF8_Solid(font, text.c_str(), color);
}
return txt_surface;
}
WidgetText::WidgetText(int width, int height, string text,
TextFit fit, bool should_wrap,
HorizontalAlign halign, VerticalAlign valign,
SDL_Color text_color,
int size, std::string font)
: Widget(width, height),
m_text(text),
m_font_file(font),
m_size(size),
m_fit(fit),
m_should_wrap(should_wrap),
m_halign(halign),
m_valign(valign),
m_text_color(text_color)
{
if (nullptr != m_surface)
{
SDL_SetSurfaceBlendMode(m_surface, SDL_BLENDMODE_BLEND);
}
}
WidgetText::WidgetText(int width, int height, string text,
TextFit fit, bool should_wrap,
int size, string font)
: Widget(width, height),
m_text(text),
m_font_file(font),
m_size(size),
m_fit(fit),
m_should_wrap(should_wrap),
m_halign(HALIGN_CENTER),
m_valign(VALIGN_CENTER),
m_text_color{.r = 0, .g = 0, .b = 0, .a = SDL_ALPHA_OPAQUE}
{
if (nullptr != m_surface)
{
SDL_SetSurfaceBlendMode(m_surface, SDL_BLENDMODE_BLEND);
}
}
WidgetText::WidgetText(int width, int height, string text,
int size, string font)
: Widget(width, height),
m_text(text),
m_font_file(font),
m_size(size),
m_fit(FIT_NONE),
m_halign(HALIGN_CENTER),
m_valign(VALIGN_CENTER),
m_text_color{.r = 0, .g = 0, .b = 0, .a = SDL_ALPHA_OPAQUE}
{
if (nullptr != m_surface)
{
SDL_SetSurfaceBlendMode(m_surface, SDL_BLENDMODE_BLEND);
}
}
void WidgetText::set_text(const string& text)
{
m_text = text;
}
void WidgetText::set_font(const string& font_file)
{
m_font_file = font_file;
}
void WidgetText::set_font_size(int size)
{
m_size = size;
}
void WidgetText::set_fit(TextFit fit)
{
m_fit = fit;
}
void WidgetText::set_halign(HorizontalAlign halign)
{
m_halign = halign;
}
void WidgetText::set_valign(VerticalAlign valign)
{
m_valign = valign;
}
void WidgetText::set_color(SDL_Color text_color)
{
m_text_color = text_color;
}
void WidgetText::draw()
{
// Clear surface
SDL_FillRect(m_surface, nullptr, SDL_MapRGBA(m_surface->format, 255, 255, 255, SDL_ALPHA_TRANSPARENT));
string font_name = m_font_file;
if (font_name.empty())
{
font_name = default_font_name;
}
TTF_Font* font = get_font(m_size, font_name);
if (nullptr == font)
{
// TODO: Message printing
return;
}
// Render text
SDL_Surface* txt_surface = render_text(m_should_wrap, font, m_text, m_text_color, m_rect.w);
if (nullptr == txt_surface)
{
// TODO: Message printing
return;
}
// Check if text fits
if (m_fit != FIT_NONE)
{
double x_scale;
double y_scale;
x_scale = m_surface->w;
x_scale /= txt_surface->w;
y_scale = m_surface->h;
y_scale /= txt_surface->h;
// Find the scale needed to shrink or enlarge with
double min_scale = x_scale;
if (y_scale < min_scale)
{
min_scale = y_scale;
}
// Do not scale up if only shrinkage is allowed
if ((min_scale > 1.0) && (FIT_SHRINK == m_fit))
{
min_scale = 1.0;
}
// Find new font size
int new_text_size = m_size;
new_text_size *= min_scale;
// Re-render text
if (new_text_size != m_size)
{
SDL_FreeSurface(txt_surface);
font = get_font(new_text_size, font_name);
if (nullptr == font)
{
// TODO: Message printing
return;
}
txt_surface = render_text(m_should_wrap, font, m_text, m_text_color, m_rect.w);
if (nullptr == txt_surface)
{
// TODO: Message printing
return;
}
}
}
// Now we have the final rendered text surface
SDL_Rect align = surface_align(m_surface, txt_surface, m_halign, m_valign);
SDL_BlitSurface(txt_surface, NULL, m_surface, &align);
SDL_FreeSurface(txt_surface);
}
Widget* WidgetText::builder(const nlohmann::json& j)
{
int width = 0;
int height = 0;
string text = "";
TextFit fit = FIT_NONE;
bool should_wrap = false;
HorizontalAlign halign = HALIGN_CENTER;
VerticalAlign valign = VALIGN_CENTER;
SDL_Color text_color = {.r = 0, .g = 0, .b = 0, .a = SDL_ALPHA_OPAQUE};
int size = 0;
string font = "";
json_extract(j, "width", width);
json_extract(j, "height", height);
json_extract(j, "text", text);
json_extract(j, "fit", fit);
json_extract(j, "should_wrap", should_wrap);
json_extract(j, "halign", halign);
json_extract(j, "valign", valign);
json_extract(j, "color", text_color);
json_extract(j, "size", size);
json_extract(j, "font", font);
if ((0 == width) || (0 == height) || (0 == size))
{
return nullptr;
}
return new WidgetText(width, height, text, fit, should_wrap, halign, valign, text_color, size, font);
}

71
Widgets/WidgetText.h Normal file
View File

@@ -0,0 +1,71 @@
#ifndef WIDGET_TEXT_H_
#define WIDGET_TEXT_H_
#include "Widget.h"
#include <SDL2/SDL.h>
#include <string>
#include "../sdl_helpers.h"
#include "../json.hpp"
class WidgetText : public Widget
{
protected:
// Text to display
std::string m_text;
// Desired font file
// Leave empty for default
std::string m_font_file;
// Desired font size
int m_size;
// Whether to fit text inside rectangle
// FIT_SHRINK will try with the desired font size and shrink if needed
// FIT_AUTO will with the desired font size and shrink or enlarge if needed
// Default - FIT_NONE
TextFit m_fit;
// Whether to wrap to multiple lines
// Default - false
bool m_should_wrap;
// Default - center
HorizontalAlign m_halign;
// Default - center
VerticalAlign m_valign;
// Default - black
SDL_Color m_text_color;
public:
WidgetText(int width, int height, std::string text,
TextFit fit, bool should_wrap,
HorizontalAlign halign, VerticalAlign valign,
SDL_Color text_color,
int size, std::string font = "");
WidgetText(int width, int height, std::string text,
TextFit fit, bool should_wrap,
int size, std::string font = "");
WidgetText(int width, int height, std::string text,
int size, std::string font = "");
void set_text(const std::string& text);
void set_font(const std::string& font_file);
void set_font_size(int size);
void set_fit(TextFit fit);
void set_halign(HorizontalAlign halign);
void set_valign(VerticalAlign valign);
void set_color(SDL_Color text_color);
virtual void draw() override;
static Widget* builder(const nlohmann::json& j);
};
#endif // WIDGET_TEXT_H_