#pragma once #include "event.hpp" #include "ui.hpp" #include #include #include #include namespace Rml { class Element; } namespace dusk::ui { class Component { public: Component() = default; explicit Component(Rml::Element* root); virtual ~Component(); Component(const Component&) = delete; Component& operator=(const Component&) = delete; virtual void update(); virtual bool focus(); virtual bool focus_from(NavCommand direction) { return focus(); } virtual bool selected() const { return mRoot->IsPseudoClassSet("selected"); } virtual void set_selected(bool selected); virtual bool disabled() const { return mRoot->IsPseudoClassSet("disabled"); } virtual void set_disabled(bool disabled); void listen(Rml::Element* element, Rml::EventId event, ScopedEventListener::Callback callback, bool capture = false); void listen(Rml::Element* element, const Rml::String& event, ScopedEventListener::Callback callback, bool capture = false); bool contains(Rml::Element* element) const; template requires std::is_base_of_v T& add_child(Args&&... args) { auto child = std::make_unique(mRoot, std::forward(args)...); T& ref = *child; mChildren.emplace_back(std::move(child)); return ref; } Rml::Element* root() const { return mRoot; } protected: void clear_children(); Rml::Element* mRoot = nullptr; std::vector> mChildren; std::vector> mListeners; }; template class FluentComponent : public Component { public: using Component::Component; Derived& listen( Rml::EventId event, ScopedEventListener::Callback callback, bool capture = false) { Component::listen(mRoot, event, std::move(callback), capture); return static_cast(*this); } Derived& on_nav_command(std::function callback) { listen(Rml::EventId::Click, [this, callback](Rml::Event& event) { if (!disabled() && callback(event, NavCommand::Confirm)) { event.StopPropagation(); } }); listen(Rml::EventId::Keydown, [this, callback = std::move(callback)](Rml::Event& event) { if (disabled()) { return; } const auto cmd = map_nav_event(event); if (cmd != NavCommand::None && callback(event, cmd)) { event.StopPropagation(); } }); return static_cast(*this); } }; } // namespace dusk::ui