big hierarchy refactor, some little changes, add Font class
This commit is contained in:
parent
98f51426b8
commit
dd3ff9358a
|
@ -1,91 +0,0 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
#include <basic_widgets/button.hpp>
|
||||
#include <basic_widgets/horizontal_layout.hpp>
|
||||
#include <basic_widgets/utils/font.hpp>
|
||||
#include <basic_widgets/vertical_layout.hpp>
|
||||
|
||||
using namespace bwidgets::widget;
|
||||
using namespace bwidgets::utils;
|
||||
|
||||
int main()
|
||||
{
|
||||
int width = 640;
|
||||
int height = 480;
|
||||
|
||||
TTF_Init();
|
||||
TTF_Font* font = TTF_OpenFont(font::find("Monospace").c_str(), 20);
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
SDL_Window* win = SDL_CreateWindow(
|
||||
"Widget test",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
width,
|
||||
height,
|
||||
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
|
||||
);
|
||||
auto rend = bwidgets::sdl::Renderer(win, -1, SDL_RENDERER_ACCELERATED);
|
||||
rend.blend_mode(SDL_BLENDMODE_BLEND);
|
||||
|
||||
SDL_Rect layout_vp = {0, 0, width, height};
|
||||
auto layout = new Horizontal_Layout();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
auto column = new Vertical_Layout();
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
auto widget = new Button();
|
||||
widget->text("hello");
|
||||
widget->click_handler = [i, j](const SDL_MouseButtonEvent&) {
|
||||
std::cerr << "click@" << j << ":" << i << std::endl;
|
||||
};
|
||||
widget->font(font);
|
||||
column->add_widget(widget);
|
||||
std::cerr << " " << i << "@" << widget;
|
||||
}
|
||||
layout->add_widget(column);
|
||||
}
|
||||
layout->viewport(layout_vp);
|
||||
layout->renderer(&rend);
|
||||
bool quit = false;
|
||||
while (!quit)
|
||||
{
|
||||
SDL_Event ev;
|
||||
while (SDL_PollEvent(&ev) != 0)
|
||||
{
|
||||
switch (ev.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
quit = true;
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
|
||||
{
|
||||
auto size = rend.output_size();
|
||||
layout_vp.w = size.w;
|
||||
layout_vp.h = size.h;
|
||||
std::cerr << "== WINDOW RESIZED == " << size.w << "x" << size.h << std::endl;
|
||||
layout->viewport(layout_vp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
layout->handle_event(ev);
|
||||
}
|
||||
|
||||
rend.draw_color({75, 75, 75, SDL_ALPHA_OPAQUE});
|
||||
rend.clear();
|
||||
|
||||
layout->render();
|
||||
rend.present();
|
||||
}
|
||||
|
||||
delete layout;
|
||||
SDL_DestroyWindow(win);
|
||||
SDL_Quit();
|
||||
TTF_CloseFont(font);
|
||||
TTF_Quit();
|
||||
return 0;
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
#include <basic_widgets/caption.hpp>
|
||||
#include <basic_widgets/horizontal_layout.hpp>
|
||||
#include <basic_widgets/utils/font.hpp>
|
||||
#include <basic_widgets/vertical_layout.hpp>
|
||||
|
||||
using namespace bwidgets::widget;
|
||||
using namespace bwidgets::utils;
|
||||
|
||||
int main()
|
||||
{
|
||||
int width = 640;
|
||||
int height = 480;
|
||||
|
||||
TTF_Init();
|
||||
TTF_Font* font = TTF_OpenFont(font::find("Monospace").c_str(), 20);
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
SDL_Window* win = SDL_CreateWindow(
|
||||
"Widget test",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
width,
|
||||
height,
|
||||
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
|
||||
);
|
||||
bwidgets::sdl::Renderer rend(win, -1, SDL_RENDERER_ACCELERATED);
|
||||
rend.blend_mode(SDL_BLENDMODE_BLEND);
|
||||
|
||||
SDL_Rect layout_vp = {0, 0, width, height};
|
||||
auto layout = new Horizontal_Layout();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
auto column = new Vertical_Layout();
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
auto widget = new Caption();
|
||||
widget->text("hi");
|
||||
widget->font(font);
|
||||
column->add_widget(widget);
|
||||
std::cerr << " " << i << "@" << widget;
|
||||
}
|
||||
layout->add_widget(column);
|
||||
}
|
||||
layout->viewport(layout_vp);
|
||||
layout->renderer(&rend);
|
||||
bool quit = false;
|
||||
while (!quit)
|
||||
{
|
||||
SDL_Event ev;
|
||||
while (SDL_PollEvent(&ev) != 0)
|
||||
{
|
||||
switch (ev.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
quit = true;
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
|
||||
{
|
||||
auto size = rend.output_size();
|
||||
layout_vp.w = size.w;
|
||||
layout_vp.h = size.h;
|
||||
std::cerr << "== WINDOW RESIZED == " << size.w << "x" << size.h << std::endl;
|
||||
layout->viewport(layout_vp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
layout->handle_event(ev);
|
||||
}
|
||||
|
||||
rend.draw_color({75, 75, 75, SDL_ALPHA_OPAQUE});
|
||||
rend.clear();
|
||||
|
||||
layout->render();
|
||||
rend.present();
|
||||
}
|
||||
|
||||
delete layout;
|
||||
SDL_DestroyWindow(win);
|
||||
SDL_Quit();
|
||||
TTF_CloseFont(font);
|
||||
TTF_Quit();
|
||||
return 0;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
#ifndef FOCUS_HANDLER_HPP
|
||||
#define FOCUS_HANDLER_HPP
|
||||
|
||||
struct SDL_Rect;
|
||||
|
||||
namespace bwidgets::abstract
|
||||
{
|
||||
class FocusHandler
|
||||
{
|
||||
protected:
|
||||
const SDL_Rect* _focus_area = nullptr;
|
||||
bool _has_focus = false;
|
||||
|
||||
virtual void _handle_focus_change();
|
||||
|
||||
public:
|
||||
virtual ~FocusHandler();
|
||||
|
||||
inline void focus(bool focus)
|
||||
{
|
||||
_has_focus = focus;
|
||||
_handle_focus_change();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef FONT_HANDLER_HPP
|
||||
#define FONT_HANDLER_HPP
|
||||
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
namespace bwidgets::abstract
|
||||
{
|
||||
class FontHandler
|
||||
{
|
||||
protected:
|
||||
TTF_Font* _font {nullptr};
|
||||
|
||||
virtual void _handle_font_change() = 0;
|
||||
|
||||
public:
|
||||
virtual ~FontHandler();
|
||||
|
||||
void font(TTF_Font*);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef TEXTURE_HANDLER_
|
||||
#define TEXTURE_HANDLER_
|
||||
|
||||
namespace bwidgets::sdl {
|
||||
class Renderer;
|
||||
}
|
||||
|
||||
namespace bwidgets::abstract
|
||||
{
|
||||
class Texture_Handler
|
||||
{
|
||||
protected:
|
||||
virtual void _handle_texture_update(sdl::Renderer*) = 0;
|
||||
|
||||
public:
|
||||
virtual ~Texture_Handler() noexcept {};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,39 +0,0 @@
|
|||
#ifndef BUTTON_HPP
|
||||
#define BUTTON_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <basic_widgets/caption.hpp>
|
||||
#include <basic_widgets/abstract/mouse_handler.hpp>
|
||||
#include <basic_widgets/sdl/data_type.hpp>
|
||||
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class Button : public abstract::Widget,
|
||||
public abstract::FontHandler,
|
||||
public abstract::MouseHandler
|
||||
{
|
||||
protected:
|
||||
widget::Caption _caption;
|
||||
SDL_Rect _caption_area;
|
||||
SDL_Color _color_foreground {0, 0, 0, SDL_ALPHA_OPAQUE};
|
||||
|
||||
virtual void _handle_font_change() override;
|
||||
virtual void _handle_geometry_change(const SDL_Rect&) noexcept override;
|
||||
virtual void _handle_renderer_change(sdl::Renderer*) override;
|
||||
virtual void _handle_rendering() override;
|
||||
|
||||
public:
|
||||
int border_width {3};
|
||||
SDL_Color color_bg {150, 150, 150, SDL_ALPHA_OPAQUE};
|
||||
SDL_Color color_bg_hover {175, 175, 175, SDL_ALPHA_OPAQUE};
|
||||
|
||||
Button(Widget* parent=nullptr);
|
||||
|
||||
virtual sdl::Size size() const noexcept override;
|
||||
virtual const std::string& text() const noexcept;
|
||||
virtual void text(std::string);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,66 +0,0 @@
|
|||
#ifndef CAPTION_HPP
|
||||
#define CAPTION_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <basic_widgets/abstract/font_handler.hpp>
|
||||
#include <basic_widgets/abstract/texture_handler.hpp>
|
||||
#include <basic_widgets/abstract/widget.hpp>
|
||||
#include <basic_widgets/sdl/data_type.hpp>
|
||||
|
||||
struct SDL_Surface;
|
||||
|
||||
namespace bwidgets::sdl {
|
||||
class Texture;
|
||||
}
|
||||
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class Caption : public abstract::Widget, public abstract::FontHandler,
|
||||
public abstract::Texture_Handler
|
||||
{
|
||||
public:
|
||||
enum struct AlignmentH {
|
||||
CENTER,
|
||||
LEFT,
|
||||
RIGHT
|
||||
};
|
||||
|
||||
enum struct AlignmentV {
|
||||
BOTTOM,
|
||||
CENTER,
|
||||
TOP
|
||||
};
|
||||
|
||||
private:
|
||||
SDL_Color _color_fg {0, 0, 0, SDL_ALPHA_OPAQUE};
|
||||
std::string _text;
|
||||
SDL_Surface* _text_surface {nullptr};
|
||||
sdl::Texture* _text_texture {nullptr};
|
||||
|
||||
virtual void _handle_font_change() override;
|
||||
virtual void _handle_geometry_change(const SDL_Rect&) noexcept override;
|
||||
virtual void _handle_renderer_change(sdl::Renderer*) override;
|
||||
virtual void _handle_rendering() override;
|
||||
virtual void _handle_texture_update(sdl::Renderer*) override;
|
||||
virtual void _render_text();
|
||||
|
||||
public:
|
||||
struct {
|
||||
AlignmentH h;
|
||||
AlignmentV v;
|
||||
} alignment {AlignmentH::LEFT, AlignmentV::CENTER};
|
||||
SDL_Color color_bg {0, 0, 0, SDL_ALPHA_TRANSPARENT};
|
||||
sdl::Size margins {2, 2};
|
||||
|
||||
Caption(Widget* parent=nullptr) : Widget(parent) {}
|
||||
~Caption() noexcept;
|
||||
|
||||
virtual void color_fg(const SDL_Color&);
|
||||
virtual sdl::Size size() const noexcept override;
|
||||
virtual const std::string& text() const noexcept;
|
||||
virtual void text(const std::string&);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef BWIDGETS_DRAW_HPP_
|
||||
#define BWIDGETS_DRAW_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
struct SDL_Color;
|
||||
struct SDL_PixelFormat;
|
||||
struct SDL_Point;
|
||||
|
||||
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,
|
||||
Renderer*, int aa_pixels = 3);
|
||||
void set_pixels_color(Texture&, std::function<uint32_t (const SDL_Point&,
|
||||
const SDL_PixelFormat*)>);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,70 @@
|
|||
#ifndef BWIDGETS_FONT_HPP_
|
||||
#define BWIDGETS_FONT_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
#include <basic_widgets/core/type/opaque_struct.hpp>
|
||||
#include <basic_widgets/core/type/size.hpp>
|
||||
|
||||
/* struct SDL_Surface; */
|
||||
|
||||
namespace bwidgets::core
|
||||
{
|
||||
class Font final : public OpaqueStruct<TTF_Font>
|
||||
{
|
||||
public:
|
||||
enum struct Hinting {
|
||||
LIGHT = TTF_HINTING_LIGHT,
|
||||
MONO = TTF_HINTING_MONO,
|
||||
NONE = TTF_HINTING_NONE,
|
||||
NORMAL = TTF_HINTING_NORMAL
|
||||
};
|
||||
|
||||
enum struct RenderMode {
|
||||
SOLID, SHADED, BLENDED
|
||||
};
|
||||
|
||||
struct Style {
|
||||
Style() = delete;
|
||||
|
||||
static const uint8_t
|
||||
BOLD = TTF_STYLE_BOLD,
|
||||
ITALIC = TTF_STYLE_ITALIC,
|
||||
NORMAL = TTF_STYLE_NORMAL,
|
||||
STRIKETHROUGH = TTF_STYLE_STRIKETHROUGH,
|
||||
UNDERLINE = TTF_STYLE_UNDERLINE;
|
||||
};
|
||||
|
||||
const int ascent;
|
||||
const int descent;
|
||||
const int faces;
|
||||
const std::string family_name;
|
||||
const bool fixed_width;
|
||||
const int height;
|
||||
const int line_skip;
|
||||
const std::string style_name;
|
||||
|
||||
Font(TTF_Font*);
|
||||
Font(const std::string&, int);
|
||||
virtual ~Font() override;
|
||||
|
||||
Hinting hinting();
|
||||
Font* hinting(Hinting);
|
||||
bool kerning();
|
||||
Font* kerning(bool);
|
||||
int outline();
|
||||
Font* outline(int);
|
||||
SDL_Surface* render(RenderMode, const std::string&,
|
||||
const SDL_Color& fg={0, 0, 0, 255},
|
||||
const SDL_Color& bg={255, 255, 255, 255});
|
||||
uint8_t style();
|
||||
Font* style(uint8_t);
|
||||
Size text_size(const std::string&);
|
||||
|
||||
static std::string find(const std::string&);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,16 +1,12 @@
|
|||
#ifndef MATH_HPP
|
||||
#define MATH_HPP
|
||||
|
||||
#include <exception>
|
||||
#ifndef BWIDGETS_MATH_HPP
|
||||
#define BWIDGETS_MATH_HPP
|
||||
|
||||
#include <SDL2/SDL_rect.h>
|
||||
|
||||
#include <basic_widgets/sdl/data_type.hpp>
|
||||
#include <basic_widgets/core/type/size.hpp>
|
||||
|
||||
namespace bwidgets::utils::math
|
||||
namespace bwidgets::core
|
||||
{
|
||||
struct RectOverflow : std::exception {};
|
||||
|
||||
static inline int center_rect(int container_size, int rect_size) noexcept
|
||||
{
|
||||
return (container_size - rect_size) / 2;
|
||||
|
@ -36,7 +32,7 @@ namespace bwidgets::utils::math
|
|||
SDL_PointInRect(&bottom_right, &outer);
|
||||
}
|
||||
|
||||
static inline SDL_Rect rect_margin(const SDL_Rect& r, const sdl::Size& margin) noexcept
|
||||
static inline SDL_Rect rect_margin(const SDL_Rect& r, const Size& margin) noexcept
|
||||
{
|
||||
return {
|
||||
r.x + margin.w,
|
|
@ -0,0 +1,78 @@
|
|||
#ifndef BWIDGETS_RENDERER_HPP_
|
||||
#define BWIDGETS_RENDERER_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include <SDL2/SDL_render.h>
|
||||
|
||||
#include <basic_widgets/core/type/opaque_struct.hpp>
|
||||
#include <basic_widgets/core/type/sdl_error.hpp>
|
||||
#include <basic_widgets/core/type/size.hpp>
|
||||
|
||||
namespace bwidgets::core
|
||||
{
|
||||
class Texture;
|
||||
|
||||
class Renderer final : public OpaqueStruct<SDL_Renderer>
|
||||
{
|
||||
private:
|
||||
static inline SDL_RendererInfo _info(SDL_Renderer* r)
|
||||
{
|
||||
SDL_RendererInfo info;
|
||||
SDLError::success_or_throw(SDL_GetRendererInfo(r, &info),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
public:
|
||||
Renderer(SDL_Renderer*);
|
||||
Renderer(SDL_Window*, int, uint32_t);
|
||||
virtual ~Renderer() override;
|
||||
|
||||
const SDL_RendererInfo info;
|
||||
|
||||
SDL_BlendMode blend_mode();
|
||||
Renderer* blend_mode(SDL_BlendMode);
|
||||
Renderer* clear();
|
||||
Renderer* copy(Texture&, const SDL_Rect*, const SDL_Rect*);
|
||||
SDL_Color draw_color();
|
||||
Renderer* draw_color(const SDL_Color&);
|
||||
Renderer* draw_line(const SDL_Point&, const SDL_Point&);
|
||||
Renderer* draw_lines(const std::vector<SDL_Point>);
|
||||
Renderer* draw_point(const SDL_Point&);
|
||||
Renderer* draw_points(const std::vector<SDL_Point>);
|
||||
Renderer* draw_rect(const SDL_Rect&);
|
||||
Renderer* draw_rects(const std::vector<SDL_Rect>);
|
||||
Renderer* fill_rect(const SDL_Rect&);
|
||||
Renderer* fill_rects(const std::vector<SDL_Rect>);
|
||||
Size output_size();
|
||||
void present();
|
||||
SDL_Rect viewport();
|
||||
Renderer* viewport(const SDL_Rect*);
|
||||
|
||||
inline Renderer* copy(Texture& t, const SDL_Rect* src, const SDL_Rect& dst)
|
||||
{
|
||||
auto d = dst;
|
||||
return copy(t, src, &d);
|
||||
}
|
||||
inline Renderer* copy(Texture& t, const SDL_Rect& src, const SDL_Rect* dst)
|
||||
{
|
||||
auto s = src;
|
||||
return copy(t, &s, dst);
|
||||
}
|
||||
inline Renderer* copy(Texture& t, const SDL_Rect& src, const SDL_Rect& dst)
|
||||
{
|
||||
auto s = src, d = dst;
|
||||
return copy(t, &s, &d);
|
||||
}
|
||||
inline Renderer* viewport(const SDL_Rect& vp)
|
||||
{
|
||||
auto v = vp;
|
||||
return viewport(&v);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,19 +1,19 @@
|
|||
#ifndef SDL_TEXTURE_HPP
|
||||
#define SDL_TEXTURE_HPP
|
||||
#ifndef BWIDGETS_TEXTURE_HPP_
|
||||
#define BWIDGETS_TEXTURE_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <SDL2/SDL_render.h>
|
||||
#include <SDL2/SDL_pixels.h>
|
||||
|
||||
#include <basic_widgets/exception.hpp>
|
||||
#include <basic_widgets/sdl/data_type.hpp>
|
||||
#include <basic_widgets/core/type/sdl_error.hpp>
|
||||
#include <basic_widgets/core/type/opaque_struct.hpp>
|
||||
|
||||
namespace bwidgets::sdl
|
||||
namespace bwidgets::core
|
||||
{
|
||||
class Renderer;
|
||||
struct Renderer;
|
||||
|
||||
class Texture final : public DataType<SDL_Texture>
|
||||
struct Texture final : public OpaqueStruct<SDL_Texture>
|
||||
{
|
||||
struct Attr
|
||||
{
|
||||
|
@ -31,40 +31,37 @@ namespace bwidgets::sdl
|
|||
int w, int h);
|
||||
Texture(Renderer*, SDL_Surface*);
|
||||
|
||||
~Texture() noexcept override;
|
||||
virtual ~Texture() noexcept override;
|
||||
|
||||
uint8_t alpha_mode();
|
||||
Texture& alpha_mode(uint8_t);
|
||||
Texture* alpha_mode(uint8_t);
|
||||
SDL_BlendMode blend_mode();
|
||||
Texture& blend_mode(SDL_BlendMode);
|
||||
Texture* blend_mode(SDL_BlendMode);
|
||||
SDL_Color color_mode();
|
||||
Texture& color_mode(const SDL_Color&);
|
||||
Texture* color_mode(const SDL_Color&);
|
||||
SDL_ScaleMode scale_mode();
|
||||
Texture& scale_mode(SDL_ScaleMode);
|
||||
Texture& update(SDL_Rect*, const void*, int);
|
||||
Texture* scale_mode(SDL_ScaleMode);
|
||||
Texture* update(SDL_Rect*, const void*, int);
|
||||
|
||||
inline const Attr& attributes()
|
||||
{
|
||||
inline const Attr& attributes() {
|
||||
return _attributes;
|
||||
}
|
||||
|
||||
inline Texture& update(const SDL_Rect& r, const void* pix, int pitch)
|
||||
{
|
||||
inline Texture* update(const SDL_Rect& r, const void* pix, int pitch) {
|
||||
SDL_Rect rect = r;
|
||||
update(&rect, pix, pitch);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
|
||||
static inline const Attr attributes(SDL_Texture* t)
|
||||
{
|
||||
static inline const Attr attributes(SDL_Texture* t) {
|
||||
Attr attr {};
|
||||
exception::SDLError::success_or_throw(
|
||||
SDLError::success_or_throw(
|
||||
SDL_QueryTexture(t,
|
||||
&attr.format_raw, (int*)&attr.access, &attr.w, &attr.h),
|
||||
__FILE__, __FUNCTION__, __LINE__
|
||||
);
|
||||
attr.format = exception::ptr_or_throw<exception::SDLError>(
|
||||
attr.format = SDLError::ptr_or_throw(
|
||||
SDL_AllocFormat(attr.format_raw),
|
||||
__FILE__, __FUNCTION__, __LINE__
|
||||
);
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef BWIDGETS_CONCEPTS_HPP_
|
||||
#define BWIDGETS_CONCEPTS_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace bwidgets::core
|
||||
{
|
||||
template<typename T>
|
||||
concept Numeric = std::is_arithmetic_v<T>;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef BWIDGETS_EXCEPTION_HPP_
|
||||
#define BWIDGETS_EXCEPTION_HPP_
|
||||
|
||||
#include <any>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
#include <basic_widgets/core/type/concepts.hpp>
|
||||
|
||||
namespace bwidgets::core
|
||||
{
|
||||
struct BaseException : std::exception
|
||||
{
|
||||
const char* file;
|
||||
const char* func;
|
||||
const int line;
|
||||
const char* what;
|
||||
|
||||
BaseException(const char* file, const char* func, int l, const char* w)
|
||||
: file(file), func(func), line(l), what(w) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
concept Exception = std::derived_from<T, BaseException>;
|
||||
|
||||
template<Exception E, typename T>
|
||||
static inline
|
||||
T* ptr_or_throw(T* ptr, const char* file, const char* func, const int l,
|
||||
const char* w=nullptr) {
|
||||
if (ptr == nullptr) throw E(file, func, l, w);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template<Exception E, typename T>
|
||||
static inline
|
||||
T success_or_throw(T code, const char* file, const char* func, const int l,
|
||||
const char* w=nullptr,
|
||||
std::function<bool (const T&)> success=[](const T& code) {
|
||||
return code == EXIT_SUCCESS;
|
||||
}) {
|
||||
if (!success(code)) throw E(file, func, l, w);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef BWIDGETS_FC_ERROR_HPP_
|
||||
#define BWIDGETS_FC_ERROR_HPP_
|
||||
|
||||
#include <basic_widgets/core/type/exception.hpp>
|
||||
|
||||
namespace bwidgets::core
|
||||
{
|
||||
struct FCError final : BaseException
|
||||
{
|
||||
FCError(const char* file, const char* func, const int l,
|
||||
const char* w=nullptr)
|
||||
: BaseException(file, func, l, w) {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef BWIDGETS_OPAQUE_STRUCT_HPP_
|
||||
#define BWIDGETS_OPAQUE_STRUCT_HPP_
|
||||
|
||||
namespace bwidgets::core
|
||||
{
|
||||
template<typename T> struct OpaqueStruct
|
||||
{
|
||||
T* c_pod;
|
||||
|
||||
OpaqueStruct(T* ptr=nullptr) : c_pod(ptr) {}
|
||||
virtual ~OpaqueStruct<T>() noexcept = default;
|
||||
|
||||
static inline void discard(T* t) {
|
||||
if (t) {
|
||||
delete t;
|
||||
t = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef BWIDGETS_SDL_ERROR_HPP_
|
||||
#define BWIDGETS_SDL_ERROR_HPP_
|
||||
|
||||
#include <basic_widgets/core/type/exception.hpp>
|
||||
|
||||
extern "C" {
|
||||
const char* SDL_GetError();
|
||||
}
|
||||
|
||||
namespace bwidgets::core
|
||||
{
|
||||
struct SDLError final : BaseException
|
||||
{
|
||||
SDLError(const char* file, const char* func, const int l,
|
||||
const char* w=nullptr)
|
||||
: BaseException(file, func, l, w) {}
|
||||
|
||||
template<typename T>
|
||||
static inline
|
||||
T* ptr_or_throw(T* ptr, const char* file, const char* func, const int l,
|
||||
const char* w=nullptr) {
|
||||
if (ptr == nullptr) {
|
||||
if (w == nullptr) w = SDL_GetError();
|
||||
SDLError(file, func, l, w);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static inline int success_or_throw(int code, const char* file, const char* func,
|
||||
const int l, const char* w=nullptr) {
|
||||
if (code < 0) {
|
||||
if (w == nullptr) w = SDL_GetError();
|
||||
throw SDLError(file, func, l, w);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef BWIDGETS_SIZE_HPP_
|
||||
#define BWIDGETS_SIZE_HPP_
|
||||
|
||||
#include <basic_widgets/core/type/concepts.hpp>
|
||||
|
||||
namespace bwidgets::core
|
||||
{
|
||||
struct Size {
|
||||
int w;
|
||||
int h;
|
||||
|
||||
inline Size operator-() { return {-w, -h}; }
|
||||
|
||||
template<Numeric T>
|
||||
inline Size operator*(T a) { return {a * w, a * h}; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,65 +0,0 @@
|
|||
#ifndef EXCEPTION_HPP
|
||||
#define EXCEPTION_HPP
|
||||
|
||||
#include <any>
|
||||
#include <concepts>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
extern "C" {
|
||||
const char* SDL_GetError();
|
||||
}
|
||||
|
||||
namespace bwidgets::exception
|
||||
{
|
||||
struct Base : std::exception
|
||||
{
|
||||
typedef std::map<const char*, const std::any> Args;
|
||||
|
||||
const Args args;
|
||||
const char* file;
|
||||
const char* func;
|
||||
const int line;
|
||||
const char* what;
|
||||
|
||||
Base(const char* file, const char* func, int l, Args a, const char* w)
|
||||
: args(a), file(file), func(func), line(l), what(w) {}
|
||||
};
|
||||
|
||||
struct FontconfigError final : Base
|
||||
{
|
||||
FontconfigError(const char* file, const char* func, const int l, Args a={}, const char* w=nullptr)
|
||||
: Base(file, func, l, a, w) {}
|
||||
};
|
||||
|
||||
struct SDLError final : Base
|
||||
{
|
||||
SDLError(const char* file, const char* func, const int l, Args a={}, const char* w=SDL_GetError())
|
||||
: Base(file, func, l, a, w) {}
|
||||
|
||||
static inline int
|
||||
success_or_throw(int code, const char* file, const char* func, const int l, Args a={}, const char* w=SDL_GetError())
|
||||
{
|
||||
if (code < 0) throw SDLError(file, func, l, a, w);
|
||||
return code;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
concept Exception = std::derived_from<T, Base>;
|
||||
|
||||
template<Exception E, typename T>
|
||||
static inline
|
||||
T* ptr_or_throw(T* ptr, const char* file, const char* func, const int l, Base::Args a={}, const char* w=nullptr)
|
||||
{
|
||||
if constexpr (std::same_as<E, SDLError>)
|
||||
if (w == nullptr)
|
||||
w = SDL_GetError();
|
||||
|
||||
if (ptr == nullptr) throw E(file, func, l, a, w);
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef HORIZONTAL_LAYOUT_HPP
|
||||
#define HORIZONTAL_LAYOUT_HPP
|
||||
|
||||
#include <basic_widgets/abstract/layout.hpp>
|
||||
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class Horizontal_Layout final : public abstract::Layout
|
||||
{
|
||||
private:
|
||||
void _update_layout(const SDL_Rect&) noexcept override;
|
||||
|
||||
public:
|
||||
sdl::Size size() const noexcept override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,190 +0,0 @@
|
|||
#ifndef NUMERIC_INPUT_HPP
|
||||
#define NUMERIC_INPUT_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <regex>
|
||||
#include <type_traits>
|
||||
|
||||
#include <basic_widgets/abstract/input.hpp>
|
||||
#include <basic_widgets/button.hpp>
|
||||
#include <basic_widgets/utils/math.hpp>
|
||||
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
template<typename T>
|
||||
concept Numeric = std::is_arithmetic_v<T>;
|
||||
|
||||
template<typename T>
|
||||
requires Numeric<T>
|
||||
class Numeric_Input : public abstract::Input<T>
|
||||
{
|
||||
private:
|
||||
Button _increment_button;
|
||||
SDL_Rect _increment_button_area;
|
||||
Button _decrement_button;
|
||||
SDL_Rect _decrement_button_area;
|
||||
std::pair<T, T> _value_range {
|
||||
std::numeric_limits<T>::lowest(),
|
||||
std::numeric_limits<T>::max()
|
||||
};
|
||||
|
||||
virtual void _handle_font_change() override
|
||||
{
|
||||
_decrement_button.font(abstract::FontHandler::_font);
|
||||
_increment_button.font(abstract::FontHandler::_font);
|
||||
abstract::Input<T>::_handle_font_change();
|
||||
}
|
||||
|
||||
virtual void _handle_geometry_change(const SDL_Rect& vp) noexcept override
|
||||
{
|
||||
abstract::Input<T>::_handle_geometry_change(vp);
|
||||
|
||||
const int widest_button =
|
||||
_increment_button.size().w
|
||||
? _increment_button.size().w
|
||||
: _decrement_button.size().w;
|
||||
const int button_area_width = 2 * widest_button;
|
||||
const int spacing = utils::math::center_rect(button_area_width, widest_button);
|
||||
const int field_width = vp.w - 2 * button_area_width;
|
||||
|
||||
abstract::Widget::_widget_area.x =
|
||||
abstract::Widget::_widget_area.x + button_area_width;
|
||||
abstract::Widget::_widget_area.w = field_width;
|
||||
|
||||
abstract::Input<T>::_input_caption.viewport(
|
||||
utils::math::rect_offset(
|
||||
utils::math::rect_margin(
|
||||
abstract::Widget::_widget_area,
|
||||
{abstract::Input<T>::_border_width,
|
||||
abstract::Input<T>::_border_width}
|
||||
),
|
||||
vp
|
||||
)
|
||||
);
|
||||
_decrement_button_area = {
|
||||
spacing,
|
||||
abstract::Widget::_widget_area.y,
|
||||
_decrement_button.size().w,
|
||||
_decrement_button.size().h
|
||||
};
|
||||
|
||||
_increment_button_area = {
|
||||
vp.w - spacing - _increment_button.size().w,
|
||||
abstract::Widget::_widget_area.y,
|
||||
_increment_button.size().w,
|
||||
_increment_button.size().h
|
||||
};
|
||||
|
||||
_increment_button.viewport(utils::math::rect_offset(
|
||||
_increment_button_area, vp
|
||||
));
|
||||
_decrement_button.viewport(utils::math::rect_offset(
|
||||
_decrement_button_area, vp
|
||||
));
|
||||
}
|
||||
|
||||
virtual void _handle_renderer_change(sdl::Renderer* r)
|
||||
{
|
||||
abstract::Input<T>::_handle_renderer_change(r);
|
||||
_decrement_button.renderer(r);
|
||||
_increment_button.renderer(r);
|
||||
}
|
||||
|
||||
virtual void _handle_rendering() override
|
||||
{
|
||||
abstract::Input<T>::_handle_rendering();
|
||||
_increment_button.render();
|
||||
_decrement_button.render();
|
||||
}
|
||||
|
||||
public:
|
||||
T button_step = 1;
|
||||
|
||||
Numeric_Input(abstract::Widget* parent=nullptr)
|
||||
: abstract::Input<T>(parent),
|
||||
_increment_button(this),
|
||||
_decrement_button(this)
|
||||
{
|
||||
abstract::Input<T>::_input_caption.alignment.h =
|
||||
widget::Caption::AlignmentH::RIGHT;
|
||||
|
||||
_increment_button.text("+");
|
||||
|
||||
_increment_button.click_handler = [this](const SDL_MouseButtonEvent&) {
|
||||
T new_value = this->value + button_step;
|
||||
if (_value_range.second - this->value < button_step)
|
||||
new_value = _value_range.second;
|
||||
|
||||
this->value = new_value;
|
||||
this->input_text(this->value_to_string(new_value));
|
||||
};
|
||||
|
||||
_decrement_button.text("-");
|
||||
|
||||
_decrement_button.click_handler = [this](const SDL_MouseButtonEvent&) {
|
||||
T new_value = this->value - button_step;
|
||||
if (this->value - _value_range.first < button_step)
|
||||
new_value = _value_range.first;
|
||||
|
||||
this->value = new_value;
|
||||
this->input_text(this->value_to_string(new_value));
|
||||
};
|
||||
}
|
||||
|
||||
virtual void handle_event(const SDL_Event& ev) override
|
||||
{
|
||||
abstract::Widget::handle_event(ev);
|
||||
_increment_button.handle_event(ev);
|
||||
_decrement_button.handle_event(ev);
|
||||
}
|
||||
|
||||
virtual bool is_valid_input(const std::string input) const noexcept override
|
||||
{
|
||||
bool valid = false;
|
||||
|
||||
if (input.at(0) >= '0' && input.at(0) <= '9')
|
||||
valid = true;
|
||||
if constexpr(std::is_floating_point_v<T>)
|
||||
if (input.at(0) == '.'
|
||||
&& abstract::Input<T>::input_text().find('.') == std::string::npos)
|
||||
valid = true;
|
||||
if constexpr(std::is_signed_v<T>)
|
||||
{
|
||||
std::string displayed_value = abstract::Input<T>::input_text();
|
||||
if (input.at(0) == '-'
|
||||
&& !std::regex_search(
|
||||
displayed_value,
|
||||
std::regex("[^\\s]")
|
||||
))
|
||||
valid = true;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
virtual T process_value(T x) const noexcept override
|
||||
{
|
||||
T value = x;
|
||||
if (x < _value_range.first)
|
||||
value = _value_range.first;
|
||||
else if (x > _value_range.second)
|
||||
value = _value_range.second;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
virtual std::pair<T, T> value_range() const noexcept
|
||||
{
|
||||
return _value_range;
|
||||
}
|
||||
|
||||
virtual void value_range(T min, T max)
|
||||
{
|
||||
|
||||
if (min > max)
|
||||
throw std::invalid_argument("min cannot be greater than max");
|
||||
_value_range = {min, max};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,40 +0,0 @@
|
|||
#ifndef C_DATA_TYPE_HPP
|
||||
#define C_DATA_TYPE_HPP
|
||||
|
||||
#include <concepts>
|
||||
|
||||
namespace bwidgets::abstract {
|
||||
class Widget;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
concept Numeric = std::integral<T> || std::floating_point<T>;
|
||||
|
||||
namespace bwidgets::sdl
|
||||
{
|
||||
struct Size
|
||||
{
|
||||
int w = 0; int h = 0;
|
||||
|
||||
inline Size operator-() {
|
||||
return {-w, -h};
|
||||
}
|
||||
|
||||
template<Numeric T> inline Size operator*(T a) {
|
||||
return {a * w, a * h};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct DataType
|
||||
{
|
||||
friend abstract::Widget;
|
||||
|
||||
public:
|
||||
T* c_pod;
|
||||
|
||||
DataType(T* ptr=nullptr) : c_pod(ptr) {}
|
||||
virtual ~DataType<T>() noexcept {};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,77 +0,0 @@
|
|||
#ifndef SDL_RENDERER_HPP
|
||||
#define SDL_RENDERER_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include <SDL2/SDL_render.h>
|
||||
|
||||
#include <basic_widgets/exception.hpp>
|
||||
#include <basic_widgets/sdl/data_type.hpp>
|
||||
|
||||
namespace bwidgets::sdl
|
||||
{
|
||||
class Texture;
|
||||
|
||||
class Renderer final : public DataType<SDL_Renderer>
|
||||
{
|
||||
private:
|
||||
static inline SDL_RendererInfo _info(SDL_Renderer* r)
|
||||
{
|
||||
SDL_RendererInfo info;
|
||||
exception::SDLError::success_or_throw(SDL_GetRendererInfo(r, &info),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
public:
|
||||
Renderer(SDL_Renderer*);
|
||||
Renderer(SDL_Window*, int, uint32_t);
|
||||
~Renderer() override;
|
||||
|
||||
const SDL_RendererInfo info;
|
||||
|
||||
SDL_BlendMode blend_mode();
|
||||
Renderer& blend_mode(SDL_BlendMode);
|
||||
Renderer& clear();
|
||||
Renderer& copy(Texture&, const SDL_Rect*, const SDL_Rect*);
|
||||
SDL_Color draw_color();
|
||||
Renderer& draw_color(const SDL_Color&);
|
||||
Renderer& draw_line(const SDL_Point&, const SDL_Point&);
|
||||
Renderer& draw_lines(const std::vector<SDL_Point>);
|
||||
Renderer& draw_point(const SDL_Point&);
|
||||
Renderer& draw_points(const std::vector<SDL_Point>);
|
||||
Renderer& draw_rect(const SDL_Rect&);
|
||||
Renderer& draw_rects(const std::vector<SDL_Rect>);
|
||||
Renderer& fill_rect(const SDL_Rect&);
|
||||
Renderer& fill_rects(const std::vector<SDL_Rect>);
|
||||
Size output_size();
|
||||
void present();
|
||||
SDL_Rect viewport();
|
||||
Renderer& viewport(const SDL_Rect*);
|
||||
|
||||
inline Renderer& copy(Texture& t, const SDL_Rect* src, const SDL_Rect& dst)
|
||||
{
|
||||
auto d = dst;
|
||||
return copy(t, src, &d);
|
||||
}
|
||||
inline Renderer& copy(Texture& t, const SDL_Rect& src, const SDL_Rect* dst)
|
||||
{
|
||||
auto s = src;
|
||||
return copy(t, &s, dst);
|
||||
}
|
||||
inline Renderer& copy(Texture& t, const SDL_Rect& src, const SDL_Rect& dst)
|
||||
{
|
||||
auto s = src, d = dst;
|
||||
return copy(t, &s, &d);
|
||||
}
|
||||
inline Renderer& viewport(const SDL_Rect& vp)
|
||||
{
|
||||
auto v = vp;
|
||||
return viewport(&v);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef UTILS_HPP
|
||||
#define UTILS_HPP
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
namespace bwidgets::utils::font
|
||||
{
|
||||
std::string find(const std::string&);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,37 +0,0 @@
|
|||
#ifndef DRAWING_PRIMITIVE
|
||||
#define DRAWING_PRIMITIVE
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <SDL2/SDL_pixels.h>
|
||||
#include <SDL2/SDL_rect.h>
|
||||
#include <SDL2/SDL_render.h>
|
||||
|
||||
#include <basic_widgets/exception.hpp>
|
||||
#include <basic_widgets/sdl/texture.hpp>
|
||||
|
||||
struct SDL_Texture;
|
||||
|
||||
namespace bwidgets::utils::render
|
||||
{
|
||||
SDL_Color aa(const SDL_Color&&, const int, const float);
|
||||
|
||||
sdl::Texture filled_circle(const SDL_Color&,
|
||||
int resolution,
|
||||
SDL_Renderer*,
|
||||
int aa_pixels = 3);
|
||||
void set_pixels_color(sdl::Texture&, std::function<Uint32 (const SDL_Point&,
|
||||
const SDL_PixelFormat*)>);
|
||||
|
||||
static inline int render_copy(SDL_Renderer* r, SDL_Texture* t, SDL_Rect dst)
|
||||
{
|
||||
return SDL_RenderCopy(r, t, NULL, &dst);
|
||||
}
|
||||
|
||||
static inline int render_copy(SDL_Renderer* r, SDL_Texture* t, SDL_Rect src, SDL_Rect dst)
|
||||
{
|
||||
return SDL_RenderCopy(r, t, &src, &dst);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef VERTICAL_LAYOUT_HPP
|
||||
#define VERTICAL_LAYOUT_HPP
|
||||
|
||||
#include <basic_widgets/abstract/layout.hpp>
|
||||
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class Vertical_Layout final : public abstract::Layout
|
||||
{
|
||||
private:
|
||||
void _update_layout(const SDL_Rect&) noexcept override;
|
||||
|
||||
public:
|
||||
sdl::Size size() const noexcept override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef INPUT_HPP
|
||||
#define INPUT_HPP
|
||||
#ifndef BWIDGETS_INPUT_HPP_
|
||||
#define BWIDGETS_INPUT_HPP_
|
||||
|
||||
#include <exception>
|
||||
#include <iomanip>
|
||||
|
@ -11,14 +11,14 @@
|
|||
#include <SDL2/SDL_keyboard.h>
|
||||
#include <SDL2/SDL_render.h>
|
||||
|
||||
#include <basic_widgets/caption.hpp>
|
||||
#include <basic_widgets/abstract/keyboard_handler.hpp>
|
||||
#include <basic_widgets/abstract/mouse_handler.hpp>
|
||||
#include <basic_widgets/exception.hpp>
|
||||
#include <basic_widgets/utils/math.hpp>
|
||||
#include <basic_widgets/w/caption.hpp>
|
||||
#include <basic_widgets/w/feat/keyboard_handler.hpp>
|
||||
#include <basic_widgets/w/feat/mouse_handler.hpp>
|
||||
#include <basic_widgets/core/math.hpp>
|
||||
|
||||
namespace bwidgets::abstract
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
// TODO: move that to concepts
|
||||
template<typename T>
|
||||
concept CanToString = requires(T value) { std::to_string(value); };
|
||||
|
||||
|
@ -31,8 +31,8 @@ namespace bwidgets::abstract
|
|||
public MouseHandler
|
||||
{
|
||||
protected:
|
||||
const int _border_width {3};
|
||||
widget::Caption _input_caption;
|
||||
const int _border_width {3};
|
||||
Caption _input_caption;
|
||||
|
||||
Input(Widget* parent=nullptr)
|
||||
: Widget(parent)
|
||||
|
@ -42,9 +42,9 @@ namespace bwidgets::abstract
|
|||
_input_caption.text(value_to_string(value));
|
||||
}
|
||||
|
||||
virtual void _handle_focus_change() override
|
||||
virtual void _handle_focus_change(bool focus) override
|
||||
{
|
||||
if (FocusHandler::_has_focus)
|
||||
if (focus)
|
||||
{
|
||||
SDL_StartTextInput();
|
||||
}
|
||||
|
@ -56,9 +56,9 @@ namespace bwidgets::abstract
|
|||
}
|
||||
}
|
||||
|
||||
virtual void _handle_font_change() override
|
||||
virtual void _handle_font_change(core::Font* f) override
|
||||
{
|
||||
_input_caption.font(_font);
|
||||
_input_caption.font(f);
|
||||
_handle_geometry_change(_viewport);
|
||||
}
|
||||
|
||||
|
@ -67,14 +67,14 @@ namespace bwidgets::abstract
|
|||
const auto input_h = _input_caption.size().h + 2 * _border_width;
|
||||
_widget_area = {
|
||||
0,
|
||||
utils::math::center_rect(vp.h, input_h),
|
||||
core::center_rect(vp.h, input_h),
|
||||
vp.w,
|
||||
input_h
|
||||
};
|
||||
|
||||
_input_caption.viewport(
|
||||
utils::math::rect_offset({
|
||||
utils::math::rect_margin(_widget_area, {_border_width, _border_width})
|
||||
core::rect_offset({
|
||||
core::rect_margin(_widget_area, {_border_width, _border_width})
|
||||
}, vp
|
||||
)
|
||||
);
|
||||
|
@ -106,7 +106,7 @@ namespace bwidgets::abstract
|
|||
}
|
||||
}
|
||||
|
||||
virtual void _handle_renderer_change(sdl::Renderer* r) override
|
||||
virtual void _handle_renderer_change(core::Renderer* r) override
|
||||
{
|
||||
_input_caption.renderer(r);
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ namespace bwidgets::abstract
|
|||
(uint8_t)(color_border.g / (i + 1)),
|
||||
(uint8_t)(color_border.b / (i+ 1)),
|
||||
color_border.a
|
||||
}).draw_rect({
|
||||
})->draw_rect({
|
||||
_widget_area.x + i,
|
||||
_widget_area.y + i,
|
||||
_widget_area.w - 2 * i,
|
||||
|
@ -130,9 +130,9 @@ namespace bwidgets::abstract
|
|||
}
|
||||
|
||||
if (MouseHandler::_is_hovered || FocusHandler::_has_focus)
|
||||
_input_caption.color_bg = color_bg_focused;
|
||||
_input_caption.color_bg(color_bg_focused);
|
||||
else
|
||||
_input_caption.color_bg = color_bg;
|
||||
_input_caption.color_bg(color_bg);
|
||||
|
||||
_input_caption.render();
|
||||
}
|
|
@ -1,36 +1,36 @@
|
|||
#ifndef LAYOUT_HPP
|
||||
#define LAYOUT_HPP
|
||||
#ifndef BWIDGETS_LAYOUT_HPP_
|
||||
#define BWIDGETS_LAYOUT_HPP_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <basic_widgets/abstract/widget.hpp>
|
||||
#include <basic_widgets/sdl/data_type.hpp>
|
||||
#include <basic_widgets/core/type/size.hpp>
|
||||
#include <basic_widgets/w/base/widget.hpp>
|
||||
|
||||
namespace bwidgets::sdl {
|
||||
namespace bwidgets::core {
|
||||
class Renderer;
|
||||
}
|
||||
|
||||
namespace bwidgets::abstract
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class Layout : public abstract::Widget
|
||||
class Layout : public Widget
|
||||
{
|
||||
protected:
|
||||
std::vector<Widget*> _widgets;
|
||||
|
||||
virtual void _handle_geometry_change(const SDL_Rect&) noexcept override;
|
||||
virtual void _handle_renderer_change(sdl::Renderer*) override;
|
||||
virtual void _handle_renderer_change(core::Renderer*) override;
|
||||
virtual void _handle_rendering() override;
|
||||
virtual void _update_layout(const SDL_Rect&) noexcept = 0;
|
||||
|
||||
public:
|
||||
sdl::Size margins {4, 4};
|
||||
core::Size margins {4, 4};
|
||||
|
||||
virtual ~Layout() noexcept;
|
||||
|
||||
virtual void add_widget(Widget*);
|
||||
virtual void handle_event(const SDL_Event&) override;
|
||||
|
||||
virtual sdl::Size size() const noexcept override = 0;
|
||||
virtual core::Size size() const noexcept override = 0;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,25 +1,24 @@
|
|||
#ifndef WIDGET_HPP
|
||||
#define WIDGET_HPP
|
||||
#ifndef BWIDGETS_WIDGET_HPP_
|
||||
#define BWIDGETS_WIDGET_HPP_
|
||||
|
||||
#include <SDL2/SDL_events.h>
|
||||
#include <SDL2/SDL_rect.h>
|
||||
#include <basic_widgets/core/type/size.hpp>
|
||||
#include <basic_widgets/core/renderer.hpp>
|
||||
|
||||
#include <basic_widgets/sdl/data_type.hpp>
|
||||
#include <basic_widgets/sdl/renderer.hpp>
|
||||
union SDL_Event;
|
||||
|
||||
struct SDL_Renderer;
|
||||
|
||||
namespace bwidgets::abstract
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class Widget
|
||||
{
|
||||
protected:
|
||||
sdl::Renderer* _renderer {nullptr};
|
||||
core::Renderer* _renderer {nullptr};
|
||||
SDL_Rect _viewport {0, 0, 0, 0};
|
||||
SDL_Rect _widget_area {0, 0, 0, 0};
|
||||
|
||||
virtual void _handle_geometry_change(const SDL_Rect&) noexcept = 0;
|
||||
virtual void _handle_renderer_change(sdl::Renderer*) {}
|
||||
virtual void _handle_renderer_change(core::Renderer*) {}
|
||||
virtual void _handle_rendering() = 0;
|
||||
|
||||
public:
|
||||
|
@ -27,21 +26,16 @@ namespace bwidgets::abstract
|
|||
|
||||
Widget(Widget* p=nullptr) : parent(p) {}
|
||||
|
||||
//*********************************************
|
||||
//
|
||||
virtual ~Widget() noexcept = default;
|
||||
virtual void handle_event(const SDL_Event&);
|
||||
// -----
|
||||
inline virtual sdl::Size size() const noexcept
|
||||
|
||||
inline virtual core::Size size() const noexcept
|
||||
{
|
||||
return {_widget_area.w, _widget_area.h};
|
||||
}
|
||||
//
|
||||
//*********************************************
|
||||
|
||||
virtual void render() final;
|
||||
// -----
|
||||
virtual inline void renderer(sdl::Renderer* r) final
|
||||
virtual inline void renderer(core::Renderer* r) final
|
||||
{
|
||||
_handle_renderer_change(r);
|
||||
_renderer = r;
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef BWIDGETS_BUTTON_HPP_
|
||||
#define BWIDGETS_BUTTON_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <basic_widgets/w/caption.hpp>
|
||||
#include <basic_widgets/w/feat/mouse_handler.hpp>
|
||||
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class Button : public Widget, public FontHandler, public MouseHandler
|
||||
{
|
||||
protected:
|
||||
Caption _caption;
|
||||
SDL_Rect _caption_area;
|
||||
SDL_Color _color_foreground {0, 0, 0, SDL_ALPHA_OPAQUE};
|
||||
|
||||
virtual void _handle_font_change(core::Font*) override;
|
||||
virtual void _handle_font_color_change(const SDL_Color&, const SDL_Color&);
|
||||
virtual void _handle_geometry_change(const SDL_Rect&) noexcept override;
|
||||
virtual void _handle_renderer_change(core::Renderer*) override;
|
||||
virtual void _handle_rendering() override;
|
||||
|
||||
public:
|
||||
int border_width {3};
|
||||
SDL_Color color_bg {150, 150, 150, SDL_ALPHA_OPAQUE};
|
||||
SDL_Color color_bg_hover {175, 175, 175, SDL_ALPHA_OPAQUE};
|
||||
|
||||
Button(Widget* parent=nullptr);
|
||||
|
||||
virtual core::Size size() const noexcept override;
|
||||
virtual const std::string& text() const noexcept;
|
||||
virtual void text(std::string);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef BWIDGETS_CAPTION_HPP_
|
||||
#define BWIDGETS_CAPTION_HPP_
|
||||
|
||||
#include <basic_widgets/core/texture.hpp>
|
||||
#include <basic_widgets/core/type/size.hpp>
|
||||
#include <basic_widgets/w/base/widget.hpp>
|
||||
#include <basic_widgets/w/feat/font_handler.hpp>
|
||||
#include <basic_widgets/w/feat/texture_handler.hpp>
|
||||
|
||||
struct SDL_Surface;
|
||||
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class Caption : public Widget, public FontHandler,
|
||||
public TextureHandler
|
||||
{
|
||||
public:
|
||||
enum struct AlignmentH {
|
||||
CENTER,
|
||||
LEFT,
|
||||
RIGHT
|
||||
};
|
||||
|
||||
enum struct AlignmentV {
|
||||
BOTTOM,
|
||||
CENTER,
|
||||
TOP
|
||||
};
|
||||
|
||||
private:
|
||||
SDL_Color _color_fg {0, 0, 0, SDL_ALPHA_OPAQUE};
|
||||
SDL_Color _color_bg {255, 255, 255, SDL_ALPHA_OPAQUE};
|
||||
std::string _text;
|
||||
core::Texture* _text_texture {nullptr};
|
||||
|
||||
virtual void _handle_font_change(core::Font*) override;
|
||||
virtual void _handle_font_color_change(const SDL_Color&,
|
||||
const SDL_Color&) override;
|
||||
virtual void _handle_geometry_change(const SDL_Rect&) noexcept override;
|
||||
virtual void _handle_renderer_change(core::Renderer*) override;
|
||||
virtual void _handle_rendering() override;
|
||||
virtual void _handle_texture_update() override;
|
||||
|
||||
public:
|
||||
struct {
|
||||
AlignmentH h;
|
||||
AlignmentV v;
|
||||
} alignment {AlignmentH::LEFT, AlignmentV::CENTER};
|
||||
core::Size margins {2, 2};
|
||||
|
||||
Caption(Widget* parent=nullptr) : Widget(parent) {}
|
||||
~Caption() noexcept;
|
||||
|
||||
virtual void color_bg(const SDL_Color&);
|
||||
virtual void color_fg(const SDL_Color&);
|
||||
virtual core::Size size() const noexcept override;
|
||||
virtual const std::string& text() const noexcept;
|
||||
virtual void text(const std::string&);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef BWIDGETS_FOCUS_HANDLER_HPP_
|
||||
#define BWIDGETS_FOCUS_HANDLER_HPP_
|
||||
|
||||
struct SDL_Rect;
|
||||
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class FocusHandler
|
||||
{
|
||||
protected:
|
||||
const SDL_Rect* _focus_area = nullptr;
|
||||
bool _has_focus = false;
|
||||
|
||||
virtual void _handle_focus_change(bool) = 0;
|
||||
|
||||
public:
|
||||
virtual ~FocusHandler() = default;
|
||||
|
||||
virtual inline void focus(bool focus) final
|
||||
{
|
||||
_handle_focus_change(focus);
|
||||
_has_focus = focus;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef BWIDGETS_FONT_HANDLER_HPP_
|
||||
#define BWIDGETS_FONT_HANDLER_HPP_
|
||||
|
||||
#include <basic_widgets/core/font.hpp>
|
||||
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class FontHandler
|
||||
{
|
||||
protected:
|
||||
core::Font* _font {nullptr};
|
||||
SDL_Color _font_color_bg {255, 255, 255, SDL_ALPHA_OPAQUE};
|
||||
SDL_Color _font_color_fg {0, 0, 0, SDL_ALPHA_OPAQUE};
|
||||
core::Font::RenderMode _font_render_mode {core::Font::RenderMode::SHADED};
|
||||
|
||||
virtual void _handle_font_change(core::Font*) = 0;
|
||||
virtual void _handle_font_color_change(const SDL_Color&, const SDL_Color&) = 0;
|
||||
|
||||
public:
|
||||
virtual ~FontHandler() = default;
|
||||
|
||||
virtual inline FontHandler* font(core::Font* f) final {
|
||||
_handle_font_change(f);
|
||||
_font = f;
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual inline FontHandler* font_color_bg(const SDL_Color& c) final {
|
||||
_handle_font_color_change(_font_color_bg, c);
|
||||
_font_color_bg = c;
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual inline FontHandler* font_color_fg(const SDL_Color& c) final {
|
||||
_handle_font_color_change(c, _font_color_bg);
|
||||
_font_color_fg = c;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,28 +1,28 @@
|
|||
#ifndef KEYBOARD_HANDLER
|
||||
#define KEYBOARD_HANDLER
|
||||
#ifndef BWIDGETS_KEYBOARD_HANDLER_
|
||||
#define BWIDGETS_KEYBOARD_HANDLER_
|
||||
|
||||
#include <basic_widgets/abstract/focus_handler.hpp>
|
||||
#include <basic_widgets/w/feat/focus_handler.hpp>
|
||||
|
||||
struct SDL_KeyboardEvent;
|
||||
struct SDL_TextInputEvent;
|
||||
|
||||
namespace bwidgets::abstract
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class KeyboardHandler : public virtual FocusHandler
|
||||
{
|
||||
protected:
|
||||
|
||||
virtual void _handle_key(const SDL_KeyboardEvent&);
|
||||
virtual void _handle_text_input(const SDL_TextInputEvent&);
|
||||
virtual void _handle_key(const SDL_KeyboardEvent&) = 0;
|
||||
virtual void _handle_text_input(const SDL_TextInputEvent&) = 0;
|
||||
|
||||
public:
|
||||
inline void handle_keyboard(const SDL_KeyboardEvent& ev)
|
||||
virtual inline void handle_keyboard(const SDL_KeyboardEvent& ev) final
|
||||
{
|
||||
if (_has_focus)
|
||||
_handle_key(ev);
|
||||
}
|
||||
|
||||
inline void handle_keyboard(const SDL_TextInputEvent& ev)
|
||||
virtual inline void handle_keyboard(const SDL_TextInputEvent& ev) final
|
||||
{
|
||||
if (_has_focus)
|
||||
_handle_text_input(ev);
|
|
@ -1,15 +1,14 @@
|
|||
#ifndef MOUSE_HANDLER_HPP
|
||||
#define MOUSE_HANDLER_HPP
|
||||
#ifndef BWIDGETS_MOUSE_HANDLER_HPP_
|
||||
#define BWIDGETS_MOUSE_HANDLER_HPP_
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <basic_widgets/abstract/focus_handler.hpp>
|
||||
#include <basic_widgets/w/feat/focus_handler.hpp>
|
||||
|
||||
struct SDL_MouseButtonEvent;
|
||||
struct SDL_MouseMotionEvent;
|
||||
struct SDL_Rect;
|
||||
|
||||
namespace bwidgets::abstract
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class MouseHandler : public virtual FocusHandler
|
||||
{
|
||||
|
@ -19,17 +18,17 @@ namespace bwidgets::abstract
|
|||
bool _is_pushed = false;
|
||||
|
||||
virtual void _handle_mouse_button(const SDL_MouseButtonEvent&,
|
||||
const SDL_Rect&);
|
||||
const SDL_Rect&) = 0;
|
||||
virtual void _handle_mouse_motion(const SDL_MouseMotionEvent&,
|
||||
const SDL_Rect&);
|
||||
const SDL_Rect&) = 0;
|
||||
|
||||
public:
|
||||
std::function<void (const SDL_MouseButtonEvent&)> click_handler = nullptr;
|
||||
|
||||
void handle_mouse(const SDL_MouseButtonEvent&,
|
||||
const SDL_Rect&);
|
||||
void handle_mouse(const SDL_MouseMotionEvent&,
|
||||
const SDL_Rect&);
|
||||
virtual void handle_mouse(const SDL_MouseButtonEvent&,
|
||||
const SDL_Rect&) final;
|
||||
virtual void handle_mouse(const SDL_MouseMotionEvent&,
|
||||
const SDL_Rect&) final;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef BWIDGETS_TEXTURE_HANDLER_
|
||||
#define BWIDGETS_TEXTURE_HANDLER_
|
||||
|
||||
namespace bwidgets::core {
|
||||
class Renderer;
|
||||
}
|
||||
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class TextureHandler
|
||||
{
|
||||
protected:
|
||||
virtual void _handle_texture_update() = 0;
|
||||
|
||||
public:
|
||||
virtual ~TextureHandler() noexcept = default;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef BWIDGETS_HORIZONTAL_LAYOUT_HPP_
|
||||
#define BWIDGETS_HORIZONTAL_LAYOUT_HPP_
|
||||
|
||||
#include <basic_widgets/w/base/layout.hpp>
|
||||
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class HorizontalLayout final : public Layout
|
||||
{
|
||||
private:
|
||||
void _update_layout(const SDL_Rect&) noexcept override;
|
||||
|
||||
public:
|
||||
core::Size size() const noexcept override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,186 @@
|
|||
#ifndef BWIDGETS_NUMERIC_INPUT_HPP_
|
||||
#define BWIDGETS_NUMERIC_INPUT_HPP_
|
||||
|
||||
#include <limits>
|
||||
// TODO: we don't really need any regex…
|
||||
#include <regex>
|
||||
#include <type_traits>
|
||||
|
||||
#include <basic_widgets/core/math.hpp>
|
||||
#include <basic_widgets/core/type/concepts.hpp>
|
||||
#include <basic_widgets/w/base/input.hpp>
|
||||
#include <basic_widgets/w/button.hpp>
|
||||
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
template<core::Numeric T>
|
||||
class NumericInput : public Input<T>
|
||||
{
|
||||
private:
|
||||
Button _increment_button;
|
||||
SDL_Rect _increment_button_area;
|
||||
Button _decrement_button;
|
||||
SDL_Rect _decrement_button_area;
|
||||
std::pair<T, T> _value_range {std::numeric_limits<T>::lowest(),
|
||||
std::numeric_limits<T>::max()};
|
||||
|
||||
virtual void _handle_font_change() override
|
||||
{
|
||||
_decrement_button.font(FontHandler::_font);
|
||||
_increment_button.font(FontHandler::_font);
|
||||
Input<T>::_handle_font_change();
|
||||
}
|
||||
|
||||
virtual void _handle_geometry_change(const SDL_Rect& vp) noexcept override
|
||||
{
|
||||
Input<T>::_handle_geometry_change(vp);
|
||||
|
||||
const int widest_button =
|
||||
_increment_button.size().w
|
||||
? _increment_button.size().w
|
||||
: _decrement_button.size().w;
|
||||
const int button_area_width = 2 * widest_button;
|
||||
const int spacing = core::center_rect(button_area_width, widest_button);
|
||||
const int field_width = vp.w - 2 * button_area_width;
|
||||
|
||||
Widget::_widget_area.x =
|
||||
Widget::_widget_area.x + button_area_width;
|
||||
Widget::_widget_area.w = field_width;
|
||||
|
||||
Input<T>::_input_caption.viewport(
|
||||
core::rect_offset(
|
||||
core::rect_margin(
|
||||
Widget::_widget_area,
|
||||
{Input<T>::_border_width,
|
||||
Input<T>::_border_width}
|
||||
),
|
||||
vp
|
||||
)
|
||||
);
|
||||
_decrement_button_area = {
|
||||
spacing,
|
||||
Widget::_widget_area.y,
|
||||
_decrement_button.size().w,
|
||||
_decrement_button.size().h
|
||||
};
|
||||
|
||||
_increment_button_area = {
|
||||
vp.w - spacing - _increment_button.size().w,
|
||||
Widget::_widget_area.y,
|
||||
_increment_button.size().w,
|
||||
_increment_button.size().h
|
||||
};
|
||||
|
||||
_increment_button.viewport(core::rect_offset(
|
||||
_increment_button_area, vp
|
||||
));
|
||||
_decrement_button.viewport(core::rect_offset(
|
||||
_decrement_button_area, vp
|
||||
));
|
||||
}
|
||||
|
||||
virtual void _handle_renderer_change(core::Renderer* r)
|
||||
{
|
||||
Input<T>::_handle_renderer_change(r);
|
||||
_decrement_button.renderer(r);
|
||||
_increment_button.renderer(r);
|
||||
}
|
||||
|
||||
virtual void _handle_rendering() override
|
||||
{
|
||||
Input<T>::_handle_rendering();
|
||||
_increment_button.render();
|
||||
_decrement_button.render();
|
||||
}
|
||||
|
||||
public:
|
||||
T button_step = 1;
|
||||
|
||||
NumericInput(Widget* parent=nullptr)
|
||||
: Input<T>(parent),
|
||||
_increment_button(this),
|
||||
_decrement_button(this)
|
||||
{
|
||||
Input<T>::_input_caption.alignment.h =
|
||||
widget::Caption::AlignmentH::RIGHT;
|
||||
|
||||
_increment_button.text("+");
|
||||
|
||||
_increment_button.click_handler = [this](const SDL_MouseButtonEvent&) {
|
||||
T new_value = this->value + button_step;
|
||||
if (_value_range.second - this->value < button_step)
|
||||
new_value = _value_range.second;
|
||||
|
||||
this->value = new_value;
|
||||
this->input_text(this->value_to_string(new_value));
|
||||
};
|
||||
|
||||
_decrement_button.text("-");
|
||||
|
||||
_decrement_button.click_handler = [this](const SDL_MouseButtonEvent&) {
|
||||
T new_value = this->value - button_step;
|
||||
if (this->value - _value_range.first < button_step)
|
||||
new_value = _value_range.first;
|
||||
|
||||
this->value = new_value;
|
||||
this->input_text(this->value_to_string(new_value));
|
||||
};
|
||||
}
|
||||
|
||||
virtual void handle_event(const SDL_Event& ev) override
|
||||
{
|
||||
Widget::handle_event(ev);
|
||||
_increment_button.handle_event(ev);
|
||||
_decrement_button.handle_event(ev);
|
||||
}
|
||||
|
||||
virtual bool is_valid_input(const std::string input) const noexcept override
|
||||
{
|
||||
bool valid = false;
|
||||
|
||||
if (input.at(0) >= '0' && input.at(0) <= '9')
|
||||
valid = true;
|
||||
if constexpr(std::is_floating_point_v<T>)
|
||||
if (input.at(0) == '.'
|
||||
&& Input<T>::input_text().find('.') == std::string::npos)
|
||||
valid = true;
|
||||
if constexpr(std::is_signed_v<T>)
|
||||
{
|
||||
std::string displayed_value = Input<T>::input_text();
|
||||
if (input.at(0) == '-'
|
||||
&& !std::regex_search(
|
||||
displayed_value,
|
||||
std::regex("[^\\s]")
|
||||
))
|
||||
valid = true;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
virtual T process_value(T x) const noexcept override
|
||||
{
|
||||
T value = x;
|
||||
if (x < _value_range.first)
|
||||
value = _value_range.first;
|
||||
else if (x > _value_range.second)
|
||||
value = _value_range.second;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
virtual std::pair<T, T> value_range() const noexcept
|
||||
{
|
||||
return _value_range;
|
||||
}
|
||||
|
||||
virtual void value_range(T min, T max)
|
||||
{
|
||||
|
||||
if (min > max)
|
||||
throw std::invalid_argument("min cannot be greater than max");
|
||||
_value_range = {min, max};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef BWIDGETS_VERTICAL_LAYOUT_HPP_
|
||||
#define BWIDGETS_VERTICAL_LAYOUT_HPP_
|
||||
|
||||
#include <basic_widgets/w/base/layout.hpp>
|
||||
|
||||
namespace bwidgets::widget
|
||||
{
|
||||
class VerticalLayout final : public Layout
|
||||
{
|
||||
private:
|
||||
void _update_layout(const SDL_Rect&) noexcept override;
|
||||
|
||||
public:
|
||||
core::Size size() const noexcept override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
61
meson.build
61
meson.build
|
@ -1,8 +1,10 @@
|
|||
project('sdl2_basic_widgets', 'cpp',
|
||||
version : '0.1pre',
|
||||
default_options : ['warning_level=3', 'cpp_std=c++20', 'd_ndebug=if-release'],
|
||||
default_options : ['warning_level=3', 'werror=true', 'cpp_std=c++20', 'd_ndebug=if-release'],
|
||||
license: 'EUPL-1.2')
|
||||
|
||||
add_project_arguments('-Winline', '-pedantic', language: 'cpp')
|
||||
|
||||
sdl = [
|
||||
dependency('sdl2', version: '>=2.0.5'),
|
||||
dependency('SDL2_ttf')
|
||||
|
@ -12,20 +14,19 @@ fontconfig = dependency('fontconfig')
|
|||
pub_api = include_directories('inc')
|
||||
|
||||
libbasic_widgets = static_library('basic_widgets',
|
||||
'src/button.cpp',
|
||||
'src/caption.cpp',
|
||||
'src/focus_handler.cpp',
|
||||
'src/font_handler.cpp',
|
||||
'src/horizontal_layout.cpp',
|
||||
'src/keyboard_handler.cpp',
|
||||
'src/layout.cpp',
|
||||
'src/mouse_handler.cpp',
|
||||
'src/vertical_layout.cpp',
|
||||
'src/widget.cpp',
|
||||
'src/sdl/renderer.cpp',
|
||||
'src/sdl/texture.cpp',
|
||||
'src/utils/render.cpp',
|
||||
'src/utils/font.cpp',
|
||||
'src/core/draw.cpp',
|
||||
'src/core/font.cpp',
|
||||
'src/core/renderer.cpp',
|
||||
'src/core/texture.cpp',
|
||||
'src/w/base/layout.cpp',
|
||||
'src/w/base/widget.cpp',
|
||||
'src/w/feat/font_handler.cpp',
|
||||
'src/w/feat/keyboard_handler.cpp',
|
||||
'src/w/feat/mouse_handler.cpp',
|
||||
'src/w/button.cpp',
|
||||
'src/w/caption.cpp',
|
||||
'src/w/horizontal_layout.cpp',
|
||||
'src/w/vertical_layout.cpp',
|
||||
dependencies : [sdl, fontconfig],
|
||||
include_directories : pub_api,
|
||||
install : true)
|
||||
|
@ -35,20 +36,20 @@ libbasic_widgets_dep = declare_dependency(
|
|||
link_with: libbasic_widgets,
|
||||
dependencies : [sdl, fontconfig])
|
||||
|
||||
executable('button_demo',
|
||||
'examples/button_example.cpp',
|
||||
include_directories : pub_api,
|
||||
link_with : libbasic_widgets,
|
||||
install : false)
|
||||
# executable('button_demo',
|
||||
# 'examples/button_example.cpp',
|
||||
# include_directories : pub_api,
|
||||
# link_with : libbasic_widgets,
|
||||
# install : false)
|
||||
|
||||
executable('caption_demo',
|
||||
'examples/caption_example.cpp',
|
||||
include_directories : pub_api,
|
||||
link_with : libbasic_widgets,
|
||||
install : false)
|
||||
# executable('caption_demo',
|
||||
# 'examples/caption_example.cpp',
|
||||
# include_directories : pub_api,
|
||||
# link_with : libbasic_widgets,
|
||||
# install : false)
|
||||
|
||||
executable('input_demo',
|
||||
'examples/input_example.cpp',
|
||||
include_directories : pub_api,
|
||||
link_with : libbasic_widgets,
|
||||
install : false)
|
||||
# executable('input_demo',
|
||||
# 'examples/input_example.cpp',
|
||||
# include_directories : pub_api,
|
||||
# link_with : libbasic_widgets,
|
||||
# install : false)
|
||||
|
|
129
src/caption.cpp
129
src/caption.cpp
|
@ -1,129 +0,0 @@
|
|||
#include <SDL2/SDL_render.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
#include <basic_widgets/caption.hpp>
|
||||
#include <basic_widgets/sdl/renderer.hpp>
|
||||
#include <basic_widgets/sdl/texture.hpp>
|
||||
#include <basic_widgets/utils/math.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
using namespace bwidgets::utils;
|
||||
|
||||
widget::Caption::~Caption() noexcept
|
||||
{
|
||||
SDL_FreeSurface(_text_surface);
|
||||
if (_text_texture != nullptr) delete _text_texture;
|
||||
}
|
||||
|
||||
void widget::Caption::color_fg(const SDL_Color& c)
|
||||
{
|
||||
_color_fg = c;
|
||||
_render_text();
|
||||
}
|
||||
|
||||
sdl::Size widget::Caption::size() const noexcept
|
||||
{
|
||||
if (_font == nullptr)
|
||||
return {-1, -1};
|
||||
|
||||
sdl::Size size;
|
||||
TTF_SizeUTF8(_font, _text.c_str(), &size.w, &size.h);
|
||||
// 2 * margins?
|
||||
return {size.w + 2 * margins.w, size.h + 2 * margins.h};
|
||||
}
|
||||
|
||||
const std::string& widget::Caption::text() const noexcept
|
||||
{
|
||||
return _text;
|
||||
}
|
||||
|
||||
void widget::Caption::text(const std::string& t)
|
||||
{
|
||||
_text = t;
|
||||
_render_text();
|
||||
}
|
||||
|
||||
void widget::Caption::_handle_font_change()
|
||||
{
|
||||
_render_text();
|
||||
}
|
||||
|
||||
void widget::Caption::_handle_geometry_change(const SDL_Rect& vp) noexcept
|
||||
{
|
||||
_widget_area = {margins.w, margins.h, vp.w - 2 * margins.w, vp.h - 2 * margins.h};
|
||||
}
|
||||
|
||||
void widget::Caption::_handle_renderer_change(sdl::Renderer* r)
|
||||
{
|
||||
_handle_texture_update(r);
|
||||
}
|
||||
|
||||
void widget::Caption::_handle_rendering()
|
||||
{
|
||||
_renderer->draw_color(color_bg);
|
||||
_renderer->fill_rect(utils::math::rect_margin(_widget_area, -margins * 2));
|
||||
|
||||
if (_text_surface == nullptr)
|
||||
return;
|
||||
|
||||
sdl::Size size_dst {
|
||||
(int)((float)_text_surface->w / _text_surface->h * _widget_area.h),
|
||||
_widget_area.h
|
||||
};
|
||||
SDL_Rect texture_dst {
|
||||
margins.w,
|
||||
utils::math::center_rect(_widget_area.h, size_dst.h) + margins.h,
|
||||
size_dst.w,
|
||||
size_dst.h
|
||||
};
|
||||
switch (alignment.h)
|
||||
{
|
||||
case AlignmentH::CENTER:
|
||||
texture_dst.x = utils::math::center_rect(_widget_area.w, texture_dst.w)
|
||||
+ _widget_area.x;
|
||||
break;
|
||||
case AlignmentH::LEFT:
|
||||
break;
|
||||
case AlignmentH::RIGHT:
|
||||
texture_dst.x = _widget_area.w - texture_dst.w - margins.w + _widget_area.x;
|
||||
break;
|
||||
}
|
||||
switch (alignment.v)
|
||||
{
|
||||
case AlignmentV::BOTTOM:
|
||||
texture_dst.y = _widget_area.h - texture_dst.h - margins.h + _widget_area.y;
|
||||
break;
|
||||
case AlignmentV::CENTER:
|
||||
break;
|
||||
case AlignmentV::TOP:
|
||||
texture_dst.y = margins.h + _widget_area.y;
|
||||
}
|
||||
_renderer->copy(*_text_texture, NULL, texture_dst);
|
||||
}
|
||||
|
||||
void widget::Caption::_handle_texture_update(sdl::Renderer* r)
|
||||
{
|
||||
if (r != nullptr && _text_surface != nullptr)
|
||||
{
|
||||
if (_text_texture != nullptr)
|
||||
{
|
||||
delete _text_texture;
|
||||
_text_texture = nullptr;
|
||||
}
|
||||
_text_texture = new sdl::Texture(r, _text_surface);
|
||||
}
|
||||
}
|
||||
|
||||
void widget::Caption::_render_text()
|
||||
{
|
||||
if (_font == nullptr)
|
||||
return;
|
||||
|
||||
SDL_FreeSurface(_text_surface);
|
||||
_text_surface = TTF_RenderUTF8_Blended(
|
||||
_font,
|
||||
_text.c_str(),
|
||||
_color_fg
|
||||
);
|
||||
_handle_texture_update(_renderer);
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
#include "SDL_error.h"
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include <basic_widgets/exception.hpp>
|
||||
#include <basic_widgets/utils/math.hpp>
|
||||
#include <basic_widgets/utils/render.hpp>
|
||||
#include <SDL2/SDL_render.h>
|
||||
|
||||
using bwidgets::exception::ptr_or_throw;
|
||||
using bwidgets::exception::SDLError;
|
||||
#include <basic_widgets/core/draw.hpp>
|
||||
#include <basic_widgets/core/math.hpp>
|
||||
#include <basic_widgets/core/texture.hpp>
|
||||
|
||||
namespace bwidgets::utils::render
|
||||
namespace bwidgets::core
|
||||
{
|
||||
SDL_Color aa(
|
||||
const SDL_Color& base_color,
|
||||
|
@ -23,29 +22,29 @@ namespace bwidgets::utils::render
|
|||
|
||||
return {
|
||||
base_color.r, base_color.g, base_color.b,
|
||||
static_cast<Uint8>(base_color.a * factor)
|
||||
(uint8_t)(base_color.a * factor)
|
||||
};
|
||||
}
|
||||
|
||||
sdl::Texture filled_circle(
|
||||
core::Texture filled_circle(
|
||||
const SDL_Color& c,
|
||||
const int resolution,
|
||||
sdl::Renderer* r,
|
||||
core::Renderer* r,
|
||||
const int aa_pixels
|
||||
)
|
||||
{
|
||||
sdl::Texture texture (r,
|
||||
SDL_PIXELFORMAT_RGBA32,
|
||||
SDL_TEXTUREACCESS_STATIC,
|
||||
resolution, resolution);
|
||||
const auto radius {resolution / 2};
|
||||
const SDL_Point center {radius, radius};
|
||||
core::Texture texture (r,
|
||||
SDL_PIXELFORMAT_RGBA32,
|
||||
SDL_TEXTUREACCESS_STATIC,
|
||||
resolution, resolution);
|
||||
const auto radius {resolution / 2};
|
||||
const SDL_Point center {radius, radius};
|
||||
|
||||
bwidgets::utils::render::set_pixels_color(
|
||||
set_pixels_color(
|
||||
texture,
|
||||
[aa_pixels, c, center, radius]
|
||||
(const SDL_Point& p, const SDL_PixelFormat* format) -> Uint32 {
|
||||
const auto d_delta = math::distance(center, p) - radius;
|
||||
(const SDL_Point& p, const SDL_PixelFormat* format) -> uint32_t {
|
||||
const auto d_delta = core::distance(center, p) - radius;
|
||||
const auto aa_color = aa(c, aa_pixels, d_delta);
|
||||
|
||||
return SDL_MapRGBA(format,
|
||||
|
@ -60,7 +59,7 @@ namespace bwidgets::utils::render
|
|||
}
|
||||
|
||||
void set_pixels_color(
|
||||
sdl::Texture& t,
|
||||
core::Texture& t,
|
||||
std::function<Uint32 (const SDL_Point&, const SDL_PixelFormat*)> pixel_color
|
||||
)
|
||||
{
|
|
@ -0,0 +1,171 @@
|
|||
#include "SDL_ttf.h"
|
||||
#include <any>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
#include <basic_widgets/core/font.hpp>
|
||||
#include <basic_widgets/core/type/fc_error.hpp>
|
||||
#include <basic_widgets/core/type/sdl_error.hpp>
|
||||
|
||||
namespace bwidgets::core
|
||||
{
|
||||
Font::Font(TTF_Font* f)
|
||||
: OpaqueStruct(f), ascent(TTF_FontAscent(f)), descent(TTF_FontDescent(f)),
|
||||
faces(TTF_FontFaces(f)), family_name(TTF_FontFaceFamilyName(f)),
|
||||
fixed_width(TTF_FontFaceIsFixedWidth(f)), height(TTF_FontHeight(f)),
|
||||
line_skip(TTF_FontLineSkip(f)), style_name(TTF_FontFaceStyleName(f))
|
||||
{
|
||||
}
|
||||
|
||||
Font::Font(const std::string& file, int size)
|
||||
: Font(ptr_or_throw<FCError>(TTF_OpenFont(file.c_str(), size),
|
||||
__FILE__, __FUNCTION__, __LINE__, "failed to open font"))
|
||||
{
|
||||
}
|
||||
|
||||
Font::~Font()
|
||||
{
|
||||
TTF_CloseFont(c_pod);
|
||||
}
|
||||
|
||||
Font::Hinting Font::hinting()
|
||||
{
|
||||
return (Hinting)TTF_GetFontHinting(c_pod);
|
||||
}
|
||||
|
||||
Font* Font::hinting(Font::Hinting h)
|
||||
{
|
||||
TTF_SetFontHinting(c_pod, (int)h);
|
||||
return this;
|
||||
}
|
||||
|
||||
bool Font::kerning()
|
||||
{
|
||||
return TTF_GetFontHinting(c_pod);
|
||||
}
|
||||
|
||||
Font* Font::kerning(bool allowed)
|
||||
{
|
||||
TTF_SetFontKerning(c_pod, allowed);
|
||||
return this;
|
||||
}
|
||||
|
||||
int Font::outline()
|
||||
{
|
||||
return TTF_GetFontOutline(c_pod);
|
||||
}
|
||||
|
||||
Font* Font::outline(int size)
|
||||
{
|
||||
TTF_SetFontOutline(c_pod, size);
|
||||
return this;
|
||||
}
|
||||
|
||||
SDL_Surface* Font::render(RenderMode m, const std::string& str,
|
||||
const SDL_Color& fg,
|
||||
const SDL_Color& bg)
|
||||
{
|
||||
std::function<SDL_Surface* ()> renderer;
|
||||
|
||||
switch (m)
|
||||
{
|
||||
case RenderMode::BLENDED:
|
||||
renderer = [&fg, &str, this]() {
|
||||
return TTF_RenderUTF8_Blended(c_pod, str.c_str(), fg);
|
||||
};
|
||||
break;
|
||||
case RenderMode::SHADED:
|
||||
renderer = [&bg, &fg, &str, this]() {
|
||||
return TTF_RenderUTF8_Shaded(c_pod, str.c_str(), fg, bg);
|
||||
};
|
||||
break;
|
||||
case RenderMode::SOLID:
|
||||
renderer = [&fg, &str, this]() {
|
||||
return TTF_RenderUTF8_Solid(c_pod, str.c_str(), fg);
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
return ptr_or_throw<SDLError>(renderer(), __FILE__, __FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
uint8_t Font::style()
|
||||
{
|
||||
return TTF_GetFontStyle(c_pod);
|
||||
}
|
||||
|
||||
Font* Font::style(uint8_t s)
|
||||
{
|
||||
TTF_SetFontStyle(c_pod, s);
|
||||
return this;
|
||||
}
|
||||
|
||||
Size Font::text_size(const std::string& str)
|
||||
{
|
||||
Size s;
|
||||
TTF_SizeUTF8(c_pod, str.c_str(), &s.w, &s.h);
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string Font::find(const std::string& pat)
|
||||
{
|
||||
std::vector<std::any> ptrs;
|
||||
|
||||
auto clean = [&ptrs](int lvl) mutable
|
||||
{
|
||||
switch (lvl)
|
||||
{
|
||||
case 2:
|
||||
FcPatternDestroy(std::any_cast<FcPattern*>(ptrs.at(1)));
|
||||
[[fallthrough]];
|
||||
case 1:
|
||||
FcConfigDestroy(std::any_cast<FcConfig*>(ptrs.at(0)));
|
||||
FcFini();
|
||||
}
|
||||
};
|
||||
|
||||
FcConfig* conf = ptr_or_throw<FCError>(FcInitLoadConfigAndFonts(),
|
||||
__FILE__, __FUNCTION__, __LINE__, "init failed");
|
||||
ptrs.push_back(conf);
|
||||
|
||||
FcPattern* pattern;
|
||||
try
|
||||
{
|
||||
pattern = ptr_or_throw<FCError>(FcNameParse((FcChar8*)pat.c_str()),
|
||||
__FILE__, __FUNCTION__, __LINE__, "pattern parsing failed");
|
||||
ptrs.push_back(pattern);
|
||||
|
||||
if(FcConfigSubstitute(conf, pattern, FcMatchPattern) == FcFalse)
|
||||
throw FCError {__FILE__, __FUNCTION__, __LINE__, "FcConfigSubstitute failed"};
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
clean(ptrs.size());
|
||||
throw e;
|
||||
}
|
||||
|
||||
FcDefaultSubstitute(pattern);
|
||||
|
||||
std::string file_path;
|
||||
FcResult res;
|
||||
FcPattern* font = FcFontMatch(conf, pattern, &res);
|
||||
if (font != nullptr)
|
||||
{
|
||||
FcChar8* file = nullptr;
|
||||
if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch)
|
||||
{
|
||||
file_path = (char*)file;
|
||||
}
|
||||
FcPatternDestroy(font);
|
||||
}
|
||||
|
||||
clean(ptrs.size());
|
||||
|
||||
if (file_path.empty())
|
||||
throw FCError {__FILE__, __FUNCTION__, __LINE__, "no font found"};
|
||||
|
||||
return file_path;
|
||||
}
|
||||
}
|
|
@ -1,39 +1,26 @@
|
|||
#include <string>
|
||||
|
||||
#include <basic_widgets/sdl/renderer.hpp>
|
||||
#include <basic_widgets/sdl/texture.hpp>
|
||||
#include <basic_widgets/core/renderer.hpp>
|
||||
#include <basic_widgets/core/texture.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
using exception::SDLError;
|
||||
using exception::ptr_or_throw;
|
||||
|
||||
using std::vector;
|
||||
|
||||
sdl::Renderer::Renderer(SDL_Renderer* r)
|
||||
: DataType(r),
|
||||
core::Renderer::Renderer(SDL_Renderer* r)
|
||||
: OpaqueStruct(r),
|
||||
info(_info(r))
|
||||
{
|
||||
}
|
||||
|
||||
sdl::Renderer::Renderer(SDL_Window* w, int index, uint32_t flags=0)
|
||||
: DataType(ptr_or_throw<SDLError>(SDL_CreateRenderer(w, index, flags),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
exception::Base::Args({
|
||||
{"w", std::to_string((size_t)w)},
|
||||
{"index", std::to_string(index)},
|
||||
{"flags", std::to_string(flags)}
|
||||
}))),
|
||||
info(_info(c_pod))
|
||||
core::Renderer::Renderer(SDL_Window* w, int index, uint32_t flags=0)
|
||||
: Renderer(ptr_or_throw<SDLError>(SDL_CreateRenderer(w, index, flags),
|
||||
__FILE__, __FUNCTION__, __LINE__))
|
||||
{
|
||||
}
|
||||
|
||||
sdl::Renderer::~Renderer()
|
||||
core::Renderer::~Renderer()
|
||||
{
|
||||
SDL_DestroyRenderer(c_pod);
|
||||
}
|
||||
|
||||
SDL_BlendMode sdl::Renderer::blend_mode()
|
||||
SDL_BlendMode core::Renderer::blend_mode()
|
||||
{
|
||||
SDL_BlendMode mode;
|
||||
SDLError::success_or_throw(SDL_GetRenderDrawBlendMode(c_pod, &mode),
|
||||
|
@ -42,23 +29,23 @@ SDL_BlendMode sdl::Renderer::blend_mode()
|
|||
return mode;
|
||||
}
|
||||
|
||||
sdl::Renderer& sdl::Renderer::blend_mode(SDL_BlendMode mode)
|
||||
core::Renderer* core::Renderer::blend_mode(SDL_BlendMode mode)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_SetRenderDrawBlendMode(c_pod, mode),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
|
||||
sdl::Renderer& sdl::Renderer::clear()
|
||||
core::Renderer* core::Renderer::clear()
|
||||
{
|
||||
SDLError::success_or_throw(SDL_RenderClear(c_pod),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
|
||||
sdl::Renderer& sdl::Renderer::copy(sdl::Texture& t,
|
||||
core::Renderer* core::Renderer::copy(core::Texture& t,
|
||||
const SDL_Rect* src, const SDL_Rect* dst)
|
||||
{
|
||||
SDLError::success_or_throw(
|
||||
|
@ -66,10 +53,10 @@ sdl::Renderer& sdl::Renderer::copy(sdl::Texture& t,
|
|||
__FILE__, __FUNCTION__, __LINE__
|
||||
);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
|
||||
SDL_Color sdl::Renderer::draw_color()
|
||||
SDL_Color core::Renderer::draw_color()
|
||||
{
|
||||
SDL_Color c;
|
||||
SDLError::success_or_throw(
|
||||
|
@ -80,83 +67,83 @@ SDL_Color sdl::Renderer::draw_color()
|
|||
return c;
|
||||
}
|
||||
|
||||
sdl::Renderer& sdl::Renderer::draw_color(const SDL_Color& c)
|
||||
core::Renderer* core::Renderer::draw_color(const SDL_Color& c)
|
||||
{
|
||||
SDLError::success_or_throw(
|
||||
SDL_SetRenderDrawColor(c_pod, c.r, c.g, c.b, c.a),
|
||||
__FILE__, __FUNCTION__, __LINE__
|
||||
);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
|
||||
sdl::Renderer& sdl::Renderer::draw_line(const SDL_Point& a, const SDL_Point& b)
|
||||
core::Renderer* core::Renderer::draw_line(const SDL_Point& a, const SDL_Point& b)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_RenderDrawLine(c_pod, a.x, a.y, b.x, b.y),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
|
||||
sdl::Renderer& sdl::Renderer::draw_lines(vector<SDL_Point> pts)
|
||||
core::Renderer* core::Renderer::draw_lines(std::vector<SDL_Point> pts)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_RenderDrawLines(c_pod, pts.data(), pts.size()),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
|
||||
sdl::Renderer& sdl::Renderer::draw_point(const SDL_Point& p)
|
||||
core::Renderer* core::Renderer::draw_point(const SDL_Point& p)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_RenderDrawPoint(c_pod, p.x, p.y),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
|
||||
sdl::Renderer& sdl::Renderer::draw_points(const vector<SDL_Point> pts)
|
||||
core::Renderer* core::Renderer::draw_points(const std::vector<SDL_Point> pts)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_RenderDrawPoints(c_pod, pts.data(), pts.size()),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
|
||||
sdl::Renderer& sdl::Renderer::draw_rect(const SDL_Rect& r)
|
||||
core::Renderer* core::Renderer::draw_rect(const SDL_Rect& r)
|
||||
{
|
||||
const SDL_Rect rect = r;
|
||||
SDLError::success_or_throw(SDL_RenderDrawRect(c_pod, &rect),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
|
||||
sdl::Renderer& sdl::Renderer::draw_rects(const vector<SDL_Rect> rs)
|
||||
core::Renderer* core::Renderer::draw_rects(const std::vector<SDL_Rect> rs)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_RenderDrawRects(c_pod, rs.data(), rs.size()),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
|
||||
sdl::Renderer& sdl::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),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
|
||||
sdl::Renderer& sdl::Renderer::fill_rects(const std::vector<SDL_Rect> rs)
|
||||
core::Renderer* core::Renderer::fill_rects(const std::vector<SDL_Rect> rs)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_RenderFillRects(c_pod, rs.data(), rs.size()),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
|
||||
sdl::Size sdl::Renderer::output_size()
|
||||
core::Size core::Renderer::output_size()
|
||||
{
|
||||
Size s;
|
||||
SDLError::success_or_throw(SDL_GetRendererOutputSize(c_pod, &s.w, &s.h),
|
||||
|
@ -165,12 +152,12 @@ sdl::Size sdl::Renderer::output_size()
|
|||
return s;
|
||||
}
|
||||
|
||||
void sdl::Renderer::present()
|
||||
void core::Renderer::present()
|
||||
{
|
||||
SDL_RenderPresent(c_pod);
|
||||
}
|
||||
|
||||
SDL_Rect sdl::Renderer::viewport()
|
||||
SDL_Rect core::Renderer::viewport()
|
||||
{
|
||||
SDL_Rect vp;
|
||||
SDL_RenderGetViewport(c_pod, &vp);
|
||||
|
@ -178,10 +165,10 @@ SDL_Rect sdl::Renderer::viewport()
|
|||
return vp;
|
||||
}
|
||||
|
||||
sdl::Renderer& sdl::Renderer::viewport(const SDL_Rect* vp)
|
||||
core::Renderer* core::Renderer::viewport(const SDL_Rect* vp)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_RenderSetViewport(c_pod, vp),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return *this;
|
||||
return this;
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
#include <basic_widgets/core/renderer.hpp>
|
||||
#include <basic_widgets/core/texture.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
core::Texture::Texture(SDL_Texture* t)
|
||||
: OpaqueStruct(t)
|
||||
{
|
||||
_attributes = attributes(t);
|
||||
}
|
||||
|
||||
core::Texture::Texture(
|
||||
Renderer* r,
|
||||
SDL_PixelFormatEnum f,
|
||||
SDL_TextureAccess a,
|
||||
int w, int h
|
||||
)
|
||||
: Texture(ptr_or_throw<SDLError>(SDL_CreateTexture(r->c_pod, f, a, w, h),
|
||||
__FILE__, __FUNCTION__, __LINE__))
|
||||
{
|
||||
}
|
||||
|
||||
core::Texture::Texture(Renderer* r, SDL_Surface* s)
|
||||
: OpaqueStruct(ptr_or_throw<SDLError>(SDL_CreateTextureFromSurface(r->c_pod, s),
|
||||
__FILE__, __FUNCTION__, __LINE__))
|
||||
{
|
||||
_attributes = attributes(c_pod);
|
||||
}
|
||||
|
||||
core::Texture::~Texture() noexcept
|
||||
{
|
||||
SDL_DestroyTexture(c_pod);
|
||||
}
|
||||
|
||||
uint8_t core::Texture::alpha_mode()
|
||||
{
|
||||
uint8_t mode;
|
||||
SDLError::success_or_throw(SDL_GetTextureAlphaMod(c_pod, &mode),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
core::Texture* core::Texture::alpha_mode(uint8_t m)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_SetTextureAlphaMod(c_pod, m),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
SDL_BlendMode core::Texture::blend_mode()
|
||||
{
|
||||
SDL_BlendMode mode;
|
||||
SDLError::success_or_throw(SDL_GetTextureBlendMode(c_pod, &mode),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
core::Texture* core::Texture::blend_mode(SDL_BlendMode m)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_SetTextureBlendMode(c_pod, m),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
SDL_Color core::Texture::color_mode()
|
||||
{
|
||||
SDL_Color mode;
|
||||
SDLError::success_or_throw(
|
||||
SDL_GetTextureColorMod(c_pod, &mode.r, &mode.g, &mode.b),
|
||||
__FILE__, __FUNCTION__, __LINE__
|
||||
);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
core::Texture* core::Texture::color_mode(const SDL_Color& m)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_SetTextureColorMod(c_pod, m.r, m.g, m.b),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
SDL_ScaleMode core::Texture::scale_mode()
|
||||
{
|
||||
SDL_ScaleMode mode;
|
||||
SDLError::success_or_throw(SDL_GetTextureScaleMode(c_pod, &mode),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
core::Texture* core::Texture::scale_mode(SDL_ScaleMode m)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_SetTextureScaleMode(c_pod, m),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
core::Texture* core::Texture::update(SDL_Rect* r, const void* pixels, int pitch)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_UpdateTexture(c_pod, r, pixels, pitch),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return this;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
#include <basic_widgets/abstract/focus_handler.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
abstract::FocusHandler::~FocusHandler()
|
||||
{
|
||||
}
|
||||
|
||||
void abstract::FocusHandler::_handle_focus_change()
|
||||
{
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#include <basic_widgets/abstract/font_handler.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
abstract::FontHandler::~FontHandler()
|
||||
{
|
||||
}
|
||||
|
||||
void abstract::FontHandler::font(TTF_Font* f)
|
||||
{
|
||||
_font = f;
|
||||
_handle_font_change();
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#include <SDL2/SDL_events.h>
|
||||
|
||||
#include <basic_widgets/abstract/keyboard_handler.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
void abstract::KeyboardHandler::_handle_key(const SDL_KeyboardEvent&)
|
||||
{
|
||||
}
|
||||
|
||||
void abstract::KeyboardHandler::_handle_text_input(const SDL_TextInputEvent&)
|
||||
{
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
#include <SDL2/SDL_render.h>
|
||||
|
||||
#include <basic_widgets/abstract/layout.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
abstract::Layout::~Layout() noexcept
|
||||
{
|
||||
for (Widget* widget_ptr : _widgets)
|
||||
delete widget_ptr;
|
||||
}
|
||||
|
||||
void abstract::Layout::add_widget(Widget *widget_ptr)
|
||||
{
|
||||
_widgets.push_back(widget_ptr);
|
||||
}
|
||||
|
||||
void abstract::Layout::handle_event(const SDL_Event& ev)
|
||||
{
|
||||
for (Widget* widget_ptr : _widgets)
|
||||
widget_ptr->handle_event(ev);
|
||||
}
|
||||
|
||||
void abstract::Layout::_handle_geometry_change(const SDL_Rect& vp) noexcept
|
||||
{
|
||||
_update_layout(vp);
|
||||
}
|
||||
|
||||
void abstract::Layout::_handle_renderer_change(sdl::Renderer* r)
|
||||
{
|
||||
for (auto* widget : _widgets)
|
||||
widget->renderer(r);
|
||||
}
|
||||
|
||||
void abstract::Layout::_handle_rendering()
|
||||
{
|
||||
for (Widget* widget_ptr : _widgets)
|
||||
widget_ptr->render();
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
#include <string>
|
||||
|
||||
#include <basic_widgets/sdl/renderer.hpp>
|
||||
#include <basic_widgets/sdl/texture.hpp>
|
||||
|
||||
#include "to_string.hpp"
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
using exception::Base;
|
||||
using exception::SDLError;
|
||||
using exception::ptr_or_throw;
|
||||
|
||||
sdl::Texture::Texture(SDL_Texture* t)
|
||||
: DataType(t)
|
||||
{
|
||||
_attributes = attributes(t);
|
||||
}
|
||||
|
||||
sdl::Texture::Texture(
|
||||
Renderer* r,
|
||||
SDL_PixelFormatEnum f,
|
||||
SDL_TextureAccess a,
|
||||
int w, int h
|
||||
)
|
||||
: Texture(ptr_or_throw<SDLError>(SDL_CreateTexture(r->c_pod, f, a, w, h),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
Base::Args({{"r", std::to_string((size_t)r)},
|
||||
{"f", SDL_GetPixelFormatName(f)},
|
||||
{"a", to_string(a)},
|
||||
{"w", std::to_string(w)}, {"h", std::to_string(h)}})))
|
||||
{
|
||||
}
|
||||
|
||||
sdl::Texture::Texture(Renderer* r, SDL_Surface* s)
|
||||
: DataType(ptr_or_throw<SDLError>(SDL_CreateTextureFromSurface(r->c_pod, s),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
Base::Args({{"r", std::to_string((size_t)r)},
|
||||
{"s", std::to_string((size_t)s)}})))
|
||||
{
|
||||
_attributes = attributes(c_pod);
|
||||
}
|
||||
|
||||
sdl::Texture::~Texture() noexcept
|
||||
{
|
||||
SDL_DestroyTexture(c_pod);
|
||||
}
|
||||
|
||||
uint8_t sdl::Texture::alpha_mode()
|
||||
{
|
||||
uint8_t mode;
|
||||
SDLError::success_or_throw(SDL_GetTextureAlphaMod(c_pod, &mode),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
sdl::Texture& sdl::Texture::alpha_mode(uint8_t m)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_SetTextureAlphaMod(c_pod, m),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
Base::Args({{"m", std::to_string(m)}}));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SDL_BlendMode sdl::Texture::blend_mode()
|
||||
{
|
||||
SDL_BlendMode mode;
|
||||
SDLError::success_or_throw(SDL_GetTextureBlendMode(c_pod, &mode),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
sdl::Texture& sdl::Texture::blend_mode(SDL_BlendMode m)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_SetTextureBlendMode(c_pod, m),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
Base::Args({{"m", to_string(m)}}));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SDL_Color sdl::Texture::color_mode()
|
||||
{
|
||||
SDL_Color mode;
|
||||
SDLError::success_or_throw(
|
||||
SDL_GetTextureColorMod(c_pod, &mode.r, &mode.g, &mode.b),
|
||||
__FILE__, __FUNCTION__, __LINE__
|
||||
);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
sdl::Texture& sdl::Texture::color_mode(const SDL_Color& m)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_SetTextureColorMod(c_pod, m.r, m.g, m.b),
|
||||
__FILE__, __FUNCTION__, __LINE__, Base::Args({{"m", to_string(m)}}));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SDL_ScaleMode sdl::Texture::scale_mode()
|
||||
{
|
||||
SDL_ScaleMode mode;
|
||||
SDLError::success_or_throw(SDL_GetTextureScaleMode(c_pod, &mode),
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
sdl::Texture& sdl::Texture::scale_mode(SDL_ScaleMode m)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_SetTextureScaleMode(c_pod, m),
|
||||
__FILE__, __FUNCTION__, __LINE__, Base::Args({{"m", to_string(m)}}));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
sdl::Texture& sdl::Texture::update(SDL_Rect* r, const void* pixels, int pitch)
|
||||
{
|
||||
SDLError::success_or_throw(SDL_UpdateTexture(c_pod, r, pixels, pitch),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
Base::Args({
|
||||
{"r", r },
|
||||
{"pixels", std::to_string((size_t)pixels)},
|
||||
{"pitch", std::to_string(pitch)}
|
||||
}));
|
||||
|
||||
return *this;
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
#ifndef SDL_TO_STRING_HPP
|
||||
#define SDL_TO_STRING_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <SDL2/SDL_render.h>
|
||||
|
||||
namespace bwidgets::sdl
|
||||
{
|
||||
static inline const char* to_string(SDL_BlendMode m)
|
||||
{
|
||||
switch (m)
|
||||
{
|
||||
case SDL_BLENDMODE_ADD:
|
||||
return "add";
|
||||
case SDL_BLENDMODE_BLEND:
|
||||
return "blend";
|
||||
case SDL_BLENDMODE_MOD:
|
||||
return "mod";
|
||||
case SDL_BLENDMODE_MUL:
|
||||
return "mul";
|
||||
case SDL_BLENDMODE_NONE:
|
||||
return "none";
|
||||
[[unlikely]] default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static inline const std::string to_string(const SDL_Color& c)
|
||||
{
|
||||
return "r:" + std::to_string(c.r) + "g:" + std::to_string(c.g)
|
||||
+ "b:" + std::to_string(c.b) + "a:" + std::to_string(c.a);
|
||||
}
|
||||
|
||||
static inline const char* to_string(SDL_ScaleMode m)
|
||||
{
|
||||
switch (m)
|
||||
{
|
||||
case SDL_ScaleModeBest:
|
||||
return "best";
|
||||
case SDL_ScaleModeLinear:
|
||||
return "linear";
|
||||
case SDL_ScaleModeNearest:
|
||||
return "nearest";
|
||||
[[unlikely]] default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static inline const char* to_string(SDL_TextureAccess a)
|
||||
{
|
||||
switch (a)
|
||||
{
|
||||
case SDL_TEXTUREACCESS_STATIC:
|
||||
return "static";
|
||||
case SDL_TEXTUREACCESS_STREAMING:
|
||||
return "streaming";
|
||||
case SDL_TEXTUREACCESS_TARGET:
|
||||
return "target";
|
||||
[[unlikely]] default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,74 +0,0 @@
|
|||
#include <any>
|
||||
#include <vector>
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
#include <basic_widgets/exception.hpp>
|
||||
#include <basic_widgets/utils/font.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
using exception::FontconfigError;
|
||||
using exception::ptr_or_throw;
|
||||
|
||||
namespace bwidgets::utils::font
|
||||
{
|
||||
std::string find(const std::string& pat)
|
||||
{
|
||||
std::vector<std::any> ptrs;
|
||||
|
||||
auto clean = [&ptrs](int lvl) mutable
|
||||
{
|
||||
switch (lvl)
|
||||
{
|
||||
case 2:
|
||||
FcPatternDestroy(std::any_cast<FcPattern*>(ptrs.at(1)));
|
||||
[[fallthrough]];
|
||||
case 1:
|
||||
FcConfigDestroy(std::any_cast<FcConfig*>(ptrs.at(0)));
|
||||
FcFini();
|
||||
}
|
||||
};
|
||||
|
||||
FcConfig* conf = ptr_or_throw<FontconfigError>(FcInitLoadConfigAndFonts(),
|
||||
__FILE__, __FUNCTION__, __LINE__, exception::Base::Args(), "init failed");
|
||||
ptrs.push_back(conf);
|
||||
|
||||
FcPattern* pattern;
|
||||
try
|
||||
{
|
||||
pattern = ptr_or_throw<FontconfigError>(FcNameParse((FcChar8*)pat.c_str()),
|
||||
__FILE__, __FUNCTION__, __LINE__, exception::Base::Args(), "pattern parsing failed");
|
||||
ptrs.push_back(pattern);
|
||||
|
||||
if(FcConfigSubstitute(conf, pattern, FcMatchPattern) == FcFalse)
|
||||
throw exception::FontconfigError {__FILE__, __FUNCTION__, __LINE__, exception::Base::Args(), "FcConfigSubstitute failed"};
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
clean(ptrs.size());
|
||||
throw e;
|
||||
}
|
||||
|
||||
FcDefaultSubstitute(pattern);
|
||||
|
||||
std::string file_path;
|
||||
FcResult res;
|
||||
FcPattern* font = FcFontMatch(conf, pattern, &res);
|
||||
if (font != nullptr)
|
||||
{
|
||||
FcChar8* file = nullptr;
|
||||
if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch)
|
||||
{
|
||||
file_path = (char*)file;
|
||||
}
|
||||
FcPatternDestroy(font);
|
||||
}
|
||||
|
||||
clean(ptrs.size());
|
||||
|
||||
if (file_path.empty())
|
||||
throw exception::FontconfigError {__FILE__, __FUNCTION__, __LINE__, exception::Base::Args(), "no font found"};
|
||||
|
||||
return file_path;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
#include <basic_widgets/w/base/layout.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
widget::Layout::~Layout() noexcept
|
||||
{
|
||||
for (Widget* widget_ptr : _widgets)
|
||||
delete widget_ptr;
|
||||
}
|
||||
|
||||
void widget::Layout::add_widget(Widget *widget_ptr)
|
||||
{
|
||||
_widgets.push_back(widget_ptr);
|
||||
}
|
||||
|
||||
void widget::Layout::handle_event(const SDL_Event& ev)
|
||||
{
|
||||
for (Widget* widget_ptr : _widgets)
|
||||
widget_ptr->handle_event(ev);
|
||||
}
|
||||
|
||||
void widget::Layout::_handle_geometry_change(const SDL_Rect& vp) noexcept
|
||||
{
|
||||
_update_layout(vp);
|
||||
}
|
||||
|
||||
void widget::Layout::_handle_renderer_change(core::Renderer* r)
|
||||
{
|
||||
for (auto* widget : _widgets)
|
||||
widget->renderer(r);
|
||||
}
|
||||
|
||||
void widget::Layout::_handle_rendering()
|
||||
{
|
||||
for (Widget* widget_ptr : _widgets)
|
||||
widget_ptr->render();
|
||||
}
|
|
@ -1,13 +1,12 @@
|
|||
#include <SDL2/SDL_events.h>
|
||||
#include <SDL2/SDL_render.h>
|
||||
|
||||
#include <basic_widgets/abstract/keyboard_handler.hpp>
|
||||
#include <basic_widgets/abstract/mouse_handler.hpp>
|
||||
#include <basic_widgets/abstract/widget.hpp>
|
||||
#include <basic_widgets/w/feat/keyboard_handler.hpp>
|
||||
#include <basic_widgets/w/feat/mouse_handler.hpp>
|
||||
#include <basic_widgets/w/base/widget.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
void abstract::Widget::handle_event(const SDL_Event &ev)
|
||||
void widget::Widget::handle_event(const SDL_Event &ev)
|
||||
{
|
||||
if (auto handler = dynamic_cast<KeyboardHandler*>(this);
|
||||
handler != nullptr)
|
||||
|
@ -40,15 +39,15 @@ void abstract::Widget::handle_event(const SDL_Event &ev)
|
|||
}
|
||||
}
|
||||
|
||||
void abstract::Widget::render()
|
||||
void widget::Widget::render()
|
||||
{
|
||||
if (_renderer == nullptr)
|
||||
return;
|
||||
|
||||
//#ifndef _NDEBUG
|
||||
_renderer->viewport(nullptr)
|
||||
.draw_color({0, 255, 0, SDL_ALPHA_TRANSPARENT})
|
||||
.fill_rect({
|
||||
->draw_color({0, 255, 0, SDL_ALPHA_TRANSPARENT})
|
||||
->fill_rect({
|
||||
_viewport.x - 1, _viewport.y - 1,
|
||||
_viewport.w + 2, _viewport.h + 2
|
||||
});
|
|
@ -1,24 +1,19 @@
|
|||
#include <SDL2/SDL_render.h>
|
||||
|
||||
#include <basic_widgets/button.hpp>
|
||||
#include <basic_widgets/exception.hpp>
|
||||
#include <basic_widgets/utils/math.hpp>
|
||||
#include <cstdint>
|
||||
#include <basic_widgets/w/button.hpp>
|
||||
#include <basic_widgets/core/math.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
using namespace bwidgets::utils;
|
||||
|
||||
using exception::SDLError;
|
||||
|
||||
widget::Button::Button(Widget* parent)
|
||||
: abstract::Widget(parent),
|
||||
: Widget(parent),
|
||||
_caption(this)
|
||||
{
|
||||
_focus_area = _click_area = &_widget_area;
|
||||
_caption.alignment.h = Caption::AlignmentH::CENTER;
|
||||
}
|
||||
|
||||
sdl::Size widget::Button::size() const noexcept
|
||||
core::Size widget::Button::size() const noexcept
|
||||
{
|
||||
return {
|
||||
_caption.size().w + 2 * border_width,
|
||||
|
@ -37,19 +32,25 @@ void widget::Button::text(std::string txt)
|
|||
_handle_geometry_change(_viewport);
|
||||
}
|
||||
|
||||
void widget::Button::_handle_font_change()
|
||||
void widget::Button::_handle_font_change(core::Font* f)
|
||||
{
|
||||
_caption.font(_font);
|
||||
_caption.font(f);
|
||||
_handle_geometry_change(_viewport);
|
||||
}
|
||||
|
||||
void widget::Button::_handle_font_color_change(const SDL_Color& fg, const SDL_Color& bg)
|
||||
{
|
||||
_caption.color_fg(fg);
|
||||
_caption.color_bg(bg);
|
||||
}
|
||||
|
||||
void widget::Button::_handle_geometry_change(const SDL_Rect& vp) noexcept
|
||||
{
|
||||
int h = _caption.size().h + 2 * border_width;
|
||||
|
||||
_widget_area = {
|
||||
0,
|
||||
math::center_rect(vp.h, _caption.size().h) - border_width,
|
||||
core::center_rect(vp.h, _caption.size().h) - border_width,
|
||||
vp.w,
|
||||
h
|
||||
};
|
||||
|
@ -57,8 +58,8 @@ void widget::Button::_handle_geometry_change(const SDL_Rect& vp) noexcept
|
|||
auto txt_size = _caption.size();
|
||||
|
||||
_caption_area = {
|
||||
math::center_rect(vp.w, txt_size.w),
|
||||
math::center_rect(vp.h, txt_size.h),
|
||||
core::center_rect(vp.w, txt_size.w),
|
||||
core::center_rect(vp.h, txt_size.h),
|
||||
txt_size.w,
|
||||
txt_size.h
|
||||
};
|
||||
|
@ -70,7 +71,7 @@ void widget::Button::_handle_geometry_change(const SDL_Rect& vp) noexcept
|
|||
});
|
||||
}
|
||||
|
||||
void widget::Button::_handle_renderer_change(sdl::Renderer* r)
|
||||
void widget::Button::_handle_renderer_change(core::Renderer* r)
|
||||
{
|
||||
_caption.renderer(r);
|
||||
}
|
||||
|
@ -94,7 +95,7 @@ void widget::Button::_handle_rendering()
|
|||
color_shade(c.b, i, border_width),
|
||||
c.a
|
||||
})
|
||||
.draw_rect({
|
||||
->draw_rect({
|
||||
_widget_area.x + i,
|
||||
_widget_area.y + i,
|
||||
_widget_area.w - i * 2,
|
||||
|
@ -112,7 +113,7 @@ void widget::Button::_handle_rendering()
|
|||
color_shade(c.g, i, border_width),
|
||||
color_shade(c.b, i, border_width),
|
||||
c.a
|
||||
}).draw_rect({
|
||||
})->draw_rect({
|
||||
_widget_area.x + margin,
|
||||
_widget_area.y + margin,
|
||||
_widget_area.w - margin * 2,
|
||||
|
@ -121,7 +122,7 @@ void widget::Button::_handle_rendering()
|
|||
}
|
||||
}
|
||||
|
||||
_renderer->draw_color(c).fill_rect({
|
||||
_renderer->draw_color(c)->fill_rect({
|
||||
_widget_area.x + border_width,
|
||||
_widget_area.y + border_width,
|
||||
_widget_area.w - 2 * border_width,
|
|
@ -0,0 +1,126 @@
|
|||
#include <SDL2/SDL_assert.h>
|
||||
|
||||
#include <basic_widgets/core/math.hpp>
|
||||
#include <basic_widgets/core/texture.hpp>
|
||||
#include <basic_widgets/w/caption.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
widget::Caption::~Caption() noexcept
|
||||
{
|
||||
core::OpaqueStruct<core::Texture>::discard(_text_texture);
|
||||
}
|
||||
|
||||
void widget::Caption::color_fg(const SDL_Color& c)
|
||||
{
|
||||
_color_fg = c;
|
||||
core::OpaqueStruct<core::Texture>::discard(_text_texture);
|
||||
}
|
||||
|
||||
core::Size widget::Caption::size() const noexcept
|
||||
{
|
||||
if (_font == nullptr)
|
||||
return {-1, -1};
|
||||
|
||||
core::Size size = _font->text_size(_text);
|
||||
|
||||
return {size.w + 2 * margins.w, size.h + 2 * margins.h};
|
||||
}
|
||||
|
||||
const std::string& widget::Caption::text() const noexcept
|
||||
{
|
||||
return _text;
|
||||
}
|
||||
|
||||
void widget::Caption::text(const std::string& t)
|
||||
{
|
||||
_text = t;
|
||||
core::OpaqueStruct<core::Texture>::discard(_text_texture);
|
||||
}
|
||||
|
||||
void widget::Caption::_handle_font_change(core::Font*)
|
||||
{
|
||||
core::OpaqueStruct<core::Texture>::discard(_text_texture);
|
||||
}
|
||||
|
||||
static inline bool operator!=(const SDL_Color& a, const SDL_Color& b)
|
||||
{
|
||||
return a.r != b.r || a.g != b.g || a.b != b.b || a.a != b.a;
|
||||
}
|
||||
|
||||
void widget::Caption::_handle_font_color_change(const SDL_Color& fg, const SDL_Color& bg)
|
||||
{
|
||||
if (fg != _font_color_fg || (bg != _font_color_bg &&
|
||||
_font_render_mode == core::Font::RenderMode::SHADED))
|
||||
{
|
||||
core::OpaqueStruct<core::Texture>::discard(_text_texture);
|
||||
}
|
||||
}
|
||||
|
||||
void widget::Caption::_handle_geometry_change(const SDL_Rect& vp) noexcept
|
||||
{
|
||||
if (vp.w != _viewport.w || vp.h != _viewport.h)
|
||||
{
|
||||
_widget_area = {margins.w, margins.h,
|
||||
vp.w - 2 * margins.w, vp.h - 2 * margins.h};
|
||||
}
|
||||
}
|
||||
|
||||
void widget::Caption::_handle_renderer_change(core::Renderer*)
|
||||
{
|
||||
core::OpaqueStruct<core::Texture>::discard(_text_texture);
|
||||
}
|
||||
|
||||
void widget::Caption::_handle_rendering()
|
||||
{
|
||||
if (_text_texture == nullptr)
|
||||
{
|
||||
_handle_texture_update();
|
||||
SDL_assert_release(_text_texture != nullptr);
|
||||
}
|
||||
|
||||
core::Size size_dst {
|
||||
(int)((float)_text_texture->attributes().w
|
||||
/ _text_texture->attributes().h * _widget_area.h),
|
||||
_widget_area.h
|
||||
};
|
||||
SDL_Rect texture_dst {
|
||||
margins.w,
|
||||
core::center_rect(_widget_area.h, size_dst.h) + margins.h,
|
||||
size_dst.w,
|
||||
size_dst.h
|
||||
};
|
||||
switch (alignment.h)
|
||||
{
|
||||
case AlignmentH::CENTER:
|
||||
texture_dst.x = core::center_rect(_widget_area.w, texture_dst.w)
|
||||
+ _widget_area.x;
|
||||
break;
|
||||
case AlignmentH::LEFT:
|
||||
break;
|
||||
case AlignmentH::RIGHT:
|
||||
texture_dst.x = _widget_area.w - texture_dst.w - margins.w + _widget_area.x;
|
||||
break;
|
||||
}
|
||||
switch (alignment.v)
|
||||
{
|
||||
case AlignmentV::BOTTOM:
|
||||
texture_dst.y = _widget_area.h - texture_dst.h - margins.h + _widget_area.y;
|
||||
break;
|
||||
case AlignmentV::CENTER:
|
||||
break;
|
||||
case AlignmentV::TOP:
|
||||
texture_dst.y = margins.h + _widget_area.y;
|
||||
}
|
||||
_renderer->copy(*_text_texture, NULL, texture_dst);
|
||||
}
|
||||
|
||||
void widget::Caption::_handle_texture_update()
|
||||
{
|
||||
SDL_assert_release(_renderer != nullptr);
|
||||
core::OpaqueStruct<core::Texture>::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);
|
||||
}
|
|
@ -1,20 +1,19 @@
|
|||
#include <SDL2/SDL_rect.h>
|
||||
#include <SDL2/SDL_events.h>
|
||||
|
||||
#include <basic_widgets/abstract/mouse_handler.hpp>
|
||||
#include <basic_widgets/utils/math.hpp>
|
||||
#include <basic_widgets/w/feat/mouse_handler.hpp>
|
||||
#include <basic_widgets/core/math.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
using namespace bwidgets::utils;
|
||||
|
||||
void abstract::MouseHandler::handle_mouse(const SDL_MouseButtonEvent& ev,
|
||||
const SDL_Rect& orig)
|
||||
void widget::MouseHandler::handle_mouse(const SDL_MouseButtonEvent& ev,
|
||||
const SDL_Rect& orig)
|
||||
{
|
||||
if (_click_area == nullptr)
|
||||
return;
|
||||
|
||||
SDL_Point p {ev.x, ev.y};
|
||||
SDL_Rect vp {math::rect_offset(*_click_area, orig)};
|
||||
SDL_Rect vp {core::rect_offset(*_click_area, orig)};
|
||||
|
||||
if (ev.type == SDL_MOUSEBUTTONDOWN)
|
||||
{
|
||||
|
@ -43,30 +42,20 @@ void abstract::MouseHandler::handle_mouse(const SDL_MouseButtonEvent& ev,
|
|||
}
|
||||
}
|
||||
|
||||
void abstract::MouseHandler::handle_mouse(const SDL_MouseMotionEvent& ev,
|
||||
const SDL_Rect& orig)
|
||||
void widget::MouseHandler::handle_mouse(const SDL_MouseMotionEvent& ev,
|
||||
const SDL_Rect& orig)
|
||||
{
|
||||
if (_click_area == nullptr)
|
||||
return;
|
||||
|
||||
SDL_Point p {ev.x, ev.y};
|
||||
SDL_Rect vp {math::rect_offset(*_click_area, orig)};
|
||||
SDL_Rect vp {core::rect_offset(*_click_area, orig)};
|
||||
|
||||
if (SDL_PointInRect(&p, &vp))
|
||||
_is_hovered = true;
|
||||
else
|
||||
_is_hovered = false;
|
||||
|
||||
if (_has_focus)
|
||||
if (_is_hovered)
|
||||
_handle_mouse_motion(ev, orig);
|
||||
}
|
||||
|
||||
void abstract::MouseHandler::_handle_mouse_button(const SDL_MouseButtonEvent&,
|
||||
const SDL_Rect&)
|
||||
{
|
||||
}
|
||||
|
||||
void abstract::MouseHandler::_handle_mouse_motion(const SDL_MouseMotionEvent&,
|
||||
const SDL_Rect&)
|
||||
{
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
#include <basic_widgets/horizontal_layout.hpp>
|
||||
#include <basic_widgets/w/horizontal_layout.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
sdl::Size widget::Horizontal_Layout::size() const noexcept
|
||||
core::Size widget::HorizontalLayout::size() const noexcept
|
||||
{
|
||||
sdl::Size max {0, 0};
|
||||
core::Size max {0, 0};
|
||||
|
||||
for (const auto* w : _widgets)
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ sdl::Size widget::Horizontal_Layout::size() const noexcept
|
|||
};
|
||||
}
|
||||
|
||||
void widget::Horizontal_Layout::_update_layout(const SDL_Rect& vp) noexcept
|
||||
void widget::HorizontalLayout::_update_layout(const SDL_Rect& vp) noexcept
|
||||
{
|
||||
int widget_size = (vp.w - (_widgets.size() + 1) * margins.w)
|
||||
/ _widgets.size();
|
|
@ -1,10 +1,10 @@
|
|||
#include <basic_widgets/vertical_layout.hpp>
|
||||
#include <basic_widgets/w/vertical_layout.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
sdl::Size widget::Vertical_Layout::size() const noexcept
|
||||
core::Size widget::VerticalLayout::size() const noexcept
|
||||
{
|
||||
sdl::Size max {0, 0};
|
||||
core::Size max {0, 0};
|
||||
|
||||
for (const auto* w : _widgets)
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ sdl::Size widget::Vertical_Layout::size() const noexcept
|
|||
};
|
||||
}
|
||||
|
||||
void widget::Vertical_Layout::_update_layout(const SDL_Rect& vp) noexcept
|
||||
void widget::VerticalLayout::_update_layout(const SDL_Rect& vp) noexcept
|
||||
{
|
||||
int widget_size = (vp.h - (_widgets.size() + 1) * margins.h)
|
||||
/ _widgets.size();
|
Loading…
Reference in New Issue