format code with custom clang-format style

This commit is contained in:
Andrea Blankenstijn 2021-07-29 16:06:03 +02:00
parent a83c4521e5
commit 3b6e900a22
42 changed files with 986 additions and 1088 deletions

61
.clang-format Normal file
View File

@ -0,0 +1,61 @@
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignArrayOfStructures: Right
AlignConsecutiveAssignments: AcrossComments
AlignConsecutiveBitFields: AcrossComments
AlignConsecutiveDeclarations: AcrossComments
AlignConsecutiveMacros: AcrossComments
AlignOperands: AlignAfterOperator
AllowShortBlocksOnASingleLine: Always
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AllowShortLoopsOnASingleLine: true
AlwaysBreakTemplateDeclarations: Yes
BraceWrapping:
AfterClass: true
AfterControlStatement: MultiLine
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
BeforeElse: true
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BreakInheritanceList: AfterComma
ColumnLimit: 89
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
EmptyLineBeforeAccessModifier: Always
FixNamespaceComments: false
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '<[[:alnum:].]+>'
Priority: -10
- Regex: '^<fontconfig/'
Priority: -5
- Regex: '^<SDL2/'
Priority: -5
- Regex: '^<basic_widgets/'
Priority: 0
- Regex: '^".*"$'
Priority: 5
IndentCaseLabels: true
IndentExternBlock: true
IndentGotoLabels: false
IndentRequires: true
IndentWidth: 4
KeepEmptyLinesAtTheStartOfBlocks: false
Language: Cpp
NamespaceIndentation: All
PointerAlignment: Left
SortIncludes: CaseInsensitive
SpaceAfterTemplateKeyword: false
SpaceBeforeCpp11BracedList: true
SpaceBeforeParens: ControlStatementsExceptControlMacros
Standard: c++20
TabWidth: 4

View File

@ -9,11 +9,11 @@ using widget::Button;
int main()
{
run_example<Button>([](Button* w, core::Font* f, int x, int y) {
w->click_handler = [x, y](const SDL_MouseButtonEvent&) {
std::cout << "button(" << x << ',' << y << "):click!" << std::endl;
};
w->font(f);
w->text("+");
});
w->click_handler = [x, y](const SDL_MouseButtonEvent&) {
std::cout << "button(" << x << ',' << y << "):click!" << std::endl;
};
w->font(f);
w->text("+");
});
return 0;
}

View File

@ -6,10 +6,12 @@ using widget::Caption;
int main()
{
run_example<Caption>([](Caption* w, core::Font* f, int, int) {
w->alignment = Caption::Alignment::CENTER;
w->text("¡jello!");
w->font(f);
}, 4, 8);
run_example<Caption>(
[](Caption* w, core::Font* f, int, int) {
w->alignment = Caption::Alignment::CENTER;
w->text("¡jello!");
w->font(f);
},
4, 8);
return 0;
}

View File

@ -4,8 +4,8 @@
int main()
{
run_example<Example>([](Example* w, core::Font*, int x, int y) {
w->cycle_r = (x + 1) * 3000;
w->cycle_b = (y + 1) * 3000;
w->cycle_b = (1 + x + y) * (y + 1) * 400;
});
w->cycle_r = (x + 1) * 3000;
w->cycle_b = (y + 1) * 3000;
w->cycle_b = (1 + x + y) * (y + 1) * 400;
});
}

View File

