Support delaying posted callbacks until a ui element gets attached to an event loop

This commit is contained in:
Nikita Lisitsa 2022-02-02 22:05:40 +03:00
parent e4bd58c5ef
commit a01bd019f8
2 changed files with 34 additions and 2 deletions

View file

@ -19,7 +19,7 @@ namespace psemek::ui
: std::enable_shared_from_this<element>
{
virtual element * parent() const { return parent_; }
virtual void set_parent(element * parent) { parent_ = parent; }
virtual void set_parent(element * parent);
using children_range = util::span<element * const>;
@ -28,7 +28,7 @@ namespace psemek::ui
virtual element * root();
virtual element const * root() const;
virtual async::event_loop * loop() const;
virtual void set_loop(async::event_loop * loop) { loop_ = loop; }
virtual void set_loop(async::event_loop * loop);
virtual bool on_event(mouse_move const &) { return false; }
virtual bool on_event(mouse_click const &) { return false; }
@ -81,6 +81,10 @@ namespace psemek::ui
std::shared_ptr<struct style const> own_style_;
mutable std::shared_ptr<struct style const> merged_style_;
mutable std::shared_ptr<struct style const> merged_own_style_;
mutable std::vector<util::function<void()>> delayed_callbacks_;
void post_delayed_callbacks() const;
};
}

View file

@ -7,6 +7,13 @@
namespace psemek::ui
{
void element::set_parent(element * parent)
{
parent_ = parent;
if (loop())
post_delayed_callbacks();
}
element * element::root()
{
element * r = this;
@ -28,6 +35,12 @@ namespace psemek::ui
return e->loop_;
}
void element::set_loop(async::event_loop * loop)
{
loop_ = loop;
post_delayed_callbacks();
}
void element::reshape()
{
reshape(shape().bbox());
@ -111,6 +124,8 @@ namespace psemek::ui
auto l = loop();
if (l)
l->post(std::move(f));
else
delayed_callbacks_.push_back(std::move(f));
}
void element::post_reshape()
@ -128,4 +143,17 @@ namespace psemek::ui
if (c) c->set_parent(nullptr);
}
void element::post_delayed_callbacks() const
{
auto l = loop();
assert(l);
for (auto & c : delayed_callbacks_)
l->post(std::move(c));
delayed_callbacks_.clear();
for (auto const & c : children())
if (c)
c->post_delayed_callbacks();
}
}