// // Created by robtor on 26.01.23. // #ifndef FLOATPUMP_NEWMENU_H #define FLOATPUMP_NEWMENU_H #include #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 { return buildString({(*m_storage) ? "ON " : "OFF"}); } auto u_press() -> void override { *m_storage = !(*m_storage); } 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 { *m_storage = true; } 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 { return buildString({(*m_storage) ? "[--]" : "[XX]"}); } }; class MenuEntryNumeric : public MenuEntry { public: MenuEntryNumeric(uint16_t *linked_config, const std::string &name) : MenuEntry(linked_config, name) {} auto u_press() -> void override { m_entered = !m_entered; } auto u_increase(uint16_t steps) -> void override { (*m_storage)++; } auto u_decrease(uint16_t steps) -> void override { (*m_storage)--; } auto is_entered() -> bool override { return m_entered; } auto toString() -> std::string override { if (m_entered) { return buildString({"> " + std::to_string(*m_storage)}); } else { return buildString({" " + std::to_string(*m_storage)}); } } }; class MenuEntryPercent : public MenuEntry { public: MenuEntryPercent(uint8_t *linked_config, const std::string &name) : MenuEntry(linked_config, name) {} auto u_press() -> void override { m_entered = !m_entered; } auto u_increase(uint16_t steps) -> void override { if (*m_storage < 100) (*m_storage)++; } auto u_decrease(uint16_t steps) -> void override { if (*m_storage > 0) { (*m_storage)--; } } auto is_entered() -> bool override { return m_entered; } auto toString() -> std::string override { if (m_entered) { return buildString({"> %" + std::to_string(*m_storage)}); } else { return buildString({" %" + std::to_string(*m_storage)}); } } }; class Menu { public: explicit Menu(const std::string &m_name) : m_name(m_name) {} template auto addEntry(As &&...args) -> void { m_entries.push_back(std::make_unique(std::forward(args)...)); } auto addSubmenu(Menu *submenu) -> void { submenu->m_parent = this; m_submenus.push_back(submenu); } auto printLine() -> const std::string { return m_name; } auto getDisplayList() -> std::vector { std::vector list; list.reserve(m_submenus.size() + m_entries.size()); //Append all Submenus for (auto &m_submenu: m_submenus) { list.push_back(m_submenu->printLine()); } //Append all Entries for (auto &m_entry: m_entries) { list.push_back(m_entry->toString()); } //Append Go-Back-Entry if we are within a submenu if (m_parent != nullptr) { list.emplace_back("<- Zurueck"); } return list; } auto getAllEntriesNum() -> unsigned const int { return (m_entries.size() + m_submenus.size()) + ((m_parent != nullptr) ? 1 : 0); } auto getSubmenu(int index) -> Menu * { if (index >= 0 && index < m_submenus.size()) { return m_submenus[index]; } else { return nullptr; } } auto getEntry(int index) -> std::optional> { if (index >= m_submenus.size() && index < m_entries.size() + m_submenus.size()) { return *m_entries[index - m_submenus.size()]; } else { return std::nullopt; } } 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_NEWMENU_H