moar Button widget wip

This commit is contained in:
Andrea Blankenstijn 2021-06-07 10:26:31 +02:00
parent 282497cc61
commit cc8b231623
4 changed files with 128 additions and 48 deletions

View file

@ -1,13 +1,15 @@
#include <iostream>
#include "SDL_ttf.h"
#include "button.hpp"
#include "widget.hpp"
Button::Button(SDL_Renderer* r, SDL_Rect& vp, TTF_Font* f)
: Widget(r, vp), _font(f)
: Widget(r, vp), _font(f), _font_height(TTF_FontHeight(f))
{
set_caption("");
_update_caption_area();
set_viewport(vp);
}
Button::~Button()
@ -17,11 +19,7 @@ Button::~Button()
void Button::handle_event(const SDL_Event& ev)
{
}
SDL_Rect Button::minimal_size() const
{
return _caption_size;
Widget::handle_event(ev);
}
void Button::render()
@ -31,26 +29,49 @@ void Button::render()
SDL_RenderGetViewport(_renderer, &old_vp);
SDL_RenderSetViewport(_renderer, &_viewport);
for (int i = border_width; i >= 0; i--)
SDL_Color bg_color = _hovered ? color_background_hover : color_background;
if (_pushed)
{
SDL_SetRenderDrawColor(
_renderer,
color_background.r * 10 / (i + 11),
color_background.g * 10 / (i + 11),
color_background.b * 10 / (i + 11),
color_background.a
);
int margin = border_width - i;
SDL_Rect rect = {
margin,
margin,
_viewport.w - margin * 2,
_viewport.h - margin * 2
};
SDL_RenderFillRect(_renderer, &rect);
for (int i = 0; i < border_width; i++)
{
SDL_SetRenderDrawColor(
_renderer,
bg_color.r * (i + 10) / 10,
bg_color.g * (i + 10) / 10,
bg_color.b * (i + 10) / 10,
bg_color.a
);
SDL_Rect rect = {
_padding_h + i,
_padding_v + i,
_widget_area.w - i * 2,
_widget_area.h - i * 2
};
SDL_RenderFillRect(_renderer, &rect);
}
}
else
{
for (int i = border_width; i >= 0; i--)
{
SDL_SetRenderDrawColor(
_renderer,
bg_color.r * (i + 10) / 10,
bg_color.g * (i + 10) / 10,
bg_color.b * (i + 10) / 10,
bg_color.a
);
int margin = border_width - i;
SDL_Rect rect = {
_padding_h + margin,
_padding_v + margin,
_widget_area.w - margin * 2,
_widget_area.h - margin * 2
};
SDL_RenderFillRect(_renderer, &rect);
}
}
SDL_RenderSetViewport(_renderer, &_caption_viewport);
SDL_RenderCopy(_renderer, _caption_texture, NULL, &_caption_area);
SDL_RenderSetViewport(_renderer, &old_vp);
@ -59,6 +80,7 @@ void Button::render()
void Button::set_caption(std::string text)
{
_caption_text = text;
TTF_SizeUTF8(_font, _caption_text.c_str(), &_caption_size.w, &_caption_size.h);
_render_caption_text();
_update_caption_area();
}
@ -66,41 +88,39 @@ void Button::set_caption(std::string text)
void Button::set_font(TTF_Font* font)
{
_font = font;
_font_height = TTF_FontHeight(_font) + 2 * border_width;
_render_caption_text();
}
void Button::set_viewport(const SDL_Rect& vp)
void Button::set_viewport(SDL_Rect& vp)
{
_padding_v = vp.h / 2.0 - (
_font_height * _caption_height_multiplicator + 2 * border_width
) / 2.0;
Widget::set_viewport(vp);
_caption_viewport = {
_viewport.x + border_width,
_viewport.y + border_width,
_viewport.w - 2 * border_width,
_viewport.h - 2 * border_width
};
_update_caption_area();
}
void Button::_render_caption_text()
{
if (_font == NULL)
return;
SDL_Surface* surface = TTF_RenderUTF8_Blended(
_font,
_caption_text.c_str(),
color_foreground);
_caption_texture = SDL_CreateTextureFromSurface(_renderer, surface);
SDL_FreeSurface(surface);
TTF_SizeUTF8(_font, _caption_text.c_str(), &_caption_size.w, &_caption_size.h);
}
void Button::_update_caption_area()
{
if (_caption_text.length() < 1)
return;
_caption_area = {0, 0, 0, 0};
int y_offset = _caption_viewport.h / 2.0 - _caption_size.h / 2.0;
int x_offset = _caption_viewport.w / 2.0 - _caption_size.w / 2.0;
int y_offset = _widget_area.h / 2.0 - _caption_size.h / 2.0 + _padding_v;
int x_offset = _widget_area.w / 2.0 - _caption_size.w / 2.0 + _padding_h;
_caption_area = {x_offset, y_offset, _caption_size.w, _caption_size.h};
TTF_SizeUTF8(_font, _caption_text.c_str(), &_caption_size.w, &_caption_size.h);
}

