#include namespace psemek::ui::impl { struct controller::impl { component_factory & factory; geom::vector screen_size = {0, 0}; util::signal<>::subscription_token root_token; util::signal<>::subscription_token root_reshape_token; std::unique_ptr root; impl(component_factory & factory) : factory(factory) {} void set_ui(react::value ui) { root_token = ui.subscribe([this](std::any const & value) { root = factory.reconciliate(std::move(root), value); subscribe_reshape(); }, true); on_event(resize_event{screen_size}); } void subscribe_reshape() { root_reshape_token = nullptr; if (root) root_reshape_token = root->size_constraints().subscribe([this](psemek::ui::impl::size_constraints const &) { do_reshape(); }); } void do_reshape() { if (root) root->reshape({{{0.f, screen_size[0]}, {0.f, screen_size[1]}}}); } template bool on_event(Event const & event) { return on_event_impl(event, root.get()); } bool on_event(resize_event const & event) { screen_size = event.size; bool result = on_event_impl(event, root.get()); do_reshape(); return result; } template bool on_event_impl(Event const & event, component * element) { if (!element) return false; for (auto const & child : element->children()) if (on_event_impl(event, child.get())) return true; return element->on_event(event); } void draw(renderer & renderer) { draw_impl(renderer, root.get()); } void draw_impl(renderer & renderer, component * element) { if (!element) return; element->draw(renderer); for (auto const & child : element->children()) draw_impl(renderer, child.get()); element->post_draw(renderer); } }; controller::controller(component_factory & factory) : pimpl_(make_impl(factory)) {} controller::~controller() = default; void controller::set_ui(react::value ui) { impl().set_ui(std::move(ui)); } component * controller::root() { return impl().root.get(); } bool controller::on_event(resize_event const & event) { return impl().on_event(event); } bool controller::on_event(mouse_move_event const & event) { return impl().on_event(event); } bool controller::on_event(mouse_wheel_event const & event) { return impl().on_event(event); } bool controller::on_event(mouse_button_event const & event) { return impl().on_event(event); } bool controller::on_event(key_event const & event) { return impl().on_event(event); } void controller::draw(renderer & renderer) { impl().draw(renderer); } }