// // Created by robtor on 26.01.23. // #ifndef FLOATPUMP_MENU_H #define FLOATPUMP_MENU_H #include #include #include #include namespace floatpump { namespace menu { struct IMenuEntry { virtual ~IMenuEntry() = default; virtual auto u_press() -> void = 0; virtual auto u_increase(uint16_t steps = 1) -> void = 0; virtual auto u_decrease(uint16_t steps = 1) -> void = 0; virtual auto is_entered() -> bool = 0; virtual auto toString() -> std::string = 0; }; template class MenuEntry : public IMenuEntry { public: MenuEntry(T *linked_config, std::string name) : m_name(name) { m_storage = linked_config; }; auto getValue() -> T & { return (*m_storage); } auto setValue(T &value) -> void { *m_storage = value; } auto relinkConfig(T *linked_config) -> void { m_storage = linked_config; } protected: T *m_storage; std::string m_name; bool m_entered = false; auto buildString(std::string appendix) -> std::string { int spaces = 19 - (m_name.length() + appendix.length()); std::string spacer; if (spaces > 0) spacer.append(spaces, ' '); else if (spaces < 0) return "ERROR"; return {m_name + spacer + appendix}; } }; class MenuEntryCheckable : public MenuEntry { public: MenuEntryCheckable(bool *linked_config, const std::string &name) : MenuEntry(linked_config, name) {} auto toString() -> std::string override; auto u_press() -> void override; auto u_increase(uint16_t steps) -> void override {} auto u_decrease(uint16_t steps) -> void override {} auto is_entered() -> bool override { return false; } }; class MenuEntryExecute : public MenuEntry { public: MenuEntryExecute(bool *linked_config, const std::string &name) : MenuEntry(linked_config, name) {} auto u_press() -> void override; auto u_increase(uint16_t steps) -> void override {} auto u_decrease(uint16_t steps) -> void override {} auto is_entered() -> bool override { return false; } auto toString() -> std::string override; }; class MenuEntryNumeric : public MenuEntry { public: MenuEntryNumeric(uint16_t *linked_config, const std::string &name) : MenuEntry(linked_config, name) {} auto u_press() -> void override; auto u_increase(uint16_t steps) -> void override; auto u_decrease(uint16_t steps) -> void override; auto is_entered() -> bool override; auto toString() -> std::string override; }; class MenuEntryPercent : public MenuEntry { public: MenuEntryPercent(uint8_t *linked_config, const std::string &name) : MenuEntry(linked_config, name) {} auto u_press() -> void override; auto u_increase(uint16_t steps) -> void override; auto u_decrease(uint16_t steps) -> void override; auto is_entered() -> bool override; auto toString() -> std::string override; }; class Menu { public: explicit Menu(const std::string &m_name) : m_name(m_name) {} enum class Error { invalid_index }; template auto addEntry(As &&...args) -> void { m_entries.push_back(std::make_unique(std::forward(args)...)); } auto addSubmenu(Menu &menu) -> void { m_submenus.emplace_back(std::make_unique(std::move(menu)))->m_parent = this; } auto printLine() -> const std::string { return m_name; } auto getDisplayList() -> std::vector; auto getAllEntriesNum() -> unsigned const int { return (m_entries.size() + m_submenus.size()) + ((m_parent != nullptr) ? 1 : 0); } auto getSubmenu(int index) -> Menu *; auto getEntry(int index) -> IMenuEntry* ; auto getParent() -> Menu * { return m_parent; } private: std::vector> m_entries; std::vector> m_submenus; Menu *m_parent = nullptr; std::string m_name; }; } } #endif //FLOATPUMP_MENU_H