Support focused ui elements
This commit is contained in:
parent
c06a465f51
commit
bd6d0f9f93
2 changed files with 62 additions and 37 deletions
|
|
@ -38,6 +38,8 @@ namespace psemek::ui
|
|||
virtual bool on_event(key_press const &) { return false; }
|
||||
virtual bool on_event(text_input const &) { return false; }
|
||||
|
||||
virtual bool focused() const { return false; }
|
||||
|
||||
virtual struct shape const & shape() const = 0;
|
||||
virtual void reshape(geom::box<float, 2> const & bbox) = 0;
|
||||
virtual void reshape();
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ namespace psemek::ui
|
|||
async::event_loop * loop;
|
||||
painter_impl painter;
|
||||
std::shared_ptr<root_proxy> root;
|
||||
element * focused = nullptr;
|
||||
std::optional<geom::point<int, 2>> mouse;
|
||||
float hint_delay = 0.f;
|
||||
float hint_timer = 0.f;
|
||||
|
|
@ -66,9 +67,9 @@ namespace psemek::ui
|
|||
impl(async::event_loop * loop);
|
||||
|
||||
template <typename E>
|
||||
bool event(E const & e);
|
||||
element * event(E const & e);
|
||||
|
||||
std::pair<bool, element *> event(mouse_move const & e);
|
||||
element * hinted();
|
||||
|
||||
element * hint() const;
|
||||
|
||||
|
|
@ -87,49 +88,69 @@ namespace psemek::ui
|
|||
}
|
||||
|
||||
template <typename E>
|
||||
bool controller::impl::event(E const & e)
|
||||
element * controller::impl::event(E const & e)
|
||||
{
|
||||
auto visitor = util::recursive([&](auto && self, element * elem) -> bool {
|
||||
if (elem->hidden()) return false;
|
||||
auto visitor = util::recursive([&](auto && self, element * elem) -> element * {
|
||||
if (elem->hidden()) return nullptr;
|
||||
|
||||
auto cs = elem->children();
|
||||
for (auto it = cs.rbegin(); it != cs.rend(); ++it)
|
||||
if (*it && self(*it)) return true;
|
||||
if (*it)
|
||||
if (auto p = self(*it))
|
||||
return p;
|
||||
|
||||
if (elem->enabled() && elem->on_event(e)) return true;
|
||||
return false;
|
||||
if (elem->enabled() && elem->on_event(e)) return elem;
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
if (focused)
|
||||
{
|
||||
if (focused->focused())
|
||||
{
|
||||
auto result = focused->on_event(e);
|
||||
if (!focused->focused())
|
||||
focused = nullptr;
|
||||
if (result)
|
||||
return focused;
|
||||
}
|
||||
else
|
||||
focused = nullptr;
|
||||
}
|
||||
|
||||
if (root)
|
||||
if (auto result = visitor(root.get()))
|
||||
{
|
||||
if (!focused && result->focused())
|
||||
focused = result;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
element * controller::impl::hinted()
|
||||
{
|
||||
if (!mouse)
|
||||
return nullptr;
|
||||
|
||||
auto m = geom::cast<float>(*mouse);
|
||||
auto visitor = util::recursive([&](auto && self, element * elem) -> element * {
|
||||
if (elem->hidden()) return nullptr;
|
||||
|
||||
auto cs = elem->children();
|
||||
for (auto it = cs.rbegin(); it != cs.rend(); ++it)
|
||||
if (*it)
|
||||
if (auto p = self(*it))
|
||||
return p;
|
||||
|
||||
if (elem->enabled() && elem->hint() && elem->shape().contains(m))
|
||||
return elem;
|
||||
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
if (root)
|
||||
return visitor(root.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::pair<bool, element *> controller::impl::event(mouse_move const & e)
|
||||
{
|
||||
element * hinted = nullptr;
|
||||
auto m = geom::cast<float>(e.position);
|
||||
auto visitor = util::recursive([&](auto && self, element * elem) -> bool {
|
||||
if (elem->hidden()) return false;
|
||||
|
||||
auto cs = elem->children();
|
||||
for (auto it = cs.rbegin(); it != cs.rend(); ++it)
|
||||
if (*it && self(*it)) return true;
|
||||
|
||||
if (elem->enabled())
|
||||
{
|
||||
if (elem->hint() && elem->shape().contains(m) && !hinted)
|
||||
hinted = elem;
|
||||
if (elem->on_event(e))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
bool result = false;
|
||||
if (root)
|
||||
result = visitor(root.get());
|
||||
return {result, hinted};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void controller::impl::update(float dt)
|
||||
|
|
@ -194,7 +215,9 @@ namespace psemek::ui
|
|||
bool controller::event(mouse_move const & e)
|
||||
{
|
||||
impl().mouse = e.position;
|
||||
auto [ result, new_hinted_element ] = impl().event(e);
|
||||
auto result = impl().event(e);
|
||||
|
||||
auto new_hinted_element = impl().hinted();
|
||||
|
||||
if (new_hinted_element != impl().hinted_element)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue