Add root element proxy in ui::controller to resend mouse events on reshape

This commit is contained in:
Nikita Lisitsa 2021-02-26 23:15:23 +03:00
parent 1e9eb51911
commit 87d5edc386

View file

@ -1,6 +1,7 @@
#include <psemek/ui/controller.hpp>
#include <psemek/ui/painter_impl.hpp>
#include <psemek/ui/box_shape.hpp>
#include <psemek/gfx/gl.hpp>
#include <psemek/util/recursive.hpp>
#include <psemek/geom/camera.hpp>
@ -8,12 +9,54 @@
namespace psemek::ui
{
namespace
{
struct root_proxy
: element
{
children_range children() const override
{
return children_range{&root_raw, &root_raw + 1};
}
struct shape const & shape() const override
{
return shape_;
}
using element::reshape;
void reshape(geom::box<float, 2> const & bbox)
{
shape_.box = bbox;
if (root)
root->reshape(bbox);
if (on_reshape)
on_reshape();
}
geom::box<float, 2> size_constraints() const override
{
return root->size_constraints();
}
void draw(painter &) const override {}
std::shared_ptr<element> root;
element * root_raw = nullptr;
box_shape shape_;
std::function<void()> on_reshape;
};
}
struct controller::impl
{
async::executor * loop;
painter_impl painter;
std::shared_ptr<element> root;
geom::box<float, 2> shape{{{0.f, 0.f}, {0.f, 0.f}}};
std::shared_ptr<root_proxy> root;
std::optional<geom::point<int, 2>> mouse;
impl(async::executor * loop);
@ -23,7 +66,14 @@ namespace psemek::ui
controller::impl::impl(async::executor * loop)
: loop(loop)
{}
, root{std::make_shared<root_proxy>()}
{
root->set_loop(loop);
root->on_reshape = [this]{
if (mouse)
event(mouse_move{*mouse});
};
}
template <typename E>
bool controller::impl::event(E const & e)
@ -49,31 +99,33 @@ namespace psemek::ui
std::shared_ptr<element> controller::set_root(std::shared_ptr<element> 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);
}
auto old = std::move(impl().root->root);
if (old)
old->set_parent(nullptr);
impl().root->root = std::move(r);
impl().root->root_raw = impl().root->root.get();
if (impl().root->root)
impl().root->root->set_parent(impl().root.get());
impl().root->reshape();
return old;
}
element * controller::root()
{
return impl().root.get();
return impl().root->root.get();
}
void controller::reshape(geom::box<float, 2> const & shape)
{
impl().shape = shape;
if (impl().root)
impl().root->reshape(impl().shape);
impl().root->reshape(shape);
}
bool controller::event(mouse_move const & e)
{
impl().mouse = e.position;
return impl().event(e);
}
@ -105,8 +157,7 @@ namespace psemek::ui
if (c) self(c);
});
if (impl().root)
visitor(impl().root.get());
visitor(impl().root.get());
impl().painter.render(geom::window_camera{rt.viewport[0].length(), rt.viewport[1].length()}.transform());
}