#include #include #include namespace psemek::ui::impl { struct controller::impl { component_factory & factory; event_state state; util::signal<>::subscription_token root_token; std::unique_ptr root; async::event_loop delayed_queue; 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, state, delayed_queue, [this]{ delayed_queue.post([this]{ reshape(); }); }); }, true); } void reshape() { if (!root) return; root->reshape({{{0.f, state.size[0]}, {0.f, state.size[1]}}}); on_event_impl(mouse_move_event{state.mouse, {0, 0}}, root.get()); } template bool on_event(Event const & event) { apply(state, event); return on_event_impl(event, root.get()); } 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 update(float dt) { delayed_queue.pump(); animate_impl(dt, root.get()); } void animate_impl(float dt, component * element) { if (!element) return; element->animate(dt); for (auto const & child : element->children()) animate_impl(dt, child.get()); } 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::update(float dt) { impl().update(dt); } void controller::draw(renderer & renderer) { impl().draw(renderer); } }