#include #include #include #include #include namespace psemek::ui { struct controller::impl { async::executor * loop; painter_impl painter; std::shared_ptr root; geom::box shape{{{0.f, 0.f}, {0.f, 0.f}}}; impl(async::executor * loop); template bool event(E const & e); }; controller::impl::impl(async::executor * loop) : loop(loop) {} template bool controller::impl::event(E const & e) { auto visitor = util::recursive([&](auto && self, element * elem) -> bool { for (auto c : elem->children()) if (c && self(c)) return true; if (elem->enabled() && elem->on_event(e)) return true; return false; }); if (root) return visitor(root.get()); return false; } controller::controller(async::executor * loop) : pimpl_{make_impl(loop)} {} controller::~controller() = default; std::shared_ptr controller::set_root(std::shared_ptr r) { auto old = std::move(impl().root); impl().root = std::move(r); if (old) old->set_loop(nullptr); if (impl().root) { impl().root->set_loop(impl().loop); impl().root->reshape(impl().shape); } return old; } element * controller::root() { return impl().root.get(); } void controller::reshape(geom::box const & shape) { impl().shape = shape; if (impl().root) impl().root->reshape(impl().shape); } bool controller::event(mouse_move const & e) { return impl().event(e); } bool controller::event(mouse_click const & e) { return impl().event(e); } bool controller::event(mouse_wheel const & e) { return impl().event(e); } void controller::render(gfx::render_target const & rt) { rt.bind(); gl::Enable(gl::DEPTH_TEST); gl::DepthFunc(gl::LEQUAL); gl::Enable(gl::BLEND); gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); auto visitor = util::recursive([&](auto && self, element * elem) -> void { elem->draw(impl().painter); for (auto c : elem->children()) if (c) self(c); }); if (impl().root) visitor(impl().root.get()); impl().painter.render(geom::window_camera{rt.viewport[0].length(), rt.viewport[1].length()}.transform()); } }