@ -22,23 +22,22 @@ private:
virtual void _handle_rendering() override
{
auto now = SDL_GetTicks();
uint8_t r = 255 * (now % cycle_r / (float)cycle_r);
uint8_t g = 255 * (now % cycle_g / (float)cycle_g);
uint8_t b = 255 * (now % cycle_b / (float)cycle_b);
auto now = SDL_GetTicks();
uint8_t r = 255 * (now % cycle_r / (float)cycle_r);
uint8_t g = 255 * (now % cycle_g / (float)cycle_g);
uint8_t b = 255 * (now % cycle_b / (float)cycle_b);
SDL_Color base_color {r, g, b, 255};
int border = 10;
for (auto i = 0; i < border; i+=3)
{
for (auto i = 0; i < border; i += 3) {
uint8_t alpha = 255 * i / border;
_renderer->draw_color({base_color.r, base_color.g, base_color.b, alpha})
->draw_rect(rect_margin(_widget_area, {i, i}));
->draw_rect(rect_margin(_widget_area, {i, i}));
}
_renderer->draw_color(base_color)
->draw_rect(nullptr)
->fill_rect(rect_margin(_widget_area, {border*2, border*2}));
->draw_rect(nullptr)
->fill_rect(rect_margin(_widget_area, {border * 2, border * 2}));
}
public:

View File

@ -6,10 +6,11 @@ using widget::NumericInput;
int main()
{
run_example<NumericInput<float> >([](NumericInput<float>* w, core::Font* f, int, int) {
w->font(f);
w->button_step = 0.5;
w->value_range(-3.14, 8.5);
});
run_example<NumericInput<float>>(
[](NumericInput<float>* w, core::Font* f, int, int) {
w->font(f);
w->button_step = 0.5;
w->value_range(-3.14, 8.5);
});
return 0;
}

View File

@ -20,31 +20,28 @@ template<typename T>
concept WidgetType = std::derived_from<T, widget::Widget>;
template<WidgetType W>
void run_example(std::function<void (W*, core::Font*, int, int)> setup, int w=3, int h=3)
void run_example(std::function<void(W*, core::Font*, int, int)> setup, int w = 3,
int h = 3)
{
try
{
core::SDLError::success_or_throw(SDL_Init(SDL_INIT_VIDEO),
__FILE__, __FUNCTION__, __LINE__);
core::SDLError::success_or_throw(TTF_Init(),
__FILE__, __FUNCTION__, __LINE__);
try {
core::SDLError::success_or_throw(SDL_Init(SDL_INIT_VIDEO), __FILE__,
__FUNCTION__, __LINE__);
core::SDLError::success_or_throw(TTF_Init(), __FILE__, __FUNCTION__, __LINE__);
const core::Size size_init {854, 480};
auto* font {new core::Font(core::Font::find("Monospace"), 16)};
auto* win {SDL_CreateWindow("basic_widgets example",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
size_init.w, size_init.h,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_UTILITY)};
auto* font {new core::Font(core::Font::find("Monospace"), 16)};
auto* win {SDL_CreateWindow("basic_widgets example", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, size_init.w, size_init.h,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
| SDL_WINDOW_UTILITY)};
auto* renderer {new core::Renderer(win, -1, SDL_RENDERER_ACCELERATED)};
renderer->blend_mode(SDL_BLENDMODE_BLEND);
auto* layout {new widget::HorizontalLayout()};
auto* layout {new widget::HorizontalLayout()};
for (auto x = 0; x < w; x++)
{
for (auto x = 0; x < w; x++) {
auto* col = new widget::VerticalLayout();
for (auto y = 0; y < h; y++)
{
for (auto y = 0; y < h; y++) {
auto* widget = new W();
setup(widget, font, x, y);
col->add_widget(widget);
@ -56,19 +53,15 @@ void run_example(std::function<void (W*, core::Font*, int, int)> setup, int w=3,
layout->viewport({0, 0, size_init.w, size_init.h});
bool quit {false};
while (!quit)
{
while (!quit) {
SDL_Event ev;
while (SDL_PollEvent(&ev) != 0)
{
switch (ev.type)
{
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)
{
if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
auto size = renderer->output_size();
layout->viewport({0, 0, size.w, size.h});
}
@ -83,11 +76,9 @@ void run_example(std::function<void (W*, core::Font*, int, int)> setup, int w=3,
layout->render();
renderer->present();
}
}
catch (const core::SDLError& e)
{
std::cerr << "Error: " << e.file << ":" << e.func << ":" << e.line
<< ": " << e.what << std::endl;
} catch (const core::SDLError& e) {
std::cerr << "Error: " << e.file << ":" << e.func << ":" << e.line << ": "
<< e.what << std::endl;
}
}

View File

@ -14,10 +14,11 @@ namespace bwidgets::core
struct 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*)>);
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

View File

@ -14,26 +14,29 @@ namespace bwidgets::core
{
struct Font final : OpaqueStruct<TTF_Font>
{
enum struct Hinting {
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
enum struct RenderMode
{
SOLID,
SHADED,
BLENDED
};
struct Style {
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;
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;
@ -60,8 +63,8 @@ namespace bwidgets::core
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});
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&);

View File

@ -29,28 +29,19 @@ namespace bwidgets::core
SDL_Point top_left {inner.x, inner.y};
SDL_Point bottom_right {inner.x + inner.w, inner.y + inner.h};
return
SDL_PointInRect(&top_left, &outer) &&
SDL_PointInRect(&bottom_right, &outer);
return SDL_PointInRect(&top_left, &outer)
&& SDL_PointInRect(&bottom_right, &outer);
}
static inline SDL_Rect rect_margin(const SDL_Rect& r, const Size& margin) noexcept
{
return {
r.x + margin.w,
r.y + margin.h,
r.w - 2 * margin.w,
r.h - 2 * margin.h
};
return {r.x + margin.w, r.y + margin.h, r.w - 2 * margin.w, r.h - 2 * margin.h};
}
static inline SDL_Rect rect_offset(const SDL_Rect& r, const SDL_Rect& offset) noexcept
static inline SDL_Rect rect_offset(const SDL_Rect& r,
const SDL_Rect& offset) noexcept
{
return {
r.x + offset.x,
r.y + offset.y,
r.w, r.h
};
return {r.x + offset.x, r.y + offset.y, r.w, r.h};
}
}

View File

@ -16,66 +16,72 @@ namespace bwidgets::core
struct Renderer final : 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__);
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;
}
return info;
}
public:
Renderer(SDL_Renderer*);
Renderer(SDL_Window*, int, uint32_t);
virtual ~Renderer() override;
public:
Renderer(SDL_Renderer*);
Renderer(SDL_Window*, int, uint32_t);
virtual ~Renderer() override;
const SDL_RendererInfo info;
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*);
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* draw_rect(const SDL_Rect& r) {
auto rect = r;
return draw_rect(&rect);
}
inline Renderer* fill_rect(const SDL_Rect& r) {
auto rect = r;
return fill_rect(&rect);
}
inline Renderer* viewport(const SDL_Rect& vp) {
auto v = vp;
return viewport(&v);
}
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* draw_rect(const SDL_Rect& r)
{
auto rect = r;
return draw_rect(&rect);
}
inline Renderer* fill_rect(const SDL_Rect& r)
{
auto rect = r;
return fill_rect(&rect);
}
inline Renderer* viewport(const SDL_Rect& vp)
{
auto v = vp;
return viewport(&v);
}
};
}

View File

@ -3,8 +3,8 @@
#include <cstdint>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_pixels.h>
#include <SDL2/SDL_render.h>
#include <basic_widgets/core/type/opaque_struct.hpp>
#include <basic_widgets/core/type/sdl_error.hpp>
@ -15,59 +15,56 @@ namespace bwidgets::core
struct Texture final : OpaqueStruct<SDL_Texture>
{
struct Attr
{
uint32_t format_raw;
SDL_PixelFormat* format;
SDL_TextureAccess access;
int w, h;
} _attributes;
struct Attr
{
uint32_t format_raw;
SDL_PixelFormat* format;
SDL_TextureAccess access;
int w, h;
} _attributes;
public:
Texture(SDL_Texture*);
Texture(Renderer* r,
SDL_PixelFormatEnum f,
SDL_TextureAccess a,
int w, int h);
Texture(Renderer*, SDL_Surface*);
public:
Texture(SDL_Texture*);
Texture(Renderer* r, SDL_PixelFormatEnum f, SDL_TextureAccess a, int w, int h);
Texture(Renderer*, SDL_Surface*);
virtual ~Texture() noexcept override;
virtual ~Texture() noexcept override;
uint8_t alpha_mode();
Texture* alpha_mode(uint8_t);
SDL_BlendMode blend_mode();
Texture* blend_mode(SDL_BlendMode);
SDL_Color color_mode();
Texture* color_mode(const SDL_Color&);
SDL_ScaleMode scale_mode();
Texture* scale_mode(SDL_ScaleMode);
Texture* update(SDL_Rect*, const void*, int);
uint8_t alpha_mode();
Texture* alpha_mode(uint8_t);
SDL_BlendMode blend_mode();
Texture* blend_mode(SDL_BlendMode);
SDL_Color color_mode();
Texture* color_mode(const SDL_Color&);
SDL_ScaleMode scale_mode();
Texture* scale_mode(SDL_ScaleMode);
Texture* update(SDL_Rect*, const void*, int);
inline const Attr& attributes() {
return _attributes;
}
inline const Attr& attributes()
{
return _attributes;
}
inline Texture* update(const SDL_Rect& r, const void* pix, int pitch) {
SDL_Rect rect = r;
update(&rect, pix, 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) {
Attr attr {};
SDLError::success_or_throw(
SDL_QueryTexture(t,
&attr.format_raw, (int*)&attr.access, &attr.w, &attr.h),
__FILE__, __FUNCTION__, __LINE__
);
attr.format = SDLError::ptr_or_throw(
SDL_AllocFormat(attr.format_raw),
__FILE__, __FUNCTION__, __LINE__
);
static inline const Attr attributes(SDL_Texture* t)
{
Attr attr {};
SDLError::success_or_throw(SDL_QueryTexture(t, &attr.format_raw,
(int*)&attr.access, &attr.w,
&attr.h),
__FILE__, __FUNCTION__, __LINE__);
attr.format = SDLError::ptr_or_throw(SDL_AllocFormat(attr.format_raw),
__FILE__, __FUNCTION__, __LINE__);
return attr;
}
return attr;
}
};
}

View File

@ -3,18 +3,25 @@
#include <ostream>
#include <string>
#include <type_traits>
namespace bwidgets::core
{
template<typename T>
concept CanToString = requires(T value) { std::to_string(value); };
concept CanToString = requires(T value)
{
std::to_string(value);
};
template<typename T>
concept Numeric = std::is_arithmetic_v<T>;
template<typename T>
concept Printable = requires(T value) { std::declval<std::ostream&>() << value; };
concept Printable = requires(T value)
{
std::declval<std::ostream&>() << value;
};
}
#endif

View File

@ -19,27 +19,28 @@ namespace bwidgets::core
const char* what;
BaseException(const char* file, const char* func, int l, const char* w)
: file(file), func(func), line(l), what(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) {
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;
}) {
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;
}

View File

@ -7,9 +7,9 @@ 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) {}
FCError(const char* file, const char* func, const int l, const char* w = nullptr)
: BaseException(file, func, l, w)
{}
};
}

View File

