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/ui/event_interceptor.hpp>
|
||||||
|
|
||||||
#include <psemek/util/recursive.hpp>
|
#include <psemek/util/recursive.hpp>
|
||||||
|
#include <psemek/util/to_shared.hpp>
|
||||||
|
|
||||||
#include <psemek/geom/contains.hpp>
|
#include <psemek/geom/contains.hpp>
|
||||||
|
|
||||||
|
|
@ -246,6 +247,12 @@ namespace psemek::ui
|
||||||
: event_interceptor
|
: event_interceptor
|
||||||
{
|
{
|
||||||
bool transparent() const override { return false; }
|
bool transparent() const override { return false; }
|
||||||
|
|
||||||
|
~opaque_event_interceptor()
|
||||||
|
{
|
||||||
|
int fuck = 42;
|
||||||
|
(void)fuck;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -261,6 +268,8 @@ namespace psemek::ui
|
||||||
positioner->set_child(selector);
|
positioner->set_child(selector);
|
||||||
event_interceptor->set_child(positioner);
|
event_interceptor->set_child(positioner);
|
||||||
|
|
||||||
|
auto loop = screen->loop();
|
||||||
|
|
||||||
auto close = [selector_root = event_interceptor.get(), selector = selector.get(), on_canceled]{
|
auto close = [selector_root = event_interceptor.get(), selector = selector.get(), on_canceled]{
|
||||||
if (on_canceled)
|
if (on_canceled)
|
||||||
on_canceled();
|
on_canceled();
|
||||||
|
|
@ -270,43 +279,53 @@ namespace psemek::ui
|
||||||
p->remove_child(selector_root);
|
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){
|
target->on_selected([target, close, cb = target->on_selected()](std::size_t index){
|
||||||
close();
|
close();
|
||||||
if (cb)
|
if (cb)
|
||||||
cb(index);
|
cb(index);
|
||||||
target->on_selected(cb);
|
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)
|
for (std::size_t i = 0; i < target->size(); ++i)
|
||||||
if (auto s = target->submenu(i))
|
if (auto s = target->submenu(i))
|
||||||
self(s.get());
|
self(s.get());
|
||||||
});
|
});
|
||||||
patch_callback_recursive(selector.get());
|
patch_callback_recursive(selector.get());
|
||||||
|
|
||||||
selector->on_selected([close, cb = selector->on_selected()](std::size_t index){
|
event_interceptor->on_mouse_click([loop, cancel](ui::mouse_click const & e) -> bool {
|
||||||
close();
|
|
||||||
if (cb)
|
|
||||||
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))
|
if (e.down && (e.button == ui::mouse_button::right || e.button == ui::mouse_button::left))
|
||||||
{
|
{
|
||||||
close();
|
loop->post(cancel);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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)
|
if (e.down && e.key == SDLK_ESCAPE)
|
||||||
{
|
{
|
||||||
close();
|
loop->post(cancel);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue