Store focused & hinted elements via weak_ptr in ui::controller

This commit is contained in:
Nikita Lisitsa 2022-04-10 00:01:36 +03:00
parent b9187c6b75
commit 32bb106467

View file

@ -56,12 +56,12 @@ namespace psemek::ui
async::event_loop * loop; async::event_loop * loop;
painter_impl painter; painter_impl painter;
std::shared_ptr<root_proxy> root; std::shared_ptr<root_proxy> root;
element * focused = nullptr; std::weak_ptr<element> focused;
std::optional<geom::point<int, 2>> mouse; std::optional<geom::point<int, 2>> mouse;
float hint_delay = 0.f; float hint_delay = 0.f;
float hint_timer = 0.f; float hint_timer = 0.f;
util::function<void(element *)> on_hint; util::function<void(element *)> on_hint;
element * hinted_element = nullptr; std::optional<std::weak_ptr<element>> hinted_element = std::nullopt;
std::optional<std::string> hint_called = std::nullopt; std::optional<std::string> hint_called = std::nullopt;
impl(async::event_loop * loop); impl(async::event_loop * loop);
@ -69,9 +69,7 @@ namespace psemek::ui
template <typename E> template <typename E>
element * event(E const & e); element * event(E const & e);
element * hinted(); element * hinted() const;
element * hint() const;
void update(float dt); void update(float dt);
}; };
@ -103,31 +101,31 @@ namespace psemek::ui
return nullptr; return nullptr;
}); });
if (focused) if (auto p = focused.lock())
{ {
if (focused->focused()) if (p->focused())
{ {
auto result = focused->on_event(e); auto result = p->on_event(e);
if (!focused->focused()) if (!p->focused())
focused = nullptr; focused.reset();
if (result) if (result)
return focused; return p.get();
} }
else else
focused = nullptr; focused.reset();
} }
if (root) if (root)
if (auto result = visitor(root.get())) if (auto result = visitor(root.get()))
{ {
if (!focused && result->focused()) if (!focused.lock() && result->focused())
focused = result; focused = result->weak_from_this();
} }
return nullptr; return nullptr;
} }
element * controller::impl::hinted() element * controller::impl::hinted() const
{ {
if (!mouse) if (!mouse)
return nullptr; return nullptr;
@ -217,16 +215,37 @@ namespace psemek::ui
impl().mouse = e.position; impl().mouse = e.position;
auto result = impl().event(e); auto result = impl().event(e);
if (impl().hinted_element)
{
auto p = impl().hinted_element->lock();
if (!p)
{
if (impl().hint_called && impl().on_hint)
impl().on_hint(nullptr);
impl().hinted_element = std::nullopt;
impl().hint_timer = 0.f;
impl().hint_called = std::nullopt;
}
}
auto new_hinted_element = impl().hinted(); auto new_hinted_element = impl().hinted();
if (new_hinted_element != impl().hinted_element) std::shared_ptr<element> old_hinted_element;
if (impl().hinted_element)
old_hinted_element = impl().hinted_element->lock();
if (new_hinted_element != old_hinted_element.get())
{ {
if (impl().hint_called && impl().on_hint) if (impl().hint_called && impl().on_hint)
impl().on_hint(nullptr); impl().on_hint(nullptr);
impl().hint_timer = 0.f; impl().hint_timer = 0.f;
impl().hint_called = std::nullopt; impl().hint_called = std::nullopt;
if (new_hinted_element)
impl().hinted_element = new_hinted_element->weak_from_this();
else
impl().hinted_element = std::nullopt;
} }
impl().hinted_element = new_hinted_element;
return result; return result;
} }
@ -255,14 +274,30 @@ namespace psemek::ui
{ {
impl().update(dt); impl().update(dt);
if (impl().hinted_element && (!impl().hint_called || *impl().hint_called != *impl().hinted_element->hint())) std::shared_ptr<element> p;
if (impl().hinted_element)
{
p = impl().hinted_element->lock();
if (!p)
{
if (impl().hint_called && impl().on_hint)
impl().on_hint(nullptr);
impl().hinted_element = std::nullopt;
impl().hint_timer = 0.f;
impl().hint_called = std::nullopt;
}
}
if (p && (!impl().hint_called || *impl().hint_called != *p->hint()))
{ {
impl().hint_timer += dt; impl().hint_timer += dt;
if (impl().hint_timer >= impl().hint_delay) if (impl().hint_timer >= impl().hint_delay)
{ {
if (impl().on_hint) if (impl().on_hint)
impl().on_hint(impl().hinted_element); impl().on_hint(p.get());
impl().hint_called = *impl().hinted_element->hint(); impl().hint_called = *p->hint();
} }
} }
} }