@ -3,15 +3,18 @@
namespace bwidgets::core
{
template<typename T> struct OpaqueStruct
template<typename T>
struct OpaqueStruct
{
T* c_pod;
OpaqueStruct(T* ptr=nullptr) : c_pod(ptr) {}
OpaqueStruct(T* ptr = nullptr) : c_pod(ptr) {}
virtual ~OpaqueStruct<T>() noexcept = default;
};
template<typename ... Ts> void discard(Ts*& ... ptrs) {
template<typename... Ts>
void discard(Ts*&... ptrs)
{
((delete ptrs), ...);
((ptrs = nullptr), ...);
}

View File

@ -12,13 +12,14 @@ 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) {}
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) {
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);
@ -27,7 +28,8 @@ namespace bwidgets::core
}
static inline int success_or_throw(int code, const char* file, const char* func,
const int l, const char* w=nullptr) {
const int l, const char* w = nullptr)
{
if (code < 0) {
if (w == nullptr) w = SDL_GetError();
throw SDLError(file, func, l, w);

View File

@ -5,16 +5,29 @@
namespace bwidgets::core
{
struct Size {
struct Size
{
int w;
int h;
inline Size operator-() { return {-w, -h}; }
inline Size operator+(const Size& s) { return {w + s.w, h + s.h}; }
inline Size operator-(const Size& s) { return {w - s.w, h - s.h}; }
inline Size operator-()
{
return {-w, -h};
}
inline Size operator+(const Size& s)
{
return {w + s.w, h + s.h};
}
inline Size operator-(const Size& s)
{
return {w - s.w, h - s.h};
}
template<Numeric T>
inline Size operator*(T a) { return {a * w, a * h}; }
inline Size operator*(T a)
{
return {a * w, a * h};
}
};
}

View File

@ -18,225 +18,196 @@
namespace bwidgets::widget
{
template<typename T> class Input : public Widget,
public FontHandler,
public KeyboardHandler,
public MouseHandler
template<typename T>
class Input : public Widget,
public FontHandler,
public KeyboardHandler,
public MouseHandler
{
protected:
const int _border_width {3};
Caption _input_caption;
protected:
const int _border_width {3};
Caption _input_caption;
Input(Widget* parent=nullptr)
: Widget(parent)
{
FocusHandler::_focus_area = &_widget_area;
MouseHandler::_click_area = &_widget_area;
_input_caption.text(value_to_string(value));
Input(Widget* parent = nullptr) : Widget(parent)
{
FocusHandler::_focus_area = &_widget_area;
MouseHandler::_click_area = &_widget_area;
_input_caption.text(value_to_string(value));
}
virtual void _handle_focus_change(bool focus) override
{
if (focus) {
SDL_StartTextInput();
}
virtual void _handle_focus_change(bool focus) override
{
if (focus)
{
SDL_StartTextInput();
}
else
{
value = value_from_string(input_text());
input_text(value_to_string(value));
SDL_StopTextInput();
}
else {
value = value_from_string(input_text());
input_text(value_to_string(value));
SDL_StopTextInput();
}
}
virtual void _handle_font_change(core::Font* f) override
{
_input_caption.font(f);
_handle_geometry_change(_viewport);
}
virtual void _handle_font_change(core::Font* f) override
{
_input_caption.font(f);
_handle_geometry_change(_viewport);
}
virtual void _handle_font_color_change(const SDL_Color& fg,
const SDL_Color& bg) override
{
_input_caption.color_bg(bg)->color_fg(fg);
}
virtual void _handle_font_color_change(const SDL_Color& fg,
const SDL_Color& bg) override
{
_input_caption.color_bg(bg)->color_fg(fg);
}
virtual void _handle_geometry_change(const SDL_Rect& vp) noexcept override
{
const auto input_h = _input_caption.size().h + 2 * _border_width;
_widget_area = {
0,
core::center_rect(vp.h, input_h),
vp.w,
input_h
};
virtual void _handle_geometry_change(const SDL_Rect& vp) noexcept override
{
const auto input_h = _input_caption.size().h + 2 * _border_width;
_widget_area = {0, core::center_rect(vp.h, input_h), vp.w, input_h};
_input_caption.viewport(
core::rect_offset({
core::rect_margin(_widget_area, {_border_width, _border_width})
}, vp
)
);
}
_input_caption.viewport(core::rect_offset(
{core::rect_margin(_widget_area, {_border_width, _border_width})}, vp));
}
virtual void _handle_key(const SDL_KeyboardEvent& key) override
{
if (key.type == SDL_KEYDOWN)
{
switch (key.keysym.sym)
{
case SDLK_BACKSPACE:
{
std::string txt = input_text();
if (txt.length() > 0)
{
txt.pop_back();
input_text(txt);
}
break;
}
case SDLK_RETURN:
case SDLK_RETURN2: // what is return2 btw?
case SDLK_KP_ENTER:
value = value_from_string(input_text());
focus(false);
break;
virtual void _handle_key(const SDL_KeyboardEvent& key) override
{
if (key.type == SDL_KEYDOWN) {
switch (key.keysym.sym) {
case SDLK_BACKSPACE: {
std::string txt = input_text();
if (txt.length() > 0) {
txt.pop_back();
input_text(txt);
}
break;
}
case SDLK_RETURN:
case SDLK_RETURN2: // what is return2 btw?
case SDLK_KP_ENTER:
value = value_from_string(input_text());
focus(false);
break;
}
}
}
virtual void _handle_renderer_change(core::Renderer* r) override
{
_input_caption.renderer(r);
virtual void _handle_renderer_change(core::Renderer* r) override
{
_input_caption.renderer(r);
}
virtual void _handle_rendering() override
{
// TODO: smoothstep
for (int i = _border_width - 1; i >= 0; i--) {
_renderer
->draw_color({(uint8_t)(color_border.r / (i + 1)),
(uint8_t)(color_border.g / (i + 1)),
(uint8_t)(color_border.b / (i + 1)), color_border.a})
->draw_rect({_widget_area.x + i, _widget_area.y + i,
_widget_area.w - 2 * i, _widget_area.h - 2 * i});
}
virtual void _handle_rendering() override
{
// TODO: smoothstep
for (int i = _border_width - 1; i >= 0; i--)
{
_renderer->draw_color({
(uint8_t)(color_border.r / (i + 1)),
(uint8_t)(color_border.g / (i + 1)),
(uint8_t)(color_border.b / (i+ 1)),
color_border.a
})
->draw_rect({
_widget_area.x + i,
_widget_area.y + i,
_widget_area.w - 2 * i,
_widget_area.h - 2 * i
});
}
if (MouseHandler::_is_hovered || FocusHandler::_has_focus)
_input_caption.color_bg(color_bg_focused);
else _input_caption.color_bg(color_bg);
if (MouseHandler::_is_hovered || FocusHandler::_has_focus)
_input_caption.color_bg(color_bg_focused);
else
_input_caption.color_bg(color_bg);
_input_caption.render();
}
_input_caption.render();
virtual void _handle_text_input(const SDL_TextInputEvent& input) override
{
if (is_valid_input(input.text)) {
input_text(input_text() + input.text);
}
}
virtual void _handle_text_input(const SDL_TextInputEvent& input) override
{
if (is_valid_input(input.text))
{
input_text(input_text() + input.text);
}
public:
SDL_Color color_border {160, 160, 160, SDL_ALPHA_OPAQUE};
SDL_Color color_bg {200, 200, 200, SDL_ALPHA_OPAQUE};
SDL_Color color_bg_focused {255, 255, 255, SDL_ALPHA_OPAQUE};
int float_precision {2};
int input_min_width {1};
char input_width_unit {'W'};
T value {};
virtual Input<T>* color_fg(const SDL_Color& c) noexcept
{
_input_caption.color_fg(c);
return this;
}
virtual const std::string& input_text() const noexcept
{
return _input_caption.text();
}
virtual Input<T>* input_text(std::string txt) noexcept
{
_input_caption.text(txt);
return this;
}
virtual bool is_valid_input(const std::string) const noexcept
{
return true;
}
virtual T process_value(T x) const noexcept
{
return x;
}
virtual inline core::Size size() const noexcept override
{
return {
_font->text_size(std::string(input_min_width, input_width_unit)).w
+ 2 * _border_width,
_font->line_skip + 4 * _border_width // _why_ 4 and not 2?…
};
}
T value_from_string(std::string s)
{
T v;
if constexpr (std::is_arithmetic_v<T>) {
s = s.length() > 0 ? s : "0";
if constexpr (std::is_floating_point_v<T>) v = (T)std::stold(s);
else if constexpr (std::is_integral_v<T>) v = (T)std::stoll(s);
}
else if constexpr (std::is_same_v<
T, std::string> || std::convertible_to<std::string, T>)
v = s;
else
static_assert(sizeof(T) && false,
"string cannot be converted to v type T.");
public:
SDL_Color color_border {160, 160, 160, SDL_ALPHA_OPAQUE};
SDL_Color color_bg {200, 200, 200, SDL_ALPHA_OPAQUE};
SDL_Color color_bg_focused {255, 255, 255, SDL_ALPHA_OPAQUE};
int float_precision {2};
int input_min_width {1};
char input_width_unit {'W'};
T value {};
return process_value(v);
}
virtual Input<T>* color_fg(const SDL_Color& c) noexcept
{
_input_caption.color_fg(c);
return this;
std::string value_to_string(T value)
{
std::string s;
if constexpr (std::is_same_v<std::string,
T> || std::convertible_to<T, std::string>)
s = std::move(value);
else if constexpr (core::CanToString<T>) {
std::stringstream ss;
ss << std::fixed << std::setprecision(float_precision) << value;
s = std::move(ss).str();
}
virtual const std::string& input_text() const noexcept
{
return _input_caption.text();
else if constexpr (core::Printable<T>) {
std::stringstream ss;
ss << value;
s = std::move(ss).str();
}
else
static_assert(sizeof(T) && false,
"value cannot be converted to string.");
virtual Input<T>* input_text(std::string txt) noexcept
{
_input_caption.text(txt);
return this;
}
virtual bool is_valid_input(const std::string) const noexcept
{
return true;
}
virtual T process_value(T x) const noexcept
{
return x;
}
virtual inline core::Size size() const noexcept override
{
return {
_font->text_size(
std::string(input_min_width, input_width_unit)
).w + 2 * _border_width,
_font->line_skip + 4 * _border_width // _why_ 4 and not 2?…
};
}
T value_from_string(std::string s)
{
T v;
if constexpr(std::is_arithmetic_v<T>)
{
s = s.length() > 0 ? s : "0";
if constexpr(std::is_floating_point_v<T>)
v = (T)std::stold(s);
else if constexpr(std::is_integral_v<T>)
v = (T)std::stoll(s);
}
else if constexpr(std::is_same_v<T, std::string> || std::convertible_to<std::string, T>)
v = s;
else
static_assert(sizeof(T) && false, "string cannot be converted to v type T.");
return process_value(v);
}
std::string value_to_string(T value)
{
std::string s;
if constexpr(std::is_same_v<std::string, T> || std::convertible_to<T, std::string>)
s = std::move(value);
else if constexpr(core::CanToString<T>)
{
std::stringstream ss;
ss << std::fixed
<< std::setprecision(float_precision)
<< value;
s = std::move(ss).str();
}
else if constexpr(core::Printable<T>)
{
std::stringstream ss;
ss << value;
s = std::move(ss).str();
}
else
static_assert(sizeof(T) && false, "value cannot be converted to string.");
return s;
}
return s;
}
};
}

View File

@ -7,7 +7,8 @@
#include <basic_widgets/core/type/size.hpp>
#include <basic_widgets/w/base/widget.hpp>
namespace bwidgets::core {
namespace bwidgets::core
{
struct Renderer;
}
@ -15,24 +16,24 @@ namespace bwidgets::widget
{
class Layout : public Widget
{
protected:
std::vector<Widget*> _widgets;
protected:
std::vector<Widget*> _widgets;
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 _update_layout(const SDL_Rect&) noexcept = 0;
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 _update_layout(const SDL_Rect&) noexcept = 0;
public:
core::Size margins {8, 8};
public:
core::Size margins {8, 8};
virtual ~Layout() noexcept;
virtual ~Layout() noexcept;
virtual Layout* add_widget(Widget*);
virtual void for_widgets(std::function<void (Widget*)>);
virtual Layout* handle_event(const SDL_Event&) override;
virtual Layout* add_widget(Widget*);
virtual void for_widgets(std::function<void(Widget*)>);
virtual Layout* handle_event(const SDL_Event&) override;
virtual core::Size size() const noexcept override = 0;
virtual core::Size size() const noexcept override = 0;
};
}

View File

@ -12,41 +12,44 @@ namespace bwidgets::widget
{
class Widget
{
protected:
core::Renderer* _renderer {nullptr};
SDL_Rect _viewport {0, 0, 0, 0};
SDL_Rect _widget_area {0, 0, 0, 0};
protected:
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(core::Renderer*) {}
virtual void _handle_rendering() = 0;
virtual void _handle_geometry_change(const SDL_Rect&) noexcept = 0;
virtual void _handle_renderer_change(core::Renderer*) {}
virtual void _handle_rendering() = 0;
public:
Widget* parent;
public:
Widget* parent;
Widget(Widget* p=nullptr) : parent(p) {}
Widget(Widget* p = nullptr) : parent(p) {}
virtual ~Widget() noexcept = default;
virtual Widget* handle_event(const SDL_Event&);
virtual ~Widget() noexcept = default;
virtual Widget* handle_event(const SDL_Event&);
inline virtual core::Size size() const noexcept = 0;
inline virtual core::Size size() const noexcept = 0;
virtual Widget* render() final;
virtual Widget* render() final;
virtual inline Widget* renderer(core::Renderer* r) final {
_handle_renderer_change(r);
_renderer = r;
return this;
}
virtual inline Widget* renderer(core::Renderer* r) final
{
_handle_renderer_change(r);
_renderer = r;
return this;
}
virtual inline const SDL_Rect& viewport() const noexcept final {
return _viewport;
}
virtual inline Widget* viewport(const SDL_Rect& vp) noexcept final {
_handle_geometry_change(vp);
_viewport = vp;
return this;
}
virtual inline const SDL_Rect& viewport() const noexcept final
{
return _viewport;
}
virtual inline Widget* viewport(const SDL_Rect& vp) noexcept final
{
_handle_geometry_change(vp);
_viewport = vp;
return this;
}
};
}

View File

@ -8,30 +8,33 @@
namespace bwidgets::widget
{
class Button : public Widget, public FontHandler, public MouseHandler
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};
protected:
Caption _caption;
SDL_Rect _caption_area;
SDL_Color _color_foreground {0, 0, 0, SDL_ALPHA_OPAQUE};
virtual void _handle_focus_change(bool) override {}
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_focus_change(bool) override {}
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;
public:
core::Size border_size {3, 3};
SDL_Color color_bg {150, 150, 150, SDL_ALPHA_OPAQUE};
SDL_Color color_bg_hover {175, 175, 175, SDL_ALPHA_OPAQUE};
public:
core::Size border_size {3, 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);
Button(Widget* parent = nullptr);
virtual core::Size size() const noexcept override;
virtual const std::string& text() const noexcept;
virtual Button* text(std::string);
virtual core::Size size() const noexcept override;
virtual const std::string& text() const noexcept;
virtual Button* text(std::string);
};
}

View File

@ -11,45 +11,47 @@ struct SDL_Surface;
namespace bwidgets::widget
{
class Caption : public Widget, public FontHandler,
class Caption : public Widget,
public FontHandler,
public TextureHandler
{
public:
enum struct Alignment {
CENTER,
LEFT,
RIGHT
};
public:
enum struct Alignment
{
CENTER,
LEFT,
RIGHT
};
protected:
SDL_Color _color_fg {0, 0, 0, SDL_ALPHA_OPAQUE};
SDL_Color _color_bg {255, 255, 255, SDL_ALPHA_TRANSPARENT};
core::Font::RenderMode _render_mode {core::Font::RenderMode::SHADED};
std::string _text;
core::Texture* _text_texture {nullptr};
protected:
SDL_Color _color_fg {0, 0, 0, SDL_ALPHA_OPAQUE};
SDL_Color _color_bg {255, 255, 255, SDL_ALPHA_TRANSPARENT};
core::Font::RenderMode _render_mode {core::Font::RenderMode::SHADED};
std::string _text;
core::Texture* _text_texture {nullptr};
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;
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:
Alignment alignment {Alignment::LEFT};
core::Size margins {2, 2};
public:
Alignment alignment {Alignment::LEFT};
core::Size margins {2, 2};
Caption(Widget* parent=nullptr) : Widget(parent) {}
~Caption() noexcept;
Caption(Widget* parent = nullptr) : Widget(parent) {}
~Caption() noexcept;
virtual Caption* color_bg(const SDL_Color&);
virtual Caption* color_fg(const SDL_Color&);
virtual Caption* render_mode(core::Font::RenderMode) noexcept;
virtual const std::string& text() const noexcept;
virtual Caption* text(const std::string&);
virtual Caption* color_bg(const SDL_Color&);
virtual Caption* color_fg(const SDL_Color&);
virtual Caption* render_mode(core::Font::RenderMode) noexcept;
virtual const std::string& text() const noexcept;
virtual Caption* text(const std::string&);
virtual core::Size size() const noexcept override;
virtual core::Size size() const noexcept override;
};
}

View File

@ -7,20 +7,20 @@ namespace bwidgets::widget
{
class FocusHandler
{
protected:
const SDL_Rect* _focus_area = nullptr;
bool _has_focus = false;
protected:
const SDL_Rect* _focus_area = nullptr;
bool _has_focus = false;
virtual void _handle_focus_change(bool) = 0;
virtual void _handle_focus_change(bool) = 0;
public:
virtual ~FocusHandler() = default;
public:
virtual ~FocusHandler() = default;
virtual inline void focus(bool focus) final
{
_handle_focus_change(focus);
_has_focus = focus;
}
virtual inline void focus(bool focus) final
{
_handle_focus_change(focus);
_has_focus = focus;
}
};
}

View File

@ -7,35 +7,38 @@ 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};
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;
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;
public:
virtual ~FontHandler() = default;
virtual inline FontHandler* font(core::Font* f) final {
_handle_font_change(f);
_font = f;
return this;
}
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_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;
}
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;
}
};
}

View File

@ -10,23 +10,20 @@ namespace bwidgets::widget
{
class KeyboardHandler : public virtual FocusHandler
{
protected:
protected:
virtual void _handle_key(const SDL_KeyboardEvent&) = 0;
virtual void _handle_text_input(const SDL_TextInputEvent&) = 0;
virtual void _handle_key(const SDL_KeyboardEvent&) = 0;
virtual void _handle_text_input(const SDL_TextInputEvent&) = 0;
public:
virtual inline void handle_keyboard(const SDL_KeyboardEvent& ev) final
{
if (_has_focus) _handle_key(ev);
}
public:
virtual inline void handle_keyboard(const SDL_KeyboardEvent& ev) final
{
if (_has_focus)
_handle_key(ev);
}
virtual inline void handle_keyboard(const SDL_TextInputEvent& ev) final
{
if (_has_focus)
_handle_text_input(ev);
}
virtual inline void handle_keyboard(const SDL_TextInputEvent& ev) final
{
if (_has_focus) _handle_text_input(ev);
}
};
}

View File

@ -12,23 +12,21 @@ namespace bwidgets::widget
{
class MouseHandler : public virtual FocusHandler
{
protected:
const SDL_Rect* _click_area = nullptr;
bool _is_hovered = false;
bool _is_pushed = false;
protected:
const SDL_Rect* _click_area = nullptr;
bool _is_hovered = false;
bool _is_pushed = false;
virtual void _handle_mouse_button(const SDL_MouseButtonEvent&,
const SDL_Rect&) {};
virtual void _handle_mouse_motion(const SDL_MouseMotionEvent&,
const SDL_Rect&) {};
virtual void _handle_mouse_button(const SDL_MouseButtonEvent&,
const SDL_Rect&) {};
virtual void _handle_mouse_motion(const SDL_MouseMotionEvent&,
const SDL_Rect&) {};
public:
std::function<void (const SDL_MouseButtonEvent&)> click_handler = nullptr;
public:
std::function<void(const SDL_MouseButtonEvent&)> click_handler = nullptr;
virtual void handle_mouse(const SDL_MouseButtonEvent&,
const SDL_Rect&) final;
virtual void handle_mouse(const SDL_MouseMotionEvent&,
const SDL_Rect&) final;
virtual void handle_mouse(const SDL_MouseButtonEvent&, const SDL_Rect&) final;
virtual void handle_mouse(const SDL_MouseMotionEvent&, const SDL_Rect&) final;
};
}

View File

@ -1,7 +1,8 @@
#ifndef BWIDGETS_TEXTURE_HANDLER_
#define BWIDGETS_TEXTURE_HANDLER_
namespace bwidgets::core {
namespace bwidgets::core
{
struct Renderer;
}
@ -9,11 +10,11 @@ namespace bwidgets::widget
{
class TextureHandler
{
protected:
virtual void _handle_texture_update() = 0;
protected:
virtual void _handle_texture_update() = 0;
public:
virtual ~TextureHandler() noexcept = default;
public:
virtual ~TextureHandler() noexcept = default;
};
}

View File

@ -7,11 +7,11 @@ namespace bwidgets::widget
{
class HorizontalLayout final : public Layout
{
private:
void _update_layout(const SDL_Rect&) noexcept override;
private:
void _update_layout(const SDL_Rect&) noexcept override;
public:
core::Size size() const noexcept override;
public:
core::Size size() const noexcept override;
};
}

View File

@ -2,115 +2,95 @@
#define BWIDGETS_NUMERIC_INPUT_HPP_
#include <limits>
#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>
#include <type_traits>
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()};
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(core::Font* f) override
{
_decrement_button.font(f);
_increment_button.font(f);
Input<T>::_handle_font_change(f);
}
virtual void _handle_font_color_change(const SDL_Color& fg,
const SDL_Color& bg) override
{
Input<T>::_handle_font_color_change(fg, bg);
_decrement_button.font_color_bg(bg)->font_color_fg(fg);
_increment_button.font_color_bg(bg)->font_color_fg(fg);
}
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) override
{
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)
virtual void _handle_font_change(core::Font* f) override
{
Input<T>::_input_caption.alignment =
widget::Caption::Alignment::RIGHT;
_decrement_button.font(f);
_increment_button.font(f);
Input<T>::_handle_font_change(f);
}
Input<T>::input_min_width = 10;
virtual void _handle_font_color_change(const SDL_Color& fg,
const SDL_Color& bg) override
{
Input<T>::_handle_font_color_change(fg, bg);
_decrement_button.font_color_bg(bg)->font_color_fg(fg);
_increment_button.font_color_bg(bg)->font_color_fg(fg);
}
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) override
{
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 = widget::Caption::Alignment::RIGHT;
Input<T>::input_min_width = 10;
Input<T>::input_width_unit = '0';
_increment_button.text("+");
@ -136,69 +116,59 @@ namespace bwidgets::widget
};
}
virtual Widget* handle_event(const SDL_Event& ev) override
{
Widget::handle_event(ev);
_increment_button.handle_event(ev);
_decrement_button.handle_event(ev);
return this;
}
virtual Widget* handle_event(const SDL_Event& ev) override
{
Widget::handle_event(ev);
_increment_button.handle_event(ev);
_decrement_button.handle_event(ev);
return this;
}
virtual bool is_valid_input(const std::string input) const noexcept override
{
bool valid = false;
virtual bool is_valid_input(const std::string input) const noexcept override
{
bool valid = false;
if (input.at(0) >= '0' && input.at(0) <= '9')
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_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) == '-' && displayed_value.empty())
valid = true;
}
return valid;
if constexpr (std::is_signed_v<T>) {
std::string displayed_value = Input<T>::input_text();
if (input.at(0) == '-' && displayed_value.empty()) 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;
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;
}
return value;
}
virtual inline core::Size size() const noexcept override
{
auto base = Input<T>::size();
auto btns_width = 4 * _increment_button.size().w;
return {
base.w + btns_width,
base.h
};
}
virtual inline core::Size size() const noexcept override
{
auto base = Input<T>::size();
auto btns_width = 4 * _increment_button.size().w;
return {base.w + btns_width, base.h};
}
virtual std::pair<T, T> value_range() const noexcept
{
return _value_range;
}
virtual std::pair<T, T> value_range() const noexcept
{
return _value_range;
}
virtual NumericInput<T>* value_range(T min, T max)
{
if (min > max)
throw std::invalid_argument("min cannot be greater than max");
_value_range = {min, max};
Input<T>::value = process_value(Input<T>::value);
Input<T>::input_text(Input<T>::value_to_string(Input<T>::value));
return this;
}
virtual NumericInput<T>* value_range(T min, T max)
{
if (min > max) throw std::invalid_argument("min cannot be greater than max");
_value_range = {min, max};
Input<T>::value = process_value(Input<T>::value);
Input<T>::input_text(Input<T>::value_to_string(Input<T>::value));
return this;
}
};
}

