rewrite how events are held

This commit is contained in:
Andrea Blankenstijn 2021-08-15 20:04:53 +02:00
parent 07f7061c20
commit d9eccc940a
23 changed files with 396 additions and 248 deletions

View File

@ -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

View File

@ -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("+");
});

View File

@ -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};

View File

@ -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*;

View File

@ -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;

View File

@ -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;

View 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

View 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

View File

@ -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;
};
}

View 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

View File

@ -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;
};
}

View 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

View File

@ -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;
};
}

View 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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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;

View File

@ -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;

View 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};
}

View 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);
}});
}

View File

@ -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;
}

View 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);
}});
}