145 lines
2.8 KiB
C++
145 lines
2.8 KiB
C++
#include <psemek/ui/impl/controller.hpp>
|
|
#include <psemek/ui/impl/event_state.hpp>
|
|
#include <psemek/async/event_loop.hpp>
|
|
|
|
namespace psemek::ui::impl
|
|
{
|
|
|
|
struct controller::impl
|
|
{
|
|
component_factory & factory;
|
|
event_state state;
|
|
|
|
util::signal<>::subscription_token root_token;
|
|
std::unique_ptr<ui::impl::component> root;
|
|
|
|
async::event_loop delayed_queue;
|
|
|
|
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, 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 <typename Event>
|
|
bool on_event(Event const & event)
|
|
{
|
|
apply(state, event);
|
|
return on_event_impl(event, root.get());
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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<std::any> 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);
|
|
}
|
|
|
|
}
|