View File

@ -7,11 +7,11 @@ namespace bwidgets::widget
{
class VerticalLayout final : public Layout
{
private:
void _update_layout(const SDL_Rect&) noexcept override;
private:
void _update_layout(const SDL_Rect&) noexcept override;
public:
core::Size size() const noexcept override;
public:
core::Size size() const noexcept override;
};
}

View File

@ -10,56 +10,41 @@
namespace bwidgets::core
{
SDL_Color aa(
const SDL_Color& base_color,
const int aa_pixels,
const float d
)
noexcept
{
SDL_Color c {base_color};
if (aa_pixels == 0)
{
if (d > 0) c.a = 0;
}
else
{
const auto d_clamp {std::abs(std::clamp<float>(d, -aa_pixels, 0))};
const auto d_norm {d_clamp / aa_pixels};
const auto factor {3 * d_norm * d_norm - 2 * d_norm * d_norm * d_norm};
SDL_Color aa(const SDL_Color& base_color, const int aa_pixels,
const float d) noexcept
{
SDL_Color c {base_color};
if (aa_pixels == 0) {
if (d > 0) c.a = 0;
}
else {
const auto d_clamp {std::abs(std::clamp<float>(d, -aa_pixels, 0))};
const auto d_norm {d_clamp / aa_pixels};
const auto factor {3 * d_norm * d_norm - 2 * d_norm * d_norm * d_norm};
c.a *= factor;
}
return c;
c.a *= factor;
}
core::Texture* filled_circle(
const SDL_Color& c,
const int resolution,
core::Renderer* r,
const int aa_pixels
)
return c;
}
core::Texture* filled_circle(const SDL_Color& c, const int resolution,
core::Renderer* r, const int aa_pixels)
{
auto* texture {new core::Texture(r,
SDL_PIXELFORMAT_RGBA32,
SDL_TEXTUREACCESS_STATIC,
resolution, resolution)};
const auto radius {resolution / 2};
const SDL_Point center {radius, radius};
auto* texture {new core::Texture(
r, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, resolution, resolution)};
const auto radius {resolution / 2};
const SDL_Point center {radius, radius};
set_pixels_color(
texture,
[aa_pixels, c, center, 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);
texture,
[aa_pixels, c, center, 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,
aa_color.r, aa_color.g, aa_color.b,
aa_color.a);
}
);
return SDL_MapRGBA(format, aa_color.r, aa_color.g, aa_color.b, aa_color.a);
});
texture->blend_mode(SDL_BLENDMODE_BLEND);
texture->scale_mode(SDL_ScaleModeNearest);
@ -67,19 +52,16 @@ namespace bwidgets::core
}
void set_pixels_color(
core::Texture* t,
std::function<Uint32 (const SDL_Point&, const SDL_PixelFormat*)> pixel_color
)
core::Texture* t,
std::function<Uint32(const SDL_Point&, const SDL_PixelFormat*)> pixel_color)
{
auto attr = t->attributes();
auto attr = t->attributes();
auto pitch = attr.w * attr.format->BytesPerPixel;
std::vector<Uint32> pixels;
pixels.reserve(attr.h * pitch);
for (auto y = 0; y < attr.h; y++)
{
for (auto x = 0; x < attr.w; x++)
{
for (auto y = 0; y < attr.h; y++) {
for (auto x = 0; x < attr.w; x++) {
pixels.push_back(pixel_color({x, y}, attr.format));
}
}

View File

@ -11,18 +11,21 @@
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))
{
}
: 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(ptr_or_throw<FCError>(TTF_OpenFont(file.c_str(), size), __FILE__,
__FUNCTION__, __LINE__, "failed to open font"))
{}
Font::~Font()
{
@ -62,15 +65,13 @@ namespace bwidgets::core
return this;
}
SDL_Surface* Font::render(RenderMode m, const std::string& str,
const SDL_Color& fg,
SDL_Surface* Font::render(RenderMode m, const std::string& str, const SDL_Color& fg,
const SDL_Color& bg)
{
std::function<SDL_Surface* ()> renderer;
const char* c_str = str.empty() ? " " : str.c_str();
std::function<SDL_Surface*()> renderer;
const char* c_str = str.empty() ? " " : str.c_str();
switch (m)
{
switch (m) {
case RenderMode::BLENDED:
renderer = [&fg, c_str, this]() {
return TTF_RenderUTF8_Blended(c_pod, c_str, fg);
@ -113,10 +114,8 @@ namespace bwidgets::core
{
std::vector<std::any> ptrs;
auto clean = [&ptrs](int lvl) mutable
{
switch (lvl)
{
auto clean = [&ptrs](int lvl) mutable {
switch (lvl) {
case 2:
FcPatternDestroy(std::any_cast<FcPattern*>(ptrs.at(1)));
[[fallthrough]];
@ -126,22 +125,21 @@ namespace bwidgets::core
}
};
FcConfig* conf = ptr_or_throw<FCError>(FcInitLoadConfigAndFonts(),
__FILE__, __FUNCTION__, __LINE__, "init failed");
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");
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)
{
if (FcConfigSubstitute(conf, pattern, FcMatchPattern) == FcFalse)
throw FCError {__FILE__, __FUNCTION__, __LINE__,
"FcConfigSubstitute failed"};
} catch (const std::exception& e) {
clean(ptrs.size());
throw e;
}
@ -149,13 +147,11 @@ namespace bwidgets::core
FcDefaultSubstitute(pattern);
std::string file_path;
FcResult res;
FcPattern* font = FcFontMatch(conf, pattern, &res);
if (font != nullptr)
{
FcResult res;
FcPattern* font = FcFontMatch(conf, pattern, &res);
if (font != nullptr) {
FcChar8* file = nullptr;
if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch)
{
if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch) {
file_path = (char*)file;
}
FcPatternDestroy(font);

View File

@ -3,17 +3,12 @@
using namespace bwidgets;
core::Renderer::Renderer(SDL_Renderer* r)
: OpaqueStruct(r),
info(_info(r))
{
}
core::Renderer::Renderer(SDL_Renderer* r) : OpaqueStruct(r), info(_info(r)) {}
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__))
{
}
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__))
{}
core::Renderer::~Renderer()
{
@ -23,35 +18,32 @@ core::Renderer::~Renderer()
SDL_BlendMode core::Renderer::blend_mode()
{
SDL_BlendMode mode;
SDLError::success_or_throw(SDL_GetRenderDrawBlendMode(c_pod, &mode),
__FILE__, __FUNCTION__, __LINE__);
SDLError::success_or_throw(SDL_GetRenderDrawBlendMode(c_pod, &mode), __FILE__,
__FUNCTION__, __LINE__);
return mode;
}
core::Renderer* core::Renderer::blend_mode(SDL_BlendMode mode)
{
SDLError::success_or_throw(SDL_SetRenderDrawBlendMode(c_pod, mode),
__FILE__, __FUNCTION__, __LINE__);
SDLError::success_or_throw(SDL_SetRenderDrawBlendMode(c_pod, mode), __FILE__,
__FUNCTION__, __LINE__);
return this;
}
core::Renderer* core::Renderer::clear()
{
SDLError::success_or_throw(SDL_RenderClear(c_pod),
__FILE__, __FUNCTION__, __LINE__);
SDLError::success_or_throw(SDL_RenderClear(c_pod), __FILE__, __FUNCTION__, __LINE__);
return this;
}
core::Renderer* core::Renderer::copy(core::Texture* t,
const SDL_Rect* src, const SDL_Rect* dst)
core::Renderer* core::Renderer::copy(core::Texture* t, const SDL_Rect* src,
const SDL_Rect* dst)
{
SDLError::success_or_throw(
SDL_RenderCopy(c_pod, t->c_pod, src, dst),
__FILE__, __FUNCTION__, __LINE__
);
SDLError::success_or_throw(SDL_RenderCopy(c_pod, t->c_pod, src, dst), __FILE__,
__FUNCTION__, __LINE__);
return this;
}
@ -59,28 +51,24 @@ core::Renderer* core::Renderer::copy(core::Texture* t,
SDL_Color core::Renderer::draw_color()
{
SDL_Color c;
SDLError::success_or_throw(
SDL_GetRenderDrawColor(c_pod, &c.r, &c.g, &c.b, &c.a),
__FILE__, __FUNCTION__, __LINE__
);
SDLError::success_or_throw(SDL_GetRenderDrawColor(c_pod, &c.r, &c.g, &c.b, &c.a),
__FILE__, __FUNCTION__, __LINE__);
return 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__
);
SDLError::success_or_throw(SDL_SetRenderDrawColor(c_pod, c.r, c.g, c.b, c.a),
__FILE__, __FUNCTION__, __LINE__);
return this;
}
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__);
SDLError::success_or_throw(SDL_RenderDrawLine(c_pod, a.x, a.y, b.x, b.y), __FILE__,
__FUNCTION__, __LINE__);
return this;
}
@ -88,15 +76,15 @@ core::Renderer* core::Renderer::draw_line(const SDL_Point& a, const SDL_Point& b
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__);
__FILE__, __FUNCTION__, __LINE__);
return this;
}
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__);
SDLError::success_or_throw(SDL_RenderDrawPoint(c_pod, p.x, p.y), __FILE__,
__FUNCTION__, __LINE__);
return this;
}
@ -104,7 +92,7 @@ core::Renderer* core::Renderer::draw_point(const SDL_Point& p)
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__);
__FILE__, __FUNCTION__, __LINE__);
return this;
}
@ -115,15 +103,12 @@ core::Renderer* core::Renderer::draw_rect(const SDL_Rect* r)
// Has glitch at top-left and bottom-right corner.
// The first corner has an extra pixel at y-1 and surimpression.
// The second corner is missing a pixel.
if (r)
viewport({vp.x + r->x, vp.y + r->y, r->w - 1, r->h - 1}); // crop extra pixel
SDLError::success_or_throw(SDL_RenderDrawRect(c_pod, nullptr),
__FILE__, __FUNCTION__, __LINE__);
if (r) viewport({vp.x + r->x, vp.y + r->y, r->w - 1, r->h - 1}); // crop extra pixel
SDLError::success_or_throw(SDL_RenderDrawRect(c_pod, nullptr), __FILE__,
__FUNCTION__, __LINE__);
if (r)
draw_point({r->w - 1, r->h - 1}); // add missing pixel
else
draw_point({vp.w - 1, vp.h - 1});
if (r) draw_point({r->w - 1, r->h - 1}); // add missing pixel
else draw_point({vp.w - 1, vp.h - 1});
viewport(vp);
@ -133,15 +118,15 @@ core::Renderer* core::Renderer::draw_rect(const SDL_Rect* r)
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__);
__FILE__, __FUNCTION__, __LINE__);
return this;
}
core::Renderer* core::Renderer::fill_rect(const SDL_Rect* r)
{
SDLError::success_or_throw(SDL_RenderFillRect(c_pod, r),
__FILE__, __FUNCTION__, __LINE__);
SDLError::success_or_throw(SDL_RenderFillRect(c_pod, r), __FILE__, __FUNCTION__,
__LINE__);
return this;
}
@ -149,7 +134,7 @@ core::Renderer* core::Renderer::fill_rect(const SDL_Rect* r)
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__);
__FILE__, __FUNCTION__, __LINE__);
return this;
}
@ -157,8 +142,8 @@ core::Renderer* core::Renderer::fill_rects(const std::vector<SDL_Rect> rs)
core::Size core::Renderer::output_size()
{
Size s;
SDLError::success_or_throw(SDL_GetRendererOutputSize(c_pod, &s.w, &s.h),
__FILE__, __FUNCTION__, __LINE__);
SDLError::success_or_throw(SDL_GetRendererOutputSize(c_pod, &s.w, &s.h), __FILE__,
__FUNCTION__, __LINE__);
return s;
}
@ -178,8 +163,8 @@ SDL_Rect core::Renderer::viewport()
core::Renderer* core::Renderer::viewport(const SDL_Rect* vp)
{
SDLError::success_or_throw(SDL_RenderSetViewport(c_pod, vp),
__FILE__, __FUNCTION__, __LINE__);
SDLError::success_or_throw(SDL_RenderSetViewport(c_pod, vp), __FILE__, __FUNCTION__,
__LINE__);
return this;
}

View File

@ -3,26 +3,20 @@
using namespace bwidgets;
core::Texture::Texture(SDL_Texture* t)
: OpaqueStruct(t)
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_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__))
: OpaqueStruct(ptr_or_throw<SDLError>(SDL_CreateTextureFromSurface(r->c_pod, s),
__FILE__, __FUNCTION__, __LINE__))
{
_attributes = attributes(c_pod);
}
@ -36,16 +30,16 @@ core::Texture::~Texture() noexcept
uint8_t core::Texture::alpha_mode()
{
uint8_t mode;
SDLError::success_or_throw(SDL_GetTextureAlphaMod(c_pod, &mode),
__FILE__, __FUNCTION__, __LINE__);
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__);
SDLError::success_or_throw(SDL_SetTextureAlphaMod(c_pod, m), __FILE__, __FUNCTION__,
__LINE__);
return this;
}
@ -53,16 +47,16 @@ core::Texture* core::Texture::alpha_mode(uint8_t m)
SDL_BlendMode core::Texture::blend_mode()
{
SDL_BlendMode mode;
SDLError::success_or_throw(SDL_GetTextureBlendMode(c_pod, &mode),
__FILE__, __FUNCTION__, __LINE__);
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__);
SDLError::success_or_throw(SDL_SetTextureBlendMode(c_pod, m), __FILE__, __FUNCTION__,
__LINE__);
return this;
}
@ -70,18 +64,16 @@ core::Texture* core::Texture::blend_mode(SDL_BlendMode m)
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__
);
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__);
SDLError::success_or_throw(SDL_SetTextureColorMod(c_pod, m.r, m.g, m.b), __FILE__,
__FUNCTION__, __LINE__);
return this;
}
@ -89,24 +81,24 @@ core::Texture* core::Texture::color_mode(const SDL_Color& m)
SDL_ScaleMode core::Texture::scale_mode()
{
SDL_ScaleMode mode;
SDLError::success_or_throw(SDL_GetTextureScaleMode(c_pod, &mode),
__FILE__, __FUNCTION__, __LINE__);
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__);
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__);
SDLError::success_or_throw(SDL_UpdateTexture(c_pod, r, pixels, pitch), __FILE__,
__FUNCTION__, __LINE__);
return this;
}

