Store focused & hinted elements via weak_ptr in ui::controller
This commit is contained in:
parent
b9187c6b75
commit
32bb106467
1 changed files with 55 additions and 20 deletions
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue