diff --git a/inc/basic_widgets/core/draw.hpp b/inc/basic_widgets/core/draw.hpp index 0e26597..075f625 100644 --- a/inc/basic_widgets/core/draw.hpp +++ b/inc/basic_widgets/core/draw.hpp @@ -13,11 +13,11 @@ namespace bwidgets::core class Renderer; class Texture; - SDL_Color aa(const SDL_Color&, const int, const float) noexcept; - core::Texture filled_circle(const SDL_Color&, int resolution, + SDL_Color aa(const SDL_Color&, const int, const float) noexcept; + core::Texture* filled_circle(const SDL_Color&, int resolution, Renderer*, int aa_pixels = 3); - void set_pixels_color(Texture&, std::function); + void set_pixels_color(Texture*, std::function); } #endif diff --git a/inc/basic_widgets/core/renderer.hpp b/inc/basic_widgets/core/renderer.hpp index 3734783..960624e 100644 --- a/inc/basic_widgets/core/renderer.hpp +++ b/inc/basic_widgets/core/renderer.hpp @@ -45,7 +45,7 @@ namespace bwidgets::core Renderer* draw_points(const std::vector); Renderer* draw_rect(const SDL_Rect&); Renderer* draw_rects(const std::vector); - Renderer* fill_rect(const SDL_Rect&); + Renderer* fill_rect(const SDL_Rect*); Renderer* fill_rects(const std::vector); Size output_size(); void present(); @@ -67,6 +67,11 @@ namespace bwidgets::core auto s = src, d = dst; return copy(t, &s, &d); } + inline Renderer* fill_rect(const SDL_Rect& r) + { + auto rect = r; + return fill_rect(&rect); + } inline Renderer* viewport(const SDL_Rect& vp) { auto v = vp; diff --git a/inc/basic_widgets/w/base/input.hpp b/inc/basic_widgets/w/base/input.hpp index c2c356b..0bf0555 100644 --- a/inc/basic_widgets/w/base/input.hpp +++ b/inc/basic_widgets/w/base/input.hpp @@ -150,6 +150,8 @@ namespace bwidgets::widget SDL_Color color_bg {200, 200, 200, SDL_ALPHA_OPAQUE}; SDL_Color color_bg_focused {255, 255, 255, SDL_ALPHA_OPAQUE}; int float_precision {2}; + int input_min_width {1}; + char input_width_unit {'W'}; T value {}; virtual Input* color_fg(const SDL_Color& c) noexcept @@ -179,6 +181,16 @@ namespace bwidgets::widget return x; } + virtual inline core::Size size() const noexcept override + { + return { + _font->text_size( + std::string(input_min_width, input_width_unit) + ).w + 2 * _border_width, + _font->height + 2 * _border_width + }; + } + T value_from_string(std::string s) { T v; diff --git a/inc/basic_widgets/w/base/layout.hpp b/inc/basic_widgets/w/base/layout.hpp index c48f92a..a2fb062 100644 --- a/inc/basic_widgets/w/base/layout.hpp +++ b/inc/basic_widgets/w/base/layout.hpp @@ -1,6 +1,7 @@ #ifndef BWIDGETS_LAYOUT_HPP_ #define BWIDGETS_LAYOUT_HPP_ +#include #include #include @@ -28,6 +29,7 @@ namespace bwidgets::widget virtual ~Layout() noexcept; virtual Layout* add_widget(Widget*); + virtual void for_widgets(std::function); virtual Layout* handle_event(const SDL_Event&) override; virtual core::Size size() const noexcept override = 0; diff --git a/inc/basic_widgets/w/base/widget.hpp b/inc/basic_widgets/w/base/widget.hpp index 7e14db7..8fe0754 100644 --- a/inc/basic_widgets/w/base/widget.hpp +++ b/inc/basic_widgets/w/base/widget.hpp @@ -29,9 +29,7 @@ namespace bwidgets::widget virtual ~Widget() noexcept = default; virtual Widget* handle_event(const SDL_Event&); - inline virtual core::Size size() const noexcept { - return {_widget_area.w, _widget_area.h}; - } + inline virtual core::Size size() const noexcept = 0; virtual Widget* render() final; diff --git a/inc/basic_widgets/w/caption.hpp b/inc/basic_widgets/w/caption.hpp index a27e068..2cd7bf1 100644 --- a/inc/basic_widgets/w/caption.hpp +++ b/inc/basic_widgets/w/caption.hpp @@ -24,6 +24,7 @@ namespace bwidgets::widget private: SDL_Color _color_fg {0, 0, 0, SDL_ALPHA_OPAQUE}; SDL_Color _color_bg {255, 255, 255, SDL_ALPHA_TRANSPARENT}; + core::Font::RenderMode _render_mode {core::Font::RenderMode::SHADED}; std::string _text; core::Texture* _text_texture {nullptr}; @@ -44,9 +45,11 @@ namespace bwidgets::widget virtual Caption* color_bg(const SDL_Color&); virtual Caption* color_fg(const SDL_Color&); - virtual core::Size size() const noexcept override; + virtual Caption* render_mode(core::Font::RenderMode) noexcept; virtual const std::string& text() const noexcept; virtual Caption* text(const std::string&); + + virtual core::Size size() const noexcept override; }; } diff --git a/inc/basic_widgets/w/numeric_input.hpp b/inc/basic_widgets/w/numeric_input.hpp index a405bf3..f435334 100644 --- a/inc/basic_widgets/w/numeric_input.hpp +++ b/inc/basic_widgets/w/numeric_input.hpp @@ -110,6 +110,9 @@ namespace bwidgets::widget Input::_input_caption.alignment = widget::Caption::Alignment::RIGHT; + Input::input_min_width = 10; + Input::input_width_unit = '0'; + _increment_button.text("+"); _increment_button.click_handler = [this](const SDL_MouseButtonEvent&) { @@ -171,6 +174,16 @@ namespace bwidgets::widget return value; } + virtual inline core::Size size() const noexcept override + { + auto base = Input::size(); + auto btns_width = 4 * _increment_button.size().w; + return { + base.w + btns_width, + base.h + }; + } + virtual std::pair value_range() const noexcept { return _value_range; diff --git a/src/core/draw.cpp b/src/core/draw.cpp index 8c79ac0..21c58ff 100644 --- a/src/core/draw.cpp +++ b/src/core/draw.cpp @@ -26,17 +26,17 @@ namespace bwidgets::core }; } - core::Texture filled_circle( + core::Texture* filled_circle( const SDL_Color& c, const int resolution, core::Renderer* r, const int aa_pixels ) { - core::Texture texture (r, + auto* texture {new core::Texture(r, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, - resolution, resolution); + resolution, resolution)}; const auto radius {resolution / 2}; const SDL_Point center {radius, radius}; @@ -52,18 +52,18 @@ namespace bwidgets::core aa_color.a); } ); - texture.blend_mode(SDL_BLENDMODE_BLEND); - texture.scale_mode(SDL_ScaleModeNearest); + texture->blend_mode(SDL_BLENDMODE_BLEND); + texture->scale_mode(SDL_ScaleModeNearest); return texture; } void set_pixels_color( - core::Texture& t, + core::Texture* t, std::function pixel_color ) { - auto attr = t.attributes(); + auto attr = t->attributes(); auto pitch = attr.w * attr.format->BytesPerPixel; std::vector pixels; @@ -76,6 +76,6 @@ namespace bwidgets::core } } - t.update(nullptr, (const void*)pixels.data(), pitch); + t->update(nullptr, (const void*)pixels.data(), pitch); } } diff --git a/src/core/renderer.cpp b/src/core/renderer.cpp index e110b99..b152572 100644 --- a/src/core/renderer.cpp +++ b/src/core/renderer.cpp @@ -126,10 +126,9 @@ core::Renderer* core::Renderer::draw_rects(const std::vector rs) return this; } -core::Renderer* core::Renderer::fill_rect(const SDL_Rect& r) +core::Renderer* core::Renderer::fill_rect(const SDL_Rect* r) { - SDL_Rect rect = r; - SDLError::success_or_throw(SDL_RenderFillRect(c_pod, &rect), + SDLError::success_or_throw(SDL_RenderFillRect(c_pod, r), __FILE__, __FUNCTION__, __LINE__); return this; diff --git a/src/w/base/layout.cpp b/src/w/base/layout.cpp index 7065a4d..6b48c7f 100644 --- a/src/w/base/layout.cpp +++ b/src/w/base/layout.cpp @@ -10,10 +10,17 @@ widget::Layout::~Layout() noexcept widget::Layout* widget::Layout::add_widget(Widget *widget_ptr) { + widget_ptr->renderer(_renderer); _widgets.push_back(widget_ptr); return this; } +void widget::Layout::for_widgets(std::function f) +{ + for (auto* w : _widgets) + f(w); +} + widget::Layout* widget::Layout::handle_event(const SDL_Event& ev) { for (Widget* widget_ptr : _widgets) @@ -28,8 +35,8 @@ void widget::Layout::_handle_geometry_change(const SDL_Rect& vp) noexcept void widget::Layout::_handle_renderer_change(core::Renderer* r) { - for (auto* widget : _widgets) - widget->renderer(r); + for (auto* w : _widgets) + w->renderer(r); } void widget::Layout::_handle_rendering() diff --git a/src/w/base/widget.cpp b/src/w/base/widget.cpp index 65df2f9..fccbdb2 100644 --- a/src/w/base/widget.cpp +++ b/src/w/base/widget.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -43,7 +44,8 @@ widget::Widget* widget::Widget::handle_event(const SDL_Event &ev) widget::Widget* widget::Widget::render() { - if (_renderer == nullptr) + SDL_assert_release(_renderer); + if (!_renderer) return this; #ifndef _NDEBUG diff --git a/src/w/caption.cpp b/src/w/caption.cpp index 45e4cd5..749ccab 100644 --- a/src/w/caption.cpp +++ b/src/w/caption.cpp @@ -26,6 +26,13 @@ widget::Caption* widget::Caption::color_fg(const SDL_Color& c) return this; } +widget::Caption* widget::Caption::render_mode(core::Font::RenderMode m) noexcept +{ + _render_mode = m; + core::OpaqueStruct::discard(_text_texture); + return this; +} + core::Size widget::Caption::size() const noexcept { if (_font == nullptr) @@ -115,8 +122,17 @@ void widget::Caption::_handle_rendering() void widget::Caption::_handle_texture_update() { + SDL_assert_release(_font); core::OpaqueStruct::discard(_text_texture); - auto txt_surface = _font->render(core::Font::RenderMode::SHADED, - _text, _color_fg, _color_bg); - _text_texture = new core::Texture(_renderer, txt_surface); + SDL_Surface* s; + switch (_render_mode) + { + case core::Font::RenderMode::SHADED: + s = _font->render(_render_mode, _text, _color_fg, _color_bg); + break; + default: + s = _font->render(_render_mode, _text, _color_fg); + break; + } + _text_texture = new core::Texture(_renderer, s); } diff --git a/src/w/horizontal_layout.cpp b/src/w/horizontal_layout.cpp index bfe1da5..9a597e1 100644 --- a/src/w/horizontal_layout.cpp +++ b/src/w/horizontal_layout.cpp @@ -1,3 +1,4 @@ +#include #include using namespace bwidgets; @@ -27,11 +28,12 @@ void widget::HorizontalLayout::_update_layout(const SDL_Rect& vp) noexcept for (std::vector::size_type i = 0; i < _widgets.size(); i++) { - _widgets.at(i)->viewport({ + auto* w = _widgets[i]; + w->viewport({ vp.x + margins.w + (int)i * (widget_size + margins.w), - vp.y, + vp.y + core::center_rect(vp.h, w->size().h), widget_size, - vp.h + w->size().h }); } } diff --git a/src/w/vertical_layout.cpp b/src/w/vertical_layout.cpp index 07a40ea..c40e9d6 100644 --- a/src/w/vertical_layout.cpp +++ b/src/w/vertical_layout.cpp @@ -1,38 +1,38 @@ +#include #include using namespace bwidgets; core::Size widget::VerticalLayout::size() const noexcept { - core::Size max {0, 0}; + core::Size size {0, 0}; for (const auto* w : _widgets) { - if (w->size().w > max.w) - max.w = w->size().w; - if (w->size().h > max.h) - max.h = w->size().h; + if (w->size().w > size.w) + size.w = w->size().w; + + size.h += w->size().h; } return { - max.w + 2 * margins.w, - (int)_widgets.size() * max.h + ((int)_widgets.size() + 1) * margins.h + size.w + 2 * margins.w, + size.h + ((int)_widgets.size() + 1) * margins.h }; } void widget::VerticalLayout::_update_layout(const SDL_Rect& vp) noexcept { - int widget_size = (vp.h - (_widgets.size() + 1) * margins.h) - / _widgets.size(); - + int offset = 0; for (std::vector::size_type i = 0; i < _widgets.size(); i++) { - SDL_Rect widget_vp = { - vp.x, - vp.y + ((int)i + 1) * margins.h + (int)i * widget_size, - vp.w, - widget_size, - }; - _widgets.at(i)->viewport(widget_vp); + auto* w = _widgets[i]; + w->viewport({ + vp.x, + vp.y + ((int)i + 1) * margins.h + offset, + vp.w, + w->size().h, + }); + offset += w->size().h; } }