Fix selectors lifetime issues
This commit is contained in:
parent
6fe5d72415
commit
79eceaa616
1 changed files with 34 additions and 15 deletions
|
|
@ -4,6 +4,7 @@
|
|||
#include <psemek/ui/event_interceptor.hpp>
|
||||
|
||||
#include <psemek/util/recursive.hpp>
|
||||
#include <psemek/util/to_shared.hpp>
|
||||
|
||||
#include <psemek/geom/contains.hpp>
|
||||
|
||||
|
|
@ -246,6 +247,12 @@ namespace psemek::ui
|
|||
: event_interceptor
|
||||
{
|
||||
bool transparent() const override { return false; }
|
||||
|
||||
~opaque_event_interceptor()
|
||||
{
|
||||
int fuck = 42;
|
||||
(void)fuck;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -256,11 +263,13 @@ namespace psemek::ui
|
|||
if (!screen)
|
||||
return false;
|
||||
|
||||
auto event_interceptor= std::make_shared<opaque_event_interceptor>();
|
||||
auto event_interceptor = std::make_shared<opaque_event_interceptor>();
|
||||
auto positioner = std::make_shared<struct positioner>();
|
||||
positioner->set_child(selector);
|
||||
event_interceptor->set_child(positioner);
|
||||
|
||||
auto loop = screen->loop();
|
||||
|
||||
auto close = [selector_root = event_interceptor.get(), selector = selector.get(), on_canceled]{
|
||||
if (on_canceled)
|
||||
on_canceled();
|
||||
|
|
@ -270,43 +279,53 @@ namespace psemek::ui
|
|||
p->remove_child(selector_root);
|
||||
};
|
||||
|
||||
auto patch_callback = [&](struct selector * target){
|
||||
std::vector<std::pair<ui::selector *, ui::selector::callback_type>> old_callbacks;
|
||||
|
||||
util::recursive([&](auto && self, struct selector * target) -> void{
|
||||
old_callbacks.push_back({target, target->on_selected()});
|
||||
for (std::size_t i = 0; i < target->size(); ++i)
|
||||
if (auto s = target->submenu(i))
|
||||
self(s.get());
|
||||
})(selector.get());
|
||||
|
||||
auto revert_callbacks = [old_callbacks = util::to_shared(std::move(old_callbacks))]{
|
||||
for (auto & p : *old_callbacks)
|
||||
p.first->on_selected(std::move(p.second));
|
||||
};
|
||||
|
||||
auto cancel = [close, revert_callbacks]{
|
||||
close();
|
||||
revert_callbacks();
|
||||
};
|
||||
|
||||
auto patch_callback_recursive = util::recursive([&](auto && self, struct selector * target) -> void {
|
||||
target->on_selected([target, close, cb = target->on_selected()](std::size_t index){
|
||||
close();
|
||||
if (cb)
|
||||
cb(index);
|
||||
target->on_selected(cb);
|
||||
});
|
||||
};
|
||||
|
||||
auto patch_callback_recursive = util::recursive([&](auto && self, struct selector * target) -> void {
|
||||
patch_callback(target);
|
||||
for (std::size_t i = 0; i < target->size(); ++i)
|
||||
if (auto s = target->submenu(i))
|
||||
self(s.get());
|
||||
});
|
||||
patch_callback_recursive(selector.get());
|
||||
|
||||
selector->on_selected([close, cb = selector->on_selected()](std::size_t index){
|
||||
close();
|
||||
if (cb)
|
||||
cb(index);
|
||||
});
|
||||
|
||||
event_interceptor->on_mouse_click([close](ui::mouse_click const & e) -> bool {
|
||||
event_interceptor->on_mouse_click([loop, cancel](ui::mouse_click const & e) -> bool {
|
||||
if (e.down && (e.button == ui::mouse_button::right || e.button == ui::mouse_button::left))
|
||||
{
|
||||
close();
|
||||
loop->post(cancel);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
event_interceptor->on_key_press([close](key_press const & e) -> bool {
|
||||
event_interceptor->on_key_press([loop, cancel](key_press const & e) -> bool {
|
||||
if (e.down && e.key == SDLK_ESCAPE)
|
||||
{
|
||||
close();
|
||||
loop->post(cancel);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue