//Albatross's Rapid Numeric Menu Development Header. Keep out of reach of the people in CIS 29.
#ifndef NUMERICMENU_H
#define NUMERICMENU_H
#include <iostream>
#include <string>
#include <vector>
#if __cplusplus < 201103L && __cplusplus != 1
#error This program relies on C++11 features. Please retry compilation with these features enabled.
#endif
namespace nmenu {
class MenuBase {
public:
MenuBase() {
prev = nullptr;
}
MenuBase(std::string naem, MenuBase* togoto = nullptr) {
prev = togoto;
descript=naem;
}
virtual void exec() = 0;
virtual std::string name() {
return descript;
}
virtual void set_name(std::string naem) {
descript = naem;
}
virtual void set_return(MenuBase* returnto) {
prev = returnto;
}
protected:
std::string descript;
MenuBase* prev;
};
template <typename T>
class MenuItem : public MenuBase {
public:
void exec() {
action();
if (prev != nullptr)
prev->exec();
}
explicit MenuItem(std::string naem, T tocall, MenuBase* previous = nullptr) : MenuBase(naem,previous) {
action = tocall;
}
protected:
T action;
};
template <typename T>
class MenuItem<T*> : public MenuBase {
public:
void exec() {
if (action != nullptr)
(*action)();
if (prev != nullptr)
prev->exec();
}
explicit MenuItem(std::string naem, T* tocall, MenuBase* previous = nullptr) : MenuBase(naem,previous) {
action = tocall;
}
protected:
T* action;
};
class MenuExit : public MenuBase {
public:
void exec() {
std::cout << message;
}
explicit MenuExit(std::string naem, std::string finaltext = "") : MenuBase(naem) {
message = finaltext;
}
protected:
std::string message;
};
template <>
class MenuItem<void> : public MenuBase {
public:
void exec() {
if (prev != nullptr)
prev->exec();
}
explicit MenuItem(std::string naem, MenuBase* previous = nullptr) : MenuBase(naem, previous) {
set_name(naem);
}
protected:
};
class MenuList : public MenuBase {
public:
explicit MenuList(std::string naem = "", MenuBase* previ = nullptr) : MenuBase(naem, previ) {}
void exec() {
if(callables.empty()) {
std::cout << "This menu is empty.\n";
if (prev != nullptr)
prev->exec();
return;
}
for (size_t i = 0; i < callables.size(); ++i) {
if (callables[i]->name().empty())
std::cout << i << " - ???\n";
else
std::cout << i << " - " << callables[i]->name() << '\n';
}
std::cout << "Choose an option: ";
size_t i;
do {
std::cin >> i;
if (i >= callables.size())
std::cout << "Invalid option. Please choose an option between 0 and " << callables.size() -1 << ": ";
} while (i >= callables.size());
callables[i]->exec();
}
void connect(MenuBase* node) {
if (node != nullptr)
callables.push_back(node);
}
void disconnect(size_t item) {
if (item < callables.size()) {
callables.erase(callables.begin() + item);
}
}
void disconnect_last() {
callables.pop_back();
}
void disconnect_all() {
callables.clear();
}
private:
std::vector<MenuBase*> callables;
};
}
#endif // NUMERICMENU_H