106 lines
3 KiB
C++
106 lines
3 KiB
C++
#include <cmath>
|
|
|
|
#include <SDL2/SDL_render.h>
|
|
|
|
#include <basic_widgets/core/math.hpp>
|
|
#include <basic_widgets/w/button.hpp>
|
|
|
|
using namespace bwidgets;
|
|
|
|
const Color Button::default_color_bg {150, 150, 150, SDL_ALPHA_OPAQUE};
|
|
const Color Button::default_color_bg_hover {175, 175, 175, SDL_ALPHA_OPAQUE};
|
|
const Color Button::default_color_fg {0, 0, 0, SDL_ALPHA_OPAQUE};
|
|
|
|
Button::Button(Widget* parent) noexcept : Widget{parent}, _caption{this}
|
|
{
|
|
_focus_area = _click_area = &_widget_area;
|
|
_caption.alignment = Caption::Alignment::CENTER;
|
|
|
|
_caption.render_mode(Font::RenderMode::BLENDED);
|
|
|
|
border_gradient = [this](int len, int pos, float divider) -> Color {
|
|
const auto& end_color = _is_hovered ? color_bg_hover : color_bg;
|
|
const auto start_color = end_color / divider;
|
|
const auto factor = linear(pos, 0, len);
|
|
return lerp(start_color, end_color, factor);
|
|
};
|
|
}
|
|
|
|
auto Button::size() const noexcept -> Size
|
|
{
|
|
return _caption.size() + border_size * 2;
|
|
}
|
|
|
|
auto Button::text() const noexcept -> const std::string&
|
|
{
|
|
return _caption.text();
|
|
}
|
|
|
|
auto Button::text(const std::string& txt) -> Button*
|
|
{
|
|
_caption.text(txt);
|
|
_handle_geometry_change(_viewport);
|
|
return this;
|
|
}
|
|
|
|
void Button::_handle_font_change(const std::shared_ptr<Font>& f)
|
|
{
|
|
_caption.font(f);
|
|
_handle_geometry_change(_viewport);
|
|
}
|
|
|
|
void Button::_handle_font_color_change(const Color& fg, const Color&)
|
|
{
|
|
_caption.font_color_fg(fg);
|
|
}
|
|
|
|
void Button::_handle_geometry_change(const SDL_Rect& vp)
|
|
{
|
|
const auto h = _caption.size().h + 2 * border_size.h;
|
|
|
|
_widget_area = {0, center_line(vp.h, _caption.size().h) - border_size.h, vp.w, h};
|
|
|
|
const auto txt_size = _caption.size();
|
|
|
|
_caption_area = {center_line(vp.w, txt_size.w), center_line(vp.h, txt_size.h),
|
|
txt_size.w, txt_size.h};
|
|
_caption.viewport(rect_offset(_caption_area, vp));
|
|
}
|
|
|
|
void Button::_handle_renderer_change(const std::shared_ptr<Renderer>& r)
|
|
{
|
|
_caption.renderer(r);
|
|
}
|
|
|
|
void Button::_handle_rendering()
|
|
{
|
|
const Color& c = _is_hovered ? color_bg_hover : color_bg;
|
|
const auto divider = _is_pushed ? 1.5 : 2;
|
|
auto x = 0;
|
|
auto y = 0;
|
|
const auto biggest = border_size.w > border_size.h ? border_size.w : border_size.h;
|
|
while (x < border_size.w || y < border_size.h) {
|
|
const auto max = x > y ? x : y;
|
|
const auto margin = Size({x, y});
|
|
_renderer->draw_color(border_gradient(biggest, max, divider))
|
|
->draw_rect(rect_margin(_widget_area, margin));
|
|
if (x < border_size.w) x++;
|
|
if (y < border_size.h) y++;
|
|
}
|
|
|
|
_renderer->draw_color(c)->fill_rect(rect_margin(_widget_area, border_size));
|
|
_caption.font_color_bg(c);
|
|
_caption.render();
|
|
}
|
|
|
|
void Button::_on_push(bool state)
|
|
{
|
|
SDL_Point offset {_viewport.x, _viewport.y};
|
|
if (state) {
|
|
offset.x += 1;
|
|
offset.y += 1;
|
|
}
|
|
|
|
_caption.viewport(rect_offset(_caption_area, offset));
|
|
}
|