View File

@ -4,27 +4,24 @@ using namespace bwidgets;
widget::Layout::~Layout() noexcept
{
for (Widget* widget_ptr : _widgets)
delete widget_ptr;
for (Widget* widget_ptr : _widgets) delete widget_ptr;
}
widget::Layout* widget::Layout::add_widget(Widget *widget_ptr)
widget::Layout* widget::Layout::add_widget(Widget* widget_ptr)
{
widget_ptr->renderer(_renderer);
_widgets.push_back(widget_ptr);
return this;
}
void widget::Layout::for_widgets(std::function<void (Widget*)> f)
void widget::Layout::for_widgets(std::function<void(Widget*)> f)
{
for (auto* w : _widgets)
f(w);
for (auto* w : _widgets) f(w);
}
widget::Layout* widget::Layout::handle_event(const SDL_Event& ev)
{
for (Widget* widget_ptr : _widgets)
widget_ptr->handle_event(ev);
for (Widget* widget_ptr : _widgets) widget_ptr->handle_event(ev);
return this;
}
@ -35,12 +32,10 @@ void widget::Layout::_handle_geometry_change(const SDL_Rect& vp) noexcept
void widget::Layout::_handle_renderer_change(core::Renderer* r)
{
for (auto* w : _widgets)
w->renderer(r);
for (auto* w : _widgets) w->renderer(r);
}
void widget::Layout::_handle_rendering()
{
for (Widget* widget_ptr : _widgets)
widget_ptr->render();
for (Widget* widget_ptr : _widgets) widget_ptr->render();
}

