rewrite how events are held
This commit is contained in:
parent
07f7061c20
commit
c07dbfe8ff
24 changed files with 441 additions and 248 deletions
|
@ -34,11 +34,11 @@ EmptyLineBeforeAccessModifier: Always
|
|||
FixNamespaceComments: false
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '<[[:alnum:].]+>'
|
||||
- Regex: '<[[:alnum:]._]+>'
|
||||
Priority: -10
|
||||
- Regex: '^<fontconfig/'
|
||||
- Regex: '^<fontconfig'
|
||||
Priority: -5
|
||||
- Regex: '^<SDL2/'
|
||||
- Regex: '^<SDL'
|
||||
Priority: -5
|
||||
- Regex: '^<basic_widgets/'
|
||||
Priority: 0
|
||||
|
|
|
@ -9,9 +9,9 @@ using bwidgets::Button;
|
|||
auto main() -> int
|
||||
{
|
||||
run_example<Button>([](auto w, auto f, auto x, auto y) {
|
||||
w->click_handler = [x, y](const SDL_MouseButtonEvent&) {
|
||||
w->click_handler([x, y](const SDL_MouseButtonEvent&) {
|
||||
std::cout << "button(" << x << ',' << y << "):click!" << std::endl;
|
||||
};
|
||||
});
|
||||
w->font(f);
|
||||
w->text("+");
|
||||
});
|
||||
|
|
45
inc/basic_widgets/impl/mouse_handler_impl.hpp
Normal file
45
inc/basic_widgets/impl/mouse_handler_impl.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef BWIDGETS_MOUSE_HANDLER_IMPL_HPP
|
||||
#define BWIDGETS_MOUSE_HANDLER_IMPL_HPP
|
||||
|
||||
#include <basic_widgets/w/feat/mouse_handler.hpp>
|
||||
|
||||
namespace bwidgets
|
||||
{
|
||||
class MouseHandlerImpl : public MouseHandler
|
||||
{
|
||||
private:
|
||||
const SDL_Rect* _area {nullptr};
|
||||
bool _hovered {false};
|
||||
bool _pushed {false};
|
||||
|
||||
std::function<void(const SDL_MouseButtonEvent&)> _click_handler;
|
||||
std::function<void(const SDL_MouseMotionEvent&)> _motion_handler;
|
||||
|
||||
protected:
|
||||
MouseHandlerImpl() = default;
|
||||
|
||||
public:
|
||||
void
|
||||
click_handler(std::function<void(const SDL_MouseButtonEvent&)> handler) override
|
||||
{
|
||||
_click_handler = std::move(handler);
|
||||
}
|
||||
void disable_mouse_handler() override;
|
||||
void enable_mouse_handler(const SDL_Rect*) override;
|
||||
[[nodiscard]] bool hovered() const override
|
||||
{
|
||||
return _hovered;
|
||||
}
|
||||
void mouse_motion_handler(
|
||||
std::function<void(const SDL_MouseMotionEvent&)> handler) override
|
||||
{
|
||||
_motion_handler = std::move(handler);
|
||||
}
|
||||
[[nodiscard]] bool pushed() const override
|
||||
{
|
||||
return _pushed;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -13,8 +13,8 @@
|
|||
#include <basic_widgets/core/math.hpp>
|
||||
#include <basic_widgets/core/type/concepts.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/w/feat/keyboard_handler_impl.hpp>
|
||||
#include <basic_widgets/w/feat/mouse_handler_impl.hpp>
|
||||
|
||||
namespace bwidgets
|
||||
{
|
||||
|
@ -22,29 +22,57 @@ namespace bwidgets
|
|||
template<typename T>
|
||||
class Input : public Widget,
|
||||
public FontHandler,
|
||||
public KeyboardHandler,
|
||||
public MouseHandler
|
||||
public KeyboardHandlerImpl,
|
||||
public MouseHandlerImpl
|
||||
{
|
||||
protected:
|
||||
Caption _input_caption;
|
||||
|
||||
Input(Widget* parent = nullptr) : Widget {parent}, _input_caption {this}
|
||||
{
|
||||
FocusHandler::_focus_area = &_widget_area;
|
||||
MouseHandler::_click_area = &_widget_area;
|
||||
_input_caption.text(value_to_string(value));
|
||||
}
|
||||
FocusHandlerImpl::focus_handler([this](bool focus) {
|
||||
if (focus) {
|
||||
SDL_StartTextInput();
|
||||
}
|
||||
// focus loss.
|
||||
else if (FocusHandlerImpl::focus()) {
|
||||
value = value_from_string(input_text());
|
||||
input_text(value_to_string(value));
|
||||
SDL_StopTextInput();
|
||||
_input_caption.text(value_to_string(value));
|
||||
}
|
||||
});
|
||||
|
||||
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();
|
||||
}
|
||||
KeyboardHandlerImpl::key_handler([this](const SDL_KeyboardEvent& key) {
|
||||
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());
|
||||
FocusHandlerImpl::focus(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
KeyboardHandlerImpl::text_input_handler(
|
||||
[this](const SDL_TextInputEvent& input) {
|
||||
if (is_valid_input(input.text)) {
|
||||
input_text(input_text() + input.text);
|
||||
}
|
||||
});
|
||||
KeyboardHandlerImpl::enable_keyboard_handler();
|
||||
|
||||
MouseHandlerImpl::enable_mouse_handler(&(Input::_widget_area),
|
||||
&(Input::_viewport));
|
||||
}
|
||||
|
||||
void _handle_font_change(const std::shared_ptr<Font>& f) override
|
||||
|
@ -67,28 +95,6 @@ namespace bwidgets
|
|||
{rect_margin(_widget_area, {border_width, border_width})}, vp));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _handle_renderer_change(const std::shared_ptr<Renderer>& r) override
|
||||
{
|
||||
_input_caption.renderer(r);
|
||||
|
@ -97,27 +103,21 @@ namespace bwidgets
|
|||
void _handle_rendering() override
|
||||
{
|
||||
for (int i = border_width - 1; i >= 0; i--) {
|
||||
const auto factor = linear(i, 0, border_width);
|
||||
const auto& color_end = _has_focus ? color_bg_focused : color_bg;
|
||||
const auto color_start = color_end / 2;
|
||||
const auto factor = linear(i, 0, border_width);
|
||||
const auto& color_end =
|
||||
FocusHandlerImpl::focus() ? color_bg_focused : color_bg;
|
||||
const auto color_start = color_end / 2;
|
||||
_renderer->draw_color(lerp(color_start, color_end, factor))
|
||||
->draw_rect(rect_margin(_widget_area, {i, i}));
|
||||
}
|
||||
|
||||
if (MouseHandler::_is_hovered || FocusHandler::_has_focus)
|
||||
if (hovered() || FocusHandlerImpl::focus())
|
||||
_input_caption.font_color_bg(color_bg_focused);
|
||||
else _input_caption.font_color_bg(color_bg);
|
||||
|
||||
_input_caption.render();
|
||||
}
|
||||
|
||||
void _handle_text_input(const SDL_TextInputEvent& input) override
|
||||
{
|
||||
if (is_valid_input(input.text)) {
|
||||
input_text(input_text() + input.text);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static const int default_border_width = 3;
|
||||
inline static const Color default_color_bg = {200, 200, 200, SDL_ALPHA_OPAQUE};
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace bwidgets
|
|||
auto operator=(const Layout&) = delete;
|
||||
auto operator=(Layout&&) = delete;
|
||||
|
||||
auto handle_event(const SDL_Event&) -> Layout* override;
|
||||
void handle_event(const SDL_Event&) override;
|
||||
[[nodiscard]] auto size() const noexcept -> Size override = 0;
|
||||
|
||||
virtual auto add_widget(std::unique_ptr<Widget>) -> Layout*;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <basic_widgets/core/renderer.hpp>
|
||||
#include <basic_widgets/core/type/size.hpp>
|
||||
#include <basic_widgets/w/feat/event_handler_impl.hpp>
|
||||
|
||||
union SDL_Event;
|
||||
|
||||
|
@ -12,15 +13,13 @@ struct SDL_Renderer;
|
|||
|
||||
namespace bwidgets
|
||||
{
|
||||
class Widget
|
||||
class Widget : public virtual EventHandlerImpl
|
||||
{
|
||||
protected:
|
||||
std::shared_ptr<Renderer> _renderer;
|
||||
SDL_Rect _viewport {0, 0, 0, 0};
|
||||
SDL_Rect _widget_area {0, 0, 0, 0};
|
||||
|
||||
explicit Widget(Widget* p = nullptr) noexcept : parent {p} {}
|
||||
|
||||
virtual void _handle_geometry_change(const SDL_Rect&) = 0;
|
||||
virtual void _handle_renderer_change(const std::shared_ptr<Renderer>&) {}
|
||||
virtual void _handle_rendering() = 0;
|
||||
|
@ -28,14 +27,8 @@ namespace bwidgets
|
|||
public:
|
||||
Widget* parent;
|
||||
|
||||
Widget(const Widget&) noexcept = default;
|
||||
Widget(Widget&&) noexcept = default;
|
||||
virtual ~Widget() noexcept = default;
|
||||
explicit Widget(Widget* p = nullptr) noexcept : parent {p} {}
|
||||
|
||||
auto operator=(const Widget&) = delete;
|
||||
auto operator=(Widget&&) = delete;
|
||||
|
||||
virtual auto handle_event(const SDL_Event&) -> Widget*;
|
||||
[[nodiscard]] virtual auto size() const noexcept -> Size = 0;
|
||||
|
||||
virtual auto render() -> Widget* final;
|
||||
|
|
|
@ -6,20 +6,19 @@
|
|||
|
||||
#include <basic_widgets/core/type/color.hpp>
|
||||
#include <basic_widgets/w/caption.hpp>
|
||||
#include <basic_widgets/w/feat/mouse_handler.hpp>
|
||||
#include <basic_widgets/w/feat/mouse_handler_impl.hpp>
|
||||
|
||||
namespace bwidgets
|
||||
{
|
||||
class Button : public Widget,
|
||||
public FontHandler,
|
||||
public MouseHandler
|
||||
class Button : public virtual Widget,
|
||||
public virtual FontHandler,
|
||||
public virtual MouseHandlerImpl
|
||||
{
|
||||
protected:
|
||||
Caption _caption;
|
||||
SDL_Rect _caption_area {};
|
||||
Color _color_foreground = default_color_fg;
|
||||
|
||||
void _handle_focus_change(bool) override {}
|
||||
void _handle_font_change(const std::shared_ptr<Font>&) override;
|
||||
void _handle_font_color_change(Color, Color)
|
||||
override;
|
||||
|
@ -38,6 +37,10 @@ namespace bwidgets
|
|||
Color color_bg = default_color_bg;
|
||||
Color color_bg_hover = default_color_bg_hover;
|
||||
|
||||
using EventHandlerImpl::handle_event;
|
||||
using FocusHandlerImpl::focus;
|
||||
using FocusHandlerImpl::focus_handler;
|
||||
|
||||
Button(Widget* parent = nullptr) noexcept;
|
||||
Button(const Button&) = delete;
|
||||
Button(Button&&) = delete;
|
||||
|
|
32
inc/basic_widgets/w/feat/event_handler.hpp
Normal file
32
inc/basic_widgets/w/feat/event_handler.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef BWIDGETS_EVENT_HANDLER_HPP
|
||||
#define BWIDGETS_EVENT_HANDLER_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include <SDL_events.h>
|
||||
|
||||
namespace bwidgets
|
||||
{
|
||||
class EventHandler
|
||||
{
|
||||
public:
|
||||
using handler_t =
|
||||
std::pair<SDL_EventType, std::function<void(const SDL_Event&)>>;
|
||||
|
||||
protected:
|
||||
EventHandler() = default;
|
||||
|
||||
public:
|
||||
EventHandler(const EventHandler&) = delete;
|
||||
EventHandler(EventHandler&&) = delete;
|
||||
auto operator=(const EventHandler&) -> EventHandler& = delete;
|
||||
auto operator=(EventHandler&&) -> EventHandler& = delete;
|
||||
|
||||
virtual ~EventHandler() = default;
|
||||
|
||||
virtual void handle_event(const SDL_Event&) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
24
inc/basic_widgets/w/feat/event_handler_impl.hpp
Normal file
24
inc/basic_widgets/w/feat/event_handler_impl.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef BWIDGETS_EVENT_HANDLER_IMPL_HPP
|
||||
#define BWIDGETS_EVENT_HANDLER_IMPL_HPP
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <basic_widgets/w/feat/event_handler.hpp>
|
||||
|
||||
namespace bwidgets
|
||||
{
|
||||
class EventHandlerImpl : public virtual EventHandler
|
||||
{
|
||||
std::unordered_map<SDL_EventType, std::function<void(const SDL_Event&)>>
|
||||
_event_handlers {};
|
||||
|
||||
protected:
|
||||
auto _add_event_handler(handler_t) -> bool;
|
||||
auto _remove_event_handler(SDL_EventType) -> std::pair<handler_t, bool>;
|
||||
|
||||
public:
|
||||
void handle_event(const SDL_Event&) override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,32 +1,25 @@
|
|||
#ifndef BWIDGETS_FOCUS_HANDLER_HPP
|
||||
#define BWIDGETS_FOCUS_HANDLER_HPP
|
||||
|
||||
#include <functional>
|
||||
|
||||
struct SDL_Rect;
|
||||
|
||||
namespace bwidgets
|
||||
{
|
||||
class FocusHandler
|
||||
{
|
||||
protected:
|
||||
const SDL_Rect* _focus_area = nullptr;
|
||||
bool _has_focus = false;
|
||||
|
||||
virtual void _handle_focus_change(bool) = 0;
|
||||
|
||||
public:
|
||||
FocusHandler() = default;
|
||||
FocusHandler(const FocusHandler&) = delete;
|
||||
FocusHandler(FocusHandler&&) = delete;
|
||||
virtual ~FocusHandler() = default;
|
||||
|
||||
auto operator=(FocusHandler&&) = delete;
|
||||
auto operator=(const FocusHandler&) = delete;
|
||||
|
||||
virtual void focus(bool focus) final
|
||||
{
|
||||
_handle_focus_change(focus);
|
||||
_has_focus = focus;
|
||||
}
|
||||
virtual ~FocusHandler() = default;
|
||||
virtual void focus(bool focus) = 0;
|
||||
virtual bool focus() = 0;
|
||||
virtual void focus_handler(std::function<void(bool)>) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
32
inc/basic_widgets/w/feat/focus_handler_impl.hpp
Normal file
32
inc/basic_widgets/w/feat/focus_handler_impl.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef BWIDGETS_FOCUS_HANDLER_IMPL_HPP
|
||||
#define BWIDGETS_FOCUS_HANDLER_IMPL_HPP
|
||||
|
||||
#include <basic_widgets/w/feat/focus_handler.hpp>
|
||||
|
||||
namespace bwidgets
|
||||
{
|
||||
class FocusHandlerImpl : public virtual FocusHandler
|
||||
{
|
||||
bool _has_focus {false};
|
||||
std::function<void(bool)> _focus_handler {[](auto) {}};
|
||||
|
||||
public:
|
||||
void focus(bool focus_) override
|
||||
{
|
||||
_focus_handler(focus_);
|
||||
_has_focus = focus_;
|
||||
}
|
||||
|
||||
bool focus() override
|
||||
{
|
||||
return _has_focus;
|
||||
}
|
||||
|
||||
void focus_handler(decltype(_focus_handler) handler) final
|
||||
{
|
||||
_focus_handler = std::move(handler);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef BWIDGETS_KEYBOARD_HANDLER
|
||||
#define BWIDGETS_KEYBOARD_HANDLER
|
||||
#ifndef BWIDGETS_KEYBOARD_HANDLER_HPP
|
||||
#define BWIDGETS_KEYBOARD_HANDLER_HPP
|
||||
|
||||
#include <basic_widgets/w/feat/event_handler.hpp>
|
||||
#include <basic_widgets/w/feat/focus_handler.hpp>
|
||||
|
||||
struct SDL_KeyboardEvent;
|
||||
|
@ -8,34 +9,18 @@ struct SDL_TextInputEvent;
|
|||
|
||||
namespace bwidgets
|
||||
{
|
||||
class KeyboardHandler : public virtual FocusHandler
|
||||
class KeyboardHandler : public virtual EventHandler,
|
||||
public virtual FocusHandler
|
||||
{
|
||||
protected:
|
||||
virtual void _handle_key(const SDL_KeyboardEvent&) = 0;
|
||||
virtual void _handle_text_input(const SDL_TextInputEvent&) = 0;
|
||||
using EventHandler::EventHandler;
|
||||
|
||||
public:
|
||||
using FocusHandler::FocusHandler;
|
||||
|
||||
KeyboardHandler(const KeyboardHandler&) = delete;
|
||||
KeyboardHandler(KeyboardHandler&&) = delete;
|
||||
~KeyboardHandler() override = default;
|
||||
auto operator=(const KeyboardHandler&) = delete;
|
||||
auto operator=(KeyboardHandler&&) = delete;
|
||||
|
||||
virtual auto handle_keyboard(const SDL_KeyboardEvent& ev)
|
||||
-> KeyboardHandler* final
|
||||
{
|
||||
if (_has_focus) _handle_key(ev);
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual auto handle_keyboard(const SDL_TextInputEvent& ev)
|
||||
-> KeyboardHandler* final
|
||||
{
|
||||
if (_has_focus) _handle_text_input(ev);
|
||||
return this;
|
||||
}
|
||||
virtual void disable_keyboard_handler() = 0;
|
||||
virtual void enable_keyboard_handler() = 0;
|
||||
virtual void key_handler(std::function<void(const SDL_KeyboardEvent&)>) = 0;
|
||||
virtual void
|
||||
text_input_handler(std::function<void(const SDL_TextInputEvent&)>) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
31
inc/basic_widgets/w/feat/keyboard_handler_impl.hpp
Normal file
31
inc/basic_widgets/w/feat/keyboard_handler_impl.hpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef BWIDGETS_KEYBOARD_HANDLER_IMPL_HPP
|
||||
#define BWIDGETS_KEYBOARD_HANDLER_IMPL_HPP
|
||||
|
||||
#include <basic_widgets/w/feat/event_handler_impl.hpp>
|
||||
#include <basic_widgets/w/feat/focus_handler_impl.hpp>
|
||||
#include <basic_widgets/w/feat/keyboard_handler.hpp>
|
||||
|
||||
namespace bwidgets
|
||||
{
|
||||
class KeyboardHandlerImpl : public KeyboardHandler,
|
||||
virtual public EventHandlerImpl,
|
||||
virtual public FocusHandlerImpl
|
||||
{
|
||||
std::function<void(const SDL_KeyboardEvent&)> _key_handler {[](auto) {}};
|
||||
std::function<void(const SDL_TextInputEvent&)> _input_handler {[](auto) {}};
|
||||
|
||||
public:
|
||||
void disable_keyboard_handler() override;
|
||||
void enable_keyboard_handler() override;
|
||||
void key_handler(decltype(_key_handler) handler) override
|
||||
{
|
||||
_key_handler = std::move(handler);
|
||||
}
|
||||
void text_input_handler(decltype(_input_handler) handler) override
|
||||
{
|
||||
_input_handler = std::move(handler);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,8 +1,7 @@
|
|||
#ifndef BWIDGETS_MOUSE_HANDLER_HPP
|
||||
#define BWIDGETS_MOUSE_HANDLER_HPP
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <basic_widgets/w/feat/event_handler.hpp>
|
||||
#include <basic_widgets/w/feat/focus_handler.hpp>
|
||||
|
||||
struct SDL_MouseButtonEvent;
|
||||
|
@ -10,35 +9,22 @@ struct SDL_MouseMotionEvent;
|
|||
|
||||
namespace bwidgets
|
||||
{
|
||||
class MouseHandler : public virtual FocusHandler
|
||||
class MouseHandler : virtual public FocusHandler,
|
||||
virtual public EventHandler
|
||||
{
|
||||
protected:
|
||||
const SDL_Rect* _click_area = nullptr;
|
||||
bool _is_hovered = false;
|
||||
bool _is_pushed = false;
|
||||
using EventHandler::EventHandler;
|
||||
|
||||
virtual void _handle_mouse_button(const SDL_MouseButtonEvent&,
|
||||
const SDL_Rect&) {};
|
||||
virtual void _handle_mouse_motion(const SDL_MouseMotionEvent&,
|
||||
const SDL_Rect&) {};
|
||||
virtual void _on_push(bool) {};
|
||||
virtual void _on_push(bool) = 0;
|
||||
|
||||
public:
|
||||
std::function<void(const SDL_MouseButtonEvent&)> click_handler = nullptr;
|
||||
|
||||
using FocusHandler::FocusHandler;
|
||||
|
||||
MouseHandler(const MouseHandler&) = delete;
|
||||
MouseHandler(MouseHandler&&) = delete;
|
||||
~MouseHandler() override = default;
|
||||
auto operator=(const MouseHandler&) = delete;
|
||||
auto operator=(MouseHandler&&) = delete;
|
||||
|
||||
virtual auto handle_mouse(const SDL_MouseButtonEvent&, const SDL_Rect&)
|
||||
-> MouseHandler* final;
|
||||
virtual auto handle_mouse(const SDL_MouseMotionEvent&, const SDL_Rect&)
|
||||
-> MouseHandler* final;
|
||||
virtual auto push(bool) -> MouseHandler* final;
|
||||
virtual void click_handler(std::function<void(const SDL_MouseButtonEvent&)>) = 0;
|
||||
virtual void disable_mouse_handler() = 0;
|
||||
virtual void enable_mouse_handler(const SDL_Rect*, const SDL_Rect*) = 0;
|
||||
[[nodiscard]] virtual bool hovered() const = 0;
|
||||
virtual void
|
||||
mouse_motion_handler(std::function<void(const SDL_MouseMotionEvent&)>) = 0;
|
||||
[[nodiscard]] virtual bool pushed() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
54
inc/basic_widgets/w/feat/mouse_handler_impl.hpp
Normal file
54
inc/basic_widgets/w/feat/mouse_handler_impl.hpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
#ifndef BWIDGETS_MOUSE_HANDLER_IMPL_HPP
|
||||
#define BWIDGETS_MOUSE_HANDLER_IMPL_HPP
|
||||
|
||||
#include <basic_widgets/w/feat/event_handler_impl.hpp>
|
||||
#include <basic_widgets/w/feat/focus_handler_impl.hpp>
|
||||
#include <basic_widgets/w/feat/mouse_handler.hpp>
|
||||
|
||||
namespace bwidgets
|
||||
{
|
||||
class MouseHandlerImpl : public MouseHandler,
|
||||
virtual public EventHandlerImpl,
|
||||
virtual public FocusHandlerImpl
|
||||
{
|
||||
private:
|
||||
bool _hovered {false};
|
||||
bool _pushed {false};
|
||||
|
||||
std::function<void(const SDL_MouseButtonEvent&)> _click_handler {[](auto) {}};
|
||||
std::function<void(const SDL_MouseMotionEvent&)> _motion_handler {[](auto) {}};
|
||||
|
||||
protected:
|
||||
using MouseHandler::MouseHandler;
|
||||
|
||||
void _on_push(bool) override {}
|
||||
|
||||
public:
|
||||
void
|
||||
click_handler(std::function<void(const SDL_MouseButtonEvent&)> handler) override
|
||||
{
|
||||
_click_handler = std::move(handler);
|
||||
}
|
||||
|
||||
void disable_mouse_handler() override;
|
||||
|
||||
void enable_mouse_handler(const SDL_Rect*, const SDL_Rect*) override;
|
||||
[[nodiscard]] bool hovered() const override
|
||||
{
|
||||
return _hovered;
|
||||
}
|
||||
|
||||
void mouse_motion_handler(
|
||||
std::function<void(const SDL_MouseMotionEvent&)> handler) override
|
||||
{
|
||||
_motion_handler = std::move(handler);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool pushed() const override
|
||||
{
|
||||
return _pushed;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -2,14 +2,13 @@
|
|||
#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
|
||||
{
|
||||
template<Numeric T>
|
||||
|
@ -94,25 +93,25 @@ namespace bwidgets
|
|||
|
||||
_increment_button.text("+");
|
||||
|
||||
_increment_button.click_handler = [this](const SDL_MouseButtonEvent&) {
|
||||
_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&) {
|
||||
_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));
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
NumericInput(const NumericInput&) = delete;
|
||||
|
@ -121,12 +120,11 @@ namespace bwidgets
|
|||
auto operator=(const NumericInput&) = delete;
|
||||
auto operator=(NumericInput&&) = delete;
|
||||
|
||||
auto handle_event(const SDL_Event& ev) -> Widget* override
|
||||
void handle_event(const SDL_Event& ev) override
|
||||
{
|
||||
Input<T>::handle_event(ev);
|
||||
_increment_button.handle_event(ev);
|
||||
_decrement_button.handle_event(ev);
|
||||
return this;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_valid_input(const std::string& input) const noexcept
|
||||
|
|
10
meson.build
10
meson.build
|
@ -9,7 +9,7 @@ project('sdl2_basic_widgets', 'cpp',
|
|||
],
|
||||
license: 'EUPL-1.2')
|
||||
|
||||
add_project_arguments('-pedantic', '-Winline', language: 'cpp')
|
||||
add_project_arguments('-pedantic', language: 'cpp')
|
||||
|
||||
if (get_option('buildtype').startswith('debug'))
|
||||
add_project_arguments('-DBWIDGETS_DEBUG', language: 'cpp')
|
||||
|
@ -32,7 +32,9 @@ libbasic_widgets = static_library('basic_widgets',
|
|||
'src/w/base/widget.cpp',
|
||||
'src/w/button.cpp',
|
||||
'src/w/caption.cpp',
|
||||
'src/w/feat/mouse_handler.cpp',
|
||||
'src/w/feat/event_handler_impl.cpp',
|
||||
'src/w/feat/keyboard_handler_impl.cpp',
|
||||
'src/w/feat/mouse_handler_impl.cpp',
|
||||
dependencies : [sdl, fontconfig],
|
||||
include_directories : pub_api,
|
||||
install : true)
|
||||
|
@ -44,24 +46,28 @@ libbasic_widgets_dep = declare_dependency(
|
|||
|
||||
executable('button_demo',
|
||||
'examples/button_example.cpp',
|
||||
dependencies: [sdl],
|
||||
include_directories : pub_api,
|
||||
link_with : libbasic_widgets,
|
||||
install : false)
|
||||
|
||||
executable('caption_demo',
|
||||
'examples/caption_example.cpp',
|
||||
dependencies: [sdl],
|
||||
include_directories : pub_api,
|
||||
link_with : libbasic_widgets,
|
||||
install : false)
|
||||
|
||||
executable('example_demo',
|
||||
'examples/example_example.cpp',
|
||||
dependencies: [sdl],
|
||||
include_directories : pub_api,
|
||||
link_with : libbasic_widgets,
|
||||
install : false)
|
||||
|
||||
executable('input_demo',
|
||||
'examples/input_example.cpp',
|
||||
dependencies: [sdl],
|
||||
include_directories : pub_api,
|
||||
link_with : libbasic_widgets,
|
||||
install : false)
|
||||
|
|
|
@ -17,10 +17,10 @@ void Layout::for_widgets(const std::function<void(Widget*)>& f)
|
|||
for (const auto& w : _widgets) f(w.get());
|
||||
}
|
||||
|
||||
auto Layout::handle_event(const SDL_Event& ev) -> Layout*
|
||||
void Layout::handle_event(const SDL_Event& ev)
|
||||
{
|
||||
EventHandlerImpl::handle_event(ev);
|
||||
for (const auto& w : _widgets) w->handle_event(ev);
|
||||
return this;
|
||||
}
|
||||
|
||||
void Layout::_handle_geometry_change(const SDL_Rect& vp)
|
||||
|
|
|
@ -1,41 +1,7 @@
|
|||
#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>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
auto Widget::handle_event(const SDL_Event& ev) -> Widget*
|
||||
{
|
||||
if (auto* handler = dynamic_cast<KeyboardHandler*>(this); handler) {
|
||||
switch (ev.type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
handler->handle_keyboard(ev.key);
|
||||
break;
|
||||
case SDL_TEXTINPUT:
|
||||
handler->handle_keyboard(ev.text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto* handler = dynamic_cast<MouseHandler*>(this); handler) {
|
||||
switch (ev.type) {
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
handler->handle_mouse(ev.button, _viewport);
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
handler->handle_mouse(ev.motion, _viewport);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
auto Widget::render() -> Widget*
|
||||
{
|
||||
if (_renderer == nullptr) return this;
|
||||
|
|
|
@ -13,13 +13,13 @@ const Color Button::default_color_fg {0, 0, 0, SDL_ALPHA_OPAQUE};
|
|||
|
||||
Button::Button(Widget* parent) noexcept : Widget {parent}, _caption {this}
|
||||
{
|
||||
_focus_area = _click_area = &_widget_area;
|
||||
_caption.alignment = Caption::Alignment::CENTER;
|
||||
enable_mouse_handler(&_widget_area, &_viewport);
|
||||
_caption.alignment = Caption::Alignment::CENTER;
|
||||
|
||||
_caption.render_mode(Font::RenderMode::BLENDED);
|
||||
|
||||
border_gradient = [this](int len, int pos, float divider) -> Color {
|
||||
const auto& end_color = _is_hovered ? color_bg_hover : color_bg;
|
||||
const auto& end_color = hovered() ? color_bg_hover : color_bg;
|
||||
const auto start_color = end_color / divider;
|
||||
const auto factor = linear(pos, 0, len);
|
||||
return lerp(start_color, end_color, factor);
|
||||
|
@ -74,8 +74,8 @@ void Button::_handle_renderer_change(const std::shared_ptr<Renderer>& r)
|
|||
|
||||
void Button::_handle_rendering()
|
||||
{
|
||||
Color c = _is_hovered ? color_bg_hover : color_bg;
|
||||
const auto divider = _is_pushed ? 1.5 : 2;
|
||||
Color c = hovered() ? color_bg_hover : color_bg;
|
||||
const auto divider = pushed() ? 1.5 : 2;
|
||||
auto x = 0;
|
||||
auto y = 0;
|
||||
const auto biggest = border_size.w > border_size.h ? border_size.w : border_size.h;
|
||||
|
|
32
src/w/feat/event_handler_impl.cpp
Normal file
32
src/w/feat/event_handler_impl.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include <basic_widgets/w/feat/event_handler_impl.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
void EventHandlerImpl::handle_event(const SDL_Event& ev)
|
||||
{
|
||||
auto type = static_cast<SDL_EventType>(ev.type);
|
||||
if (!_event_handlers.contains(type)) return;
|
||||
|
||||
_event_handlers[type](ev);
|
||||
}
|
||||
|
||||
auto EventHandlerImpl::_add_event_handler(handler_t event_handler) -> bool
|
||||
{
|
||||
if (_event_handlers.contains(event_handler.first)) return false;
|
||||
|
||||
_event_handlers.emplace(event_handler);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto EventHandlerImpl::_remove_event_handler(SDL_EventType ev_type)
|
||||
-> std::pair<handler_t, bool>
|
||||
{
|
||||
handler_t handler;
|
||||
auto pos = _event_handlers.find(ev_type);
|
||||
if (pos == _event_handlers.end()) return {handler, false};
|
||||
|
||||
handler = {ev_type, _event_handlers[ev_type]};
|
||||
_event_handlers.erase(pos);
|
||||
|
||||
return {handler, true};
|
||||
}
|
23
src/w/feat/keyboard_handler_impl.cpp
Normal file
23
src/w/feat/keyboard_handler_impl.cpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include <basic_widgets/w/feat/keyboard_handler_impl.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
void KeyboardHandlerImpl::disable_keyboard_handler()
|
||||
{
|
||||
_remove_event_handler(SDL_KEYDOWN);
|
||||
_remove_event_handler(SDL_KEYUP);
|
||||
_remove_event_handler(SDL_TEXTINPUT);
|
||||
}
|
||||
|
||||
void KeyboardHandlerImpl::enable_keyboard_handler()
|
||||
{
|
||||
const auto keyboard_handler = [this](const SDL_Event& ev) {
|
||||
if (FocusHandlerImpl::focus()) _key_handler(ev.key);
|
||||
};
|
||||
|
||||
_add_event_handler({SDL_KEYDOWN, keyboard_handler});
|
||||
_add_event_handler({SDL_KEYUP, keyboard_handler});
|
||||
_add_event_handler({SDL_TEXTINPUT, [this](const SDL_Event& ev) {
|
||||
if (FocusHandlerImpl::focus()) _input_handler(ev.text);
|
||||
}});
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
#include <SDL2/SDL_events.h>
|
||||
#include <SDL2/SDL_rect.h>
|
||||
|
||||
#include <basic_widgets/core/math.hpp>
|
||||
#include <basic_widgets/w/feat/mouse_handler.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
auto MouseHandler::handle_mouse(const SDL_MouseButtonEvent& ev, const SDL_Rect& orig)
|
||||
-> MouseHandler*
|
||||
{
|
||||
if (_click_area == nullptr) return this;
|
||||
|
||||
const SDL_Point p {ev.x, ev.y};
|
||||
const SDL_Rect vp {rect_offset(*_click_area, orig)};
|
||||
|
||||
if (ev.type == SDL_MOUSEBUTTONDOWN) {
|
||||
if (SDL_PointInRect(&p, &vp) == SDL_TRUE) {
|
||||
push(true);
|
||||
_handle_mouse_button(ev, vp);
|
||||
}
|
||||
else focus(false);
|
||||
}
|
||||
else {
|
||||
if (_is_pushed) {
|
||||
if (SDL_PointInRect(&p, &vp) == SDL_TRUE) {
|
||||
focus(true);
|
||||
|
||||
if (click_handler != nullptr) click_handler(ev);
|
||||
}
|
||||
push(false);
|
||||
_handle_mouse_button(ev, vp);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
auto MouseHandler::handle_mouse(const SDL_MouseMotionEvent& ev, const SDL_Rect& orig)
|
||||
-> MouseHandler*
|
||||
{
|
||||
if (_click_area == nullptr) return this;
|
||||
|
||||
const SDL_Point p {ev.x, ev.y};
|
||||
const SDL_Rect vp {rect_offset(*_click_area, orig)};
|
||||
|
||||
_is_hovered = SDL_PointInRect(&p, &vp) != 0;
|
||||
|
||||
if (_is_hovered) _handle_mouse_motion(ev, orig);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
auto MouseHandler::push(bool state) -> MouseHandler*
|
||||
{
|
||||
_on_push(state);
|
||||
_is_pushed = state;
|
||||
|
||||
return this;
|
||||
}
|
50
src/w/feat/mouse_handler_impl.cpp
Normal file
50
src/w/feat/mouse_handler_impl.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
#include <basic_widgets/core/math.hpp>
|
||||
#include <basic_widgets/w/feat/mouse_handler_impl.hpp>
|
||||
|
||||
using namespace bwidgets;
|
||||
|
||||
void MouseHandlerImpl::disable_mouse_handler()
|
||||
{
|
||||
EventHandlerImpl::_remove_event_handler(SDL_MOUSEBUTTONDOWN);
|
||||
EventHandlerImpl::_remove_event_handler(SDL_MOUSEBUTTONUP);
|
||||
_remove_event_handler(SDL_MOUSEMOTION);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
void MouseHandlerImpl::enable_mouse_handler(const SDL_Rect* area, const SDL_Rect* vp)
|
||||
{
|
||||
if (!area || !vp) throw std::logic_error("ptr parameters cannot be null.");
|
||||
|
||||
_add_event_handler({SDL_MOUSEBUTTONDOWN, [this, area, vp](const SDL_Event& ev) {
|
||||
auto absolute_area = rect_offset(*area, *vp);
|
||||
SDL_Point p = {ev.button.x, ev.button.y};
|
||||
if (SDL_PointInRect(&p, &absolute_area) == SDL_FALSE) {
|
||||
FocusHandlerImpl::focus(false);
|
||||
return;
|
||||
}
|
||||
_on_push(true);
|
||||
_pushed = true;
|
||||
}});
|
||||
_add_event_handler({SDL_MOUSEBUTTONUP, [this, area, vp](const SDL_Event& ev) {
|
||||
auto absolute_area = rect_offset(*area, *vp);
|
||||
SDL_Point p = {ev.button.x, ev.button.y};
|
||||
if (_pushed) {
|
||||
_on_push(false);
|
||||
_pushed = false;
|
||||
}
|
||||
if (SDL_PointInRect(&p, &absolute_area) == SDL_FALSE) return;
|
||||
|
||||
FocusHandlerImpl::focus(true);
|
||||
_click_handler(ev.button);
|
||||
}});
|
||||
_add_event_handler({SDL_MOUSEMOTION, [this, area, vp](const SDL_Event& ev) {
|
||||
auto absolute_area = rect_offset(*area, *vp);
|
||||
SDL_Point p = {ev.motion.x, ev.motion.y};
|
||||
if (SDL_PointInRect(&p, &absolute_area) == SDL_FALSE) {
|
||||
_hovered = false;
|
||||
return;
|
||||
}
|
||||
_hovered = true;
|
||||
_motion_handler(ev.motion);
|
||||
}});
|
||||
}
|
Loading…
Reference in a new issue