bwidgets/src/w/caption_impl.cpp

125 lines
3.4 KiB
C++

#include <basic_widgets/core/math.hpp>
#include <basic_widgets/core/texture.hpp>
#include <basic_widgets/w/caption_impl.hpp>
#include <basic_widgets/w/numeric_input.hpp>
using namespace bwidgets;
CaptionImpl::CaptionImpl(Widget* parent) noexcept : WidgetImpl {parent}
{
_font_color_bg = default_font_color_bg;
_font_color_fg = default_font_color_fg;
}
void CaptionImpl::render_mode(const Font::RenderMode m)
{
if (m != _render_mode) {
_text_texture.reset();
_render_mode = m;
}
}
auto CaptionImpl::size() const noexcept -> Size
{
if (!_font) return {0, 0};
const auto [w, h] = _font->text_size(_text);
return {w + 2 * margins.w, h + 2 * margins.h};
}
auto CaptionImpl::text() const noexcept -> std::string_view
{
return _text;
}
void CaptionImpl::text(std::string t)
{
if (t != _text) {
_text_texture.reset();
_text = std::move(t);
}
}
void CaptionImpl::_handle_font_change(const std::shared_ptr<Font>&)
{
_text_texture.reset();
}
void CaptionImpl::_handle_font_color_change(const Color fg, const Color bg)
{
if (fg != _font_color_fg) {
_text_texture.reset();
_font_color_fg = fg;
}
if (bg != _font_color_bg && _font_render_mode == Font::RenderMode::SHADED) {
_text_texture.reset();
_font_color_bg = fg;
}
}
void CaptionImpl::_handle_geometry_change(const SDL_Rect& vp)
{
if (vp.w != _viewport.w) {
_widget_area = rect_margin({0, 0, vp.w, vp.h}, margins);
}
else if (vp.h != _viewport.h) {
_widget_area = rect_margin({0, 0, vp.w, vp.h}, margins);
_text_texture.reset();
}
}
void CaptionImpl::_handle_renderer_change(const std::shared_ptr<Renderer>&)
{
_text_texture.reset();
}
void CaptionImpl::_handle_rendering()
{
if (!_text_texture) _handle_texture_update();
// fill caption viewport with background color when using
// shaded text rendering mode.
if (_render_mode == Font::RenderMode::SHADED) {
_renderer->draw_color(_font_color_bg)
->fill_rect({0, 0, _viewport.w, _viewport.h});
}
const Size size_dst {
(int)((float)_text_texture->attributes().w / (float)_text_texture->attributes().h
* (float)_widget_area.h),
_widget_area.h};
const auto texture_dst = [size_dst, this]() -> SDL_Rect {
switch (alignment) {
case Alignment::CENTER:
return {center_line(_widget_area.w, size_dst.w) + _widget_area.x,
margins.h, size_dst.w, size_dst.h};
case Alignment::LEFT:
return {margins.w, margins.h, size_dst.w, size_dst.h};
case Alignment::RIGHT:
return {_widget_area.w - size_dst.w - margins.w + _widget_area.x,
margins.h, size_dst.w, size_dst.h};
default:
throw std::logic_error("missing switch case.");
}
}();
_renderer->copy(*_text_texture, nullptr, texture_dst);
}
void CaptionImpl::_handle_texture_update()
{
if (!_font) return;
_text_texture.reset();
auto s = [this]() {
switch (_render_mode) {
case Font::RenderMode::SHADED:
return _font->render(_render_mode, _text, _font_color_fg,
_font_color_bg);
default:
return _font->render(_render_mode, _text, _font_color_fg);
}
}();
_text_texture = std::make_shared<Texture>(*_renderer, s.get());
}