From 5bf544d032cf5bbfe0ee6fa222519fc535cc9d5e Mon Sep 17 00:00:00 2001 From: lisyarus Date: Tue, 20 Dec 2022 17:11:23 +0300 Subject: [PATCH] Add generic ui::spawn --- libs/ui/include/psemek/ui/spawn.hpp | 10 +++++ libs/ui/source/spawn.cpp | 68 +++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 libs/ui/include/psemek/ui/spawn.hpp create mode 100644 libs/ui/source/spawn.cpp diff --git a/libs/ui/include/psemek/ui/spawn.hpp b/libs/ui/include/psemek/ui/spawn.hpp new file mode 100644 index 00000000..6fa26440 --- /dev/null +++ b/libs/ui/include/psemek/ui/spawn.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace psemek::ui +{ + + bool spawn(element * root, std::shared_ptr element, geom::point const & position); + +} diff --git a/libs/ui/source/spawn.cpp b/libs/ui/source/spawn.cpp new file mode 100644 index 00000000..6afc5a1e --- /dev/null +++ b/libs/ui/source/spawn.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +namespace psemek::ui +{ + + namespace + { + + struct opaque_event_interceptor + : event_interceptor + { + bool transparent() const override { return false; } + }; + + } + + bool spawn(element * root, std::shared_ptr element, geom::point const & position) + { + ui::screen * screen = find_last_parent_of_type(root); + if (!screen) + return false; + + auto event_interceptor = std::make_shared(); + auto positioner = std::make_shared(); + positioner->set_child(element); + event_interceptor->set_child(positioner); + + auto loop = screen->loop(); + + auto close = [root = event_interceptor.get()]{ + auto p = dynamic_cast(root->parent()); + if (p) + p->remove_child(root); + }; + + event_interceptor->on_mouse_click([loop, close](ui::mouse_click const & e) -> bool { + if (e.down && (e.button == ui::mouse_button::right || e.button == ui::mouse_button::left)) + { + loop->post(close); + return true; + } + + return false; + }); + + event_interceptor->on_key_press([loop, close](key_press const & e) -> bool { + if (e.down && e.key == SDLK_ESCAPE) + { + loop->post(close); + return true; + } + + return false; + }); + + event_interceptor->on_mouse_move([](mouse_move const &){ return true; }); + + send_fake_mouse_move_event(event_interceptor.get(), true); + + positioner->set_position(position, positioner::x_align::left, positioner::y_align::top); + screen->add_child(event_interceptor, screen::x_policy::fill, screen::y_policy::fill); + return true; + } + +}