View file

@ -12,13 +12,13 @@
class Button : public Widget
{
protected:
SDL_Rect _caption_area = {0, 0, 0, 0};
SDL_Rect _caption_size = {0, 0, 0, 0};
SDL_Rect _caption_area;
SDL_Rect _caption_size;
std::string _caption_text;
SDL_Texture* _caption_texture = NULL;
SDL_Rect _caption_viewport = {0, 0, 0, 0};
TTF_Font* _font = NULL;
SDL_Rect _minimal_size = {0, 0, 0, 0};
int _font_height;
float _caption_height_multiplicator = 1.2;
virtual void _render_caption_text();
virtual void _update_caption_area();
@ -26,16 +26,16 @@ protected:
public:
int border_width = 6;
SDL_Color color_background = {175, 175, 175, SDL_ALPHA_OPAQUE};
SDL_Color color_background_hover = {200, 200, 200, SDL_ALPHA_OPAQUE};
SDL_Color color_foreground = {0, 0, 0, SDL_ALPHA_OPAQUE};
Button(SDL_Renderer*, SDL_Rect&, TTF_Font*);
~Button();
virtual void handle_event(const SDL_Event&);
virtual SDL_Rect minimal_size() const;
virtual void render();
virtual void set_caption(std::string);
virtual void set_font(TTF_Font*);
virtual void set_viewport(const SDL_Rect&);
virtual void set_viewport(SDL_Rect&);
};
#endif

View file

@ -1,21 +1,79 @@
#ifndef WIDGET_HPP
#define WIDGET_HPP
#include <functional>
#include <iostream>
#include <SDL2/SDL.h>
class Widget
{
protected:
bool _hovered = false;
bool _pushed = false;
SDL_Renderer* _renderer;
SDL_Rect& _viewport;
SDL_Rect _widget_area;
int _padding_h = 0;
int _padding_v = 0;
virtual void _on_release(const SDL_MouseButtonEvent& button)
{
if (_pushed && click_handler != NULL)
{
click_handler(button);
}
_pushed = false;
}
virtual void _on_push(const SDL_MouseButtonEvent& button)
{
SDL_Point position = {button.x - _viewport.x, button.y - _viewport.y};
if (SDL_PointInRect(&position, &_widget_area) == SDL_TRUE)
{
_pushed = true;
}
}
virtual void _update_hover_state(const SDL_MouseMotionEvent& mouse)
{
SDL_Point position = {mouse.x - _viewport.x, mouse.y - _viewport.y};
_hovered = SDL_PointInRect(&position, &_widget_area) == SDL_TRUE;
}
public:
Widget(SDL_Renderer* r, SDL_Rect& vp) : _renderer(r), _viewport(vp) {}
std::function<void (const SDL_MouseButtonEvent&)> click_handler = NULL;
Widget(SDL_Renderer* r, SDL_Rect& vp)
: _renderer(r), _viewport(vp)
{
set_viewport(vp);
}
virtual ~Widget() {}
virtual SDL_Rect minimal_size() const { return {0, 0, 0, 0}; }
virtual void handle_event(const SDL_Event&) = 0;
virtual void handle_event(const SDL_Event& ev)
{
switch (ev.type)
{
case SDL_MOUSEMOTION:
_update_hover_state(ev.motion);
break;
case SDL_MOUSEBUTTONDOWN:
_on_push(ev.button);
break;
case SDL_MOUSEBUTTONUP:
_on_release(ev.button);
break;
}
}
virtual void render() = 0;
virtual void set_viewport(const SDL_Rect& vp) { _viewport = vp; }
virtual void set_viewport(SDL_Rect& vp)
{
_viewport = vp;
_widget_area = {
_padding_h,
_padding_v,
vp.w - 2 * _padding_h,
vp.h - 2 * _padding_v
};
}
};
#endif

View file

@ -1,5 +1,6 @@
#include <iostream>
#include "button.hpp"
#include <SDL2/SDL_ttf.h>
int main()
{
@ -23,7 +24,7 @@ int main()
SDL_Rect widget_vp = {50, 100, width - 100, height - 200};
Button widget = Button(rend, widget_vp, font);
widget.set_caption("H");
widget.set_caption("Hrtdyjhguk yukvu");
bool quit = false;
while (!quit)
{
@ -48,6 +49,7 @@ int main()
//_handle_click({ev.button.x, ev.button.y});
break;
}
widget.handle_event(ev);
}
SDL_SetRenderDrawColor(rend, 0, 0, 0, SDL_ALPHA_OPAQUE);