#ifndef _ABSTRACTUISCENE_H #define _ABSTRACTUISCENE_H #include "scenes/IScene.h" #include class IWidget; /** * The WidgetFocusChain is an important event handling mechanism in AbstractUIScene based scenes. * * If the current widget does not handle a navigation key input, it will determine to which widget the focus should be shifted if any * * It's so integral into the AbstractUIScene based scenes, that there's no input handling without setting one. So don't forget to set one! */ typedef struct WidgetFocusChainSegment { /** * @brief widget that is supposed to be focused when this segment is active */ IWidget* current; /** * @brief WidgetFocusChainSegment that is supposed to become active when the user navigates to the left with analog stick or dpad */ WidgetFocusChainSegment* onLeft; /** * @brief WidgetFocusChainSegment that is supposed to become active when the user navigates to the right with analog stick or dpad */ WidgetFocusChainSegment* onRight; /** * @brief WidgetFocusChainSegment that is supposed to become active when the user navigates upwards with analog stick or dpad */ WidgetFocusChainSegment* onUp; /** * @brief WidgetFocusChainSegment that is supposed to become active when the user navigates downwards with analog stick or dpad */ WidgetFocusChainSegment* onDown; } WidgetFocusChainSegment; /** * @brief This abstract IScene implementation implements some common functionality for UI scenes. * * The common functionality here is: * - user input handling and forwarding. * - focus handling -> if the focused widget hasn't handled a directional input on analog stick/dpad, AbstractUIScene will check the focusChain if * the focus needs to be switched to a different widget. */ class AbstractUIScene : public IScene { public: static const uint16_t MINIMUM_TIME_BETWEEN_INPUT_EVENTS; AbstractUIScene(SceneDependencies& deps); virtual ~AbstractUIScene(); /** * @brief This function reads the user input and forwards it to the focused widget (as determined by the focusChain) * if the focused widget doesn't handle any pressed navigational keys, AbstractUIScene will check the current WidgetFocusChainSegment * to see if a different widget can be selected for the given direction. */ void processUserInput() override; bool handleUserInput(joypad_port_t port, const joypad_inputs_t& inputs) override; void destroy() override; /** * This function sets a focus chain onto the scene. * * The focus chain is an important part of the event handling chain in the AbstractUIScene based screens * * The initial focus is set by this and events are basically being directed according to the focusChain. * Without a focusChain, there's no event handling. At least for AbstractUIScene based Scenes * * So don't forget to set one! */ void setFocusChain(WidgetFocusChainSegment* focusChain); SceneDependencies& getDependencies(); protected: SceneDependencies& deps_; private: WidgetFocusChainSegment* focusChain_; uint64_t lastInputHandleTime_; }; #endif