View File

@ -1,19 +1,16 @@
#include <SDL2/SDL_assert.h>
#include <SDL2/SDL_events.h>
#include <basic_widgets/w/base/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;
widget::Widget* widget::Widget::handle_event(const SDL_Event &ev)
widget::Widget* widget::Widget::handle_event(const SDL_Event& ev)
{
if (auto handler = dynamic_cast<KeyboardHandler*>(this);
handler != nullptr)
{
switch (ev.type)
{
if (auto handler = dynamic_cast<KeyboardHandler*>(this); handler != nullptr) {
switch (ev.type) {
case SDL_KEYDOWN:
case SDL_KEYUP:
handler->handle_keyboard(ev.key);
@ -24,11 +21,8 @@ widget::Widget* widget::Widget::handle_event(const SDL_Event &ev)
}
}
if (auto handler = dynamic_cast<MouseHandler*>(this);
handler != nullptr)
{
switch (ev.type)
{
if (auto handler = dynamic_cast<MouseHandler*>(this); handler != nullptr) {
switch (ev.type) {
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
handler->handle_mouse(ev.button, _viewport);
@ -45,12 +39,10 @@ widget::Widget* widget::Widget::handle_event(const SDL_Event &ev)
widget::Widget* widget::Widget::render()
{
SDL_assert_release(_renderer);
if (!_renderer)
return this;
if (!_renderer) return this;
#ifdef _NDEBUG
_renderer->draw_color({0, 255, 0, SDL_ALPHA_TRANSPARENT})
->draw_rect(nullptr);
_renderer->draw_color({0, 255, 0, SDL_ALPHA_TRANSPARENT})->draw_rect(nullptr);
#endif
_renderer->viewport(_viewport);

View File

@ -1,24 +1,20 @@
#include <SDL2/SDL_render.h>
#include <basic_widgets/w/button.hpp>
#include <basic_widgets/core/math.hpp>
#include <basic_widgets/w/button.hpp>
using namespace bwidgets;
widget::Button::Button(Widget* parent)
: Widget(parent),
_caption(this)
widget::Button::Button(Widget* parent) : Widget(parent), _caption(this)
{
_focus_area = _click_area = &_widget_area;
_caption.alignment = Caption::Alignment::CENTER;
_caption.alignment = Caption::Alignment::CENTER;
}
core::Size widget::Button::size() const noexcept
{
return {
_caption.size().w + 2 * border_size.w,
_caption.size().h + 2 * border_size.h
};
return {_caption.size().w + 2 * border_size.w,
_caption.size().h + 2 * border_size.h};
}
const std::string& widget::Button::text() const noexcept
@ -48,21 +44,13 @@ void widget::Button::_handle_geometry_change(const SDL_Rect& vp) noexcept
{
int h = _caption.size().h + 2 * border_size.h;
_widget_area = {
0,
core::center_rect(vp.h, _caption.size().h) - border_size.h,
vp.w,
h
};
_widget_area = {0, core::center_rect(vp.h, _caption.size().h) - border_size.h, vp.w,
h};
auto txt_size = _caption.size();
_caption_area = {
core::center_rect(vp.w, txt_size.w),
core::center_rect(vp.h, txt_size.h),
txt_size.w,
txt_size.h
};
_caption_area = {core::center_rect(vp.w, txt_size.w),
core::center_rect(vp.h, txt_size.h), txt_size.w, txt_size.h};
_caption.viewport(core::rect_offset(_caption_area, vp));
}
@ -80,55 +68,37 @@ void widget::Button::_handle_rendering()
};
SDL_Color c = _is_hovered ? color_bg_hover : color_bg;
if (_is_pushed)
{
if (_is_pushed) {
auto x = 0, y = 0;
auto biggest = border_size.w > border_size.h ? border_size.w : border_size.h;
while (x < border_size.w || y < border_size.h)
{
while (x < border_size.w || y < border_size.h) {
auto max = x > y ? x : y;
_renderer->draw_color({
color_shade(c.r, max, biggest),
color_shade(c.g, max, biggest),
color_shade(c.b, max, biggest),
c.a
})
->draw_rect({
_widget_area.x + x,
_widget_area.y + y,
_widget_area.w - x * 2,
_widget_area.h - y * 2
});
if (x < border_size.w)
x++;
if (y < border_size.h)
y++;
_renderer
->draw_color({color_shade(c.r, max, biggest),
color_shade(c.g, max, biggest),
color_shade(c.b, max, biggest), c.a})
->draw_rect({_widget_area.x + x, _widget_area.y + y,
_widget_area.w - x * 2, _widget_area.h - y * 2});
if (x < border_size.w) x++;
if (y < border_size.h) y++;
}
}
else
{
else {
auto x = 0, y = 0;
auto biggest = border_size.w > border_size.h ? border_size.w : border_size.h;
while (x < border_size.w || y < border_size.h)
{
auto max = x > y ? x : y;
while (x < border_size.w || y < border_size.h) {
auto max = x > y ? x : y;
core::Size margin = border_size - core::Size({x, y});
_renderer->draw_color({
color_shade(c.r, max, biggest),
color_shade(c.g, max, biggest),
color_shade(c.b, max, biggest),
c.a
})
->draw_rect(core::rect_margin(_widget_area, margin));
if (x < border_size.w)
x++;
if (y < border_size.h)
y++;
_renderer
->draw_color({color_shade(c.r, max, biggest),
color_shade(c.g, max, biggest),
color_shade(c.b, max, biggest), c.a})
->draw_rect(core::rect_margin(_widget_area, margin));
if (x < border_size.w) x++;
if (y < border_size.h) y++;
}
}
_renderer->draw_color(c)->fill_rect(
core::rect_margin(_widget_area, border_size)
);
_renderer->draw_color(c)->fill_rect(core::rect_margin(_widget_area, border_size));
_caption.color_bg(c)->render();
}

View File

@ -34,8 +34,7 @@ widget::Caption* widget::Caption::render_mode(core::Font::RenderMode m) noexcept
core::Size widget::Caption::size() const noexcept
{
if (_font == nullptr)
return {-1, -1};
if (_font == nullptr) return {-1, -1};
core::Size size = _font->text_size(_text);
@ -66,8 +65,8 @@ static inline bool operator!=(const SDL_Color& a, const SDL_Color& b)
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))
if (fg != _font_color_fg
|| (bg != _font_color_bg && _font_render_mode == core::Font::RenderMode::SHADED))
{
core::discard(_text_texture);
}
@ -75,8 +74,7 @@ void widget::Caption::_handle_font_color_change(const SDL_Color& fg, const SDL_C
void widget::Caption::_handle_geometry_change(const SDL_Rect& vp) noexcept
{
if (vp.w != _viewport.w || vp.h != _viewport.h)
{
if (vp.w != _viewport.w || vp.h != _viewport.h) {
_widget_area = core::rect_margin({0, 0, vp.w, vp.h}, margins);
}
}
@ -88,31 +86,21 @@ void widget::Caption::_handle_renderer_change(core::Renderer*)
void widget::Caption::_handle_rendering()
{
if (!_text_texture)
_handle_texture_update();
if (!_text_texture) _handle_texture_update();
if (_render_mode == core::Font::RenderMode::SHADED)
_renderer->draw_color(_color_bg)->fill_rect({0, 0, _viewport.w, _viewport.h});
if (!_text_texture)
_handle_texture_update();
if (!_text_texture) _handle_texture_update();
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,
margins.h,
size_dst.w,
size_dst.h
};
switch (alignment)
{
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, margins.h, size_dst.w, size_dst.h};
switch (alignment) {
case Alignment::CENTER:
texture_dst.x = core::center_rect(_widget_area.w, texture_dst.w)
+ _widget_area.x;
texture_dst.x =
core::center_rect(_widget_area.w, texture_dst.w) + _widget_area.x;
break;
case Alignment::LEFT:
break;
@ -128,14 +116,13 @@ void widget::Caption::_handle_texture_update()
SDL_assert_release(_font);
core::discard(_text_texture);
SDL_Surface* s;
switch (_render_mode)
{
switch (_render_mode) {
case core::Font::RenderMode::SHADED:
s = _font->render(_render_mode, _text, _color_fg, _color_bg);
break;
s = _font->render(_render_mode, _text, _color_fg, _color_bg);
break;
default:
s = _font->render(_render_mode, _text, _color_fg);
break;
s = _font->render(_render_mode, _text, _color_fg);
break;
}
_text_texture = new core::Texture(_renderer, s);
SDL_FreeSurface(s);

View File

@ -1,40 +1,32 @@
#include <SDL2/SDL_rect.h>
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_rect.h>
#include <basic_widgets/w/feat/mouse_handler.hpp>
#include <basic_widgets/core/math.hpp>
#include <basic_widgets/w/feat/mouse_handler.hpp>
using namespace bwidgets;
void widget::MouseHandler::handle_mouse(const SDL_MouseButtonEvent& ev,
const SDL_Rect& orig)
const SDL_Rect& orig)
{
if (_click_area == nullptr)
return;
if (_click_area == nullptr) return;
SDL_Point p {ev.x, ev.y};
SDL_Rect vp {core::rect_offset(*_click_area, orig)};
SDL_Rect vp {core::rect_offset(*_click_area, orig)};
if (ev.type == SDL_MOUSEBUTTONDOWN)
{
if (SDL_PointInRect(&p, &vp))
{
if (ev.type == SDL_MOUSEBUTTONDOWN) {
if (SDL_PointInRect(&p, &vp)) {
_is_pushed = true;
_handle_mouse_button(ev, vp);
}
else
focus(false);
else focus(false);
}
else
{
if (_is_pushed)
{
if (SDL_PointInRect(&p, &vp))
{
else {
if (_is_pushed) {
if (SDL_PointInRect(&p, &vp)) {
focus(true);
if (click_handler != nullptr)
click_handler(ev);
if (click_handler != nullptr) click_handler(ev);
}
_is_pushed = false;
_handle_mouse_button(ev, vp);
@ -43,19 +35,15 @@ void widget::MouseHandler::handle_mouse(const SDL_MouseButtonEvent& ev,
}
void widget::MouseHandler::handle_mouse(const SDL_MouseMotionEvent& ev,
const SDL_Rect& orig)
const SDL_Rect& orig)
{
if (_click_area == nullptr)
return;
if (_click_area == nullptr) return;
SDL_Point p {ev.x, ev.y};
SDL_Rect vp {core::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 (SDL_PointInRect(&p, &vp)) _is_hovered = true;
else _is_hovered = false;
if (_is_hovered)
_handle_mouse_motion(ev, orig);
if (_is_hovered) _handle_mouse_motion(ev, orig);
}

View File

@ -7,33 +7,23 @@ core::Size widget::HorizontalLayout::size() const noexcept
{
core::Size max {0, 0};
for (const auto* w : _widgets)
{
if (w->size().w > max.w)
max.w = w->size().w;
if (w->size().h > max.h)
max.h = w->size().h;
for (const auto* w : _widgets) {
if (w->size().w > max.w) max.w = w->size().w;
if (w->size().h > max.h) max.h = w->size().h;
}
return {
(int)_widgets.size() * max.w + ((int)_widgets.size() + 1) * margins.w,
max.h + 2 * margins.h
};
return {(int)_widgets.size() * max.w + ((int)_widgets.size() + 1) * margins.w,
max.h + 2 * margins.h};
}
void widget::HorizontalLayout::_update_layout(const SDL_Rect& vp) noexcept
{
int widget_size = (vp.w - (_widgets.size() + 1) * margins.w)
/ _widgets.size();
int widget_size = (vp.w - (_widgets.size() + 1) * margins.w) / _widgets.size();
for (std::vector<Widget*>::size_type i = 0; i < _widgets.size(); i++)
{
for (std::vector<Widget*>::size_type i = 0; i < _widgets.size(); i++) {
auto* w = _widgets[i];
w->viewport({
vp.x + margins.w + (int)i * (widget_size + margins.w),
vp.y + core::center_rect(vp.h, w->size().h),
widget_size,
w->size().h
});
w->viewport({vp.x + margins.w + (int)i * (widget_size + margins.w),
vp.y + core::center_rect(vp.h, w->size().h), widget_size,
w->size().h});
}
}

View File

@ -7,31 +7,25 @@ core::Size widget::VerticalLayout::size() const noexcept
{
core::Size size {0, 0};
for (const auto* w : _widgets)
{
if (w->size().w > size.w)
size.w = w->size().w;
for (const auto* w : _widgets) {
if (w->size().w > size.w) size.w = w->size().w;
size.h += w->size().h;
}
return {
size.w + 2 * margins.w,
size.h + ((int)_widgets.size() + 1) * margins.h
};
return {size.w + 2 * margins.w, size.h + ((int)_widgets.size() + 1) * margins.h};
}
void widget::VerticalLayout::_update_layout(const SDL_Rect& vp) noexcept
{
int offset = 0;
for (std::vector<Widget*>::size_type i = 0; i < _widgets.size(); i++)
{
for (std::vector<Widget*>::size_type i = 0; i < _widgets.size(); i++) {
auto* w = _widgets[i];
w->viewport({
vp.x,
vp.y + ((int)i + 1) * margins.h + offset,
vp.w,
w->size().h,
vp.x,
vp.y + ((int)i + 1) * margins.h + offset,
vp.w,
w->size().h,
});
offset += w->size().h;
}