psemek/libs/ui/source/impl/controller.cpp

111 lines
2.2 KiB
C++

#include <psemek/ui/impl/controller.hpp>
namespace psemek::ui::impl
{
struct controller::impl
{
component_factory & factory;
geom::vector<int, 2> screen_size = {0, 0};
util::signal<>::subscription_token root_token;
util::signal<>::subscription_token root_reshape_token;
std::unique_ptr<ui::impl::component> root;
impl(component_factory & factory)
: factory(factory)
{}
void set_ui(react::value<std::any> ui)
{
root_token = ui.subscribe([this](std::any const & value)
{
root = factory.reconciliate(std::move(root), value);
subscribe_reshape();
}, true);
subscribe_reshape();
}
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 <typename Event>
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 <typename Event>
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);
}
};
controller::controller(component_factory & factory)
: pimpl_(make_impl(factory))
{}
controller::~controller() = default;
void controller::set_ui(react::value<std::any> ui)
{
impl().set_ui(std::move(ui));
}
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);
}
}