From 83df1a82ef36511780713dfd6660e7b3b74edc2e Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 10 Mar 2022 12:23:23 +0300 Subject: [PATCH] Add ui::spawn helper for creating dropdown lists --- libs/ui/include/psemek/ui/selector.hpp | 2 + libs/ui/source/selector.cpp | 53 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/libs/ui/include/psemek/ui/selector.hpp b/libs/ui/include/psemek/ui/selector.hpp index 68594cf1..0949f714 100644 --- a/libs/ui/include/psemek/ui/selector.hpp +++ b/libs/ui/include/psemek/ui/selector.hpp @@ -47,4 +47,6 @@ namespace psemek::ui std::function callback_; }; + bool spawn(element * root, std::shared_ptr selector, geom::point const & position, std::function on_selected); + } diff --git a/libs/ui/source/selector.cpp b/libs/ui/source/selector.cpp index fd59e433..5ac0fe7b 100644 --- a/libs/ui/source/selector.cpp +++ b/libs/ui/source/selector.cpp @@ -1,4 +1,7 @@ #include +#include +#include +#include #include @@ -123,5 +126,55 @@ namespace psemek::ui callback_ = std::move(callback); } + bool spawn(element * root, std::shared_ptr selector, geom::point const & position, std::function on_selected) + { + ui::screen * screen = find_last_parent_of_type(root); + if (!screen) + return false; + + auto event_interceptor = std::make_shared(); + auto positioner = std::make_shared(); + + event_interceptor->set_child(positioner); + positioner->set_child(selector); + + auto close = [event_interceptor = event_interceptor.get(), selector = selector.get()]{ + auto p = dynamic_cast(event_interceptor->parent()); + if (p) + p->remove_child(event_interceptor); + + selector->on_selected([](std::size_t){}); + }; + + selector->on_selected([close, cb = std::move(on_selected)](std::size_t index){ + close(); + cb(index); + }); + + event_interceptor->on_mouse_click([close](ui::mouse_click const & e) -> bool { + if (e.down && (e.button == ui::mouse_button::right || e.button == ui::mouse_button::left)) + { + close(); + return true; + } + + return false; + }); + + event_interceptor->on_key_press([close](key_press const & e) -> bool { + if (e.down && e.key == SDLK_ESCAPE) + { + close(); + return true; + } + + return false; + }); + + send_fake_mouse_move_event(event_interceptor.get(), true); + positioner->set_position(geom::cast(position), positioner::x_align::left, positioner::y_align::top); + screen->add_child(event_interceptor, screen::x_policy::fill, screen::y_policy::fill); + return true; + } }